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 |