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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 // | 109 // |
110 struct Register { | 110 struct Register { |
111 enum Code { | 111 enum Code { |
112 #define REGISTER_CODE(R) kCode_##R, | 112 #define REGISTER_CODE(R) kCode_##R, |
113 GENERAL_REGISTERS(REGISTER_CODE) | 113 GENERAL_REGISTERS(REGISTER_CODE) |
114 #undef REGISTER_CODE | 114 #undef REGISTER_CODE |
115 kAfterLast, | 115 kAfterLast, |
116 kCode_no_reg = -1 | 116 kCode_no_reg = -1 |
117 }; | 117 }; |
118 | 118 |
119 static const int kNumRegisters = Code::kAfterLast; | 119 static constexpr int kNumRegisters = Code::kAfterLast; |
120 | 120 |
121 static Register from_code(int code) { | 121 static Register from_code(int code) { |
122 DCHECK(code >= 0); | 122 DCHECK(code >= 0); |
123 DCHECK(code < kNumRegisters); | 123 DCHECK(code < kNumRegisters); |
124 Register r = {code}; | 124 Register r = {code}; |
125 return r; | 125 return r; |
126 } | 126 } |
127 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } | 127 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } |
128 bool is(Register reg) const { return reg_code == reg.reg_code; } | 128 bool is(Register reg) const { return reg_code == reg.reg_code; } |
129 int code() const { | 129 int code() const { |
130 DCHECK(is_valid()); | 130 DCHECK(is_valid()); |
131 return reg_code; | 131 return reg_code; |
132 } | 132 } |
133 int bit() const { | 133 int bit() const { |
134 DCHECK(is_valid()); | 134 DCHECK(is_valid()); |
135 return 1 << reg_code; | 135 return 1 << reg_code; |
136 } | 136 } |
137 | 137 |
138 bool is_byte_register() const { return reg_code <= 3; } | 138 bool is_byte_register() const { return reg_code <= 3; } |
139 | 139 |
140 // Unfortunately we can't make this private in a struct. | 140 // Unfortunately we can't make this private in a struct. |
141 int reg_code; | 141 int reg_code; |
142 }; | 142 }; |
143 | 143 |
| 144 #define DEFINE_REGISTER(R) constexpr Register R = {Register::kCode_##R}; |
| 145 GENERAL_REGISTERS(DEFINE_REGISTER) |
| 146 #undef DEFINE_REGISTER |
| 147 constexpr Register no_reg = {Register::kCode_no_reg}; |
144 | 148 |
145 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; | 149 constexpr bool kSimpleFPAliasing = true; |
146 GENERAL_REGISTERS(DECLARE_REGISTER) | 150 constexpr bool kSimdMaskRegisters = false; |
147 #undef DECLARE_REGISTER | |
148 const Register no_reg = {Register::kCode_no_reg}; | |
149 | |
150 static const bool kSimpleFPAliasing = true; | |
151 static const bool kSimdMaskRegisters = false; | |
152 | 151 |
153 struct XMMRegister { | 152 struct XMMRegister { |
154 enum Code { | 153 enum Code { |
155 #define REGISTER_CODE(R) kCode_##R, | 154 #define REGISTER_CODE(R) kCode_##R, |
156 DOUBLE_REGISTERS(REGISTER_CODE) | 155 DOUBLE_REGISTERS(REGISTER_CODE) |
157 #undef REGISTER_CODE | 156 #undef REGISTER_CODE |
158 kAfterLast, | 157 kAfterLast, |
159 kCode_no_reg = -1 | 158 kCode_no_reg = -1 |
160 }; | 159 }; |
161 | 160 |
162 static const int kMaxNumRegisters = Code::kAfterLast; | 161 static constexpr int kMaxNumRegisters = Code::kAfterLast; |
163 | 162 |
164 static XMMRegister from_code(int code) { | 163 static XMMRegister from_code(int code) { |
165 XMMRegister result = {code}; | 164 XMMRegister result = {code}; |
166 return result; | 165 return result; |
167 } | 166 } |
168 | 167 |
169 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } | 168 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } |
170 | 169 |
171 int code() const { | 170 int code() const { |
172 DCHECK(is_valid()); | 171 DCHECK(is_valid()); |
173 return reg_code; | 172 return reg_code; |
174 } | 173 } |
175 | 174 |
176 bool is(XMMRegister reg) const { return reg_code == reg.reg_code; } | 175 bool is(XMMRegister reg) const { return reg_code == reg.reg_code; } |
177 | 176 |
178 int reg_code; | 177 int reg_code; |
179 }; | 178 }; |
180 | 179 |
181 typedef XMMRegister FloatRegister; | 180 typedef XMMRegister FloatRegister; |
182 | 181 |
183 typedef XMMRegister DoubleRegister; | 182 typedef XMMRegister DoubleRegister; |
184 | 183 |
185 typedef XMMRegister Simd128Register; | 184 typedef XMMRegister Simd128Register; |
186 | 185 |
187 #define DECLARE_REGISTER(R) \ | 186 #define DEFINE_REGISTER(R) \ |
188 const DoubleRegister R = {DoubleRegister::kCode_##R}; | 187 constexpr DoubleRegister R = {DoubleRegister::kCode_##R}; |
189 DOUBLE_REGISTERS(DECLARE_REGISTER) | 188 DOUBLE_REGISTERS(DEFINE_REGISTER) |
190 #undef DECLARE_REGISTER | 189 #undef DEFINE_REGISTER |
191 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg}; | 190 constexpr DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg}; |
192 | 191 |
193 enum Condition { | 192 enum Condition { |
194 // any value < 0 is considered no_condition | 193 // any value < 0 is considered no_condition |
195 no_condition = -1, | 194 no_condition = -1, |
196 | 195 |
197 overflow = 0, | 196 overflow = 0, |
198 no_overflow = 1, | 197 no_overflow = 1, |
199 below = 2, | 198 below = 2, |
200 above_equal = 3, | 199 above_equal = 3, |
201 equal = 4, | 200 equal = 4, |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 private: | 461 private: |
463 // We check before assembling an instruction that there is sufficient | 462 // We check before assembling an instruction that there is sufficient |
464 // space to write an instruction and its relocation information. | 463 // space to write an instruction and its relocation information. |
465 // The relocation writer's position must be kGap bytes above the end of | 464 // The relocation writer's position must be kGap bytes above the end of |
466 // the generated instructions. This leaves enough space for the | 465 // the generated instructions. This leaves enough space for the |
467 // longest possible ia32 instruction, 15 bytes, and the longest possible | 466 // longest possible ia32 instruction, 15 bytes, and the longest possible |
468 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. | 467 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. |
469 // (There is a 15 byte limit on ia32 instruction length that rules out some | 468 // (There is a 15 byte limit on ia32 instruction length that rules out some |
470 // otherwise valid instructions.) | 469 // otherwise valid instructions.) |
471 // This allows for a single, fast space check per instruction. | 470 // This allows for a single, fast space check per instruction. |
472 static const int kGap = 32; | 471 static constexpr int kGap = 32; |
473 | 472 |
474 public: | 473 public: |
475 // Create an assembler. Instructions and relocation information are emitted | 474 // Create an assembler. Instructions and relocation information are emitted |
476 // into a buffer, with the instructions starting from the beginning and the | 475 // into a buffer, with the instructions starting from the beginning and the |
477 // relocation information starting from the end of the buffer. See CodeDesc | 476 // relocation information starting from the end of the buffer. See CodeDesc |
478 // for a detailed comment on the layout (globals.h). | 477 // for a detailed comment on the layout (globals.h). |
479 // | 478 // |
480 // If the provided buffer is NULL, the assembler allocates and grows its own | 479 // If the provided buffer is NULL, the assembler allocates and grows its own |
481 // buffer, and buffer_size determines the initial buffer size. The buffer is | 480 // buffer, and buffer_size determines the initial buffer size. The buffer is |
482 // owned by the assembler and deallocated upon destruction of the assembler. | 481 // owned by the assembler and deallocated upon destruction of the assembler. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 Isolate* isolate, Address instruction_payload, Code* code, | 513 Isolate* isolate, Address instruction_payload, Code* code, |
515 Address target) { | 514 Address target) { |
516 set_target_address_at(isolate, instruction_payload, code, target); | 515 set_target_address_at(isolate, instruction_payload, code, target); |
517 } | 516 } |
518 | 517 |
519 // This sets the internal reference at the pc. | 518 // This sets the internal reference at the pc. |
520 inline static void deserialization_set_target_internal_reference_at( | 519 inline static void deserialization_set_target_internal_reference_at( |
521 Isolate* isolate, Address pc, Address target, | 520 Isolate* isolate, Address pc, Address target, |
522 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); | 521 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); |
523 | 522 |
524 static const int kSpecialTargetSize = kPointerSize; | 523 static constexpr int kSpecialTargetSize = kPointerSize; |
525 | 524 |
526 // Distance between the address of the code target in the call instruction | 525 // Distance between the address of the code target in the call instruction |
527 // and the return address | 526 // and the return address |
528 static const int kCallTargetAddressOffset = kPointerSize; | 527 static constexpr int kCallTargetAddressOffset = kPointerSize; |
529 | 528 |
530 static const int kCallInstructionLength = 5; | 529 static constexpr int kCallInstructionLength = 5; |
531 | 530 |
532 // The debug break slot must be able to contain a call instruction. | 531 // The debug break slot must be able to contain a call instruction. |
533 static const int kDebugBreakSlotLength = kCallInstructionLength; | 532 static constexpr int kDebugBreakSlotLength = kCallInstructionLength; |
534 | 533 |
535 // Distance between start of patched debug break slot and the emitted address | 534 // Distance between start of patched debug break slot and the emitted address |
536 // to jump to. | 535 // to jump to. |
537 static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. | 536 static constexpr int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. |
538 | 537 |
539 // One byte opcode for test al, 0xXX. | 538 // One byte opcode for test al, 0xXX. |
540 static const byte kTestAlByte = 0xA8; | 539 static constexpr byte kTestAlByte = 0xA8; |
541 // One byte opcode for nop. | 540 // One byte opcode for nop. |
542 static const byte kNopByte = 0x90; | 541 static constexpr byte kNopByte = 0x90; |
543 | 542 |
544 // One byte opcode for a short unconditional jump. | 543 // One byte opcode for a short unconditional jump. |
545 static const byte kJmpShortOpcode = 0xEB; | 544 static constexpr byte kJmpShortOpcode = 0xEB; |
546 // One byte prefix for a short conditional jump. | 545 // One byte prefix for a short conditional jump. |
547 static const byte kJccShortPrefix = 0x70; | 546 static constexpr byte kJccShortPrefix = 0x70; |
548 static const byte kJncShortOpcode = kJccShortPrefix | not_carry; | 547 static constexpr byte kJncShortOpcode = kJccShortPrefix | not_carry; |
549 static const byte kJcShortOpcode = kJccShortPrefix | carry; | 548 static constexpr byte kJcShortOpcode = kJccShortPrefix | carry; |
550 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero; | 549 static constexpr byte kJnzShortOpcode = kJccShortPrefix | not_zero; |
551 static const byte kJzShortOpcode = kJccShortPrefix | zero; | 550 static constexpr byte kJzShortOpcode = kJccShortPrefix | zero; |
552 | |
553 | 551 |
554 // --------------------------------------------------------------------------- | 552 // --------------------------------------------------------------------------- |
555 // Code generation | 553 // Code generation |
556 // | 554 // |
557 // - function names correspond one-to-one to ia32 instruction mnemonics | 555 // - function names correspond one-to-one to ia32 instruction mnemonics |
558 // - unless specified otherwise, instructions operate on 32bit operands | 556 // - unless specified otherwise, instructions operate on 32bit operands |
559 // - instructions on 8bit (byte) operands/registers have a trailing '_b' | 557 // - instructions on 8bit (byte) operands/registers have a trailing '_b' |
560 // - instructions on 16bit (word) operands/registers have a trailing '_w' | 558 // - instructions on 16bit (word) operands/registers have a trailing '_w' |
561 // - naming conflicts with C++ keywords are resolved via a trailing '_' | 559 // - naming conflicts with C++ keywords are resolved via a trailing '_' |
562 | 560 |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1459 // Get the number of bytes available in the buffer. | 1457 // Get the number of bytes available in the buffer. |
1460 inline int available_space() const { return reloc_info_writer.pos() - pc_; } | 1458 inline int available_space() const { return reloc_info_writer.pos() - pc_; } |
1461 | 1459 |
1462 static bool IsNop(Address addr); | 1460 static bool IsNop(Address addr); |
1463 | 1461 |
1464 int relocation_writer_size() { | 1462 int relocation_writer_size() { |
1465 return (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 1463 return (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
1466 } | 1464 } |
1467 | 1465 |
1468 // Avoid overflows for displacements etc. | 1466 // Avoid overflows for displacements etc. |
1469 static const int kMaximalBufferSize = 512*MB; | 1467 static constexpr int kMaximalBufferSize = 512 * MB; |
1470 | 1468 |
1471 byte byte_at(int pos) { return buffer_[pos]; } | 1469 byte byte_at(int pos) { return buffer_[pos]; } |
1472 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } | 1470 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } |
1473 | 1471 |
1474 void PatchConstantPoolAccessInstruction(int pc_offset, int offset, | 1472 void PatchConstantPoolAccessInstruction(int pc_offset, int offset, |
1475 ConstantPoolEntry::Access access, | 1473 ConstantPoolEntry::Access access, |
1476 ConstantPoolEntry::Type type) { | 1474 ConstantPoolEntry::Type type) { |
1477 // No embedded constant pool support. | 1475 // No embedded constant pool support. |
1478 UNREACHABLE(); | 1476 UNREACHABLE(); |
1479 } | 1477 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1593 Assembler* assembler_; | 1591 Assembler* assembler_; |
1594 #ifdef DEBUG | 1592 #ifdef DEBUG |
1595 int space_before_; | 1593 int space_before_; |
1596 #endif | 1594 #endif |
1597 }; | 1595 }; |
1598 | 1596 |
1599 } // namespace internal | 1597 } // namespace internal |
1600 } // namespace v8 | 1598 } // namespace v8 |
1601 | 1599 |
1602 #endif // V8_IA32_ASSEMBLER_IA32_H_ | 1600 #endif // V8_IA32_ASSEMBLER_IA32_H_ |
OLD | NEW |