| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 static int NumAllocatableRegisters() { | 77 static int NumAllocatableRegisters() { |
| 78 return kMaxNumAllocatableRegisters; | 78 return kMaxNumAllocatableRegisters; |
| 79 } | 79 } |
| 80 static const int kNumRegisters = 16; | 80 static const int kNumRegisters = 16; |
| 81 | 81 |
| 82 static int ToAllocationIndex(Register reg) { | 82 static int ToAllocationIndex(Register reg) { |
| 83 return kAllocationIndexByRegisterCode[reg.code()]; | 83 return kAllocationIndexByRegisterCode[reg.code()]; |
| 84 } | 84 } |
| 85 | 85 |
| 86 static Register FromAllocationIndex(int index) { | 86 static Register FromAllocationIndex(int index) { |
| 87 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 87 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
| 88 Register result = { kRegisterCodeByAllocationIndex[index] }; | 88 Register result = { kRegisterCodeByAllocationIndex[index] }; |
| 89 return result; | 89 return result; |
| 90 } | 90 } |
| 91 | 91 |
| 92 static const char* AllocationIndexToString(int index) { | 92 static const char* AllocationIndexToString(int index) { |
| 93 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 93 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
| 94 const char* const names[] = { | 94 const char* const names[] = { |
| 95 "rax", | 95 "rax", |
| 96 "rbx", | 96 "rbx", |
| 97 "rdx", | 97 "rdx", |
| 98 "rcx", | 98 "rcx", |
| 99 "rsi", | 99 "rsi", |
| 100 "rdi", | 100 "rdi", |
| 101 "r8", | 101 "r8", |
| 102 "r9", | 102 "r9", |
| 103 "r11", | 103 "r11", |
| 104 "r14", | 104 "r14", |
| 105 "r15" | 105 "r15" |
| 106 }; | 106 }; |
| 107 return names[index]; | 107 return names[index]; |
| 108 } | 108 } |
| 109 | 109 |
| 110 static Register from_code(int code) { | 110 static Register from_code(int code) { |
| 111 Register r = { code }; | 111 Register r = { code }; |
| 112 return r; | 112 return r; |
| 113 } | 113 } |
| 114 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } | 114 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
| 115 bool is(Register reg) const { return code_ == reg.code_; } | 115 bool is(Register reg) const { return code_ == reg.code_; } |
| 116 // rax, rbx, rcx and rdx are byte registers, the rest are not. | 116 // rax, rbx, rcx and rdx are byte registers, the rest are not. |
| 117 bool is_byte_register() const { return code_ <= 3; } | 117 bool is_byte_register() const { return code_ <= 3; } |
| 118 int code() const { | 118 int code() const { |
| 119 ASSERT(is_valid()); | 119 DCHECK(is_valid()); |
| 120 return code_; | 120 return code_; |
| 121 } | 121 } |
| 122 int bit() const { | 122 int bit() const { |
| 123 return 1 << code_; | 123 return 1 << code_; |
| 124 } | 124 } |
| 125 | 125 |
| 126 // Return the high bit of the register code as a 0 or 1. Used often | 126 // Return the high bit of the register code as a 0 or 1. Used often |
| 127 // when constructing the REX prefix byte. | 127 // when constructing the REX prefix byte. |
| 128 int high_bit() const { | 128 int high_bit() const { |
| 129 return code_ >> 3; | 129 return code_ >> 3; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 #endif // _WIN64 | 194 #endif // _WIN64 |
| 195 | 195 |
| 196 struct XMMRegister { | 196 struct XMMRegister { |
| 197 static const int kMaxNumRegisters = 16; | 197 static const int kMaxNumRegisters = 16; |
| 198 static const int kMaxNumAllocatableRegisters = 15; | 198 static const int kMaxNumAllocatableRegisters = 15; |
| 199 static int NumAllocatableRegisters() { | 199 static int NumAllocatableRegisters() { |
| 200 return kMaxNumAllocatableRegisters; | 200 return kMaxNumAllocatableRegisters; |
| 201 } | 201 } |
| 202 | 202 |
| 203 static int ToAllocationIndex(XMMRegister reg) { | 203 static int ToAllocationIndex(XMMRegister reg) { |
| 204 ASSERT(reg.code() != 0); | 204 DCHECK(reg.code() != 0); |
| 205 return reg.code() - 1; | 205 return reg.code() - 1; |
| 206 } | 206 } |
| 207 | 207 |
| 208 static XMMRegister FromAllocationIndex(int index) { | 208 static XMMRegister FromAllocationIndex(int index) { |
| 209 ASSERT(0 <= index && index < kMaxNumAllocatableRegisters); | 209 DCHECK(0 <= index && index < kMaxNumAllocatableRegisters); |
| 210 XMMRegister result = { index + 1 }; | 210 XMMRegister result = { index + 1 }; |
| 211 return result; | 211 return result; |
| 212 } | 212 } |
| 213 | 213 |
| 214 static const char* AllocationIndexToString(int index) { | 214 static const char* AllocationIndexToString(int index) { |
| 215 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 215 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters); |
| 216 const char* const names[] = { | 216 const char* const names[] = { |
| 217 "xmm1", | 217 "xmm1", |
| 218 "xmm2", | 218 "xmm2", |
| 219 "xmm3", | 219 "xmm3", |
| 220 "xmm4", | 220 "xmm4", |
| 221 "xmm5", | 221 "xmm5", |
| 222 "xmm6", | 222 "xmm6", |
| 223 "xmm7", | 223 "xmm7", |
| 224 "xmm8", | 224 "xmm8", |
| 225 "xmm9", | 225 "xmm9", |
| 226 "xmm10", | 226 "xmm10", |
| 227 "xmm11", | 227 "xmm11", |
| 228 "xmm12", | 228 "xmm12", |
| 229 "xmm13", | 229 "xmm13", |
| 230 "xmm14", | 230 "xmm14", |
| 231 "xmm15" | 231 "xmm15" |
| 232 }; | 232 }; |
| 233 return names[index]; | 233 return names[index]; |
| 234 } | 234 } |
| 235 | 235 |
| 236 static XMMRegister from_code(int code) { | 236 static XMMRegister from_code(int code) { |
| 237 ASSERT(code >= 0); | 237 DCHECK(code >= 0); |
| 238 ASSERT(code < kMaxNumRegisters); | 238 DCHECK(code < kMaxNumRegisters); |
| 239 XMMRegister r = { code }; | 239 XMMRegister r = { code }; |
| 240 return r; | 240 return r; |
| 241 } | 241 } |
| 242 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; } | 242 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; } |
| 243 bool is(XMMRegister reg) const { return code_ == reg.code_; } | 243 bool is(XMMRegister reg) const { return code_ == reg.code_; } |
| 244 int code() const { | 244 int code() const { |
| 245 ASSERT(is_valid()); | 245 DCHECK(is_valid()); |
| 246 return code_; | 246 return code_; |
| 247 } | 247 } |
| 248 | 248 |
| 249 // Return the high bit of the register code as a 0 or 1. Used often | 249 // Return the high bit of the register code as a 0 or 1. Used often |
| 250 // when constructing the REX prefix byte. | 250 // when constructing the REX prefix byte. |
| 251 int high_bit() const { | 251 int high_bit() const { |
| 252 return code_ >> 3; | 252 return code_ >> 3; |
| 253 } | 253 } |
| 254 // Return the 3 low bits of the register code. Used when encoding registers | 254 // Return the 3 low bits of the register code. Used when encoding registers |
| 255 // in modR/M, SIB, and opcode bytes. | 255 // in modR/M, SIB, and opcode bytes. |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 } | 351 } |
| 352 | 352 |
| 353 | 353 |
| 354 // ----------------------------------------------------------------------------- | 354 // ----------------------------------------------------------------------------- |
| 355 // Machine instruction Immediates | 355 // Machine instruction Immediates |
| 356 | 356 |
| 357 class Immediate BASE_EMBEDDED { | 357 class Immediate BASE_EMBEDDED { |
| 358 public: | 358 public: |
| 359 explicit Immediate(int32_t value) : value_(value) {} | 359 explicit Immediate(int32_t value) : value_(value) {} |
| 360 explicit Immediate(Smi* value) { | 360 explicit Immediate(Smi* value) { |
| 361 ASSERT(SmiValuesAre31Bits()); // Only available for 31-bit SMI. | 361 DCHECK(SmiValuesAre31Bits()); // Only available for 31-bit SMI. |
| 362 value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value)); | 362 value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value)); |
| 363 } | 363 } |
| 364 | 364 |
| 365 private: | 365 private: |
| 366 int32_t value_; | 366 int32_t value_; |
| 367 | 367 |
| 368 friend class Assembler; | 368 friend class Assembler; |
| 369 }; | 369 }; |
| 370 | 370 |
| 371 | 371 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 // This is for calls and branches within generated code. | 543 // This is for calls and branches within generated code. |
| 544 inline static void deserialization_set_special_target_at( | 544 inline static void deserialization_set_special_target_at( |
| 545 Address instruction_payload, Code* code, Address target) { | 545 Address instruction_payload, Code* code, Address target) { |
| 546 set_target_address_at(instruction_payload, code, target); | 546 set_target_address_at(instruction_payload, code, target); |
| 547 } | 547 } |
| 548 | 548 |
| 549 static inline RelocInfo::Mode RelocInfoNone() { | 549 static inline RelocInfo::Mode RelocInfoNone() { |
| 550 if (kPointerSize == kInt64Size) { | 550 if (kPointerSize == kInt64Size) { |
| 551 return RelocInfo::NONE64; | 551 return RelocInfo::NONE64; |
| 552 } else { | 552 } else { |
| 553 ASSERT(kPointerSize == kInt32Size); | 553 DCHECK(kPointerSize == kInt32Size); |
| 554 return RelocInfo::NONE32; | 554 return RelocInfo::NONE32; |
| 555 } | 555 } |
| 556 } | 556 } |
| 557 | 557 |
| 558 inline Handle<Object> code_target_object_handle_at(Address pc); | 558 inline Handle<Object> code_target_object_handle_at(Address pc); |
| 559 inline Address runtime_entry_at(Address pc); | 559 inline Address runtime_entry_at(Address pc); |
| 560 // Number of bytes taken up by the branch target in the code. | 560 // Number of bytes taken up by the branch target in the code. |
| 561 static const int kSpecialTargetSize = 4; // Use 32-bit displacement. | 561 static const int kSpecialTargetSize = 4; // Use 32-bit displacement. |
| 562 // Distance between the address of the code target in the call instruction | 562 // Distance between the address of the code target in the call instruction |
| 563 // and the return address pushed on the stack. | 563 // and the return address pushed on the stack. |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 inline void emit_optional_rex_32(Register rm_reg); | 1251 inline void emit_optional_rex_32(Register rm_reg); |
| 1252 | 1252 |
| 1253 // Optionally do as emit_rex_32(const Operand&) if the operand register | 1253 // Optionally do as emit_rex_32(const Operand&) if the operand register |
| 1254 // numbers have a high bit set. | 1254 // numbers have a high bit set. |
| 1255 inline void emit_optional_rex_32(const Operand& op); | 1255 inline void emit_optional_rex_32(const Operand& op); |
| 1256 | 1256 |
| 1257 void emit_rex(int size) { | 1257 void emit_rex(int size) { |
| 1258 if (size == kInt64Size) { | 1258 if (size == kInt64Size) { |
| 1259 emit_rex_64(); | 1259 emit_rex_64(); |
| 1260 } else { | 1260 } else { |
| 1261 ASSERT(size == kInt32Size); | 1261 DCHECK(size == kInt32Size); |
| 1262 } | 1262 } |
| 1263 } | 1263 } |
| 1264 | 1264 |
| 1265 template<class P1> | 1265 template<class P1> |
| 1266 void emit_rex(P1 p1, int size) { | 1266 void emit_rex(P1 p1, int size) { |
| 1267 if (size == kInt64Size) { | 1267 if (size == kInt64Size) { |
| 1268 emit_rex_64(p1); | 1268 emit_rex_64(p1); |
| 1269 } else { | 1269 } else { |
| 1270 ASSERT(size == kInt32Size); | 1270 DCHECK(size == kInt32Size); |
| 1271 emit_optional_rex_32(p1); | 1271 emit_optional_rex_32(p1); |
| 1272 } | 1272 } |
| 1273 } | 1273 } |
| 1274 | 1274 |
| 1275 template<class P1, class P2> | 1275 template<class P1, class P2> |
| 1276 void emit_rex(P1 p1, P2 p2, int size) { | 1276 void emit_rex(P1 p1, P2 p2, int size) { |
| 1277 if (size == kInt64Size) { | 1277 if (size == kInt64Size) { |
| 1278 emit_rex_64(p1, p2); | 1278 emit_rex_64(p1, p2); |
| 1279 } else { | 1279 } else { |
| 1280 ASSERT(size == kInt32Size); | 1280 DCHECK(size == kInt32Size); |
| 1281 emit_optional_rex_32(p1, p2); | 1281 emit_optional_rex_32(p1, p2); |
| 1282 } | 1282 } |
| 1283 } | 1283 } |
| 1284 | 1284 |
| 1285 // Emit the ModR/M byte, and optionally the SIB byte and | 1285 // Emit the ModR/M byte, and optionally the SIB byte and |
| 1286 // 1- or 4-byte offset for a memory operand. Also encodes | 1286 // 1- or 4-byte offset for a memory operand. Also encodes |
| 1287 // the second operand of the operation, a register or operation | 1287 // the second operand of the operation, a register or operation |
| 1288 // subcode, into the reg field of the ModR/M byte. | 1288 // subcode, into the reg field of the ModR/M byte. |
| 1289 void emit_operand(Register reg, const Operand& adr) { | 1289 void emit_operand(Register reg, const Operand& adr) { |
| 1290 emit_operand(reg.low_bits(), adr); | 1290 emit_operand(reg.low_bits(), adr); |
| 1291 } | 1291 } |
| 1292 | 1292 |
| 1293 // Emit the ModR/M byte, and optionally the SIB byte and | 1293 // Emit the ModR/M byte, and optionally the SIB byte and |
| 1294 // 1- or 4-byte offset for a memory operand. Also used to encode | 1294 // 1- or 4-byte offset for a memory operand. Also used to encode |
| 1295 // a three-bit opcode extension into the ModR/M byte. | 1295 // a three-bit opcode extension into the ModR/M byte. |
| 1296 void emit_operand(int rm, const Operand& adr); | 1296 void emit_operand(int rm, const Operand& adr); |
| 1297 | 1297 |
| 1298 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields. | 1298 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields. |
| 1299 void emit_modrm(Register reg, Register rm_reg) { | 1299 void emit_modrm(Register reg, Register rm_reg) { |
| 1300 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits()); | 1300 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits()); |
| 1301 } | 1301 } |
| 1302 | 1302 |
| 1303 // Emit a ModR/M byte with an operation subcode in the reg field and | 1303 // Emit a ModR/M byte with an operation subcode in the reg field and |
| 1304 // a register in the rm_reg field. | 1304 // a register in the rm_reg field. |
| 1305 void emit_modrm(int code, Register rm_reg) { | 1305 void emit_modrm(int code, Register rm_reg) { |
| 1306 ASSERT(is_uint3(code)); | 1306 DCHECK(is_uint3(code)); |
| 1307 emit(0xC0 | code << 3 | rm_reg.low_bits()); | 1307 emit(0xC0 | code << 3 | rm_reg.low_bits()); |
| 1308 } | 1308 } |
| 1309 | 1309 |
| 1310 // Emit the code-object-relative offset of the label's position | 1310 // Emit the code-object-relative offset of the label's position |
| 1311 inline void emit_code_relative_offset(Label* label); | 1311 inline void emit_code_relative_offset(Label* label); |
| 1312 | 1312 |
| 1313 // The first argument is the reg field, the second argument is the r/m field. | 1313 // The first argument is the reg field, the second argument is the r/m field. |
| 1314 void emit_sse_operand(XMMRegister dst, XMMRegister src); | 1314 void emit_sse_operand(XMMRegister dst, XMMRegister src); |
| 1315 void emit_sse_operand(XMMRegister reg, const Operand& adr); | 1315 void emit_sse_operand(XMMRegister reg, const Operand& adr); |
| 1316 void emit_sse_operand(XMMRegister dst, Register src); | 1316 void emit_sse_operand(XMMRegister dst, Register src); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1573 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { | 1573 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { |
| 1574 if (assembler_->buffer_overflow()) assembler_->GrowBuffer(); | 1574 if (assembler_->buffer_overflow()) assembler_->GrowBuffer(); |
| 1575 #ifdef DEBUG | 1575 #ifdef DEBUG |
| 1576 space_before_ = assembler_->available_space(); | 1576 space_before_ = assembler_->available_space(); |
| 1577 #endif | 1577 #endif |
| 1578 } | 1578 } |
| 1579 | 1579 |
| 1580 #ifdef DEBUG | 1580 #ifdef DEBUG |
| 1581 ~EnsureSpace() { | 1581 ~EnsureSpace() { |
| 1582 int bytes_generated = space_before_ - assembler_->available_space(); | 1582 int bytes_generated = space_before_ - assembler_->available_space(); |
| 1583 ASSERT(bytes_generated < assembler_->kGap); | 1583 DCHECK(bytes_generated < assembler_->kGap); |
| 1584 } | 1584 } |
| 1585 #endif | 1585 #endif |
| 1586 | 1586 |
| 1587 private: | 1587 private: |
| 1588 Assembler* assembler_; | 1588 Assembler* assembler_; |
| 1589 #ifdef DEBUG | 1589 #ifdef DEBUG |
| 1590 int space_before_; | 1590 int space_before_; |
| 1591 #endif | 1591 #endif |
| 1592 }; | 1592 }; |
| 1593 | 1593 |
| 1594 } } // namespace v8::internal | 1594 } } // namespace v8::internal |
| 1595 | 1595 |
| 1596 #endif // V8_X64_ASSEMBLER_X64_H_ | 1596 #endif // V8_X64_ASSEMBLER_X64_H_ |
| OLD | NEW |