| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 // 3) By not using an enum, we are possibly preventing the compiler from | 62 // 3) By not using an enum, we are possibly preventing the compiler from |
| 63 // doing certain constant folds, which may significantly reduce the | 63 // doing certain constant folds, which may significantly reduce the |
| 64 // code generated for some assembly instructions (because they boil down | 64 // code generated for some assembly instructions (because they boil down |
| 65 // to a few constants). If this is a problem, we could change the code | 65 // to a few constants). If this is a problem, we could change the code |
| 66 // such that we use an enum in optimized mode, and the struct in debug | 66 // such that we use an enum in optimized mode, and the struct in debug |
| 67 // mode. This way we get the compile-time error checking in debug mode | 67 // mode. This way we get the compile-time error checking in debug mode |
| 68 // and best performance in optimized code. | 68 // and best performance in optimized code. |
| 69 // | 69 // |
| 70 // Core register | 70 // Core register |
| 71 struct Register { | 71 struct Register { |
| 72 bool is_valid() const { return 0 <= code_ && code_ < 16; } | 72 static const int kNumRegisters = 16; |
| 73 static const int kNumAllocatableRegisters = 8; |
| 74 |
| 75 static int ToAllocationIndex(Register reg) { |
| 76 return reg.code(); |
| 77 } |
| 78 |
| 79 static Register FromAllocationIndex(int index) { |
| 80 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 81 return from_code(index); |
| 82 } |
| 83 |
| 84 static const char* AllocationIndexToString(int index) { |
| 85 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 86 const char* const names[] = { |
| 87 "r0", |
| 88 "r1", |
| 89 "r2", |
| 90 "r3", |
| 91 "r4", |
| 92 "r5", |
| 93 "r6", |
| 94 "r7", |
| 95 }; |
| 96 return names[index]; |
| 97 } |
| 98 |
| 99 static Register from_code(int code) { |
| 100 Register r = { code }; |
| 101 return r; |
| 102 } |
| 103 |
| 104 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
| 73 bool is(Register reg) const { return code_ == reg.code_; } | 105 bool is(Register reg) const { return code_ == reg.code_; } |
| 74 int code() const { | 106 int code() const { |
| 75 ASSERT(is_valid()); | 107 ASSERT(is_valid()); |
| 76 return code_; | 108 return code_; |
| 77 } | 109 } |
| 78 int bit() const { | 110 int bit() const { |
| 79 ASSERT(is_valid()); | 111 ASSERT(is_valid()); |
| 80 return 1 << code_; | 112 return 1 << code_; |
| 81 } | 113 } |
| 82 | 114 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 *m = code_ & 0x1; | 157 *m = code_ & 0x1; |
| 126 *vm = code_ >> 1; | 158 *vm = code_ >> 1; |
| 127 } | 159 } |
| 128 | 160 |
| 129 int code_; | 161 int code_; |
| 130 }; | 162 }; |
| 131 | 163 |
| 132 | 164 |
| 133 // Double word VFP register. | 165 // Double word VFP register. |
| 134 struct DwVfpRegister { | 166 struct DwVfpRegister { |
| 167 // d0 has been excluded from allocation. This is following ia32 |
| 168 // where xmm0 is excluded. This should be revisited. |
| 169 static const int kNumRegisters = 16; |
| 170 static const int kNumAllocatableRegisters = 15; |
| 171 |
| 172 static int ToAllocationIndex(DwVfpRegister reg) { |
| 173 ASSERT(reg.code() != 0); |
| 174 return reg.code() - 1; |
| 175 } |
| 176 |
| 177 static DwVfpRegister FromAllocationIndex(int index) { |
| 178 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 179 return from_code(index + 1); |
| 180 } |
| 181 |
| 182 static const char* AllocationIndexToString(int index) { |
| 183 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 184 const char* const names[] = { |
| 185 "d1", |
| 186 "d2", |
| 187 "d3", |
| 188 "d4", |
| 189 "d5", |
| 190 "d6", |
| 191 "d7", |
| 192 "d8", |
| 193 "d9", |
| 194 "d10", |
| 195 "d11", |
| 196 "d12", |
| 197 "d13", |
| 198 "d14", |
| 199 "d15" |
| 200 }; |
| 201 return names[index]; |
| 202 } |
| 203 |
| 204 static DwVfpRegister from_code(int code) { |
| 205 DwVfpRegister r = { code }; |
| 206 return r; |
| 207 } |
| 208 |
| 135 // Supporting d0 to d15, can be later extended to d31. | 209 // Supporting d0 to d15, can be later extended to d31. |
| 136 bool is_valid() const { return 0 <= code_ && code_ < 16; } | 210 bool is_valid() const { return 0 <= code_ && code_ < 16; } |
| 137 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } | 211 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } |
| 138 SwVfpRegister low() const { | 212 SwVfpRegister low() const { |
| 139 SwVfpRegister reg; | 213 SwVfpRegister reg; |
| 140 reg.code_ = code_ * 2; | 214 reg.code_ = code_ * 2; |
| 141 | 215 |
| 142 ASSERT(reg.is_valid()); | 216 ASSERT(reg.is_valid()); |
| 143 return reg; | 217 return reg; |
| 144 } | 218 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 160 void split_code(int* vm, int* m) const { | 234 void split_code(int* vm, int* m) const { |
| 161 ASSERT(is_valid()); | 235 ASSERT(is_valid()); |
| 162 *m = (code_ & 0x10) >> 4; | 236 *m = (code_ & 0x10) >> 4; |
| 163 *vm = code_ & 0x0F; | 237 *vm = code_ & 0x0F; |
| 164 } | 238 } |
| 165 | 239 |
| 166 int code_; | 240 int code_; |
| 167 }; | 241 }; |
| 168 | 242 |
| 169 | 243 |
| 244 typedef DwVfpRegister DoubleRegister; |
| 245 |
| 246 |
| 170 // Support for the VFP registers s0 to s31 (d0 to d15). | 247 // Support for the VFP registers s0 to s31 (d0 to d15). |
| 171 // Note that "s(N):s(N+1)" is the same as "d(N/2)". | 248 // Note that "s(N):s(N+1)" is the same as "d(N/2)". |
| 172 const SwVfpRegister s0 = { 0 }; | 249 const SwVfpRegister s0 = { 0 }; |
| 173 const SwVfpRegister s1 = { 1 }; | 250 const SwVfpRegister s1 = { 1 }; |
| 174 const SwVfpRegister s2 = { 2 }; | 251 const SwVfpRegister s2 = { 2 }; |
| 175 const SwVfpRegister s3 = { 3 }; | 252 const SwVfpRegister s3 = { 3 }; |
| 176 const SwVfpRegister s4 = { 4 }; | 253 const SwVfpRegister s4 = { 4 }; |
| 177 const SwVfpRegister s5 = { 5 }; | 254 const SwVfpRegister s5 = { 5 }; |
| 178 const SwVfpRegister s6 = { 6 }; | 255 const SwVfpRegister s6 = { 6 }; |
| 179 const SwVfpRegister s7 = { 7 }; | 256 const SwVfpRegister s7 = { 7 }; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 p11 = 11, | 356 p11 = 11, |
| 280 p12 = 12, | 357 p12 = 12, |
| 281 p13 = 13, | 358 p13 = 13, |
| 282 p14 = 14, | 359 p14 = 14, |
| 283 p15 = 15 | 360 p15 = 15 |
| 284 }; | 361 }; |
| 285 | 362 |
| 286 | 363 |
| 287 // Condition field in instructions. | 364 // Condition field in instructions. |
| 288 enum Condition { | 365 enum Condition { |
| 366 // any value < 0 is considered no_condition |
| 367 no_condition = -1, |
| 368 |
| 289 eq = 0 << 28, // Z set equal. | 369 eq = 0 << 28, // Z set equal. |
| 290 ne = 1 << 28, // Z clear not equal. | 370 ne = 1 << 28, // Z clear not equal. |
| 291 nz = 1 << 28, // Z clear not zero. | 371 nz = 1 << 28, // Z clear not zero. |
| 292 cs = 2 << 28, // C set carry set. | 372 cs = 2 << 28, // C set carry set. |
| 293 hs = 2 << 28, // C set unsigned higher or same. | 373 hs = 2 << 28, // C set unsigned higher or same. |
| 294 cc = 3 << 28, // C clear carry clear. | 374 cc = 3 << 28, // C clear carry clear. |
| 295 lo = 3 << 28, // C clear unsigned lower. | 375 lo = 3 << 28, // C clear unsigned lower. |
| 296 mi = 4 << 28, // N set negative. | 376 mi = 4 << 28, // N set negative. |
| 297 pl = 5 << 28, // N clear positive or zero. | 377 pl = 5 << 28, // N clear positive or zero. |
| 298 vs = 6 << 28, // V set overflow. | 378 vs = 6 << 28, // V set overflow. |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 | 600 |
| 521 friend class Assembler; | 601 friend class Assembler; |
| 522 }; | 602 }; |
| 523 | 603 |
| 524 // CpuFeatures keeps track of which features are supported by the target CPU. | 604 // CpuFeatures keeps track of which features are supported by the target CPU. |
| 525 // Supported features must be enabled by a Scope before use. | 605 // Supported features must be enabled by a Scope before use. |
| 526 class CpuFeatures { | 606 class CpuFeatures { |
| 527 public: | 607 public: |
| 528 // Detect features of the target CPU. Set safe defaults if the serializer | 608 // Detect features of the target CPU. Set safe defaults if the serializer |
| 529 // is enabled (snapshots must be portable). | 609 // is enabled (snapshots must be portable). |
| 530 void Probe(); | 610 void Probe(bool portable); |
| 531 | 611 |
| 532 // Check whether a feature is supported by the target CPU. | 612 // Check whether a feature is supported by the target CPU. |
| 533 bool IsSupported(CpuFeature f) const { | 613 bool IsSupported(CpuFeature f) const { |
| 534 if (f == VFP3 && !FLAG_enable_vfp3) return false; | 614 if (f == VFP3 && !FLAG_enable_vfp3) return false; |
| 535 return (supported_ & (1u << f)) != 0; | 615 return (supported_ & (1u << f)) != 0; |
| 536 } | 616 } |
| 537 | 617 |
| 538 // Check whether a feature is currently enabled. | 618 // Check whether a feature is currently enabled. |
| 539 bool IsEnabled(CpuFeature f) const { | 619 bool IsEnabled(CpuFeature f) const { |
| 540 return (enabled_ & (1u << f)) != 0; | 620 return (enabled_ & (1u << f)) != 0; |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 | 1234 |
| 1155 // Debugging | 1235 // Debugging |
| 1156 | 1236 |
| 1157 // Mark address of the ExitJSFrame code. | 1237 // Mark address of the ExitJSFrame code. |
| 1158 void RecordJSReturn(); | 1238 void RecordJSReturn(); |
| 1159 | 1239 |
| 1160 // Mark address of a debug break slot. | 1240 // Mark address of a debug break slot. |
| 1161 void RecordDebugBreakSlot(); | 1241 void RecordDebugBreakSlot(); |
| 1162 | 1242 |
| 1163 // Record a comment relocation entry that can be used by a disassembler. | 1243 // Record a comment relocation entry that can be used by a disassembler. |
| 1164 // Use --debug_code to enable. | 1244 // Use --code-comments to enable. |
| 1165 void RecordComment(const char* msg); | 1245 void RecordComment(const char* msg); |
| 1166 | 1246 |
| 1247 // Writes a single byte or word of data in the code stream. Used for |
| 1248 // inline tables, e.g., jump-tables. |
| 1249 void db(uint8_t data); |
| 1250 void dd(uint32_t data); |
| 1251 |
| 1167 int pc_offset() const { return pc_ - buffer_; } | 1252 int pc_offset() const { return pc_ - buffer_; } |
| 1168 | 1253 |
| 1169 PositionsRecorder* positions_recorder() { return &positions_recorder_; } | 1254 PositionsRecorder* positions_recorder() { return &positions_recorder_; } |
| 1170 | 1255 |
| 1171 bool can_peephole_optimize(int instructions) { | 1256 bool can_peephole_optimize(int instructions) { |
| 1172 if (!FLAG_peephole_optimization) return false; | 1257 if (!allow_peephole_optimization_) return false; |
| 1173 if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false; | 1258 if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false; |
| 1174 return reloc_info_writer.last_pc() <= pc_ - instructions * kInstrSize; | 1259 return reloc_info_writer.last_pc() <= pc_ - instructions * kInstrSize; |
| 1175 } | 1260 } |
| 1176 | 1261 |
| 1177 // Read/patch instructions | 1262 // Read/patch instructions |
| 1178 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } | 1263 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } |
| 1179 static void instr_at_put(byte* pc, Instr instr) { | 1264 static void instr_at_put(byte* pc, Instr instr) { |
| 1180 *reinterpret_cast<Instr*>(pc) = instr; | 1265 *reinterpret_cast<Instr*>(pc) = instr; |
| 1181 } | 1266 } |
| 1182 static bool IsBranch(Instr instr); | 1267 static bool IsBranch(Instr instr); |
| 1183 static int GetBranchOffset(Instr instr); | 1268 static int GetBranchOffset(Instr instr); |
| 1184 static bool IsLdrRegisterImmediate(Instr instr); | 1269 static bool IsLdrRegisterImmediate(Instr instr); |
| 1185 static int GetLdrRegisterImmediateOffset(Instr instr); | 1270 static int GetLdrRegisterImmediateOffset(Instr instr); |
| 1186 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset); | 1271 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset); |
| 1187 static bool IsStrRegisterImmediate(Instr instr); | 1272 static bool IsStrRegisterImmediate(Instr instr); |
| 1188 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset); | 1273 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset); |
| 1189 static bool IsAddRegisterImmediate(Instr instr); | 1274 static bool IsAddRegisterImmediate(Instr instr); |
| 1190 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset); | 1275 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset); |
| 1191 static Register GetRd(Instr instr); | 1276 static Register GetRd(Instr instr); |
| 1192 static bool IsPush(Instr instr); | 1277 static bool IsPush(Instr instr); |
| 1193 static bool IsPop(Instr instr); | 1278 static bool IsPop(Instr instr); |
| 1194 static bool IsStrRegFpOffset(Instr instr); | 1279 static bool IsStrRegFpOffset(Instr instr); |
| 1195 static bool IsLdrRegFpOffset(Instr instr); | 1280 static bool IsLdrRegFpOffset(Instr instr); |
| 1196 static bool IsStrRegFpNegOffset(Instr instr); | 1281 static bool IsStrRegFpNegOffset(Instr instr); |
| 1197 static bool IsLdrRegFpNegOffset(Instr instr); | 1282 static bool IsLdrRegFpNegOffset(Instr instr); |
| 1198 static bool IsLdrPcImmediateOffset(Instr instr); | 1283 static bool IsLdrPcImmediateOffset(Instr instr); |
| 1199 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); | 1284 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); |
| 1200 | 1285 |
| 1286 // Check if is time to emit a constant pool for pending reloc info entries |
| 1287 void CheckConstPool(bool force_emit, bool require_jump); |
| 1201 | 1288 |
| 1202 protected: | 1289 protected: |
| 1203 int buffer_space() const { return reloc_info_writer.pos() - pc_; } | 1290 int buffer_space() const { return reloc_info_writer.pos() - pc_; } |
| 1204 | 1291 |
| 1205 // Read/patch instructions | 1292 // Read/patch instructions |
| 1206 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } | 1293 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } |
| 1207 void instr_at_put(int pos, Instr instr) { | 1294 void instr_at_put(int pos, Instr instr) { |
| 1208 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; | 1295 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; |
| 1209 } | 1296 } |
| 1210 | 1297 |
| 1211 // Decode branch instruction at pos and return branch target pos | 1298 // Decode branch instruction at pos and return branch target pos |
| 1212 int target_at(int pos); | 1299 int target_at(int pos); |
| 1213 | 1300 |
| 1214 // Patch branch instruction at pos to branch to given branch target pos | 1301 // Patch branch instruction at pos to branch to given branch target pos |
| 1215 void target_at_put(int pos, int target_pos); | 1302 void target_at_put(int pos, int target_pos); |
| 1216 | 1303 |
| 1217 // Check if is time to emit a constant pool for pending reloc info entries | |
| 1218 void CheckConstPool(bool force_emit, bool require_jump); | |
| 1219 | |
| 1220 // Block the emission of the constant pool before pc_offset | 1304 // Block the emission of the constant pool before pc_offset |
| 1221 void BlockConstPoolBefore(int pc_offset) { | 1305 void BlockConstPoolBefore(int pc_offset) { |
| 1222 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset; | 1306 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset; |
| 1223 } | 1307 } |
| 1224 | 1308 |
| 1225 void StartBlockConstPool() { | 1309 void StartBlockConstPool() { |
| 1226 const_pool_blocked_nesting_++; | 1310 const_pool_blocked_nesting_++; |
| 1227 } | 1311 } |
| 1228 void EndBlockConstPool() { | 1312 void EndBlockConstPool() { |
| 1229 const_pool_blocked_nesting_--; | 1313 const_pool_blocked_nesting_--; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 | 1407 |
| 1324 // Record reloc info for current pc_ | 1408 // Record reloc info for current pc_ |
| 1325 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1409 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
| 1326 | 1410 |
| 1327 friend class RegExpMacroAssemblerARM; | 1411 friend class RegExpMacroAssemblerARM; |
| 1328 friend class RelocInfo; | 1412 friend class RelocInfo; |
| 1329 friend class CodePatcher; | 1413 friend class CodePatcher; |
| 1330 friend class BlockConstPoolScope; | 1414 friend class BlockConstPoolScope; |
| 1331 | 1415 |
| 1332 PositionsRecorder positions_recorder_; | 1416 PositionsRecorder positions_recorder_; |
| 1417 bool allow_peephole_optimization_; |
| 1333 friend class PositionsRecorder; | 1418 friend class PositionsRecorder; |
| 1334 friend class EnsureSpace; | 1419 friend class EnsureSpace; |
| 1335 }; | 1420 }; |
| 1336 | 1421 |
| 1337 | 1422 |
| 1338 class EnsureSpace BASE_EMBEDDED { | 1423 class EnsureSpace BASE_EMBEDDED { |
| 1339 public: | 1424 public: |
| 1340 explicit EnsureSpace(Assembler* assembler) { | 1425 explicit EnsureSpace(Assembler* assembler) { |
| 1341 assembler->CheckBuffer(); | 1426 assembler->CheckBuffer(); |
| 1342 } | 1427 } |
| 1343 }; | 1428 }; |
| 1344 | 1429 |
| 1345 | 1430 |
| 1346 } } // namespace v8::internal | 1431 } } // namespace v8::internal |
| 1347 | 1432 |
| 1348 #endif // V8_ARM_ASSEMBLER_ARM_H_ | 1433 #endif // V8_ARM_ASSEMBLER_ARM_H_ |
| OLD | NEW |