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 |