| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/macro-assembler.h" | 9 #include "src/macro-assembler.h" |
| 10 #include "src/serialize.h" | 10 #include "src/serialize.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 Label check_codesize; | 50 Label check_codesize; |
| 51 patcher.masm()->bind(&check_codesize); | 51 patcher.masm()->bind(&check_codesize); |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 // Patch the code. | 54 // Patch the code. |
| 55 patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(target), | 55 patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(target), |
| 56 Assembler::RelocInfoNone()); | 56 Assembler::RelocInfoNone()); |
| 57 patcher.masm()->call(kScratchRegister); | 57 patcher.masm()->call(kScratchRegister); |
| 58 | 58 |
| 59 // Check that the size of the code generated is as expected. | 59 // Check that the size of the code generated is as expected. |
| 60 ASSERT_EQ(Assembler::kCallSequenceLength, | 60 DCHECK_EQ(Assembler::kCallSequenceLength, |
| 61 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize)); | 61 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize)); |
| 62 | 62 |
| 63 // Add the requested number of int3 instructions after the call. | 63 // Add the requested number of int3 instructions after the call. |
| 64 for (int i = 0; i < guard_bytes; i++) { | 64 for (int i = 0; i < guard_bytes; i++) { |
| 65 patcher.masm()->int3(); | 65 patcher.masm()->int3(); |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { | 70 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 set_modrm(2, base); | 111 set_modrm(2, base); |
| 112 set_disp32(disp); | 112 set_disp32(disp); |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 | 115 |
| 116 | 116 |
| 117 Operand::Operand(Register base, | 117 Operand::Operand(Register base, |
| 118 Register index, | 118 Register index, |
| 119 ScaleFactor scale, | 119 ScaleFactor scale, |
| 120 int32_t disp) : rex_(0) { | 120 int32_t disp) : rex_(0) { |
| 121 ASSERT(!index.is(rsp)); | 121 DCHECK(!index.is(rsp)); |
| 122 len_ = 1; | 122 len_ = 1; |
| 123 set_sib(scale, index, base); | 123 set_sib(scale, index, base); |
| 124 if (disp == 0 && !base.is(rbp) && !base.is(r13)) { | 124 if (disp == 0 && !base.is(rbp) && !base.is(r13)) { |
| 125 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits | 125 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits |
| 126 // possibly set by set_sib. | 126 // possibly set by set_sib. |
| 127 set_modrm(0, rsp); | 127 set_modrm(0, rsp); |
| 128 } else if (is_int8(disp)) { | 128 } else if (is_int8(disp)) { |
| 129 set_modrm(1, rsp); | 129 set_modrm(1, rsp); |
| 130 set_disp8(disp); | 130 set_disp8(disp); |
| 131 } else { | 131 } else { |
| 132 set_modrm(2, rsp); | 132 set_modrm(2, rsp); |
| 133 set_disp32(disp); | 133 set_disp32(disp); |
| 134 } | 134 } |
| 135 } | 135 } |
| 136 | 136 |
| 137 | 137 |
| 138 Operand::Operand(Register index, | 138 Operand::Operand(Register index, |
| 139 ScaleFactor scale, | 139 ScaleFactor scale, |
| 140 int32_t disp) : rex_(0) { | 140 int32_t disp) : rex_(0) { |
| 141 ASSERT(!index.is(rsp)); | 141 DCHECK(!index.is(rsp)); |
| 142 len_ = 1; | 142 len_ = 1; |
| 143 set_modrm(0, rsp); | 143 set_modrm(0, rsp); |
| 144 set_sib(scale, index, rbp); | 144 set_sib(scale, index, rbp); |
| 145 set_disp32(disp); | 145 set_disp32(disp); |
| 146 } | 146 } |
| 147 | 147 |
| 148 | 148 |
| 149 Operand::Operand(const Operand& operand, int32_t offset) { | 149 Operand::Operand(const Operand& operand, int32_t offset) { |
| 150 ASSERT(operand.len_ >= 1); | 150 DCHECK(operand.len_ >= 1); |
| 151 // Operand encodes REX ModR/M [SIB] [Disp]. | 151 // Operand encodes REX ModR/M [SIB] [Disp]. |
| 152 byte modrm = operand.buf_[0]; | 152 byte modrm = operand.buf_[0]; |
| 153 ASSERT(modrm < 0xC0); // Disallow mode 3 (register target). | 153 DCHECK(modrm < 0xC0); // Disallow mode 3 (register target). |
| 154 bool has_sib = ((modrm & 0x07) == 0x04); | 154 bool has_sib = ((modrm & 0x07) == 0x04); |
| 155 byte mode = modrm & 0xC0; | 155 byte mode = modrm & 0xC0; |
| 156 int disp_offset = has_sib ? 2 : 1; | 156 int disp_offset = has_sib ? 2 : 1; |
| 157 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07; | 157 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07; |
| 158 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit | 158 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit |
| 159 // displacement. | 159 // displacement. |
| 160 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base. | 160 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base. |
| 161 int32_t disp_value = 0; | 161 int32_t disp_value = 0; |
| 162 if (mode == 0x80 || is_baseless) { | 162 if (mode == 0x80 || is_baseless) { |
| 163 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement. | 163 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement. |
| 164 disp_value = *BitCast<const int32_t*>(&operand.buf_[disp_offset]); | 164 disp_value = *BitCast<const int32_t*>(&operand.buf_[disp_offset]); |
| 165 } else if (mode == 0x40) { | 165 } else if (mode == 0x40) { |
| 166 // Mode 1: Byte displacement. | 166 // Mode 1: Byte displacement. |
| 167 disp_value = static_cast<signed char>(operand.buf_[disp_offset]); | 167 disp_value = static_cast<signed char>(operand.buf_[disp_offset]); |
| 168 } | 168 } |
| 169 | 169 |
| 170 // Write new operand with same registers, but with modified displacement. | 170 // Write new operand with same registers, but with modified displacement. |
| 171 ASSERT(offset >= 0 ? disp_value + offset > disp_value | 171 DCHECK(offset >= 0 ? disp_value + offset > disp_value |
| 172 : disp_value + offset < disp_value); // No overflow. | 172 : disp_value + offset < disp_value); // No overflow. |
| 173 disp_value += offset; | 173 disp_value += offset; |
| 174 rex_ = operand.rex_; | 174 rex_ = operand.rex_; |
| 175 if (!is_int8(disp_value) || is_baseless) { | 175 if (!is_int8(disp_value) || is_baseless) { |
| 176 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13. | 176 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13. |
| 177 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80); | 177 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80); |
| 178 len_ = disp_offset + 4; | 178 len_ = disp_offset + 4; |
| 179 Memory::int32_at(&buf_[disp_offset]) = disp_value; | 179 Memory::int32_at(&buf_[disp_offset]) = disp_value; |
| 180 } else if (disp_value != 0 || (base_reg == 0x05)) { | 180 } else if (disp_value != 0 || (base_reg == 0x05)) { |
| 181 // Need 8 bits of displacement. | 181 // Need 8 bits of displacement. |
| 182 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1. | 182 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1. |
| 183 len_ = disp_offset + 1; | 183 len_ = disp_offset + 1; |
| 184 buf_[disp_offset] = static_cast<byte>(disp_value); | 184 buf_[disp_offset] = static_cast<byte>(disp_value); |
| 185 } else { | 185 } else { |
| 186 // Need no displacement. | 186 // Need no displacement. |
| 187 buf_[0] = (modrm & 0x3f); // Mode 0. | 187 buf_[0] = (modrm & 0x3f); // Mode 0. |
| 188 len_ = disp_offset; | 188 len_ = disp_offset; |
| 189 } | 189 } |
| 190 if (has_sib) { | 190 if (has_sib) { |
| 191 buf_[1] = operand.buf_[1]; | 191 buf_[1] = operand.buf_[1]; |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 | 194 |
| 195 | 195 |
| 196 bool Operand::AddressUsesRegister(Register reg) const { | 196 bool Operand::AddressUsesRegister(Register reg) const { |
| 197 int code = reg.code(); | 197 int code = reg.code(); |
| 198 ASSERT((buf_[0] & 0xC0) != 0xC0); // Always a memory operand. | 198 DCHECK((buf_[0] & 0xC0) != 0xC0); // Always a memory operand. |
| 199 // Start with only low three bits of base register. Initial decoding doesn't | 199 // Start with only low three bits of base register. Initial decoding doesn't |
| 200 // distinguish on the REX.B bit. | 200 // distinguish on the REX.B bit. |
| 201 int base_code = buf_[0] & 0x07; | 201 int base_code = buf_[0] & 0x07; |
| 202 if (base_code == rsp.code()) { | 202 if (base_code == rsp.code()) { |
| 203 // SIB byte present in buf_[1]. | 203 // SIB byte present in buf_[1]. |
| 204 // Check the index register from the SIB byte + REX.X prefix. | 204 // Check the index register from the SIB byte + REX.X prefix. |
| 205 int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2); | 205 int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2); |
| 206 // Index code (including REX.X) of 0x04 (rsp) means no index register. | 206 // Index code (including REX.X) of 0x04 (rsp) means no index register. |
| 207 if (index_code != rsp.code() && index_code == code) return true; | 207 if (index_code != rsp.code() && index_code == code) return true; |
| 208 // Add REX.B to get the full base register code. | 208 // Add REX.B to get the full base register code. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 | 245 |
| 246 #ifdef GENERATED_CODE_COVERAGE | 246 #ifdef GENERATED_CODE_COVERAGE |
| 247 InitCoverageLog(); | 247 InitCoverageLog(); |
| 248 #endif | 248 #endif |
| 249 } | 249 } |
| 250 | 250 |
| 251 | 251 |
| 252 void Assembler::GetCode(CodeDesc* desc) { | 252 void Assembler::GetCode(CodeDesc* desc) { |
| 253 // Finalize code (at this point overflow() may be true, but the gap ensures | 253 // Finalize code (at this point overflow() may be true, but the gap ensures |
| 254 // that we are still not overlapping instructions and relocation info). | 254 // that we are still not overlapping instructions and relocation info). |
| 255 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. | 255 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. |
| 256 // Set up code descriptor. | 256 // Set up code descriptor. |
| 257 desc->buffer = buffer_; | 257 desc->buffer = buffer_; |
| 258 desc->buffer_size = buffer_size_; | 258 desc->buffer_size = buffer_size_; |
| 259 desc->instr_size = pc_offset(); | 259 desc->instr_size = pc_offset(); |
| 260 ASSERT(desc->instr_size > 0); // Zero-size code objects upset the system. | 260 DCHECK(desc->instr_size > 0); // Zero-size code objects upset the system. |
| 261 desc->reloc_size = | 261 desc->reloc_size = |
| 262 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos()); | 262 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos()); |
| 263 desc->origin = this; | 263 desc->origin = this; |
| 264 } | 264 } |
| 265 | 265 |
| 266 | 266 |
| 267 void Assembler::Align(int m) { | 267 void Assembler::Align(int m) { |
| 268 ASSERT(IsPowerOf2(m)); | 268 DCHECK(IsPowerOf2(m)); |
| 269 int delta = (m - (pc_offset() & (m - 1))) & (m - 1); | 269 int delta = (m - (pc_offset() & (m - 1))) & (m - 1); |
| 270 Nop(delta); | 270 Nop(delta); |
| 271 } | 271 } |
| 272 | 272 |
| 273 | 273 |
| 274 void Assembler::CodeTargetAlign() { | 274 void Assembler::CodeTargetAlign() { |
| 275 Align(16); // Preferred alignment of jump targets on x64. | 275 Align(16); // Preferred alignment of jump targets on x64. |
| 276 } | 276 } |
| 277 | 277 |
| 278 | 278 |
| 279 bool Assembler::IsNop(Address addr) { | 279 bool Assembler::IsNop(Address addr) { |
| 280 Address a = addr; | 280 Address a = addr; |
| 281 while (*a == 0x66) a++; | 281 while (*a == 0x66) a++; |
| 282 if (*a == 0x90) return true; | 282 if (*a == 0x90) return true; |
| 283 if (a[0] == 0xf && a[1] == 0x1f) return true; | 283 if (a[0] == 0xf && a[1] == 0x1f) return true; |
| 284 return false; | 284 return false; |
| 285 } | 285 } |
| 286 | 286 |
| 287 | 287 |
| 288 void Assembler::bind_to(Label* L, int pos) { | 288 void Assembler::bind_to(Label* L, int pos) { |
| 289 ASSERT(!L->is_bound()); // Label may only be bound once. | 289 DCHECK(!L->is_bound()); // Label may only be bound once. |
| 290 ASSERT(0 <= pos && pos <= pc_offset()); // Position must be valid. | 290 DCHECK(0 <= pos && pos <= pc_offset()); // Position must be valid. |
| 291 if (L->is_linked()) { | 291 if (L->is_linked()) { |
| 292 int current = L->pos(); | 292 int current = L->pos(); |
| 293 int next = long_at(current); | 293 int next = long_at(current); |
| 294 while (next != current) { | 294 while (next != current) { |
| 295 // Relative address, relative to point after address. | 295 // Relative address, relative to point after address. |
| 296 int imm32 = pos - (current + sizeof(int32_t)); | 296 int imm32 = pos - (current + sizeof(int32_t)); |
| 297 long_at_put(current, imm32); | 297 long_at_put(current, imm32); |
| 298 current = next; | 298 current = next; |
| 299 next = long_at(next); | 299 next = long_at(next); |
| 300 } | 300 } |
| 301 // Fix up last fixup on linked list. | 301 // Fix up last fixup on linked list. |
| 302 int last_imm32 = pos - (current + sizeof(int32_t)); | 302 int last_imm32 = pos - (current + sizeof(int32_t)); |
| 303 long_at_put(current, last_imm32); | 303 long_at_put(current, last_imm32); |
| 304 } | 304 } |
| 305 while (L->is_near_linked()) { | 305 while (L->is_near_linked()) { |
| 306 int fixup_pos = L->near_link_pos(); | 306 int fixup_pos = L->near_link_pos(); |
| 307 int offset_to_next = | 307 int offset_to_next = |
| 308 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos))); | 308 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos))); |
| 309 ASSERT(offset_to_next <= 0); | 309 DCHECK(offset_to_next <= 0); |
| 310 int disp = pos - (fixup_pos + sizeof(int8_t)); | 310 int disp = pos - (fixup_pos + sizeof(int8_t)); |
| 311 CHECK(is_int8(disp)); | 311 CHECK(is_int8(disp)); |
| 312 set_byte_at(fixup_pos, disp); | 312 set_byte_at(fixup_pos, disp); |
| 313 if (offset_to_next < 0) { | 313 if (offset_to_next < 0) { |
| 314 L->link_to(fixup_pos + offset_to_next, Label::kNear); | 314 L->link_to(fixup_pos + offset_to_next, Label::kNear); |
| 315 } else { | 315 } else { |
| 316 L->UnuseNear(); | 316 L->UnuseNear(); |
| 317 } | 317 } |
| 318 } | 318 } |
| 319 L->bind_to(pos); | 319 L->bind_to(pos); |
| 320 } | 320 } |
| 321 | 321 |
| 322 | 322 |
| 323 void Assembler::bind(Label* L) { | 323 void Assembler::bind(Label* L) { |
| 324 bind_to(L, pc_offset()); | 324 bind_to(L, pc_offset()); |
| 325 } | 325 } |
| 326 | 326 |
| 327 | 327 |
| 328 void Assembler::GrowBuffer() { | 328 void Assembler::GrowBuffer() { |
| 329 ASSERT(buffer_overflow()); | 329 DCHECK(buffer_overflow()); |
| 330 if (!own_buffer_) FATAL("external code buffer is too small"); | 330 if (!own_buffer_) FATAL("external code buffer is too small"); |
| 331 | 331 |
| 332 // Compute new buffer size. | 332 // Compute new buffer size. |
| 333 CodeDesc desc; // the new buffer | 333 CodeDesc desc; // the new buffer |
| 334 if (buffer_size_ < 4*KB) { | 334 if (buffer_size_ < 4*KB) { |
| 335 desc.buffer_size = 4*KB; | 335 desc.buffer_size = 4*KB; |
| 336 } else { | 336 } else { |
| 337 desc.buffer_size = 2*buffer_size_; | 337 desc.buffer_size = 2*buffer_size_; |
| 338 } | 338 } |
| 339 // Some internal data structures overflow for very large buffers, | 339 // Some internal data structures overflow for very large buffers, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 for (RelocIterator it(desc); !it.done(); it.next()) { | 381 for (RelocIterator it(desc); !it.done(); it.next()) { |
| 382 RelocInfo::Mode rmode = it.rinfo()->rmode(); | 382 RelocInfo::Mode rmode = it.rinfo()->rmode(); |
| 383 if (rmode == RelocInfo::INTERNAL_REFERENCE) { | 383 if (rmode == RelocInfo::INTERNAL_REFERENCE) { |
| 384 intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc()); | 384 intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc()); |
| 385 if (*p != 0) { // 0 means uninitialized. | 385 if (*p != 0) { // 0 means uninitialized. |
| 386 *p += pc_delta; | 386 *p += pc_delta; |
| 387 } | 387 } |
| 388 } | 388 } |
| 389 } | 389 } |
| 390 | 390 |
| 391 ASSERT(!buffer_overflow()); | 391 DCHECK(!buffer_overflow()); |
| 392 } | 392 } |
| 393 | 393 |
| 394 | 394 |
| 395 void Assembler::emit_operand(int code, const Operand& adr) { | 395 void Assembler::emit_operand(int code, const Operand& adr) { |
| 396 ASSERT(is_uint3(code)); | 396 DCHECK(is_uint3(code)); |
| 397 const unsigned length = adr.len_; | 397 const unsigned length = adr.len_; |
| 398 ASSERT(length > 0); | 398 DCHECK(length > 0); |
| 399 | 399 |
| 400 // Emit updated ModR/M byte containing the given register. | 400 // Emit updated ModR/M byte containing the given register. |
| 401 ASSERT((adr.buf_[0] & 0x38) == 0); | 401 DCHECK((adr.buf_[0] & 0x38) == 0); |
| 402 pc_[0] = adr.buf_[0] | code << 3; | 402 pc_[0] = adr.buf_[0] | code << 3; |
| 403 | 403 |
| 404 // Emit the rest of the encoded operand. | 404 // Emit the rest of the encoded operand. |
| 405 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i]; | 405 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i]; |
| 406 pc_ += length; | 406 pc_ += length; |
| 407 } | 407 } |
| 408 | 408 |
| 409 | 409 |
| 410 // Assembler Instruction implementations. | 410 // Assembler Instruction implementations. |
| 411 | 411 |
| 412 void Assembler::arithmetic_op(byte opcode, | 412 void Assembler::arithmetic_op(byte opcode, |
| 413 Register reg, | 413 Register reg, |
| 414 const Operand& op, | 414 const Operand& op, |
| 415 int size) { | 415 int size) { |
| 416 EnsureSpace ensure_space(this); | 416 EnsureSpace ensure_space(this); |
| 417 emit_rex(reg, op, size); | 417 emit_rex(reg, op, size); |
| 418 emit(opcode); | 418 emit(opcode); |
| 419 emit_operand(reg, op); | 419 emit_operand(reg, op); |
| 420 } | 420 } |
| 421 | 421 |
| 422 | 422 |
| 423 void Assembler::arithmetic_op(byte opcode, | 423 void Assembler::arithmetic_op(byte opcode, |
| 424 Register reg, | 424 Register reg, |
| 425 Register rm_reg, | 425 Register rm_reg, |
| 426 int size) { | 426 int size) { |
| 427 EnsureSpace ensure_space(this); | 427 EnsureSpace ensure_space(this); |
| 428 ASSERT((opcode & 0xC6) == 2); | 428 DCHECK((opcode & 0xC6) == 2); |
| 429 if (rm_reg.low_bits() == 4) { // Forces SIB byte. | 429 if (rm_reg.low_bits() == 4) { // Forces SIB byte. |
| 430 // Swap reg and rm_reg and change opcode operand order. | 430 // Swap reg and rm_reg and change opcode operand order. |
| 431 emit_rex(rm_reg, reg, size); | 431 emit_rex(rm_reg, reg, size); |
| 432 emit(opcode ^ 0x02); | 432 emit(opcode ^ 0x02); |
| 433 emit_modrm(rm_reg, reg); | 433 emit_modrm(rm_reg, reg); |
| 434 } else { | 434 } else { |
| 435 emit_rex(reg, rm_reg, size); | 435 emit_rex(reg, rm_reg, size); |
| 436 emit(opcode); | 436 emit(opcode); |
| 437 emit_modrm(reg, rm_reg); | 437 emit_modrm(reg, rm_reg); |
| 438 } | 438 } |
| 439 } | 439 } |
| 440 | 440 |
| 441 | 441 |
| 442 void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) { | 442 void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) { |
| 443 EnsureSpace ensure_space(this); | 443 EnsureSpace ensure_space(this); |
| 444 ASSERT((opcode & 0xC6) == 2); | 444 DCHECK((opcode & 0xC6) == 2); |
| 445 if (rm_reg.low_bits() == 4) { // Forces SIB byte. | 445 if (rm_reg.low_bits() == 4) { // Forces SIB byte. |
| 446 // Swap reg and rm_reg and change opcode operand order. | 446 // Swap reg and rm_reg and change opcode operand order. |
| 447 emit(0x66); | 447 emit(0x66); |
| 448 emit_optional_rex_32(rm_reg, reg); | 448 emit_optional_rex_32(rm_reg, reg); |
| 449 emit(opcode ^ 0x02); | 449 emit(opcode ^ 0x02); |
| 450 emit_modrm(rm_reg, reg); | 450 emit_modrm(rm_reg, reg); |
| 451 } else { | 451 } else { |
| 452 emit(0x66); | 452 emit(0x66); |
| 453 emit_optional_rex_32(reg, rm_reg); | 453 emit_optional_rex_32(reg, rm_reg); |
| 454 emit(opcode); | 454 emit(opcode); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 474 // Register is not one of al, bl, cl, dl. Its encoding needs REX. | 474 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
| 475 emit_rex_32(reg); | 475 emit_rex_32(reg); |
| 476 } | 476 } |
| 477 emit(opcode); | 477 emit(opcode); |
| 478 emit_operand(reg, op); | 478 emit_operand(reg, op); |
| 479 } | 479 } |
| 480 | 480 |
| 481 | 481 |
| 482 void Assembler::arithmetic_op_8(byte opcode, Register reg, Register rm_reg) { | 482 void Assembler::arithmetic_op_8(byte opcode, Register reg, Register rm_reg) { |
| 483 EnsureSpace ensure_space(this); | 483 EnsureSpace ensure_space(this); |
| 484 ASSERT((opcode & 0xC6) == 2); | 484 DCHECK((opcode & 0xC6) == 2); |
| 485 if (rm_reg.low_bits() == 4) { // Forces SIB byte. | 485 if (rm_reg.low_bits() == 4) { // Forces SIB byte. |
| 486 // Swap reg and rm_reg and change opcode operand order. | 486 // Swap reg and rm_reg and change opcode operand order. |
| 487 if (!rm_reg.is_byte_register() || !reg.is_byte_register()) { | 487 if (!rm_reg.is_byte_register() || !reg.is_byte_register()) { |
| 488 // Register is not one of al, bl, cl, dl. Its encoding needs REX. | 488 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
| 489 emit_rex_32(rm_reg, reg); | 489 emit_rex_32(rm_reg, reg); |
| 490 } | 490 } |
| 491 emit(opcode ^ 0x02); | 491 emit(opcode ^ 0x02); |
| 492 emit_modrm(rm_reg, reg); | 492 emit_modrm(rm_reg, reg); |
| 493 } else { | 493 } else { |
| 494 if (!reg.is_byte_register() || !rm_reg.is_byte_register()) { | 494 if (!reg.is_byte_register() || !rm_reg.is_byte_register()) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 emitw(src.value_); | 576 emitw(src.value_); |
| 577 } | 577 } |
| 578 } | 578 } |
| 579 | 579 |
| 580 | 580 |
| 581 void Assembler::immediate_arithmetic_op_8(byte subcode, | 581 void Assembler::immediate_arithmetic_op_8(byte subcode, |
| 582 const Operand& dst, | 582 const Operand& dst, |
| 583 Immediate src) { | 583 Immediate src) { |
| 584 EnsureSpace ensure_space(this); | 584 EnsureSpace ensure_space(this); |
| 585 emit_optional_rex_32(dst); | 585 emit_optional_rex_32(dst); |
| 586 ASSERT(is_int8(src.value_) || is_uint8(src.value_)); | 586 DCHECK(is_int8(src.value_) || is_uint8(src.value_)); |
| 587 emit(0x80); | 587 emit(0x80); |
| 588 emit_operand(subcode, dst); | 588 emit_operand(subcode, dst); |
| 589 emit(src.value_); | 589 emit(src.value_); |
| 590 } | 590 } |
| 591 | 591 |
| 592 | 592 |
| 593 void Assembler::immediate_arithmetic_op_8(byte subcode, | 593 void Assembler::immediate_arithmetic_op_8(byte subcode, |
| 594 Register dst, | 594 Register dst, |
| 595 Immediate src) { | 595 Immediate src) { |
| 596 EnsureSpace ensure_space(this); | 596 EnsureSpace ensure_space(this); |
| 597 if (!dst.is_byte_register()) { | 597 if (!dst.is_byte_register()) { |
| 598 // Register is not one of al, bl, cl, dl. Its encoding needs REX. | 598 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
| 599 emit_rex_32(dst); | 599 emit_rex_32(dst); |
| 600 } | 600 } |
| 601 ASSERT(is_int8(src.value_) || is_uint8(src.value_)); | 601 DCHECK(is_int8(src.value_) || is_uint8(src.value_)); |
| 602 emit(0x80); | 602 emit(0x80); |
| 603 emit_modrm(subcode, dst); | 603 emit_modrm(subcode, dst); |
| 604 emit(src.value_); | 604 emit(src.value_); |
| 605 } | 605 } |
| 606 | 606 |
| 607 | 607 |
| 608 void Assembler::shift(Register dst, | 608 void Assembler::shift(Register dst, |
| 609 Immediate shift_amount, | 609 Immediate shift_amount, |
| 610 int subcode, | 610 int subcode, |
| 611 int size) { | 611 int size) { |
| 612 EnsureSpace ensure_space(this); | 612 EnsureSpace ensure_space(this); |
| 613 ASSERT(size == kInt64Size ? is_uint6(shift_amount.value_) | 613 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_) |
| 614 : is_uint5(shift_amount.value_)); | 614 : is_uint5(shift_amount.value_)); |
| 615 if (shift_amount.value_ == 1) { | 615 if (shift_amount.value_ == 1) { |
| 616 emit_rex(dst, size); | 616 emit_rex(dst, size); |
| 617 emit(0xD1); | 617 emit(0xD1); |
| 618 emit_modrm(subcode, dst); | 618 emit_modrm(subcode, dst); |
| 619 } else { | 619 } else { |
| 620 emit_rex(dst, size); | 620 emit_rex(dst, size); |
| 621 emit(0xC1); | 621 emit(0xC1); |
| 622 emit_modrm(subcode, dst); | 622 emit_modrm(subcode, dst); |
| 623 emit(shift_amount.value_); | 623 emit(shift_amount.value_); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 } | 660 } |
| 661 | 661 |
| 662 | 662 |
| 663 void Assembler::call(Label* L) { | 663 void Assembler::call(Label* L) { |
| 664 positions_recorder()->WriteRecordedPositions(); | 664 positions_recorder()->WriteRecordedPositions(); |
| 665 EnsureSpace ensure_space(this); | 665 EnsureSpace ensure_space(this); |
| 666 // 1110 1000 #32-bit disp. | 666 // 1110 1000 #32-bit disp. |
| 667 emit(0xE8); | 667 emit(0xE8); |
| 668 if (L->is_bound()) { | 668 if (L->is_bound()) { |
| 669 int offset = L->pos() - pc_offset() - sizeof(int32_t); | 669 int offset = L->pos() - pc_offset() - sizeof(int32_t); |
| 670 ASSERT(offset <= 0); | 670 DCHECK(offset <= 0); |
| 671 emitl(offset); | 671 emitl(offset); |
| 672 } else if (L->is_linked()) { | 672 } else if (L->is_linked()) { |
| 673 emitl(L->pos()); | 673 emitl(L->pos()); |
| 674 L->link_to(pc_offset() - sizeof(int32_t)); | 674 L->link_to(pc_offset() - sizeof(int32_t)); |
| 675 } else { | 675 } else { |
| 676 ASSERT(L->is_unused()); | 676 DCHECK(L->is_unused()); |
| 677 int32_t current = pc_offset(); | 677 int32_t current = pc_offset(); |
| 678 emitl(current); | 678 emitl(current); |
| 679 L->link_to(current); | 679 L->link_to(current); |
| 680 } | 680 } |
| 681 } | 681 } |
| 682 | 682 |
| 683 | 683 |
| 684 void Assembler::call(Address entry, RelocInfo::Mode rmode) { | 684 void Assembler::call(Address entry, RelocInfo::Mode rmode) { |
| 685 ASSERT(RelocInfo::IsRuntimeEntry(rmode)); | 685 DCHECK(RelocInfo::IsRuntimeEntry(rmode)); |
| 686 positions_recorder()->WriteRecordedPositions(); | 686 positions_recorder()->WriteRecordedPositions(); |
| 687 EnsureSpace ensure_space(this); | 687 EnsureSpace ensure_space(this); |
| 688 // 1110 1000 #32-bit disp. | 688 // 1110 1000 #32-bit disp. |
| 689 emit(0xE8); | 689 emit(0xE8); |
| 690 emit_runtime_entry(entry, rmode); | 690 emit_runtime_entry(entry, rmode); |
| 691 } | 691 } |
| 692 | 692 |
| 693 | 693 |
| 694 void Assembler::call(Handle<Code> target, | 694 void Assembler::call(Handle<Code> target, |
| 695 RelocInfo::Mode rmode, | 695 RelocInfo::Mode rmode, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 726 // Should only ever be used in Code objects for calls within the | 726 // Should only ever be used in Code objects for calls within the |
| 727 // same Code object. Should not be used when generating new code (use labels), | 727 // same Code object. Should not be used when generating new code (use labels), |
| 728 // but only when patching existing code. | 728 // but only when patching existing code. |
| 729 void Assembler::call(Address target) { | 729 void Assembler::call(Address target) { |
| 730 positions_recorder()->WriteRecordedPositions(); | 730 positions_recorder()->WriteRecordedPositions(); |
| 731 EnsureSpace ensure_space(this); | 731 EnsureSpace ensure_space(this); |
| 732 // 1110 1000 #32-bit disp. | 732 // 1110 1000 #32-bit disp. |
| 733 emit(0xE8); | 733 emit(0xE8); |
| 734 Address source = pc_ + 4; | 734 Address source = pc_ + 4; |
| 735 intptr_t displacement = target - source; | 735 intptr_t displacement = target - source; |
| 736 ASSERT(is_int32(displacement)); | 736 DCHECK(is_int32(displacement)); |
| 737 emitl(static_cast<int32_t>(displacement)); | 737 emitl(static_cast<int32_t>(displacement)); |
| 738 } | 738 } |
| 739 | 739 |
| 740 | 740 |
| 741 void Assembler::clc() { | 741 void Assembler::clc() { |
| 742 EnsureSpace ensure_space(this); | 742 EnsureSpace ensure_space(this); |
| 743 emit(0xF8); | 743 emit(0xF8); |
| 744 } | 744 } |
| 745 | 745 |
| 746 | 746 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 757 | 757 |
| 758 | 758 |
| 759 void Assembler::cmovq(Condition cc, Register dst, Register src) { | 759 void Assembler::cmovq(Condition cc, Register dst, Register src) { |
| 760 if (cc == always) { | 760 if (cc == always) { |
| 761 movq(dst, src); | 761 movq(dst, src); |
| 762 } else if (cc == never) { | 762 } else if (cc == never) { |
| 763 return; | 763 return; |
| 764 } | 764 } |
| 765 // No need to check CpuInfo for CMOV support, it's a required part of the | 765 // No need to check CpuInfo for CMOV support, it's a required part of the |
| 766 // 64-bit architecture. | 766 // 64-bit architecture. |
| 767 ASSERT(cc >= 0); // Use mov for unconditional moves. | 767 DCHECK(cc >= 0); // Use mov for unconditional moves. |
| 768 EnsureSpace ensure_space(this); | 768 EnsureSpace ensure_space(this); |
| 769 // Opcode: REX.W 0f 40 + cc /r. | 769 // Opcode: REX.W 0f 40 + cc /r. |
| 770 emit_rex_64(dst, src); | 770 emit_rex_64(dst, src); |
| 771 emit(0x0f); | 771 emit(0x0f); |
| 772 emit(0x40 + cc); | 772 emit(0x40 + cc); |
| 773 emit_modrm(dst, src); | 773 emit_modrm(dst, src); |
| 774 } | 774 } |
| 775 | 775 |
| 776 | 776 |
| 777 void Assembler::cmovq(Condition cc, Register dst, const Operand& src) { | 777 void Assembler::cmovq(Condition cc, Register dst, const Operand& src) { |
| 778 if (cc == always) { | 778 if (cc == always) { |
| 779 movq(dst, src); | 779 movq(dst, src); |
| 780 } else if (cc == never) { | 780 } else if (cc == never) { |
| 781 return; | 781 return; |
| 782 } | 782 } |
| 783 ASSERT(cc >= 0); | 783 DCHECK(cc >= 0); |
| 784 EnsureSpace ensure_space(this); | 784 EnsureSpace ensure_space(this); |
| 785 // Opcode: REX.W 0f 40 + cc /r. | 785 // Opcode: REX.W 0f 40 + cc /r. |
| 786 emit_rex_64(dst, src); | 786 emit_rex_64(dst, src); |
| 787 emit(0x0f); | 787 emit(0x0f); |
| 788 emit(0x40 + cc); | 788 emit(0x40 + cc); |
| 789 emit_operand(dst, src); | 789 emit_operand(dst, src); |
| 790 } | 790 } |
| 791 | 791 |
| 792 | 792 |
| 793 void Assembler::cmovl(Condition cc, Register dst, Register src) { | 793 void Assembler::cmovl(Condition cc, Register dst, Register src) { |
| 794 if (cc == always) { | 794 if (cc == always) { |
| 795 movl(dst, src); | 795 movl(dst, src); |
| 796 } else if (cc == never) { | 796 } else if (cc == never) { |
| 797 return; | 797 return; |
| 798 } | 798 } |
| 799 ASSERT(cc >= 0); | 799 DCHECK(cc >= 0); |
| 800 EnsureSpace ensure_space(this); | 800 EnsureSpace ensure_space(this); |
| 801 // Opcode: 0f 40 + cc /r. | 801 // Opcode: 0f 40 + cc /r. |
| 802 emit_optional_rex_32(dst, src); | 802 emit_optional_rex_32(dst, src); |
| 803 emit(0x0f); | 803 emit(0x0f); |
| 804 emit(0x40 + cc); | 804 emit(0x40 + cc); |
| 805 emit_modrm(dst, src); | 805 emit_modrm(dst, src); |
| 806 } | 806 } |
| 807 | 807 |
| 808 | 808 |
| 809 void Assembler::cmovl(Condition cc, Register dst, const Operand& src) { | 809 void Assembler::cmovl(Condition cc, Register dst, const Operand& src) { |
| 810 if (cc == always) { | 810 if (cc == always) { |
| 811 movl(dst, src); | 811 movl(dst, src); |
| 812 } else if (cc == never) { | 812 } else if (cc == never) { |
| 813 return; | 813 return; |
| 814 } | 814 } |
| 815 ASSERT(cc >= 0); | 815 DCHECK(cc >= 0); |
| 816 EnsureSpace ensure_space(this); | 816 EnsureSpace ensure_space(this); |
| 817 // Opcode: 0f 40 + cc /r. | 817 // Opcode: 0f 40 + cc /r. |
| 818 emit_optional_rex_32(dst, src); | 818 emit_optional_rex_32(dst, src); |
| 819 emit(0x0f); | 819 emit(0x0f); |
| 820 emit(0x40 + cc); | 820 emit(0x40 + cc); |
| 821 emit_operand(dst, src); | 821 emit_operand(dst, src); |
| 822 } | 822 } |
| 823 | 823 |
| 824 | 824 |
| 825 void Assembler::cmpb_al(Immediate imm8) { | 825 void Assembler::cmpb_al(Immediate imm8) { |
| 826 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_)); | 826 DCHECK(is_int8(imm8.value_) || is_uint8(imm8.value_)); |
| 827 EnsureSpace ensure_space(this); | 827 EnsureSpace ensure_space(this); |
| 828 emit(0x3c); | 828 emit(0x3c); |
| 829 emit(imm8.value_); | 829 emit(imm8.value_); |
| 830 } | 830 } |
| 831 | 831 |
| 832 | 832 |
| 833 void Assembler::cpuid() { | 833 void Assembler::cpuid() { |
| 834 EnsureSpace ensure_space(this); | 834 EnsureSpace ensure_space(this); |
| 835 emit(0x0F); | 835 emit(0x0F); |
| 836 emit(0xA2); | 836 emit(0xA2); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 | 973 |
| 974 | 974 |
| 975 void Assembler::j(Condition cc, Label* L, Label::Distance distance) { | 975 void Assembler::j(Condition cc, Label* L, Label::Distance distance) { |
| 976 if (cc == always) { | 976 if (cc == always) { |
| 977 jmp(L); | 977 jmp(L); |
| 978 return; | 978 return; |
| 979 } else if (cc == never) { | 979 } else if (cc == never) { |
| 980 return; | 980 return; |
| 981 } | 981 } |
| 982 EnsureSpace ensure_space(this); | 982 EnsureSpace ensure_space(this); |
| 983 ASSERT(is_uint4(cc)); | 983 DCHECK(is_uint4(cc)); |
| 984 if (L->is_bound()) { | 984 if (L->is_bound()) { |
| 985 const int short_size = 2; | 985 const int short_size = 2; |
| 986 const int long_size = 6; | 986 const int long_size = 6; |
| 987 int offs = L->pos() - pc_offset(); | 987 int offs = L->pos() - pc_offset(); |
| 988 ASSERT(offs <= 0); | 988 DCHECK(offs <= 0); |
| 989 // Determine whether we can use 1-byte offsets for backwards branches, | 989 // Determine whether we can use 1-byte offsets for backwards branches, |
| 990 // which have a max range of 128 bytes. | 990 // which have a max range of 128 bytes. |
| 991 | 991 |
| 992 // We also need to check predictable_code_size() flag here, because on x64, | 992 // We also need to check predictable_code_size() flag here, because on x64, |
| 993 // when the full code generator recompiles code for debugging, some places | 993 // when the full code generator recompiles code for debugging, some places |
| 994 // need to be padded out to a certain size. The debugger is keeping track of | 994 // need to be padded out to a certain size. The debugger is keeping track of |
| 995 // how often it did this so that it can adjust return addresses on the | 995 // how often it did this so that it can adjust return addresses on the |
| 996 // stack, but if the size of jump instructions can also change, that's not | 996 // stack, but if the size of jump instructions can also change, that's not |
| 997 // enough and the calculated offsets would be incorrect. | 997 // enough and the calculated offsets would be incorrect. |
| 998 if (is_int8(offs - short_size) && !predictable_code_size()) { | 998 if (is_int8(offs - short_size) && !predictable_code_size()) { |
| 999 // 0111 tttn #8-bit disp. | 999 // 0111 tttn #8-bit disp. |
| 1000 emit(0x70 | cc); | 1000 emit(0x70 | cc); |
| 1001 emit((offs - short_size) & 0xFF); | 1001 emit((offs - short_size) & 0xFF); |
| 1002 } else { | 1002 } else { |
| 1003 // 0000 1111 1000 tttn #32-bit disp. | 1003 // 0000 1111 1000 tttn #32-bit disp. |
| 1004 emit(0x0F); | 1004 emit(0x0F); |
| 1005 emit(0x80 | cc); | 1005 emit(0x80 | cc); |
| 1006 emitl(offs - long_size); | 1006 emitl(offs - long_size); |
| 1007 } | 1007 } |
| 1008 } else if (distance == Label::kNear) { | 1008 } else if (distance == Label::kNear) { |
| 1009 // 0111 tttn #8-bit disp | 1009 // 0111 tttn #8-bit disp |
| 1010 emit(0x70 | cc); | 1010 emit(0x70 | cc); |
| 1011 byte disp = 0x00; | 1011 byte disp = 0x00; |
| 1012 if (L->is_near_linked()) { | 1012 if (L->is_near_linked()) { |
| 1013 int offset = L->near_link_pos() - pc_offset(); | 1013 int offset = L->near_link_pos() - pc_offset(); |
| 1014 ASSERT(is_int8(offset)); | 1014 DCHECK(is_int8(offset)); |
| 1015 disp = static_cast<byte>(offset & 0xFF); | 1015 disp = static_cast<byte>(offset & 0xFF); |
| 1016 } | 1016 } |
| 1017 L->link_to(pc_offset(), Label::kNear); | 1017 L->link_to(pc_offset(), Label::kNear); |
| 1018 emit(disp); | 1018 emit(disp); |
| 1019 } else if (L->is_linked()) { | 1019 } else if (L->is_linked()) { |
| 1020 // 0000 1111 1000 tttn #32-bit disp. | 1020 // 0000 1111 1000 tttn #32-bit disp. |
| 1021 emit(0x0F); | 1021 emit(0x0F); |
| 1022 emit(0x80 | cc); | 1022 emit(0x80 | cc); |
| 1023 emitl(L->pos()); | 1023 emitl(L->pos()); |
| 1024 L->link_to(pc_offset() - sizeof(int32_t)); | 1024 L->link_to(pc_offset() - sizeof(int32_t)); |
| 1025 } else { | 1025 } else { |
| 1026 ASSERT(L->is_unused()); | 1026 DCHECK(L->is_unused()); |
| 1027 emit(0x0F); | 1027 emit(0x0F); |
| 1028 emit(0x80 | cc); | 1028 emit(0x80 | cc); |
| 1029 int32_t current = pc_offset(); | 1029 int32_t current = pc_offset(); |
| 1030 emitl(current); | 1030 emitl(current); |
| 1031 L->link_to(current); | 1031 L->link_to(current); |
| 1032 } | 1032 } |
| 1033 } | 1033 } |
| 1034 | 1034 |
| 1035 | 1035 |
| 1036 void Assembler::j(Condition cc, Address entry, RelocInfo::Mode rmode) { | 1036 void Assembler::j(Condition cc, Address entry, RelocInfo::Mode rmode) { |
| 1037 ASSERT(RelocInfo::IsRuntimeEntry(rmode)); | 1037 DCHECK(RelocInfo::IsRuntimeEntry(rmode)); |
| 1038 EnsureSpace ensure_space(this); | 1038 EnsureSpace ensure_space(this); |
| 1039 ASSERT(is_uint4(cc)); | 1039 DCHECK(is_uint4(cc)); |
| 1040 emit(0x0F); | 1040 emit(0x0F); |
| 1041 emit(0x80 | cc); | 1041 emit(0x80 | cc); |
| 1042 emit_runtime_entry(entry, rmode); | 1042 emit_runtime_entry(entry, rmode); |
| 1043 } | 1043 } |
| 1044 | 1044 |
| 1045 | 1045 |
| 1046 void Assembler::j(Condition cc, | 1046 void Assembler::j(Condition cc, |
| 1047 Handle<Code> target, | 1047 Handle<Code> target, |
| 1048 RelocInfo::Mode rmode) { | 1048 RelocInfo::Mode rmode) { |
| 1049 EnsureSpace ensure_space(this); | 1049 EnsureSpace ensure_space(this); |
| 1050 ASSERT(is_uint4(cc)); | 1050 DCHECK(is_uint4(cc)); |
| 1051 // 0000 1111 1000 tttn #32-bit disp. | 1051 // 0000 1111 1000 tttn #32-bit disp. |
| 1052 emit(0x0F); | 1052 emit(0x0F); |
| 1053 emit(0x80 | cc); | 1053 emit(0x80 | cc); |
| 1054 emit_code_target(target, rmode); | 1054 emit_code_target(target, rmode); |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 | 1057 |
| 1058 void Assembler::jmp(Label* L, Label::Distance distance) { | 1058 void Assembler::jmp(Label* L, Label::Distance distance) { |
| 1059 EnsureSpace ensure_space(this); | 1059 EnsureSpace ensure_space(this); |
| 1060 const int short_size = sizeof(int8_t); | 1060 const int short_size = sizeof(int8_t); |
| 1061 const int long_size = sizeof(int32_t); | 1061 const int long_size = sizeof(int32_t); |
| 1062 if (L->is_bound()) { | 1062 if (L->is_bound()) { |
| 1063 int offs = L->pos() - pc_offset() - 1; | 1063 int offs = L->pos() - pc_offset() - 1; |
| 1064 ASSERT(offs <= 0); | 1064 DCHECK(offs <= 0); |
| 1065 if (is_int8(offs - short_size) && !predictable_code_size()) { | 1065 if (is_int8(offs - short_size) && !predictable_code_size()) { |
| 1066 // 1110 1011 #8-bit disp. | 1066 // 1110 1011 #8-bit disp. |
| 1067 emit(0xEB); | 1067 emit(0xEB); |
| 1068 emit((offs - short_size) & 0xFF); | 1068 emit((offs - short_size) & 0xFF); |
| 1069 } else { | 1069 } else { |
| 1070 // 1110 1001 #32-bit disp. | 1070 // 1110 1001 #32-bit disp. |
| 1071 emit(0xE9); | 1071 emit(0xE9); |
| 1072 emitl(offs - long_size); | 1072 emitl(offs - long_size); |
| 1073 } | 1073 } |
| 1074 } else if (distance == Label::kNear) { | 1074 } else if (distance == Label::kNear) { |
| 1075 emit(0xEB); | 1075 emit(0xEB); |
| 1076 byte disp = 0x00; | 1076 byte disp = 0x00; |
| 1077 if (L->is_near_linked()) { | 1077 if (L->is_near_linked()) { |
| 1078 int offset = L->near_link_pos() - pc_offset(); | 1078 int offset = L->near_link_pos() - pc_offset(); |
| 1079 ASSERT(is_int8(offset)); | 1079 DCHECK(is_int8(offset)); |
| 1080 disp = static_cast<byte>(offset & 0xFF); | 1080 disp = static_cast<byte>(offset & 0xFF); |
| 1081 } | 1081 } |
| 1082 L->link_to(pc_offset(), Label::kNear); | 1082 L->link_to(pc_offset(), Label::kNear); |
| 1083 emit(disp); | 1083 emit(disp); |
| 1084 } else if (L->is_linked()) { | 1084 } else if (L->is_linked()) { |
| 1085 // 1110 1001 #32-bit disp. | 1085 // 1110 1001 #32-bit disp. |
| 1086 emit(0xE9); | 1086 emit(0xE9); |
| 1087 emitl(L->pos()); | 1087 emitl(L->pos()); |
| 1088 L->link_to(pc_offset() - long_size); | 1088 L->link_to(pc_offset() - long_size); |
| 1089 } else { | 1089 } else { |
| 1090 // 1110 1001 #32-bit disp. | 1090 // 1110 1001 #32-bit disp. |
| 1091 ASSERT(L->is_unused()); | 1091 DCHECK(L->is_unused()); |
| 1092 emit(0xE9); | 1092 emit(0xE9); |
| 1093 int32_t current = pc_offset(); | 1093 int32_t current = pc_offset(); |
| 1094 emitl(current); | 1094 emitl(current); |
| 1095 L->link_to(current); | 1095 L->link_to(current); |
| 1096 } | 1096 } |
| 1097 } | 1097 } |
| 1098 | 1098 |
| 1099 | 1099 |
| 1100 void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) { | 1100 void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) { |
| 1101 EnsureSpace ensure_space(this); | 1101 EnsureSpace ensure_space(this); |
| 1102 // 1110 1001 #32-bit disp. | 1102 // 1110 1001 #32-bit disp. |
| 1103 emit(0xE9); | 1103 emit(0xE9); |
| 1104 emit_code_target(target, rmode); | 1104 emit_code_target(target, rmode); |
| 1105 } | 1105 } |
| 1106 | 1106 |
| 1107 | 1107 |
| 1108 void Assembler::jmp(Address entry, RelocInfo::Mode rmode) { | 1108 void Assembler::jmp(Address entry, RelocInfo::Mode rmode) { |
| 1109 ASSERT(RelocInfo::IsRuntimeEntry(rmode)); | 1109 DCHECK(RelocInfo::IsRuntimeEntry(rmode)); |
| 1110 EnsureSpace ensure_space(this); | 1110 EnsureSpace ensure_space(this); |
| 1111 ASSERT(RelocInfo::IsRuntimeEntry(rmode)); | 1111 DCHECK(RelocInfo::IsRuntimeEntry(rmode)); |
| 1112 emit(0xE9); | 1112 emit(0xE9); |
| 1113 emit_runtime_entry(entry, rmode); | 1113 emit_runtime_entry(entry, rmode); |
| 1114 } | 1114 } |
| 1115 | 1115 |
| 1116 | 1116 |
| 1117 void Assembler::jmp(Register target) { | 1117 void Assembler::jmp(Register target) { |
| 1118 EnsureSpace ensure_space(this); | 1118 EnsureSpace ensure_space(this); |
| 1119 // Opcode FF/4 r64. | 1119 // Opcode FF/4 r64. |
| 1120 emit_optional_rex_32(target); | 1120 emit_optional_rex_32(target); |
| 1121 emit(0xFF); | 1121 emit(0xFF); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1140 } | 1140 } |
| 1141 | 1141 |
| 1142 | 1142 |
| 1143 void Assembler::load_rax(void* value, RelocInfo::Mode mode) { | 1143 void Assembler::load_rax(void* value, RelocInfo::Mode mode) { |
| 1144 EnsureSpace ensure_space(this); | 1144 EnsureSpace ensure_space(this); |
| 1145 if (kPointerSize == kInt64Size) { | 1145 if (kPointerSize == kInt64Size) { |
| 1146 emit(0x48); // REX.W | 1146 emit(0x48); // REX.W |
| 1147 emit(0xA1); | 1147 emit(0xA1); |
| 1148 emitp(value, mode); | 1148 emitp(value, mode); |
| 1149 } else { | 1149 } else { |
| 1150 ASSERT(kPointerSize == kInt32Size); | 1150 DCHECK(kPointerSize == kInt32Size); |
| 1151 emit(0xA1); | 1151 emit(0xA1); |
| 1152 emitp(value, mode); | 1152 emitp(value, mode); |
| 1153 // In 64-bit mode, need to zero extend the operand to 8 bytes. | 1153 // In 64-bit mode, need to zero extend the operand to 8 bytes. |
| 1154 // See 2.2.1.4 in Intel64 and IA32 Architectures Software | 1154 // See 2.2.1.4 in Intel64 and IA32 Architectures Software |
| 1155 // Developer's Manual Volume 2. | 1155 // Developer's Manual Volume 2. |
| 1156 emitl(0); | 1156 emitl(0); |
| 1157 } | 1157 } |
| 1158 } | 1158 } |
| 1159 | 1159 |
| 1160 | 1160 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 } | 1272 } |
| 1273 | 1273 |
| 1274 | 1274 |
| 1275 void Assembler::emit_mov(Register dst, Immediate value, int size) { | 1275 void Assembler::emit_mov(Register dst, Immediate value, int size) { |
| 1276 EnsureSpace ensure_space(this); | 1276 EnsureSpace ensure_space(this); |
| 1277 emit_rex(dst, size); | 1277 emit_rex(dst, size); |
| 1278 if (size == kInt64Size) { | 1278 if (size == kInt64Size) { |
| 1279 emit(0xC7); | 1279 emit(0xC7); |
| 1280 emit_modrm(0x0, dst); | 1280 emit_modrm(0x0, dst); |
| 1281 } else { | 1281 } else { |
| 1282 ASSERT(size == kInt32Size); | 1282 DCHECK(size == kInt32Size); |
| 1283 emit(0xB8 + dst.low_bits()); | 1283 emit(0xB8 + dst.low_bits()); |
| 1284 } | 1284 } |
| 1285 emit(value); | 1285 emit(value); |
| 1286 } | 1286 } |
| 1287 | 1287 |
| 1288 | 1288 |
| 1289 void Assembler::emit_mov(const Operand& dst, Immediate value, int size) { | 1289 void Assembler::emit_mov(const Operand& dst, Immediate value, int size) { |
| 1290 EnsureSpace ensure_space(this); | 1290 EnsureSpace ensure_space(this); |
| 1291 emit_rex(dst, size); | 1291 emit_rex(dst, size); |
| 1292 emit(0xC7); | 1292 emit(0xC7); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1318 | 1318 |
| 1319 // Loads the ip-relative location of the src label into the target location | 1319 // Loads the ip-relative location of the src label into the target location |
| 1320 // (as a 32-bit offset sign extended to 64-bit). | 1320 // (as a 32-bit offset sign extended to 64-bit). |
| 1321 void Assembler::movl(const Operand& dst, Label* src) { | 1321 void Assembler::movl(const Operand& dst, Label* src) { |
| 1322 EnsureSpace ensure_space(this); | 1322 EnsureSpace ensure_space(this); |
| 1323 emit_optional_rex_32(dst); | 1323 emit_optional_rex_32(dst); |
| 1324 emit(0xC7); | 1324 emit(0xC7); |
| 1325 emit_operand(0, dst); | 1325 emit_operand(0, dst); |
| 1326 if (src->is_bound()) { | 1326 if (src->is_bound()) { |
| 1327 int offset = src->pos() - pc_offset() - sizeof(int32_t); | 1327 int offset = src->pos() - pc_offset() - sizeof(int32_t); |
| 1328 ASSERT(offset <= 0); | 1328 DCHECK(offset <= 0); |
| 1329 emitl(offset); | 1329 emitl(offset); |
| 1330 } else if (src->is_linked()) { | 1330 } else if (src->is_linked()) { |
| 1331 emitl(src->pos()); | 1331 emitl(src->pos()); |
| 1332 src->link_to(pc_offset() - sizeof(int32_t)); | 1332 src->link_to(pc_offset() - sizeof(int32_t)); |
| 1333 } else { | 1333 } else { |
| 1334 ASSERT(src->is_unused()); | 1334 DCHECK(src->is_unused()); |
| 1335 int32_t current = pc_offset(); | 1335 int32_t current = pc_offset(); |
| 1336 emitl(current); | 1336 emitl(current); |
| 1337 src->link_to(current); | 1337 src->link_to(current); |
| 1338 } | 1338 } |
| 1339 } | 1339 } |
| 1340 | 1340 |
| 1341 | 1341 |
| 1342 void Assembler::movsxbl(Register dst, const Operand& src) { | 1342 void Assembler::movsxbl(Register dst, const Operand& src) { |
| 1343 EnsureSpace ensure_space(this); | 1343 EnsureSpace ensure_space(this); |
| 1344 emit_optional_rex_32(dst, src); | 1344 emit_optional_rex_32(dst, src); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1637 | 1637 |
| 1638 | 1638 |
| 1639 void Assembler::pushfq() { | 1639 void Assembler::pushfq() { |
| 1640 EnsureSpace ensure_space(this); | 1640 EnsureSpace ensure_space(this); |
| 1641 emit(0x9C); | 1641 emit(0x9C); |
| 1642 } | 1642 } |
| 1643 | 1643 |
| 1644 | 1644 |
| 1645 void Assembler::ret(int imm16) { | 1645 void Assembler::ret(int imm16) { |
| 1646 EnsureSpace ensure_space(this); | 1646 EnsureSpace ensure_space(this); |
| 1647 ASSERT(is_uint16(imm16)); | 1647 DCHECK(is_uint16(imm16)); |
| 1648 if (imm16 == 0) { | 1648 if (imm16 == 0) { |
| 1649 emit(0xC3); | 1649 emit(0xC3); |
| 1650 } else { | 1650 } else { |
| 1651 emit(0xC2); | 1651 emit(0xC2); |
| 1652 emit(imm16 & 0xFF); | 1652 emit(imm16 & 0xFF); |
| 1653 emit((imm16 >> 8) & 0xFF); | 1653 emit((imm16 >> 8) & 0xFF); |
| 1654 } | 1654 } |
| 1655 } | 1655 } |
| 1656 | 1656 |
| 1657 | 1657 |
| 1658 void Assembler::setcc(Condition cc, Register reg) { | 1658 void Assembler::setcc(Condition cc, Register reg) { |
| 1659 if (cc > last_condition) { | 1659 if (cc > last_condition) { |
| 1660 movb(reg, Immediate(cc == always ? 1 : 0)); | 1660 movb(reg, Immediate(cc == always ? 1 : 0)); |
| 1661 return; | 1661 return; |
| 1662 } | 1662 } |
| 1663 EnsureSpace ensure_space(this); | 1663 EnsureSpace ensure_space(this); |
| 1664 ASSERT(is_uint4(cc)); | 1664 DCHECK(is_uint4(cc)); |
| 1665 if (!reg.is_byte_register()) { // Use x64 byte registers, where different. | 1665 if (!reg.is_byte_register()) { // Use x64 byte registers, where different. |
| 1666 emit_rex_32(reg); | 1666 emit_rex_32(reg); |
| 1667 } | 1667 } |
| 1668 emit(0x0F); | 1668 emit(0x0F); |
| 1669 emit(0x90 | cc); | 1669 emit(0x90 | cc); |
| 1670 emit_modrm(0x0, reg); | 1670 emit_modrm(0x0, reg); |
| 1671 } | 1671 } |
| 1672 | 1672 |
| 1673 | 1673 |
| 1674 void Assembler::shld(Register dst, Register src) { | 1674 void Assembler::shld(Register dst, Register src) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1715 } | 1715 } |
| 1716 | 1716 |
| 1717 | 1717 |
| 1718 void Assembler::store_rax(void* dst, RelocInfo::Mode mode) { | 1718 void Assembler::store_rax(void* dst, RelocInfo::Mode mode) { |
| 1719 EnsureSpace ensure_space(this); | 1719 EnsureSpace ensure_space(this); |
| 1720 if (kPointerSize == kInt64Size) { | 1720 if (kPointerSize == kInt64Size) { |
| 1721 emit(0x48); // REX.W | 1721 emit(0x48); // REX.W |
| 1722 emit(0xA3); | 1722 emit(0xA3); |
| 1723 emitp(dst, mode); | 1723 emitp(dst, mode); |
| 1724 } else { | 1724 } else { |
| 1725 ASSERT(kPointerSize == kInt32Size); | 1725 DCHECK(kPointerSize == kInt32Size); |
| 1726 emit(0xA3); | 1726 emit(0xA3); |
| 1727 emitp(dst, mode); | 1727 emitp(dst, mode); |
| 1728 // In 64-bit mode, need to zero extend the operand to 8 bytes. | 1728 // In 64-bit mode, need to zero extend the operand to 8 bytes. |
| 1729 // See 2.2.1.4 in Intel64 and IA32 Architectures Software | 1729 // See 2.2.1.4 in Intel64 and IA32 Architectures Software |
| 1730 // Developer's Manual Volume 2. | 1730 // Developer's Manual Volume 2. |
| 1731 emitl(0); | 1731 emitl(0); |
| 1732 } | 1732 } |
| 1733 } | 1733 } |
| 1734 | 1734 |
| 1735 | 1735 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1749 // Register is not one of al, bl, cl, dl. Its encoding needs REX. | 1749 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
| 1750 emit_rex_32(dst, src); | 1750 emit_rex_32(dst, src); |
| 1751 } | 1751 } |
| 1752 emit(0x84); | 1752 emit(0x84); |
| 1753 emit_modrm(dst, src); | 1753 emit_modrm(dst, src); |
| 1754 } | 1754 } |
| 1755 } | 1755 } |
| 1756 | 1756 |
| 1757 | 1757 |
| 1758 void Assembler::testb(Register reg, Immediate mask) { | 1758 void Assembler::testb(Register reg, Immediate mask) { |
| 1759 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_)); | 1759 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_)); |
| 1760 EnsureSpace ensure_space(this); | 1760 EnsureSpace ensure_space(this); |
| 1761 if (reg.is(rax)) { | 1761 if (reg.is(rax)) { |
| 1762 emit(0xA8); | 1762 emit(0xA8); |
| 1763 emit(mask.value_); // Low byte emitted. | 1763 emit(mask.value_); // Low byte emitted. |
| 1764 } else { | 1764 } else { |
| 1765 if (!reg.is_byte_register()) { | 1765 if (!reg.is_byte_register()) { |
| 1766 // Register is not one of al, bl, cl, dl. Its encoding needs REX. | 1766 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
| 1767 emit_rex_32(reg); | 1767 emit_rex_32(reg); |
| 1768 } | 1768 } |
| 1769 emit(0xF6); | 1769 emit(0xF6); |
| 1770 emit_modrm(0x0, reg); | 1770 emit_modrm(0x0, reg); |
| 1771 emit(mask.value_); // Low byte emitted. | 1771 emit(mask.value_); // Low byte emitted. |
| 1772 } | 1772 } |
| 1773 } | 1773 } |
| 1774 | 1774 |
| 1775 | 1775 |
| 1776 void Assembler::testb(const Operand& op, Immediate mask) { | 1776 void Assembler::testb(const Operand& op, Immediate mask) { |
| 1777 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_)); | 1777 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_)); |
| 1778 EnsureSpace ensure_space(this); | 1778 EnsureSpace ensure_space(this); |
| 1779 emit_optional_rex_32(rax, op); | 1779 emit_optional_rex_32(rax, op); |
| 1780 emit(0xF6); | 1780 emit(0xF6); |
| 1781 emit_operand(rax, op); // Operation code 0 | 1781 emit_operand(rax, op); // Operation code 0 |
| 1782 emit(mask.value_); // Low byte emitted. | 1782 emit(mask.value_); // Low byte emitted. |
| 1783 } | 1783 } |
| 1784 | 1784 |
| 1785 | 1785 |
| 1786 void Assembler::testb(const Operand& op, Register reg) { | 1786 void Assembler::testb(const Operand& op, Register reg) { |
| 1787 EnsureSpace ensure_space(this); | 1787 EnsureSpace ensure_space(this); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1915 | 1915 |
| 1916 void Assembler::fstp_d(const Operand& adr) { | 1916 void Assembler::fstp_d(const Operand& adr) { |
| 1917 EnsureSpace ensure_space(this); | 1917 EnsureSpace ensure_space(this); |
| 1918 emit_optional_rex_32(adr); | 1918 emit_optional_rex_32(adr); |
| 1919 emit(0xDD); | 1919 emit(0xDD); |
| 1920 emit_operand(3, adr); | 1920 emit_operand(3, adr); |
| 1921 } | 1921 } |
| 1922 | 1922 |
| 1923 | 1923 |
| 1924 void Assembler::fstp(int index) { | 1924 void Assembler::fstp(int index) { |
| 1925 ASSERT(is_uint3(index)); | 1925 DCHECK(is_uint3(index)); |
| 1926 EnsureSpace ensure_space(this); | 1926 EnsureSpace ensure_space(this); |
| 1927 emit_farith(0xDD, 0xD8, index); | 1927 emit_farith(0xDD, 0xD8, index); |
| 1928 } | 1928 } |
| 1929 | 1929 |
| 1930 | 1930 |
| 1931 void Assembler::fild_s(const Operand& adr) { | 1931 void Assembler::fild_s(const Operand& adr) { |
| 1932 EnsureSpace ensure_space(this); | 1932 EnsureSpace ensure_space(this); |
| 1933 emit_optional_rex_32(adr); | 1933 emit_optional_rex_32(adr); |
| 1934 emit(0xDB); | 1934 emit(0xDB); |
| 1935 emit_operand(0, adr); | 1935 emit_operand(0, adr); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1946 | 1946 |
| 1947 void Assembler::fistp_s(const Operand& adr) { | 1947 void Assembler::fistp_s(const Operand& adr) { |
| 1948 EnsureSpace ensure_space(this); | 1948 EnsureSpace ensure_space(this); |
| 1949 emit_optional_rex_32(adr); | 1949 emit_optional_rex_32(adr); |
| 1950 emit(0xDB); | 1950 emit(0xDB); |
| 1951 emit_operand(3, adr); | 1951 emit_operand(3, adr); |
| 1952 } | 1952 } |
| 1953 | 1953 |
| 1954 | 1954 |
| 1955 void Assembler::fisttp_s(const Operand& adr) { | 1955 void Assembler::fisttp_s(const Operand& adr) { |
| 1956 ASSERT(IsEnabled(SSE3)); | 1956 DCHECK(IsEnabled(SSE3)); |
| 1957 EnsureSpace ensure_space(this); | 1957 EnsureSpace ensure_space(this); |
| 1958 emit_optional_rex_32(adr); | 1958 emit_optional_rex_32(adr); |
| 1959 emit(0xDB); | 1959 emit(0xDB); |
| 1960 emit_operand(1, adr); | 1960 emit_operand(1, adr); |
| 1961 } | 1961 } |
| 1962 | 1962 |
| 1963 | 1963 |
| 1964 void Assembler::fisttp_d(const Operand& adr) { | 1964 void Assembler::fisttp_d(const Operand& adr) { |
| 1965 ASSERT(IsEnabled(SSE3)); | 1965 DCHECK(IsEnabled(SSE3)); |
| 1966 EnsureSpace ensure_space(this); | 1966 EnsureSpace ensure_space(this); |
| 1967 emit_optional_rex_32(adr); | 1967 emit_optional_rex_32(adr); |
| 1968 emit(0xDD); | 1968 emit(0xDD); |
| 1969 emit_operand(1, adr); | 1969 emit_operand(1, adr); |
| 1970 } | 1970 } |
| 1971 | 1971 |
| 1972 | 1972 |
| 1973 void Assembler::fist_s(const Operand& adr) { | 1973 void Assembler::fist_s(const Operand& adr) { |
| 1974 EnsureSpace ensure_space(this); | 1974 EnsureSpace ensure_space(this); |
| 1975 emit_optional_rex_32(adr); | 1975 emit_optional_rex_32(adr); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2208 void Assembler::fnclex() { | 2208 void Assembler::fnclex() { |
| 2209 EnsureSpace ensure_space(this); | 2209 EnsureSpace ensure_space(this); |
| 2210 emit(0xDB); | 2210 emit(0xDB); |
| 2211 emit(0xE2); | 2211 emit(0xE2); |
| 2212 } | 2212 } |
| 2213 | 2213 |
| 2214 | 2214 |
| 2215 void Assembler::sahf() { | 2215 void Assembler::sahf() { |
| 2216 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf | 2216 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf |
| 2217 // in 64-bit mode. Test CpuID. | 2217 // in 64-bit mode. Test CpuID. |
| 2218 ASSERT(IsEnabled(SAHF)); | 2218 DCHECK(IsEnabled(SAHF)); |
| 2219 EnsureSpace ensure_space(this); | 2219 EnsureSpace ensure_space(this); |
| 2220 emit(0x9E); | 2220 emit(0x9E); |
| 2221 } | 2221 } |
| 2222 | 2222 |
| 2223 | 2223 |
| 2224 void Assembler::emit_farith(int b1, int b2, int i) { | 2224 void Assembler::emit_farith(int b1, int b2, int i) { |
| 2225 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode | 2225 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode |
| 2226 ASSERT(is_uint3(i)); // illegal stack offset | 2226 DCHECK(is_uint3(i)); // illegal stack offset |
| 2227 emit(b1); | 2227 emit(b1); |
| 2228 emit(b2 + i); | 2228 emit(b2 + i); |
| 2229 } | 2229 } |
| 2230 | 2230 |
| 2231 | 2231 |
| 2232 // SSE operations. | 2232 // SSE operations. |
| 2233 | 2233 |
| 2234 void Assembler::andps(XMMRegister dst, XMMRegister src) { | 2234 void Assembler::andps(XMMRegister dst, XMMRegister src) { |
| 2235 EnsureSpace ensure_space(this); | 2235 EnsureSpace ensure_space(this); |
| 2236 emit_optional_rex_32(dst, src); | 2236 emit_optional_rex_32(dst, src); |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2452 EnsureSpace ensure_space(this); | 2452 EnsureSpace ensure_space(this); |
| 2453 emit(0xF3); | 2453 emit(0xF3); |
| 2454 emit_rex_64(dst, src); | 2454 emit_rex_64(dst, src); |
| 2455 emit(0x0F); | 2455 emit(0x0F); |
| 2456 emit(0x6F); | 2456 emit(0x6F); |
| 2457 emit_sse_operand(dst, src); | 2457 emit_sse_operand(dst, src); |
| 2458 } | 2458 } |
| 2459 | 2459 |
| 2460 | 2460 |
| 2461 void Assembler::extractps(Register dst, XMMRegister src, byte imm8) { | 2461 void Assembler::extractps(Register dst, XMMRegister src, byte imm8) { |
| 2462 ASSERT(IsEnabled(SSE4_1)); | 2462 DCHECK(IsEnabled(SSE4_1)); |
| 2463 ASSERT(is_uint8(imm8)); | 2463 DCHECK(is_uint8(imm8)); |
| 2464 EnsureSpace ensure_space(this); | 2464 EnsureSpace ensure_space(this); |
| 2465 emit(0x66); | 2465 emit(0x66); |
| 2466 emit_optional_rex_32(src, dst); | 2466 emit_optional_rex_32(src, dst); |
| 2467 emit(0x0F); | 2467 emit(0x0F); |
| 2468 emit(0x3A); | 2468 emit(0x3A); |
| 2469 emit(0x17); | 2469 emit(0x17); |
| 2470 emit_sse_operand(src, dst); | 2470 emit_sse_operand(src, dst); |
| 2471 emit(imm8); | 2471 emit(imm8); |
| 2472 } | 2472 } |
| 2473 | 2473 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2513 } else { | 2513 } else { |
| 2514 emit_optional_rex_32(dst, src); | 2514 emit_optional_rex_32(dst, src); |
| 2515 emit(0x0F); | 2515 emit(0x0F); |
| 2516 emit(0x28); | 2516 emit(0x28); |
| 2517 emit_sse_operand(dst, src); | 2517 emit_sse_operand(dst, src); |
| 2518 } | 2518 } |
| 2519 } | 2519 } |
| 2520 | 2520 |
| 2521 | 2521 |
| 2522 void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) { | 2522 void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) { |
| 2523 ASSERT(is_uint8(imm8)); | 2523 DCHECK(is_uint8(imm8)); |
| 2524 EnsureSpace ensure_space(this); | 2524 EnsureSpace ensure_space(this); |
| 2525 emit_optional_rex_32(src, dst); | 2525 emit_optional_rex_32(src, dst); |
| 2526 emit(0x0F); | 2526 emit(0x0F); |
| 2527 emit(0xC6); | 2527 emit(0xC6); |
| 2528 emit_sse_operand(dst, src); | 2528 emit_sse_operand(dst, src); |
| 2529 emit(imm8); | 2529 emit(imm8); |
| 2530 } | 2530 } |
| 2531 | 2531 |
| 2532 | 2532 |
| 2533 void Assembler::movapd(XMMRegister dst, XMMRegister src) { | 2533 void Assembler::movapd(XMMRegister dst, XMMRegister src) { |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2855 emit_optional_rex_32(dst, src); | 2855 emit_optional_rex_32(dst, src); |
| 2856 emit(0x0F); | 2856 emit(0x0F); |
| 2857 emit(0xC2); | 2857 emit(0xC2); |
| 2858 emit_sse_operand(dst, src); | 2858 emit_sse_operand(dst, src); |
| 2859 emit(0x01); // LT == 1 | 2859 emit(0x01); // LT == 1 |
| 2860 } | 2860 } |
| 2861 | 2861 |
| 2862 | 2862 |
| 2863 void Assembler::roundsd(XMMRegister dst, XMMRegister src, | 2863 void Assembler::roundsd(XMMRegister dst, XMMRegister src, |
| 2864 Assembler::RoundingMode mode) { | 2864 Assembler::RoundingMode mode) { |
| 2865 ASSERT(IsEnabled(SSE4_1)); | 2865 DCHECK(IsEnabled(SSE4_1)); |
| 2866 EnsureSpace ensure_space(this); | 2866 EnsureSpace ensure_space(this); |
| 2867 emit(0x66); | 2867 emit(0x66); |
| 2868 emit_optional_rex_32(dst, src); | 2868 emit_optional_rex_32(dst, src); |
| 2869 emit(0x0f); | 2869 emit(0x0f); |
| 2870 emit(0x3a); | 2870 emit(0x3a); |
| 2871 emit(0x0b); | 2871 emit(0x0b); |
| 2872 emit_sse_operand(dst, src); | 2872 emit_sse_operand(dst, src); |
| 2873 // Mask precision exeption. | 2873 // Mask precision exeption. |
| 2874 emit(static_cast<byte>(mode) | 0x8); | 2874 emit(static_cast<byte>(mode) | 0x8); |
| 2875 } | 2875 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2923 | 2923 |
| 2924 void Assembler::dd(uint32_t data) { | 2924 void Assembler::dd(uint32_t data) { |
| 2925 EnsureSpace ensure_space(this); | 2925 EnsureSpace ensure_space(this); |
| 2926 emitl(data); | 2926 emitl(data); |
| 2927 } | 2927 } |
| 2928 | 2928 |
| 2929 | 2929 |
| 2930 // Relocation information implementations. | 2930 // Relocation information implementations. |
| 2931 | 2931 |
| 2932 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { | 2932 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
| 2933 ASSERT(!RelocInfo::IsNone(rmode)); | 2933 DCHECK(!RelocInfo::IsNone(rmode)); |
| 2934 // Don't record external references unless the heap will be serialized. | 2934 // Don't record external references unless the heap will be serialized. |
| 2935 if (rmode == RelocInfo::EXTERNAL_REFERENCE && | 2935 if (rmode == RelocInfo::EXTERNAL_REFERENCE && |
| 2936 !serializer_enabled() && !emit_debug_code()) { | 2936 !serializer_enabled() && !emit_debug_code()) { |
| 2937 return; | 2937 return; |
| 2938 } else if (rmode == RelocInfo::CODE_AGE_SEQUENCE) { | 2938 } else if (rmode == RelocInfo::CODE_AGE_SEQUENCE) { |
| 2939 // Don't record psuedo relocation info for code age sequence mode. | 2939 // Don't record psuedo relocation info for code age sequence mode. |
| 2940 return; | 2940 return; |
| 2941 } | 2941 } |
| 2942 RelocInfo rinfo(pc_, rmode, data, NULL); | 2942 RelocInfo rinfo(pc_, rmode, data, NULL); |
| 2943 reloc_info_writer.Write(&rinfo); | 2943 reloc_info_writer.Write(&rinfo); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2961 void Assembler::RecordComment(const char* msg, bool force) { | 2961 void Assembler::RecordComment(const char* msg, bool force) { |
| 2962 if (FLAG_code_comments || force) { | 2962 if (FLAG_code_comments || force) { |
| 2963 EnsureSpace ensure_space(this); | 2963 EnsureSpace ensure_space(this); |
| 2964 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); | 2964 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); |
| 2965 } | 2965 } |
| 2966 } | 2966 } |
| 2967 | 2967 |
| 2968 | 2968 |
| 2969 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { | 2969 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { |
| 2970 // No out-of-line constant pool support. | 2970 // No out-of-line constant pool support. |
| 2971 ASSERT(!FLAG_enable_ool_constant_pool); | 2971 DCHECK(!FLAG_enable_ool_constant_pool); |
| 2972 return isolate->factory()->empty_constant_pool_array(); | 2972 return isolate->factory()->empty_constant_pool_array(); |
| 2973 } | 2973 } |
| 2974 | 2974 |
| 2975 | 2975 |
| 2976 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 2976 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
| 2977 // No out-of-line constant pool support. | 2977 // No out-of-line constant pool support. |
| 2978 ASSERT(!FLAG_enable_ool_constant_pool); | 2978 DCHECK(!FLAG_enable_ool_constant_pool); |
| 2979 return; | 2979 return; |
| 2980 } | 2980 } |
| 2981 | 2981 |
| 2982 | 2982 |
| 2983 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | | 2983 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | |
| 2984 1 << RelocInfo::RUNTIME_ENTRY | | 2984 1 << RelocInfo::RUNTIME_ENTRY | |
| 2985 1 << RelocInfo::INTERNAL_REFERENCE | | 2985 1 << RelocInfo::INTERNAL_REFERENCE | |
| 2986 1 << RelocInfo::CODE_AGE_SEQUENCE; | 2986 1 << RelocInfo::CODE_AGE_SEQUENCE; |
| 2987 | 2987 |
| 2988 | 2988 |
| 2989 bool RelocInfo::IsCodedSpecially() { | 2989 bool RelocInfo::IsCodedSpecially() { |
| 2990 // The deserializer needs to know whether a pointer is specially coded. Being | 2990 // The deserializer needs to know whether a pointer is specially coded. Being |
| 2991 // specially coded on x64 means that it is a relative 32 bit address, as used | 2991 // specially coded on x64 means that it is a relative 32 bit address, as used |
| 2992 // by branch instructions. | 2992 // by branch instructions. |
| 2993 return (1 << rmode_) & kApplyMask; | 2993 return (1 << rmode_) & kApplyMask; |
| 2994 } | 2994 } |
| 2995 | 2995 |
| 2996 | 2996 |
| 2997 bool RelocInfo::IsInConstantPool() { | 2997 bool RelocInfo::IsInConstantPool() { |
| 2998 return false; | 2998 return false; |
| 2999 } | 2999 } |
| 3000 | 3000 |
| 3001 | 3001 |
| 3002 } } // namespace v8::internal | 3002 } } // namespace v8::internal |
| 3003 | 3003 |
| 3004 #endif // V8_TARGET_ARCH_X64 | 3004 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |