| 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 // and best performance in optimized code. | 120 // and best performance in optimized code. |
| 121 | 121 |
| 122 struct Register { | 122 struct Register { |
| 123 enum Code { | 123 enum Code { |
| 124 #define REGISTER_CODE(R) kCode_##R, | 124 #define REGISTER_CODE(R) kCode_##R, |
| 125 GENERAL_REGISTERS(REGISTER_CODE) | 125 GENERAL_REGISTERS(REGISTER_CODE) |
| 126 #undef REGISTER_CODE | 126 #undef REGISTER_CODE |
| 127 kAfterLast, | 127 kAfterLast, |
| 128 kCode_no_reg = -1 | 128 kCode_no_reg = -1 |
| 129 }; | 129 }; |
| 130 static const int kNumRegisters = Code::kAfterLast; | 130 static constexpr int kNumRegisters = Code::kAfterLast; |
| 131 | 131 |
| 132 #define REGISTER_COUNT(R) 1 + | 132 #define REGISTER_COUNT(R) 1 + |
| 133 static const int kNumAllocatable = | 133 static constexpr int kNumAllocatable = |
| 134 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT) 0; | 134 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT) 0; |
| 135 #undef REGISTER_COUNT | 135 #undef REGISTER_COUNT |
| 136 | 136 |
| 137 #define REGISTER_BIT(R) 1 << kCode_##R | | 137 #define REGISTER_BIT(R) 1 << kCode_##R | |
| 138 static const RegList kAllocatable = | 138 static constexpr RegList kAllocatable = |
| 139 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_BIT) 0; | 139 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_BIT) 0; |
| 140 #undef REGISTER_BIT | 140 #undef REGISTER_BIT |
| 141 | 141 |
| 142 static Register from_code(int code) { | 142 static Register from_code(int code) { |
| 143 DCHECK(code >= 0); | 143 DCHECK(code >= 0); |
| 144 DCHECK(code < kNumRegisters); | 144 DCHECK(code < kNumRegisters); |
| 145 Register r = {code}; | 145 Register r = {code}; |
| 146 return r; | 146 return r; |
| 147 } | 147 } |
| 148 | 148 |
| 149 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } | 149 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } |
| 150 bool is(Register reg) const { return reg_code == reg.reg_code; } | 150 bool is(Register reg) const { return reg_code == reg.reg_code; } |
| 151 int code() const { | 151 int code() const { |
| 152 DCHECK(is_valid()); | 152 DCHECK(is_valid()); |
| 153 return reg_code; | 153 return reg_code; |
| 154 } | 154 } |
| 155 int bit() const { | 155 int bit() const { |
| 156 DCHECK(is_valid()); | 156 DCHECK(is_valid()); |
| 157 return 1 << reg_code; | 157 return 1 << reg_code; |
| 158 } | 158 } |
| 159 | 159 |
| 160 void set_code(int code) { | 160 void set_code(int code) { |
| 161 reg_code = code; | 161 reg_code = code; |
| 162 DCHECK(is_valid()); | 162 DCHECK(is_valid()); |
| 163 } | 163 } |
| 164 | 164 |
| 165 #if V8_TARGET_LITTLE_ENDIAN | 165 #if V8_TARGET_LITTLE_ENDIAN |
| 166 static const int kMantissaOffset = 0; | 166 static constexpr int kMantissaOffset = 0; |
| 167 static const int kExponentOffset = 4; | 167 static constexpr int kExponentOffset = 4; |
| 168 #else | 168 #else |
| 169 static const int kMantissaOffset = 4; | 169 static constexpr int kMantissaOffset = 4; |
| 170 static const int kExponentOffset = 0; | 170 static constexpr int kExponentOffset = 0; |
| 171 #endif | 171 #endif |
| 172 | 172 |
| 173 // Unfortunately we can't make this private in a struct. | 173 // Unfortunately we can't make this private in a struct. |
| 174 int reg_code; | 174 int reg_code; |
| 175 }; | 175 }; |
| 176 | 176 |
| 177 typedef struct Register Register; | 177 typedef struct Register Register; |
| 178 | 178 |
| 179 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; | 179 #define DEFINE_REGISTER(R) constexpr Register R = {Register::kCode_##R}; |
| 180 GENERAL_REGISTERS(DECLARE_REGISTER) | 180 GENERAL_REGISTERS(DEFINE_REGISTER) |
| 181 #undef DECLARE_REGISTER | 181 #undef DEFINE_REGISTER |
| 182 const Register no_reg = {Register::kCode_no_reg}; | 182 constexpr Register no_reg = {Register::kCode_no_reg}; |
| 183 | 183 |
| 184 // Register aliases | 184 // Register aliases |
| 185 const Register kLithiumScratch = r1; // lithium scratch. | 185 constexpr Register kLithiumScratch = r1; // lithium scratch. |
| 186 const Register kRootRegister = r10; // Roots array pointer. | 186 constexpr Register kRootRegister = r10; // Roots array pointer. |
| 187 const Register cp = r13; // JavaScript context pointer. | 187 constexpr Register cp = r13; // JavaScript context pointer. |
| 188 | 188 |
| 189 static const bool kSimpleFPAliasing = true; | 189 constexpr bool kSimpleFPAliasing = true; |
| 190 static const bool kSimdMaskRegisters = false; | 190 constexpr bool kSimdMaskRegisters = false; |
| 191 | 191 |
| 192 // Double word FP register. | 192 // Double word FP register. |
| 193 struct DoubleRegister { | 193 struct DoubleRegister { |
| 194 enum Code { | 194 enum Code { |
| 195 #define REGISTER_CODE(R) kCode_##R, | 195 #define REGISTER_CODE(R) kCode_##R, |
| 196 DOUBLE_REGISTERS(REGISTER_CODE) | 196 DOUBLE_REGISTERS(REGISTER_CODE) |
| 197 #undef REGISTER_CODE | 197 #undef REGISTER_CODE |
| 198 kAfterLast, | 198 kAfterLast, |
| 199 kCode_no_reg = -1 | 199 kCode_no_reg = -1 |
| 200 }; | 200 }; |
| 201 | 201 |
| 202 static const int kNumRegisters = Code::kAfterLast; | 202 static constexpr int kNumRegisters = Code::kAfterLast; |
| 203 static const int kMaxNumRegisters = kNumRegisters; | 203 static constexpr int kMaxNumRegisters = kNumRegisters; |
| 204 | 204 |
| 205 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } | 205 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } |
| 206 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; } | 206 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; } |
| 207 | 207 |
| 208 int code() const { | 208 int code() const { |
| 209 DCHECK(is_valid()); | 209 DCHECK(is_valid()); |
| 210 return reg_code; | 210 return reg_code; |
| 211 } | 211 } |
| 212 | 212 |
| 213 int bit() const { | 213 int bit() const { |
| 214 DCHECK(is_valid()); | 214 DCHECK(is_valid()); |
| 215 return 1 << reg_code; | 215 return 1 << reg_code; |
| 216 } | 216 } |
| 217 | 217 |
| 218 static DoubleRegister from_code(int code) { | 218 static DoubleRegister from_code(int code) { |
| 219 DoubleRegister r = {code}; | 219 DoubleRegister r = {code}; |
| 220 return r; | 220 return r; |
| 221 } | 221 } |
| 222 | 222 |
| 223 int reg_code; | 223 int reg_code; |
| 224 }; | 224 }; |
| 225 | 225 |
| 226 typedef DoubleRegister FloatRegister; | 226 typedef DoubleRegister FloatRegister; |
| 227 | 227 |
| 228 // TODO(john.yan) Define SIMD registers. | 228 // TODO(john.yan) Define SIMD registers. |
| 229 typedef DoubleRegister Simd128Register; | 229 typedef DoubleRegister Simd128Register; |
| 230 | 230 |
| 231 #define DECLARE_REGISTER(R) \ | 231 #define DEFINE_REGISTER(R) \ |
| 232 const DoubleRegister R = {DoubleRegister::kCode_##R}; | 232 constexpr DoubleRegister R = {DoubleRegister::kCode_##R}; |
| 233 DOUBLE_REGISTERS(DECLARE_REGISTER) | 233 DOUBLE_REGISTERS(DEFINE_REGISTER) |
| 234 #undef DECLARE_REGISTER | 234 #undef DEFINE_REGISTER |
| 235 const Register no_dreg = {Register::kCode_no_reg}; | 235 constexpr Register no_dreg = {Register::kCode_no_reg}; |
| 236 | 236 |
| 237 // Aliases for double registers. Defined using #define instead of | 237 constexpr DoubleRegister kDoubleRegZero = d14; |
| 238 // "static const DoubleRegister&" because Clang complains otherwise when a | 238 constexpr DoubleRegister kScratchDoubleReg = d13; |
| 239 // compilation unit that includes this header doesn't use the variables. | |
| 240 #define kDoubleRegZero d14 | |
| 241 #define kScratchDoubleReg d13 | |
| 242 | 239 |
| 243 Register ToRegister(int num); | 240 Register ToRegister(int num); |
| 244 | 241 |
| 245 // Coprocessor register | 242 // Coprocessor register |
| 246 struct CRegister { | 243 struct CRegister { |
| 247 bool is_valid() const { return 0 <= reg_code && reg_code < 8; } | 244 bool is_valid() const { return 0 <= reg_code && reg_code < 8; } |
| 248 bool is(CRegister creg) const { return reg_code == creg.reg_code; } | 245 bool is(CRegister creg) const { return reg_code == creg.reg_code; } |
| 249 int code() const { | 246 int code() const { |
| 250 DCHECK(is_valid()); | 247 DCHECK(is_valid()); |
| 251 return reg_code; | 248 return reg_code; |
| 252 } | 249 } |
| 253 int bit() const { | 250 int bit() const { |
| 254 DCHECK(is_valid()); | 251 DCHECK(is_valid()); |
| 255 return 1 << reg_code; | 252 return 1 << reg_code; |
| 256 } | 253 } |
| 257 | 254 |
| 258 // Unfortunately we can't make this private in a struct. | 255 // Unfortunately we can't make this private in a struct. |
| 259 int reg_code; | 256 int reg_code; |
| 260 }; | 257 }; |
| 261 | 258 |
| 262 const CRegister no_creg = {-1}; | 259 constexpr CRegister no_creg = {-1}; |
| 263 | 260 |
| 264 const CRegister cr0 = {0}; | 261 constexpr CRegister cr0 = {0}; |
| 265 const CRegister cr1 = {1}; | 262 constexpr CRegister cr1 = {1}; |
| 266 const CRegister cr2 = {2}; | 263 constexpr CRegister cr2 = {2}; |
| 267 const CRegister cr3 = {3}; | 264 constexpr CRegister cr3 = {3}; |
| 268 const CRegister cr4 = {4}; | 265 constexpr CRegister cr4 = {4}; |
| 269 const CRegister cr5 = {5}; | 266 constexpr CRegister cr5 = {5}; |
| 270 const CRegister cr6 = {6}; | 267 constexpr CRegister cr6 = {6}; |
| 271 const CRegister cr7 = {7}; | 268 constexpr CRegister cr7 = {7}; |
| 272 | 269 |
| 273 // ----------------------------------------------------------------------------- | 270 // ----------------------------------------------------------------------------- |
| 274 // Machine instruction Operands | 271 // Machine instruction Operands |
| 275 | 272 |
| 276 #if V8_TARGET_ARCH_S390X | 273 #if V8_TARGET_ARCH_S390X |
| 277 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64; | 274 constexpr RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64; |
| 278 #else | 275 #else |
| 279 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32; | 276 constexpr RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32; |
| 280 #endif | 277 #endif |
| 281 | 278 |
| 282 // Class Operand represents a shifter operand in data processing instructions | 279 // Class Operand represents a shifter operand in data processing instructions |
| 283 // defining immediate numbers and masks | 280 // defining immediate numbers and masks |
| 284 typedef uint8_t Length; | 281 typedef uint8_t Length; |
| 285 | 282 |
| 286 struct Mask { | 283 struct Mask { |
| 287 uint8_t mask; | 284 uint8_t mask; |
| 288 uint8_t value() { return mask; } | 285 uint8_t value() { return mask; } |
| 289 static Mask from_value(uint8_t input) { | 286 static Mask from_value(uint8_t input) { |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 inline static void deserialization_set_target_internal_reference_at( | 469 inline static void deserialization_set_target_internal_reference_at( |
| 473 Isolate* isolate, Address pc, Address target, | 470 Isolate* isolate, Address pc, Address target, |
| 474 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); | 471 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); |
| 475 | 472 |
| 476 // Here we are patching the address in the IIHF/IILF instruction pair. | 473 // Here we are patching the address in the IIHF/IILF instruction pair. |
| 477 // These values are used in the serialization process and must be zero for | 474 // These values are used in the serialization process and must be zero for |
| 478 // S390 platform, as Code, Embedded Object or External-reference pointers | 475 // S390 platform, as Code, Embedded Object or External-reference pointers |
| 479 // are split across two consecutive instructions and don't exist separately | 476 // are split across two consecutive instructions and don't exist separately |
| 480 // in the code, so the serializer should not step forwards in memory after | 477 // in the code, so the serializer should not step forwards in memory after |
| 481 // a target is resolved and written. | 478 // a target is resolved and written. |
| 482 static const int kSpecialTargetSize = 0; | 479 static constexpr int kSpecialTargetSize = 0; |
| 483 | 480 |
| 484 // Number of bytes for instructions used to store pointer sized constant. | 481 // Number of bytes for instructions used to store pointer sized constant. |
| 485 #if V8_TARGET_ARCH_S390X | 482 #if V8_TARGET_ARCH_S390X |
| 486 static const int kBytesForPtrConstant = 12; // IIHF + IILF | 483 static constexpr int kBytesForPtrConstant = 12; // IIHF + IILF |
| 487 #else | 484 #else |
| 488 static const int kBytesForPtrConstant = 6; // IILF | 485 static constexpr int kBytesForPtrConstant = 6; // IILF |
| 489 #endif | 486 #endif |
| 490 | 487 |
| 491 // Distance between the instruction referring to the address of the call | 488 // Distance between the instruction referring to the address of the call |
| 492 // target and the return address. | 489 // target and the return address. |
| 493 | 490 |
| 494 // Offset between call target address and return address | 491 // Offset between call target address and return address |
| 495 // for BRASL calls | 492 // for BRASL calls |
| 496 // Patch will be appiled to other FIXED_SEQUENCE call | 493 // Patch will be appiled to other FIXED_SEQUENCE call |
| 497 static const int kCallTargetAddressOffset = 6; | 494 static constexpr int kCallTargetAddressOffset = 6; |
| 498 | 495 |
| 499 // The length of FIXED_SEQUENCE call | 496 // The length of FIXED_SEQUENCE call |
| 500 // iihf r8, <address_hi> // <64-bit only> | 497 // iihf r8, <address_hi> // <64-bit only> |
| 501 // iilf r8, <address_lo> | 498 // iilf r8, <address_lo> |
| 502 // basr r14, r8 | 499 // basr r14, r8 |
| 503 #if V8_TARGET_ARCH_S390X | 500 #if V8_TARGET_ARCH_S390X |
| 504 static const int kCallSequenceLength = 14; | 501 static constexpr int kCallSequenceLength = 14; |
| 505 #else | 502 #else |
| 506 static const int kCallSequenceLength = 8; | 503 static constexpr int kCallSequenceLength = 8; |
| 507 #endif | 504 #endif |
| 508 | 505 |
| 509 // This is the length of the BreakLocationIterator::SetDebugBreakAtReturn() | 506 // This is the length of the BreakLocationIterator::SetDebugBreakAtReturn() |
| 510 // code patch FIXED_SEQUENCE in bytes! | 507 // code patch FIXED_SEQUENCE in bytes! |
| 511 // JS Return Sequence = Call Sequence + BKPT | 508 // JS Return Sequence = Call Sequence + BKPT |
| 512 // static const int kJSReturnSequenceLength = kCallSequenceLength + 2; | 509 // static constexpr int kJSReturnSequenceLength = kCallSequenceLength + 2; |
| 513 | 510 |
| 514 // This is the length of the code sequence from SetDebugBreakAtSlot() | 511 // This is the length of the code sequence from SetDebugBreakAtSlot() |
| 515 // FIXED_SEQUENCE in bytes! | 512 // FIXED_SEQUENCE in bytes! |
| 516 static const int kDebugBreakSlotLength = kCallSequenceLength; | 513 static constexpr int kDebugBreakSlotLength = kCallSequenceLength; |
| 517 static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset; | 514 static constexpr int kPatchDebugBreakSlotReturnOffset = |
| 515 kCallTargetAddressOffset; |
| 518 | 516 |
| 519 // Length to patch between the start of the JS return sequence | 517 // Length to patch between the start of the JS return sequence |
| 520 // from SetDebugBreakAtReturn and the address from | 518 // from SetDebugBreakAtReturn and the address from |
| 521 // break_address_from_return_address. | 519 // break_address_from_return_address. |
| 522 // | 520 // |
| 523 // frame->pc() in Debug::SetAfterBreakTarget will point to BKPT in | 521 // frame->pc() in Debug::SetAfterBreakTarget will point to BKPT in |
| 524 // JS return sequence, so the length to patch will not include BKPT | 522 // JS return sequence, so the length to patch will not include BKPT |
| 525 // instruction length. | 523 // instruction length. |
| 526 // static const int kPatchReturnSequenceAddressOffset = | 524 // static constexpr int kPatchReturnSequenceAddressOffset = |
| 527 // kCallSequenceLength - kPatchDebugBreakSlotReturnOffset; | 525 // kCallSequenceLength - kPatchDebugBreakSlotReturnOffset; |
| 528 | 526 |
| 529 // Length to patch between the start of the FIXED call sequence from | 527 // Length to patch between the start of the FIXED call sequence from |
| 530 // SetDebugBreakAtSlot() and the the address from | 528 // SetDebugBreakAtSlot() and the the address from |
| 531 // break_address_from_return_address. | 529 // break_address_from_return_address. |
| 532 static const int kPatchDebugBreakSlotAddressOffset = | 530 static constexpr int kPatchDebugBreakSlotAddressOffset = |
| 533 kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset; | 531 kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset; |
| 534 | 532 |
| 535 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) { | 533 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) { |
| 536 return ((cr.code() * CRWIDTH) + crbit); | 534 return ((cr.code() * CRWIDTH) + crbit); |
| 537 } | 535 } |
| 538 | 536 |
| 539 // --------------------------------------------------------------------------- | 537 // --------------------------------------------------------------------------- |
| 540 // Code generation | 538 // Code generation |
| 541 | 539 |
| 542 template <class T, int size, int lo, int hi> | 540 template <class T, int size, int lo, int hi> |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 | 1356 |
| 1359 // Record reloc info for current pc_ | 1357 // Record reloc info for current pc_ |
| 1360 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1358 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
| 1361 | 1359 |
| 1362 private: | 1360 private: |
| 1363 // Code generation | 1361 // Code generation |
| 1364 // The relocation writer's position is at least kGap bytes below the end of | 1362 // The relocation writer's position is at least kGap bytes below the end of |
| 1365 // the generated instructions. This is so that multi-instruction sequences do | 1363 // the generated instructions. This is so that multi-instruction sequences do |
| 1366 // not have to check for overflow. The same is true for writes of large | 1364 // not have to check for overflow. The same is true for writes of large |
| 1367 // relocation info entries. | 1365 // relocation info entries. |
| 1368 static const int kGap = 32; | 1366 static constexpr int kGap = 32; |
| 1369 | 1367 |
| 1370 // Relocation info generation | 1368 // Relocation info generation |
| 1371 // Each relocation is encoded as a variable size value | 1369 // Each relocation is encoded as a variable size value |
| 1372 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 1370 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
| 1373 RelocInfoWriter reloc_info_writer; | 1371 RelocInfoWriter reloc_info_writer; |
| 1374 std::vector<DeferredRelocInfo> relocations_; | 1372 std::vector<DeferredRelocInfo> relocations_; |
| 1375 | 1373 |
| 1376 // The bound position, before this we cannot do instruction elimination. | 1374 // The bound position, before this we cannot do instruction elimination. |
| 1377 int last_bound_pos_; | 1375 int last_bound_pos_; |
| 1378 | 1376 |
| 1379 // Code emission | 1377 // Code emission |
| 1380 inline void CheckBuffer(); | 1378 inline void CheckBuffer(); |
| 1381 void GrowBuffer(int needed = 0); | 1379 void GrowBuffer(int needed = 0); |
| 1382 inline void TrackBranch(); | 1380 inline void TrackBranch(); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 | 1467 |
| 1470 class EnsureSpace BASE_EMBEDDED { | 1468 class EnsureSpace BASE_EMBEDDED { |
| 1471 public: | 1469 public: |
| 1472 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } | 1470 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } |
| 1473 }; | 1471 }; |
| 1474 | 1472 |
| 1475 } // namespace internal | 1473 } // namespace internal |
| 1476 } // namespace v8 | 1474 } // namespace v8 |
| 1477 | 1475 |
| 1478 #endif // V8_S390_ASSEMBLER_S390_H_ | 1476 #endif // V8_S390_ASSEMBLER_S390_H_ |
| OLD | NEW |