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 |