Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(546)

Side by Side Diff: src/x64/assembler-x64.h

Issue 2733503003: [assembler] Make register definitions constexpr (Closed)
Patch Set: [assembler] Make register definitions constexpr Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips64/assembler-mips64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « src/mips64/assembler-mips64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698