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 are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 V(rsi) \ | 73 V(rsi) \ |
74 V(rdi) \ | 74 V(rdi) \ |
75 V(r8) \ | 75 V(r8) \ |
76 V(r9) \ | 76 V(r9) \ |
77 V(r11) \ | 77 V(r11) \ |
78 V(r12) \ | 78 V(r12) \ |
79 V(r14) \ | 79 V(r14) \ |
80 V(r15) | 80 V(r15) |
81 | 81 |
82 // The length of pushq(rbp), movp(rbp, rsp), Push(rsi) and Push(rdi). | 82 // The length of pushq(rbp), movp(rbp, rsp), Push(rsi) and Push(rdi). |
83 static const int kNoCodeAgeSequenceLength = kPointerSize == kInt64Size ? 6 : 17; | 83 constexpr int kNoCodeAgeSequenceLength = kPointerSize == kInt64Size ? 6 : 17; |
84 | 84 |
85 // CPU Registers. | 85 // CPU Registers. |
86 // | 86 // |
87 // 1) We would prefer to use an enum, but enum values are assignment- | 87 // 1) We would prefer to use an enum, but enum values are assignment- |
88 // compatible with int, which has caused code-generation bugs. | 88 // compatible with int, which has caused code-generation bugs. |
89 // | 89 // |
90 // 2) We would prefer to use a class instead of a struct but we don't like | 90 // 2) We would prefer to use a class instead of a struct but we don't like |
91 // the register initialization to depend on the particular initialization | 91 // the register initialization to depend on the particular initialization |
92 // order (which appears to be different on OS X, Linux, and Windows for the | 92 // order (which appears to be different on OS X, Linux, and Windows for the |
93 // installed versions of C++ we tried). Using a struct permits C-style | 93 // installed versions of C++ we tried). Using a struct permits C-style |
(...skipping 11 matching lines...) Expand all Loading... |
105 // | 105 // |
106 struct Register { | 106 struct Register { |
107 enum Code { | 107 enum Code { |
108 #define REGISTER_CODE(R) kCode_##R, | 108 #define REGISTER_CODE(R) kCode_##R, |
109 GENERAL_REGISTERS(REGISTER_CODE) | 109 GENERAL_REGISTERS(REGISTER_CODE) |
110 #undef REGISTER_CODE | 110 #undef REGISTER_CODE |
111 kAfterLast, | 111 kAfterLast, |
112 kCode_no_reg = -1 | 112 kCode_no_reg = -1 |
113 }; | 113 }; |
114 | 114 |
115 static const int kNumRegisters = Code::kAfterLast; | 115 static constexpr int kNumRegisters = Code::kAfterLast; |
116 | 116 |
117 static Register from_code(int code) { | 117 static Register from_code(int code) { |
118 DCHECK(code >= 0); | 118 DCHECK(code >= 0); |
119 DCHECK(code < kNumRegisters); | 119 DCHECK(code < kNumRegisters); |
120 Register r = {code}; | 120 Register r = {code}; |
121 return r; | 121 return r; |
122 } | 122 } |
123 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } | 123 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } |
124 bool is(Register reg) const { return reg_code == reg.reg_code; } | 124 bool is(Register reg) const { return reg_code == reg.reg_code; } |
125 int code() const { | 125 int code() const { |
(...skipping 11 matching lines...) Expand all Loading... |
137 int high_bit() const { return reg_code >> 3; } | 137 int high_bit() const { return reg_code >> 3; } |
138 // Return the 3 low bits of the register code. Used when encoding registers | 138 // Return the 3 low bits of the register code. Used when encoding registers |
139 // in modR/M, SIB, and opcode bytes. | 139 // in modR/M, SIB, and opcode bytes. |
140 int low_bits() const { return reg_code & 0x7; } | 140 int low_bits() const { return reg_code & 0x7; } |
141 | 141 |
142 // Unfortunately we can't make this private in a struct when initializing | 142 // Unfortunately we can't make this private in a struct when initializing |
143 // by assignment. | 143 // by assignment. |
144 int reg_code; | 144 int reg_code; |
145 }; | 145 }; |
146 | 146 |
147 | 147 #define DECLARE_REGISTER(R) constexpr Register R = {Register::kCode_##R}; |
148 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; | |
149 GENERAL_REGISTERS(DECLARE_REGISTER) | 148 GENERAL_REGISTERS(DECLARE_REGISTER) |
150 #undef DECLARE_REGISTER | 149 #undef DECLARE_REGISTER |
151 const Register no_reg = {Register::kCode_no_reg}; | 150 constexpr Register no_reg = {Register::kCode_no_reg}; |
152 | |
153 | 151 |
154 #ifdef _WIN64 | 152 #ifdef _WIN64 |
155 // Windows calling convention | 153 // Windows calling convention |
156 const Register arg_reg_1 = {Register::kCode_rcx}; | 154 constexpr Register arg_reg_1 = {Register::kCode_rcx}; |
157 const Register arg_reg_2 = {Register::kCode_rdx}; | 155 constexpr Register arg_reg_2 = {Register::kCode_rdx}; |
158 const Register arg_reg_3 = {Register::kCode_r8}; | 156 constexpr Register arg_reg_3 = {Register::kCode_r8}; |
159 const Register arg_reg_4 = {Register::kCode_r9}; | 157 constexpr Register arg_reg_4 = {Register::kCode_r9}; |
160 #else | 158 #else |
161 // AMD64 calling convention | 159 // AMD64 calling convention |
162 const Register arg_reg_1 = {Register::kCode_rdi}; | 160 constexpr Register arg_reg_1 = {Register::kCode_rdi}; |
163 const Register arg_reg_2 = {Register::kCode_rsi}; | 161 constexpr Register arg_reg_2 = {Register::kCode_rsi}; |
164 const Register arg_reg_3 = {Register::kCode_rdx}; | 162 constexpr Register arg_reg_3 = {Register::kCode_rdx}; |
165 const Register arg_reg_4 = {Register::kCode_rcx}; | 163 constexpr Register arg_reg_4 = {Register::kCode_rcx}; |
166 #endif // _WIN64 | 164 #endif // _WIN64 |
167 | 165 |
168 | 166 |
169 #define DOUBLE_REGISTERS(V) \ | 167 #define DOUBLE_REGISTERS(V) \ |
170 V(xmm0) \ | 168 V(xmm0) \ |
171 V(xmm1) \ | 169 V(xmm1) \ |
172 V(xmm2) \ | 170 V(xmm2) \ |
173 V(xmm3) \ | 171 V(xmm3) \ |
174 V(xmm4) \ | 172 V(xmm4) \ |
175 V(xmm5) \ | 173 V(xmm5) \ |
(...skipping 21 matching lines...) Expand all Loading... |
197 V(xmm6) \ | 195 V(xmm6) \ |
198 V(xmm7) \ | 196 V(xmm7) \ |
199 V(xmm8) \ | 197 V(xmm8) \ |
200 V(xmm9) \ | 198 V(xmm9) \ |
201 V(xmm10) \ | 199 V(xmm10) \ |
202 V(xmm11) \ | 200 V(xmm11) \ |
203 V(xmm12) \ | 201 V(xmm12) \ |
204 V(xmm13) \ | 202 V(xmm13) \ |
205 V(xmm14) | 203 V(xmm14) |
206 | 204 |
207 static const bool kSimpleFPAliasing = true; | 205 constexpr bool kSimpleFPAliasing = true; |
208 static const bool kSimdMaskRegisters = false; | 206 constexpr bool kSimdMaskRegisters = false; |
209 | 207 |
210 struct XMMRegister { | 208 struct XMMRegister { |
211 enum Code { | 209 enum Code { |
212 #define REGISTER_CODE(R) kCode_##R, | 210 #define REGISTER_CODE(R) kCode_##R, |
213 DOUBLE_REGISTERS(REGISTER_CODE) | 211 DOUBLE_REGISTERS(REGISTER_CODE) |
214 #undef REGISTER_CODE | 212 #undef REGISTER_CODE |
215 kAfterLast, | 213 kAfterLast, |
216 kCode_no_reg = -1 | 214 kCode_no_reg = -1 |
217 }; | 215 }; |
218 | 216 |
219 static const int kMaxNumRegisters = Code::kAfterLast; | 217 static constexpr int kMaxNumRegisters = Code::kAfterLast; |
220 | 218 |
221 static XMMRegister from_code(int code) { | 219 static XMMRegister from_code(int code) { |
222 XMMRegister result = {code}; | 220 XMMRegister result = {code}; |
223 return result; | 221 return result; |
224 } | 222 } |
225 | 223 |
226 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } | 224 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } |
227 bool is(XMMRegister reg) const { return reg_code == reg.reg_code; } | 225 bool is(XMMRegister reg) const { return reg_code == reg.reg_code; } |
228 int code() const { | 226 int code() const { |
229 DCHECK(is_valid()); | 227 DCHECK(is_valid()); |
(...skipping 12 matching lines...) Expand all Loading... |
242 int reg_code; | 240 int reg_code; |
243 }; | 241 }; |
244 | 242 |
245 typedef XMMRegister FloatRegister; | 243 typedef XMMRegister FloatRegister; |
246 | 244 |
247 typedef XMMRegister DoubleRegister; | 245 typedef XMMRegister DoubleRegister; |
248 | 246 |
249 typedef XMMRegister Simd128Register; | 247 typedef XMMRegister Simd128Register; |
250 | 248 |
251 #define DECLARE_REGISTER(R) \ | 249 #define DECLARE_REGISTER(R) \ |
252 const DoubleRegister R = {DoubleRegister::kCode_##R}; | 250 constexpr DoubleRegister R = {DoubleRegister::kCode_##R}; |
253 DOUBLE_REGISTERS(DECLARE_REGISTER) | 251 DOUBLE_REGISTERS(DECLARE_REGISTER) |
254 #undef DECLARE_REGISTER | 252 #undef DECLARE_REGISTER |
255 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg}; | 253 constexpr DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg}; |
256 | 254 |
257 enum Condition { | 255 enum Condition { |
258 // any value < 0 is considered no_condition | 256 // any value < 0 is considered no_condition |
259 no_condition = -1, | 257 no_condition = -1, |
260 | 258 |
261 overflow = 0, | 259 overflow = 0, |
262 no_overflow = 1, | 260 no_overflow = 1, |
263 below = 2, | 261 below = 2, |
264 above_equal = 3, | 262 above_equal = 3, |
265 equal = 4, | 263 equal = 4, |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 private: | 462 private: |
465 // We check before assembling an instruction that there is sufficient | 463 // We check before assembling an instruction that there is sufficient |
466 // space to write an instruction and its relocation information. | 464 // space to write an instruction and its relocation information. |
467 // The relocation writer's position must be kGap bytes above the end of | 465 // The relocation writer's position must be kGap bytes above the end of |
468 // the generated instructions. This leaves enough space for the | 466 // the generated instructions. This leaves enough space for the |
469 // longest possible x64 instruction, 15 bytes, and the longest possible | 467 // longest possible x64 instruction, 15 bytes, and the longest possible |
470 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. | 468 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. |
471 // (There is a 15 byte limit on x64 instruction length that rules out some | 469 // (There is a 15 byte limit on x64 instruction length that rules out some |
472 // otherwise valid instructions.) | 470 // otherwise valid instructions.) |
473 // This allows for a single, fast space check per instruction. | 471 // This allows for a single, fast space check per instruction. |
474 static const int kGap = 32; | 472 static constexpr int kGap = 32; |
475 | 473 |
476 public: | 474 public: |
477 // Create an assembler. Instructions and relocation information are emitted | 475 // Create an assembler. Instructions and relocation information are emitted |
478 // into a buffer, with the instructions starting from the beginning and the | 476 // into a buffer, with the instructions starting from the beginning and the |
479 // relocation information starting from the end of the buffer. See CodeDesc | 477 // relocation information starting from the end of the buffer. See CodeDesc |
480 // for a detailed comment on the layout (globals.h). | 478 // for a detailed comment on the layout (globals.h). |
481 // | 479 // |
482 // If the provided buffer is NULL, the assembler allocates and grows its own | 480 // If the provided buffer is NULL, the assembler allocates and grows its own |
483 // buffer, and buffer_size determines the initial buffer size. The buffer is | 481 // buffer, and buffer_size determines the initial buffer size. The buffer is |
484 // owned by the assembler and deallocated upon destruction of the assembler. | 482 // owned by the assembler and deallocated upon destruction of the assembler. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 return RelocInfo::NONE64; | 529 return RelocInfo::NONE64; |
532 } else { | 530 } else { |
533 DCHECK(kPointerSize == kInt32Size); | 531 DCHECK(kPointerSize == kInt32Size); |
534 return RelocInfo::NONE32; | 532 return RelocInfo::NONE32; |
535 } | 533 } |
536 } | 534 } |
537 | 535 |
538 inline Handle<Object> code_target_object_handle_at(Address pc); | 536 inline Handle<Object> code_target_object_handle_at(Address pc); |
539 inline Address runtime_entry_at(Address pc); | 537 inline Address runtime_entry_at(Address pc); |
540 // Number of bytes taken up by the branch target in the code. | 538 // Number of bytes taken up by the branch target in the code. |
541 static const int kSpecialTargetSize = 4; // Use 32-bit displacement. | 539 static constexpr int kSpecialTargetSize = 4; // 32-bit displacement. |
542 // Distance between the address of the code target in the call instruction | 540 // Distance between the address of the code target in the call instruction |
543 // and the return address pushed on the stack. | 541 // and the return address pushed on the stack. |
544 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement. | 542 static constexpr int kCallTargetAddressOffset = 4; // 32-bit displacement. |
545 // The length of call(kScratchRegister). | 543 // The length of call(kScratchRegister). |
546 static const int kCallScratchRegisterInstructionLength = 3; | 544 static constexpr int kCallScratchRegisterInstructionLength = 3; |
547 // The length of call(Immediate32). | 545 // The length of call(Immediate32). |
548 static const int kShortCallInstructionLength = 5; | 546 static constexpr int kShortCallInstructionLength = 5; |
549 // The length of movq(kScratchRegister, address). | 547 // The length of movq(kScratchRegister, address). |
550 static const int kMoveAddressIntoScratchRegisterInstructionLength = | 548 static constexpr int kMoveAddressIntoScratchRegisterInstructionLength = |
551 2 + kPointerSize; | 549 2 + kPointerSize; |
552 // The length of movq(kScratchRegister, address) and call(kScratchRegister). | 550 // The length of movq(kScratchRegister, address) and call(kScratchRegister). |
553 static const int kCallSequenceLength = | 551 static constexpr int kCallSequenceLength = |
554 kMoveAddressIntoScratchRegisterInstructionLength + | 552 kMoveAddressIntoScratchRegisterInstructionLength + |
555 kCallScratchRegisterInstructionLength; | 553 kCallScratchRegisterInstructionLength; |
556 | 554 |
557 // The debug break slot must be able to contain an indirect call sequence. | 555 // The debug break slot must be able to contain an indirect call sequence. |
558 static const int kDebugBreakSlotLength = kCallSequenceLength; | 556 static constexpr int kDebugBreakSlotLength = kCallSequenceLength; |
559 // Distance between start of patched debug break slot and the emitted address | 557 // Distance between start of patched debug break slot and the emitted address |
560 // to jump to. | 558 // to jump to. |
561 static const int kPatchDebugBreakSlotAddressOffset = | 559 static constexpr int kPatchDebugBreakSlotAddressOffset = |
562 kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize; | 560 kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize; |
563 | 561 |
564 // One byte opcode for test eax,0xXXXXXXXX. | 562 // One byte opcode for test eax,0xXXXXXXXX. |
565 static const byte kTestEaxByte = 0xA9; | 563 static constexpr byte kTestEaxByte = 0xA9; |
566 // One byte opcode for test al, 0xXX. | 564 // One byte opcode for test al, 0xXX. |
567 static const byte kTestAlByte = 0xA8; | 565 static constexpr byte kTestAlByte = 0xA8; |
568 // One byte opcode for nop. | 566 // One byte opcode for nop. |
569 static const byte kNopByte = 0x90; | 567 static constexpr byte kNopByte = 0x90; |
570 | 568 |
571 // One byte prefix for a short conditional jump. | 569 // One byte prefix for a short conditional jump. |
572 static const byte kJccShortPrefix = 0x70; | 570 static constexpr byte kJccShortPrefix = 0x70; |
573 static const byte kJncShortOpcode = kJccShortPrefix | not_carry; | 571 static constexpr byte kJncShortOpcode = kJccShortPrefix | not_carry; |
574 static const byte kJcShortOpcode = kJccShortPrefix | carry; | 572 static constexpr byte kJcShortOpcode = kJccShortPrefix | carry; |
575 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero; | 573 static constexpr byte kJnzShortOpcode = kJccShortPrefix | not_zero; |
576 static const byte kJzShortOpcode = kJccShortPrefix | zero; | 574 static constexpr byte kJzShortOpcode = kJccShortPrefix | zero; |
577 | 575 |
578 // VEX prefix encodings. | 576 // VEX prefix encodings. |
579 enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 }; | 577 enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 }; |
580 enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 }; | 578 enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 }; |
581 enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 }; | 579 enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 }; |
582 enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 }; | 580 enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 }; |
583 | 581 |
584 // --------------------------------------------------------------------------- | 582 // --------------------------------------------------------------------------- |
585 // Code generation | 583 // Code generation |
586 // | 584 // |
(...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2012 } | 2010 } |
2013 | 2011 |
2014 // Get the number of bytes available in the buffer. | 2012 // Get the number of bytes available in the buffer. |
2015 inline int available_space() const { | 2013 inline int available_space() const { |
2016 return static_cast<int>(reloc_info_writer.pos() - pc_); | 2014 return static_cast<int>(reloc_info_writer.pos() - pc_); |
2017 } | 2015 } |
2018 | 2016 |
2019 static bool IsNop(Address addr); | 2017 static bool IsNop(Address addr); |
2020 | 2018 |
2021 // Avoid overflows for displacements etc. | 2019 // Avoid overflows for displacements etc. |
2022 static const int kMaximalBufferSize = 512*MB; | 2020 static constexpr int kMaximalBufferSize = 512 * MB; |
2023 | 2021 |
2024 byte byte_at(int pos) { return buffer_[pos]; } | 2022 byte byte_at(int pos) { return buffer_[pos]; } |
2025 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } | 2023 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } |
2026 | 2024 |
2027 Address pc() const { return pc_; } | 2025 Address pc() const { return pc_; } |
2028 | 2026 |
2029 protected: | 2027 protected: |
2030 // Call near indirect | 2028 // Call near indirect |
2031 void call(const Operand& operand); | 2029 void call(const Operand& operand); |
2032 | 2030 |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2519 Assembler* assembler_; | 2517 Assembler* assembler_; |
2520 #ifdef DEBUG | 2518 #ifdef DEBUG |
2521 int space_before_; | 2519 int space_before_; |
2522 #endif | 2520 #endif |
2523 }; | 2521 }; |
2524 | 2522 |
2525 } // namespace internal | 2523 } // namespace internal |
2526 } // namespace v8 | 2524 } // namespace v8 |
2527 | 2525 |
2528 #endif // V8_X64_ASSEMBLER_X64_H_ | 2526 #endif // V8_X64_ASSEMBLER_X64_H_ |
OLD | NEW |