| 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 |