blob: 2d524eaf4b6e1dcf61e7ff21ee7a3f0822fc9277 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "macro-assembler.h"
31#include "serialize.h"
32
33namespace v8 {
34namespace internal {
35
36// -----------------------------------------------------------------------------
37// Implementation of Register
38
39Register rax = { 0 };
40Register rcx = { 1 };
41Register rdx = { 2 };
42Register rbx = { 3 };
43Register rsp = { 4 };
44Register rbp = { 5 };
45Register rsi = { 6 };
46Register rdi = { 7 };
47Register r8 = { 8 };
48Register r9 = { 9 };
49Register r10 = { 10 };
50Register r11 = { 11 };
51Register r12 = { 12 };
52Register r13 = { 13 };
53Register r14 = { 14 };
54Register r15 = { 15 };
55
56Register no_reg = { -1 };
57
58XMMRegister xmm0 = { 0 };
59XMMRegister xmm1 = { 1 };
60XMMRegister xmm2 = { 2 };
61XMMRegister xmm3 = { 3 };
62XMMRegister xmm4 = { 4 };
63XMMRegister xmm5 = { 5 };
64XMMRegister xmm6 = { 6 };
65XMMRegister xmm7 = { 7 };
66XMMRegister xmm8 = { 8 };
67XMMRegister xmm9 = { 9 };
68XMMRegister xmm10 = { 10 };
69XMMRegister xmm11 = { 11 };
70XMMRegister xmm12 = { 12 };
71XMMRegister xmm13 = { 13 };
72XMMRegister xmm14 = { 14 };
73XMMRegister xmm15 = { 15 };
74
75
76// -----------------------------------------------------------------------------
77// Implementation of CpuFeatures
78
79// The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
80// fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
81uint64_t CpuFeatures::supported_ = kDefaultCpuFeatures;
82uint64_t CpuFeatures::enabled_ = 0;
Steve Blockd0582a62009-12-15 09:54:21 +000083uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000084
85void CpuFeatures::Probe() {
86 ASSERT(Heap::HasBeenSetup());
87 ASSERT(supported_ == kDefaultCpuFeatures);
Steve Blockd0582a62009-12-15 09:54:21 +000088 if (Serializer::enabled()) {
89 supported_ |= OS::CpuFeaturesImpliedByPlatform();
90 return; // No features if we might serialize.
91 }
Steve Blocka7e24c12009-10-30 11:49:00 +000092
93 Assembler assm(NULL, 0);
94 Label cpuid, done;
95#define __ assm.
96 // Save old rsp, since we are going to modify the stack.
97 __ push(rbp);
98 __ pushfq();
99 __ push(rcx);
100 __ push(rbx);
101 __ movq(rbp, rsp);
102
103 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
104 __ pushfq();
105 __ pop(rax);
106 __ movq(rdx, rax);
107 __ xor_(rax, Immediate(0x200000)); // Flip bit 21.
108 __ push(rax);
109 __ popfq();
110 __ pushfq();
111 __ pop(rax);
112 __ xor_(rax, rdx); // Different if CPUID is supported.
113 __ j(not_zero, &cpuid);
114
115 // CPUID not supported. Clear the supported features in edx:eax.
116 __ xor_(rax, rax);
117 __ jmp(&done);
118
119 // Invoke CPUID with 1 in eax to get feature information in
120 // ecx:edx. Temporarily enable CPUID support because we know it's
121 // safe here.
122 __ bind(&cpuid);
123 __ movq(rax, Immediate(1));
124 supported_ = kDefaultCpuFeatures | (1 << CPUID);
125 { Scope fscope(CPUID);
126 __ cpuid();
127 // Move the result from ecx:edx to rdi.
128 __ movl(rdi, rdx); // Zero-extended to 64 bits.
129 __ shl(rcx, Immediate(32));
130 __ or_(rdi, rcx);
131
132 // Get the sahf supported flag, from CPUID(0x80000001)
133 __ movq(rax, 0x80000001, RelocInfo::NONE);
134 __ cpuid();
135 }
136 supported_ = kDefaultCpuFeatures;
137
138 // Put the CPU flags in rax.
139 // rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
140 __ movl(rax, Immediate(1));
141 __ and_(rcx, rax); // Bit 0 is set if SAHF instruction supported.
142 __ not_(rax);
143 __ and_(rax, rdi);
144 __ or_(rax, rcx);
145 __ or_(rax, Immediate(1 << CPUID));
146
147 // Done.
148 __ bind(&done);
149 __ movq(rsp, rbp);
150 __ pop(rbx);
151 __ pop(rcx);
152 __ popfq();
153 __ pop(rbp);
154 __ ret(0);
155#undef __
156
157 CodeDesc desc;
158 assm.GetCode(&desc);
159 Object* code =
160 Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB), NULL);
161 if (!code->IsCode()) return;
162 LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
163 Code::cast(code), "CpuFeatures::Probe"));
164 typedef uint64_t (*F0)();
165 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
166 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000167 found_by_runtime_probing_ = supported_;
168 found_by_runtime_probing_ &= ~kDefaultCpuFeatures;
169 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
170 supported_ |= os_guarantees;
171 found_by_runtime_probing_ &= ~os_guarantees;
Steve Blocka7e24c12009-10-30 11:49:00 +0000172 // SSE2 and CMOV must be available on an X64 CPU.
173 ASSERT(IsSupported(CPUID));
174 ASSERT(IsSupported(SSE2));
175 ASSERT(IsSupported(CMOV));
176}
177
178
179// -----------------------------------------------------------------------------
180// Implementation of RelocInfo
181
182// Patch the code at the current PC with a call to the target address.
183// Additional guard int3 instructions can be added if required.
184void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
185 // Load register with immediate 64 and call through a register instructions
186 // takes up 13 bytes and int3 takes up one byte.
187 static const int kCallCodeSize = 13;
188 int code_size = kCallCodeSize + guard_bytes;
189
190 // Create a code patcher.
191 CodePatcher patcher(pc_, code_size);
192
193 // Add a label for checking the size of the code used for returning.
194#ifdef DEBUG
195 Label check_codesize;
196 patcher.masm()->bind(&check_codesize);
197#endif
198
199 // Patch the code.
200 patcher.masm()->movq(r10, target, RelocInfo::NONE);
201 patcher.masm()->call(r10);
202
203 // Check that the size of the code generated is as expected.
204 ASSERT_EQ(kCallCodeSize,
205 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
206
207 // Add the requested number of int3 instructions after the call.
208 for (int i = 0; i < guard_bytes; i++) {
209 patcher.masm()->int3();
210 }
211}
212
213
214void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
215 // Patch the code at the current address with the supplied instructions.
216 for (int i = 0; i < instruction_count; i++) {
217 *(pc_ + i) = *(instructions + i);
218 }
219
220 // Indicate that code has changed.
221 CPU::FlushICache(pc_, instruction_count);
222}
223
224// -----------------------------------------------------------------------------
225// Implementation of Operand
226
227Operand::Operand(Register base, int32_t disp): rex_(0) {
228 len_ = 1;
229 if (base.is(rsp) || base.is(r12)) {
230 // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
231 set_sib(times_1, rsp, base);
232 }
233
234 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
235 set_modrm(0, base);
236 } else if (is_int8(disp)) {
237 set_modrm(1, base);
238 set_disp8(disp);
239 } else {
240 set_modrm(2, base);
241 set_disp32(disp);
242 }
243}
244
245
246Operand::Operand(Register base,
247 Register index,
248 ScaleFactor scale,
249 int32_t disp): rex_(0) {
250 ASSERT(!index.is(rsp));
251 len_ = 1;
252 set_sib(scale, index, base);
253 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
254 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
255 // possibly set by set_sib.
256 set_modrm(0, rsp);
257 } else if (is_int8(disp)) {
258 set_modrm(1, rsp);
259 set_disp8(disp);
260 } else {
261 set_modrm(2, rsp);
262 set_disp32(disp);
263 }
264}
265
266
267// -----------------------------------------------------------------------------
268// Implementation of Assembler
269
270#ifdef GENERATED_CODE_COVERAGE
271static void InitCoverageLog();
272#endif
273
274byte* Assembler::spare_buffer_ = NULL;
275
Steve Block3ce2e202009-11-05 08:53:23 +0000276Assembler::Assembler(void* buffer, int buffer_size)
277 : code_targets_(100) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000278 if (buffer == NULL) {
279 // do our own buffer management
280 if (buffer_size <= kMinimalBufferSize) {
281 buffer_size = kMinimalBufferSize;
282
283 if (spare_buffer_ != NULL) {
284 buffer = spare_buffer_;
285 spare_buffer_ = NULL;
286 }
287 }
288 if (buffer == NULL) {
289 buffer_ = NewArray<byte>(buffer_size);
290 } else {
291 buffer_ = static_cast<byte*>(buffer);
292 }
293 buffer_size_ = buffer_size;
294 own_buffer_ = true;
295 } else {
296 // use externally provided buffer instead
297 ASSERT(buffer_size > 0);
298 buffer_ = static_cast<byte*>(buffer);
299 buffer_size_ = buffer_size;
300 own_buffer_ = false;
301 }
302
303 // Clear the buffer in debug mode unless it was provided by the
304 // caller in which case we can't be sure it's okay to overwrite
305 // existing code in it.
306#ifdef DEBUG
307 if (own_buffer_) {
308 memset(buffer_, 0xCC, buffer_size); // int3
309 }
310#endif
311
312 // setup buffer pointers
313 ASSERT(buffer_ != NULL);
314 pc_ = buffer_;
315 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
316
317 last_pc_ = NULL;
318 current_statement_position_ = RelocInfo::kNoPosition;
319 current_position_ = RelocInfo::kNoPosition;
320 written_statement_position_ = current_statement_position_;
321 written_position_ = current_position_;
322#ifdef GENERATED_CODE_COVERAGE
323 InitCoverageLog();
324#endif
325}
326
327
328Assembler::~Assembler() {
329 if (own_buffer_) {
330 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
331 spare_buffer_ = buffer_;
332 } else {
333 DeleteArray(buffer_);
334 }
335 }
336}
337
338
339void Assembler::GetCode(CodeDesc* desc) {
340 // finalize code
341 // (at this point overflow() may be true, but the gap ensures that
342 // we are still not overlapping instructions and relocation info)
343 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap
344 // setup desc
345 desc->buffer = buffer_;
346 desc->buffer_size = buffer_size_;
347 desc->instr_size = pc_offset();
348 ASSERT(desc->instr_size > 0); // Zero-size code objects upset the system.
Steve Blockd0582a62009-12-15 09:54:21 +0000349 desc->reloc_size =
350 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000351 desc->origin = this;
352
353 Counters::reloc_info_size.Increment(desc->reloc_size);
354}
355
356
357void Assembler::Align(int m) {
358 ASSERT(IsPowerOf2(m));
359 while ((pc_offset() & (m - 1)) != 0) {
360 nop();
361 }
362}
363
364
365void Assembler::bind_to(Label* L, int pos) {
366 ASSERT(!L->is_bound()); // Label may only be bound once.
367 last_pc_ = NULL;
368 ASSERT(0 <= pos && pos <= pc_offset()); // Position must be valid.
369 if (L->is_linked()) {
370 int current = L->pos();
371 int next = long_at(current);
372 while (next != current) {
373 // relative address, relative to point after address
374 int imm32 = pos - (current + sizeof(int32_t));
375 long_at_put(current, imm32);
376 current = next;
377 next = long_at(next);
378 }
379 // Fix up last fixup on linked list.
380 int last_imm32 = pos - (current + sizeof(int32_t));
381 long_at_put(current, last_imm32);
382 }
383 L->bind_to(pos);
384}
385
386
387void Assembler::bind(Label* L) {
388 bind_to(L, pc_offset());
389}
390
391
392void Assembler::GrowBuffer() {
393 ASSERT(buffer_overflow()); // should not call this otherwise
394 if (!own_buffer_) FATAL("external code buffer is too small");
395
396 // compute new buffer size
397 CodeDesc desc; // the new buffer
398 if (buffer_size_ < 4*KB) {
399 desc.buffer_size = 4*KB;
400 } else {
401 desc.buffer_size = 2*buffer_size_;
402 }
403 // Some internal data structures overflow for very large buffers,
404 // they must ensure that kMaximalBufferSize is not too large.
405 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block3ce2e202009-11-05 08:53:23 +0000406 (desc.buffer_size > Heap::MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
408 }
409
410 // setup new buffer
411 desc.buffer = NewArray<byte>(desc.buffer_size);
412 desc.instr_size = pc_offset();
Steve Blockd0582a62009-12-15 09:54:21 +0000413 desc.reloc_size =
414 static_cast<int>((buffer_ + buffer_size_) - (reloc_info_writer.pos()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000415
416 // Clear the buffer in debug mode. Use 'int3' instructions to make
417 // sure to get into problems if we ever run uninitialized code.
418#ifdef DEBUG
419 memset(desc.buffer, 0xCC, desc.buffer_size);
420#endif
421
422 // copy the data
423 intptr_t pc_delta = desc.buffer - buffer_;
424 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
425 (buffer_ + buffer_size_);
426 memmove(desc.buffer, buffer_, desc.instr_size);
427 memmove(rc_delta + reloc_info_writer.pos(),
428 reloc_info_writer.pos(), desc.reloc_size);
429
430 // switch buffers
431 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
432 spare_buffer_ = buffer_;
433 } else {
434 DeleteArray(buffer_);
435 }
436 buffer_ = desc.buffer;
437 buffer_size_ = desc.buffer_size;
438 pc_ += pc_delta;
439 if (last_pc_ != NULL) {
440 last_pc_ += pc_delta;
441 }
442 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
443 reloc_info_writer.last_pc() + pc_delta);
444
445 // relocate runtime entries
446 for (RelocIterator it(desc); !it.done(); it.next()) {
447 RelocInfo::Mode rmode = it.rinfo()->rmode();
448 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
449 intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc());
450 if (*p != 0) { // 0 means uninitialized.
451 *p += pc_delta;
452 }
453 }
454 }
455
456 ASSERT(!buffer_overflow());
457}
458
459
460void Assembler::emit_operand(int code, const Operand& adr) {
461 ASSERT(is_uint3(code));
462 const unsigned length = adr.len_;
463 ASSERT(length > 0);
464
465 // Emit updated ModR/M byte containing the given register.
466 ASSERT((adr.buf_[0] & 0x38) == 0);
467 pc_[0] = adr.buf_[0] | code << 3;
468
469 // Emit the rest of the encoded operand.
470 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
471 pc_ += length;
472}
473
474
475// Assembler Instruction implementations
476
477void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
478 EnsureSpace ensure_space(this);
479 last_pc_ = pc_;
480 emit_rex_64(reg, op);
481 emit(opcode);
482 emit_operand(reg, op);
483}
484
485
486void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
487 EnsureSpace ensure_space(this);
488 last_pc_ = pc_;
489 emit_rex_64(reg, rm_reg);
490 emit(opcode);
491 emit_modrm(reg, rm_reg);
492}
493
494
495void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
496 EnsureSpace ensure_space(this);
497 last_pc_ = pc_;
498 emit(0x66);
499 emit_optional_rex_32(reg, rm_reg);
500 emit(opcode);
501 emit_modrm(reg, rm_reg);
502}
503
504
505void Assembler::arithmetic_op_16(byte opcode,
506 Register reg,
507 const Operand& rm_reg) {
508 EnsureSpace ensure_space(this);
509 last_pc_ = pc_;
510 emit(0x66);
511 emit_optional_rex_32(reg, rm_reg);
512 emit(opcode);
513 emit_operand(reg, rm_reg);
514}
515
516
517void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
518 EnsureSpace ensure_space(this);
519 last_pc_ = pc_;
520 emit_optional_rex_32(reg, rm_reg);
521 emit(opcode);
522 emit_modrm(reg, rm_reg);
523}
524
525
526void Assembler::arithmetic_op_32(byte opcode,
527 Register reg,
528 const Operand& rm_reg) {
529 EnsureSpace ensure_space(this);
530 last_pc_ = pc_;
531 emit_optional_rex_32(reg, rm_reg);
532 emit(opcode);
533 emit_operand(reg, rm_reg);
534}
535
536
537void Assembler::immediate_arithmetic_op(byte subcode,
538 Register dst,
539 Immediate src) {
540 EnsureSpace ensure_space(this);
541 last_pc_ = pc_;
542 emit_rex_64(dst);
543 if (is_int8(src.value_)) {
544 emit(0x83);
545 emit_modrm(subcode, dst);
546 emit(src.value_);
547 } else if (dst.is(rax)) {
548 emit(0x05 | (subcode << 3));
549 emitl(src.value_);
550 } else {
551 emit(0x81);
552 emit_modrm(subcode, dst);
553 emitl(src.value_);
554 }
555}
556
557void Assembler::immediate_arithmetic_op(byte subcode,
558 const Operand& dst,
559 Immediate src) {
560 EnsureSpace ensure_space(this);
561 last_pc_ = pc_;
562 emit_rex_64(dst);
563 if (is_int8(src.value_)) {
564 emit(0x83);
565 emit_operand(subcode, dst);
566 emit(src.value_);
567 } else {
568 emit(0x81);
569 emit_operand(subcode, dst);
570 emitl(src.value_);
571 }
572}
573
574
575void Assembler::immediate_arithmetic_op_16(byte subcode,
576 Register dst,
577 Immediate src) {
578 EnsureSpace ensure_space(this);
579 last_pc_ = pc_;
580 emit(0x66); // Operand size override prefix.
581 emit_optional_rex_32(dst);
582 if (is_int8(src.value_)) {
583 emit(0x83);
584 emit_modrm(subcode, dst);
585 emit(src.value_);
586 } else if (dst.is(rax)) {
587 emit(0x05 | (subcode << 3));
Steve Block3ce2e202009-11-05 08:53:23 +0000588 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000589 } else {
590 emit(0x81);
591 emit_modrm(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000592 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000593 }
594}
595
596
597void Assembler::immediate_arithmetic_op_16(byte subcode,
598 const Operand& dst,
599 Immediate src) {
600 EnsureSpace ensure_space(this);
601 last_pc_ = pc_;
602 emit(0x66); // Operand size override prefix.
603 emit_optional_rex_32(dst);
604 if (is_int8(src.value_)) {
605 emit(0x83);
606 emit_operand(subcode, dst);
607 emit(src.value_);
608 } else {
609 emit(0x81);
610 emit_operand(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000611 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000612 }
613}
614
615
616void Assembler::immediate_arithmetic_op_32(byte subcode,
617 Register dst,
618 Immediate src) {
619 EnsureSpace ensure_space(this);
620 last_pc_ = pc_;
621 emit_optional_rex_32(dst);
622 if (is_int8(src.value_)) {
623 emit(0x83);
624 emit_modrm(subcode, dst);
625 emit(src.value_);
626 } else if (dst.is(rax)) {
627 emit(0x05 | (subcode << 3));
628 emitl(src.value_);
629 } else {
630 emit(0x81);
631 emit_modrm(subcode, dst);
632 emitl(src.value_);
633 }
634}
635
636
637void Assembler::immediate_arithmetic_op_32(byte subcode,
638 const Operand& dst,
639 Immediate src) {
640 EnsureSpace ensure_space(this);
641 last_pc_ = pc_;
642 emit_optional_rex_32(dst);
643 if (is_int8(src.value_)) {
644 emit(0x83);
645 emit_operand(subcode, dst);
646 emit(src.value_);
647 } else {
648 emit(0x81);
649 emit_operand(subcode, dst);
650 emitl(src.value_);
651 }
652}
653
654
655void Assembler::immediate_arithmetic_op_8(byte subcode,
656 const Operand& dst,
657 Immediate src) {
658 EnsureSpace ensure_space(this);
659 last_pc_ = pc_;
660 emit_optional_rex_32(dst);
661 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
662 emit(0x80);
663 emit_operand(subcode, dst);
664 emit(src.value_);
665}
666
667
668void Assembler::immediate_arithmetic_op_8(byte subcode,
669 Register dst,
670 Immediate src) {
671 EnsureSpace ensure_space(this);
672 last_pc_ = pc_;
673 if (dst.code() > 3) {
674 // Use 64-bit mode byte registers.
675 emit_rex_64(dst);
676 }
677 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
678 emit(0x80);
679 emit_modrm(subcode, dst);
680 emit(src.value_);
681}
682
683
684void Assembler::shift(Register dst, Immediate shift_amount, int subcode) {
685 EnsureSpace ensure_space(this);
686 last_pc_ = pc_;
687 ASSERT(is_uint6(shift_amount.value_)); // illegal shift count
688 if (shift_amount.value_ == 1) {
689 emit_rex_64(dst);
690 emit(0xD1);
691 emit_modrm(subcode, dst);
692 } else {
693 emit_rex_64(dst);
694 emit(0xC1);
695 emit_modrm(subcode, dst);
696 emit(shift_amount.value_);
697 }
698}
699
700
701void Assembler::shift(Register dst, int subcode) {
702 EnsureSpace ensure_space(this);
703 last_pc_ = pc_;
704 emit_rex_64(dst);
705 emit(0xD3);
706 emit_modrm(subcode, dst);
707}
708
709
710void Assembler::shift_32(Register dst, int subcode) {
711 EnsureSpace ensure_space(this);
712 last_pc_ = pc_;
713 emit_optional_rex_32(dst);
714 emit(0xD3);
715 emit_modrm(subcode, dst);
716}
717
718
719void Assembler::shift_32(Register dst, Immediate shift_amount, int subcode) {
720 EnsureSpace ensure_space(this);
721 last_pc_ = pc_;
Steve Block3ce2e202009-11-05 08:53:23 +0000722 ASSERT(is_uint5(shift_amount.value_)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +0000723 if (shift_amount.value_ == 1) {
724 emit_optional_rex_32(dst);
725 emit(0xD1);
726 emit_modrm(subcode, dst);
727 } else {
728 emit_optional_rex_32(dst);
729 emit(0xC1);
730 emit_modrm(subcode, dst);
731 emit(shift_amount.value_);
732 }
733}
734
735
736void Assembler::bt(const Operand& dst, Register src) {
737 EnsureSpace ensure_space(this);
738 last_pc_ = pc_;
739 emit_rex_64(src, dst);
740 emit(0x0F);
741 emit(0xA3);
742 emit_operand(src, dst);
743}
744
745
746void Assembler::bts(const Operand& dst, Register src) {
747 EnsureSpace ensure_space(this);
748 last_pc_ = pc_;
749 emit_rex_64(src, dst);
750 emit(0x0F);
751 emit(0xAB);
752 emit_operand(src, dst);
753}
754
755
756void Assembler::call(Label* L) {
757 EnsureSpace ensure_space(this);
758 last_pc_ = pc_;
759 // 1110 1000 #32-bit disp
760 emit(0xE8);
761 if (L->is_bound()) {
762 int offset = L->pos() - pc_offset() - sizeof(int32_t);
763 ASSERT(offset <= 0);
764 emitl(offset);
765 } else if (L->is_linked()) {
766 emitl(L->pos());
767 L->link_to(pc_offset() - sizeof(int32_t));
768 } else {
769 ASSERT(L->is_unused());
770 int32_t current = pc_offset();
771 emitl(current);
772 L->link_to(current);
773 }
774}
775
776
Steve Block3ce2e202009-11-05 08:53:23 +0000777void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
778 EnsureSpace ensure_space(this);
779 last_pc_ = pc_;
780 // 1110 1000 #32-bit disp
781 emit(0xE8);
782 emit_code_target(target, rmode);
783}
784
785
Steve Blocka7e24c12009-10-30 11:49:00 +0000786void Assembler::call(Register adr) {
787 EnsureSpace ensure_space(this);
788 last_pc_ = pc_;
789 // Opcode: FF /2 r64
790 if (adr.high_bit()) {
791 emit_rex_64(adr);
792 }
793 emit(0xFF);
794 emit_modrm(0x2, adr);
795}
796
797
798void Assembler::call(const Operand& op) {
799 EnsureSpace ensure_space(this);
800 last_pc_ = pc_;
801 // Opcode: FF /2 m64
802 emit_rex_64(op);
803 emit(0xFF);
804 emit_operand(2, op);
805}
806
807
Steve Block3ce2e202009-11-05 08:53:23 +0000808void Assembler::clc() {
809 EnsureSpace ensure_space(this);
810 last_pc_ = pc_;
811 emit(0xF8);
812}
813
Steve Blocka7e24c12009-10-30 11:49:00 +0000814void Assembler::cdq() {
815 EnsureSpace ensure_space(this);
816 last_pc_ = pc_;
817 emit(0x99);
818}
819
820
821void Assembler::cmovq(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000822 if (cc == always) {
823 movq(dst, src);
824 } else if (cc == never) {
825 return;
826 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000827 // No need to check CpuInfo for CMOV support, it's a required part of the
828 // 64-bit architecture.
829 ASSERT(cc >= 0); // Use mov for unconditional moves.
830 EnsureSpace ensure_space(this);
831 last_pc_ = pc_;
832 // Opcode: REX.W 0f 40 + cc /r
833 emit_rex_64(dst, src);
834 emit(0x0f);
835 emit(0x40 + cc);
836 emit_modrm(dst, src);
837}
838
839
840void Assembler::cmovq(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000841 if (cc == always) {
842 movq(dst, src);
843 } else if (cc == never) {
844 return;
845 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000846 ASSERT(cc >= 0);
847 EnsureSpace ensure_space(this);
848 last_pc_ = pc_;
849 // Opcode: REX.W 0f 40 + cc /r
850 emit_rex_64(dst, src);
851 emit(0x0f);
852 emit(0x40 + cc);
853 emit_operand(dst, src);
854}
855
856
857void Assembler::cmovl(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000858 if (cc == always) {
859 movl(dst, src);
860 } else if (cc == never) {
861 return;
862 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000863 ASSERT(cc >= 0);
864 EnsureSpace ensure_space(this);
865 last_pc_ = pc_;
866 // Opcode: 0f 40 + cc /r
867 emit_optional_rex_32(dst, src);
868 emit(0x0f);
869 emit(0x40 + cc);
870 emit_modrm(dst, src);
871}
872
873
874void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000875 if (cc == always) {
876 movl(dst, src);
877 } else if (cc == never) {
878 return;
879 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000880 ASSERT(cc >= 0);
881 EnsureSpace ensure_space(this);
882 last_pc_ = pc_;
883 // Opcode: 0f 40 + cc /r
884 emit_optional_rex_32(dst, src);
885 emit(0x0f);
886 emit(0x40 + cc);
887 emit_operand(dst, src);
888}
889
890
891void Assembler::cmpb_al(Immediate imm8) {
892 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_));
893 EnsureSpace ensure_space(this);
894 last_pc_ = pc_;
895 emit(0x3c);
896 emit(imm8.value_);
897}
898
899
900void Assembler::cpuid() {
Steve Blockd0582a62009-12-15 09:54:21 +0000901 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000902 EnsureSpace ensure_space(this);
903 last_pc_ = pc_;
904 emit(0x0F);
905 emit(0xA2);
906}
907
908
909void Assembler::cqo() {
910 EnsureSpace ensure_space(this);
911 last_pc_ = pc_;
912 emit_rex_64();
913 emit(0x99);
914}
915
916
917void Assembler::decq(Register dst) {
918 EnsureSpace ensure_space(this);
919 last_pc_ = pc_;
920 emit_rex_64(dst);
921 emit(0xFF);
922 emit_modrm(0x1, dst);
923}
924
925
926void Assembler::decq(const Operand& dst) {
927 EnsureSpace ensure_space(this);
928 last_pc_ = pc_;
929 emit_rex_64(dst);
930 emit(0xFF);
931 emit_operand(1, dst);
932}
933
934
935void Assembler::decl(Register dst) {
936 EnsureSpace ensure_space(this);
937 last_pc_ = pc_;
938 emit_optional_rex_32(dst);
939 emit(0xFF);
940 emit_modrm(0x1, dst);
941}
942
943
944void Assembler::decl(const Operand& dst) {
945 EnsureSpace ensure_space(this);
946 last_pc_ = pc_;
947 emit_optional_rex_32(dst);
948 emit(0xFF);
949 emit_operand(1, dst);
950}
951
952
Steve Block3ce2e202009-11-05 08:53:23 +0000953void Assembler::decb(Register dst) {
954 EnsureSpace ensure_space(this);
955 last_pc_ = pc_;
956 if (dst.code() > 3) {
957 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
958 emit_rex_32(dst);
959 }
960 emit(0xFE);
961 emit_modrm(0x1, dst);
962}
963
964
965void Assembler::decb(const Operand& dst) {
966 EnsureSpace ensure_space(this);
967 last_pc_ = pc_;
968 emit_optional_rex_32(dst);
969 emit(0xFE);
970 emit_operand(1, dst);
971}
972
973
Steve Blocka7e24c12009-10-30 11:49:00 +0000974void Assembler::enter(Immediate size) {
975 EnsureSpace ensure_space(this);
976 last_pc_ = pc_;
977 emit(0xC8);
978 emitw(size.value_); // 16 bit operand, always.
979 emit(0);
980}
981
982
983void Assembler::hlt() {
984 EnsureSpace ensure_space(this);
985 last_pc_ = pc_;
986 emit(0xF4);
987}
988
989
990void Assembler::idivq(Register src) {
991 EnsureSpace ensure_space(this);
992 last_pc_ = pc_;
993 emit_rex_64(src);
994 emit(0xF7);
995 emit_modrm(0x7, src);
996}
997
998
999void Assembler::idivl(Register src) {
1000 EnsureSpace ensure_space(this);
1001 last_pc_ = pc_;
1002 emit_optional_rex_32(src);
1003 emit(0xF7);
1004 emit_modrm(0x7, src);
1005}
1006
1007
1008void Assembler::imul(Register src) {
1009 EnsureSpace ensure_space(this);
1010 last_pc_ = pc_;
1011 emit_rex_64(src);
1012 emit(0xF7);
1013 emit_modrm(0x5, src);
1014}
1015
1016
1017void Assembler::imul(Register dst, Register src) {
1018 EnsureSpace ensure_space(this);
1019 last_pc_ = pc_;
1020 emit_rex_64(dst, src);
1021 emit(0x0F);
1022 emit(0xAF);
1023 emit_modrm(dst, src);
1024}
1025
1026
1027void Assembler::imul(Register dst, const Operand& src) {
1028 EnsureSpace ensure_space(this);
1029 last_pc_ = pc_;
1030 emit_rex_64(dst, src);
1031 emit(0x0F);
1032 emit(0xAF);
1033 emit_operand(dst, src);
1034}
1035
1036
1037void Assembler::imul(Register dst, Register src, Immediate imm) {
1038 EnsureSpace ensure_space(this);
1039 last_pc_ = pc_;
1040 emit_rex_64(dst, src);
1041 if (is_int8(imm.value_)) {
1042 emit(0x6B);
1043 emit_modrm(dst, src);
1044 emit(imm.value_);
1045 } else {
1046 emit(0x69);
1047 emit_modrm(dst, src);
1048 emitl(imm.value_);
1049 }
1050}
1051
1052
1053void Assembler::imull(Register dst, Register src) {
1054 EnsureSpace ensure_space(this);
1055 last_pc_ = pc_;
1056 emit_optional_rex_32(dst, src);
1057 emit(0x0F);
1058 emit(0xAF);
1059 emit_modrm(dst, src);
1060}
1061
1062
1063void Assembler::incq(Register dst) {
1064 EnsureSpace ensure_space(this);
1065 last_pc_ = pc_;
1066 emit_rex_64(dst);
1067 emit(0xFF);
1068 emit_modrm(0x0, dst);
1069}
1070
1071
1072void Assembler::incq(const Operand& dst) {
1073 EnsureSpace ensure_space(this);
1074 last_pc_ = pc_;
1075 emit_rex_64(dst);
1076 emit(0xFF);
1077 emit_operand(0, dst);
1078}
1079
1080
1081void Assembler::incl(const Operand& dst) {
1082 EnsureSpace ensure_space(this);
1083 last_pc_ = pc_;
1084 emit_optional_rex_32(dst);
1085 emit(0xFF);
1086 emit_operand(0, dst);
1087}
1088
1089
1090void Assembler::int3() {
1091 EnsureSpace ensure_space(this);
1092 last_pc_ = pc_;
1093 emit(0xCC);
1094}
1095
1096
1097void Assembler::j(Condition cc, Label* L) {
Steve Block3ce2e202009-11-05 08:53:23 +00001098 if (cc == always) {
1099 jmp(L);
1100 return;
1101 } else if (cc == never) {
1102 return;
1103 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001104 EnsureSpace ensure_space(this);
1105 last_pc_ = pc_;
1106 ASSERT(is_uint4(cc));
1107 if (L->is_bound()) {
1108 const int short_size = 2;
1109 const int long_size = 6;
1110 int offs = L->pos() - pc_offset();
1111 ASSERT(offs <= 0);
1112 if (is_int8(offs - short_size)) {
1113 // 0111 tttn #8-bit disp
1114 emit(0x70 | cc);
1115 emit((offs - short_size) & 0xFF);
1116 } else {
1117 // 0000 1111 1000 tttn #32-bit disp
1118 emit(0x0F);
1119 emit(0x80 | cc);
1120 emitl(offs - long_size);
1121 }
1122 } else if (L->is_linked()) {
1123 // 0000 1111 1000 tttn #32-bit disp
1124 emit(0x0F);
1125 emit(0x80 | cc);
1126 emitl(L->pos());
1127 L->link_to(pc_offset() - sizeof(int32_t));
1128 } else {
1129 ASSERT(L->is_unused());
1130 emit(0x0F);
1131 emit(0x80 | cc);
1132 int32_t current = pc_offset();
1133 emitl(current);
1134 L->link_to(current);
1135 }
1136}
1137
1138
Steve Block3ce2e202009-11-05 08:53:23 +00001139void Assembler::j(Condition cc,
1140 Handle<Code> target,
1141 RelocInfo::Mode rmode) {
1142 EnsureSpace ensure_space(this);
1143 last_pc_ = pc_;
1144 ASSERT(is_uint4(cc));
1145 // 0000 1111 1000 tttn #32-bit disp
1146 emit(0x0F);
1147 emit(0x80 | cc);
1148 emit_code_target(target, rmode);
1149}
1150
1151
Steve Blocka7e24c12009-10-30 11:49:00 +00001152void Assembler::jmp(Label* L) {
1153 EnsureSpace ensure_space(this);
1154 last_pc_ = pc_;
1155 if (L->is_bound()) {
1156 int offs = L->pos() - pc_offset() - 1;
1157 ASSERT(offs <= 0);
1158 if (is_int8(offs - sizeof(int8_t))) {
1159 // 1110 1011 #8-bit disp
1160 emit(0xEB);
1161 emit((offs - sizeof(int8_t)) & 0xFF);
1162 } else {
1163 // 1110 1001 #32-bit disp
1164 emit(0xE9);
1165 emitl(offs - sizeof(int32_t));
1166 }
1167 } else if (L->is_linked()) {
1168 // 1110 1001 #32-bit disp
1169 emit(0xE9);
1170 emitl(L->pos());
1171 L->link_to(pc_offset() - sizeof(int32_t));
1172 } else {
1173 // 1110 1001 #32-bit disp
1174 ASSERT(L->is_unused());
1175 emit(0xE9);
1176 int32_t current = pc_offset();
1177 emitl(current);
1178 L->link_to(current);
1179 }
1180}
1181
1182
Steve Block3ce2e202009-11-05 08:53:23 +00001183void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1184 EnsureSpace ensure_space(this);
1185 last_pc_ = pc_;
1186 // 1110 1001 #32-bit disp
1187 emit(0xE9);
1188 emit_code_target(target, rmode);
1189}
1190
1191
Steve Blocka7e24c12009-10-30 11:49:00 +00001192void Assembler::jmp(Register target) {
1193 EnsureSpace ensure_space(this);
1194 last_pc_ = pc_;
1195 // Opcode FF/4 r64
1196 if (target.high_bit()) {
1197 emit_rex_64(target);
1198 }
1199 emit(0xFF);
1200 emit_modrm(0x4, target);
1201}
1202
1203
1204void Assembler::jmp(const Operand& src) {
1205 EnsureSpace ensure_space(this);
1206 last_pc_ = pc_;
1207 // Opcode FF/4 m64
1208 emit_optional_rex_32(src);
1209 emit(0xFF);
1210 emit_operand(0x4, src);
1211}
1212
1213
1214void Assembler::lea(Register dst, const Operand& src) {
1215 EnsureSpace ensure_space(this);
1216 last_pc_ = pc_;
1217 emit_rex_64(dst, src);
1218 emit(0x8D);
1219 emit_operand(dst, src);
1220}
1221
1222
1223void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
1224 EnsureSpace ensure_space(this);
1225 last_pc_ = pc_;
1226 emit(0x48); // REX.W
1227 emit(0xA1);
1228 emitq(reinterpret_cast<uintptr_t>(value), mode);
1229}
1230
1231
1232void Assembler::load_rax(ExternalReference ref) {
1233 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1234}
1235
1236
1237void Assembler::leave() {
1238 EnsureSpace ensure_space(this);
1239 last_pc_ = pc_;
1240 emit(0xC9);
1241}
1242
1243
1244void Assembler::movb(Register dst, const Operand& src) {
1245 EnsureSpace ensure_space(this);
1246 last_pc_ = pc_;
1247 emit_rex_32(dst, src);
1248 emit(0x8A);
1249 emit_operand(dst, src);
1250}
1251
1252void Assembler::movb(Register dst, Immediate imm) {
1253 EnsureSpace ensure_space(this);
1254 last_pc_ = pc_;
1255 emit_rex_32(dst);
1256 emit(0xC6);
1257 emit_modrm(0x0, dst);
1258 emit(imm.value_);
1259}
1260
1261void Assembler::movb(const Operand& dst, Register src) {
1262 EnsureSpace ensure_space(this);
1263 last_pc_ = pc_;
1264 emit_rex_32(src, dst);
1265 emit(0x88);
1266 emit_operand(src, dst);
1267}
1268
Steve Block3ce2e202009-11-05 08:53:23 +00001269void Assembler::movw(const Operand& dst, Register src) {
1270 EnsureSpace ensure_space(this);
1271 last_pc_ = pc_;
1272 emit(0x66);
1273 emit_optional_rex_32(src, dst);
1274 emit(0x89);
1275 emit_operand(src, dst);
1276}
1277
Steve Blocka7e24c12009-10-30 11:49:00 +00001278void Assembler::movl(Register dst, const Operand& src) {
1279 EnsureSpace ensure_space(this);
1280 last_pc_ = pc_;
1281 emit_optional_rex_32(dst, src);
1282 emit(0x8B);
1283 emit_operand(dst, src);
1284}
1285
1286
1287void Assembler::movl(Register dst, Register src) {
1288 EnsureSpace ensure_space(this);
1289 last_pc_ = pc_;
1290 emit_optional_rex_32(dst, src);
1291 emit(0x8B);
1292 emit_modrm(dst, src);
1293}
1294
1295
1296void Assembler::movl(const Operand& dst, Register src) {
1297 EnsureSpace ensure_space(this);
1298 last_pc_ = pc_;
1299 emit_optional_rex_32(src, dst);
1300 emit(0x89);
1301 emit_operand(src, dst);
1302}
1303
1304
1305void Assembler::movl(const Operand& dst, Immediate value) {
1306 EnsureSpace ensure_space(this);
1307 last_pc_ = pc_;
1308 emit_optional_rex_32(dst);
1309 emit(0xC7);
1310 emit_operand(0x0, dst);
1311 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1312}
1313
1314
1315void Assembler::movl(Register dst, Immediate value) {
1316 EnsureSpace ensure_space(this);
1317 last_pc_ = pc_;
1318 emit_optional_rex_32(dst);
1319 emit(0xC7);
1320 emit_modrm(0x0, dst);
1321 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1322}
1323
1324
1325void Assembler::movq(Register dst, const Operand& src) {
1326 EnsureSpace ensure_space(this);
1327 last_pc_ = pc_;
1328 emit_rex_64(dst, src);
1329 emit(0x8B);
1330 emit_operand(dst, src);
1331}
1332
1333
1334void Assembler::movq(Register dst, Register src) {
1335 EnsureSpace ensure_space(this);
1336 last_pc_ = pc_;
1337 emit_rex_64(dst, src);
1338 emit(0x8B);
1339 emit_modrm(dst, src);
1340}
1341
1342
1343void Assembler::movq(Register dst, Immediate value) {
1344 EnsureSpace ensure_space(this);
1345 last_pc_ = pc_;
1346 emit_rex_64(dst);
1347 emit(0xC7);
1348 emit_modrm(0x0, dst);
1349 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1350}
1351
1352
1353void Assembler::movq(const Operand& dst, Register src) {
1354 EnsureSpace ensure_space(this);
1355 last_pc_ = pc_;
1356 emit_rex_64(src, dst);
1357 emit(0x89);
1358 emit_operand(src, dst);
1359}
1360
1361
1362void Assembler::movq(Register dst, void* value, RelocInfo::Mode rmode) {
1363 // This method must not be used with heap object references. The stored
1364 // address is not GC safe. Use the handle version instead.
1365 ASSERT(rmode > RelocInfo::LAST_GCED_ENUM);
1366 EnsureSpace ensure_space(this);
1367 last_pc_ = pc_;
1368 emit_rex_64(dst);
1369 emit(0xB8 | dst.low_bits());
1370 emitq(reinterpret_cast<uintptr_t>(value), rmode);
1371}
1372
1373
1374void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
1375 // Non-relocatable values might not need a 64-bit representation.
1376 if (rmode == RelocInfo::NONE) {
1377 // Sadly, there is no zero or sign extending move for 8-bit immediates.
1378 if (is_int32(value)) {
1379 movq(dst, Immediate(static_cast<int32_t>(value)));
1380 return;
1381 } else if (is_uint32(value)) {
1382 movl(dst, Immediate(static_cast<int32_t>(value)));
1383 return;
1384 }
1385 // Value cannot be represented by 32 bits, so do a full 64 bit immediate
1386 // value.
1387 }
1388 EnsureSpace ensure_space(this);
1389 last_pc_ = pc_;
1390 emit_rex_64(dst);
1391 emit(0xB8 | dst.low_bits());
1392 emitq(value, rmode);
1393}
1394
1395
1396void Assembler::movq(Register dst, ExternalReference ref) {
1397 EnsureSpace ensure_space(this);
1398 last_pc_ = pc_;
1399 emit_rex_64(dst);
1400 emit(0xB8 | dst.low_bits());
1401 emitq(reinterpret_cast<uintptr_t>(ref.address()),
1402 RelocInfo::EXTERNAL_REFERENCE);
1403}
1404
1405
1406void Assembler::movq(const Operand& dst, Immediate value) {
1407 EnsureSpace ensure_space(this);
1408 last_pc_ = pc_;
1409 emit_rex_64(dst);
1410 emit(0xC7);
1411 emit_operand(0, dst);
1412 emit(value);
1413}
1414
1415
1416/*
1417 * Loads the ip-relative location of the src label into the target
1418 * location (as a 32-bit offset sign extended to 64-bit).
1419 */
1420void Assembler::movl(const Operand& dst, Label* src) {
1421 EnsureSpace ensure_space(this);
1422 last_pc_ = pc_;
1423 emit_optional_rex_32(dst);
1424 emit(0xC7);
1425 emit_operand(0, dst);
1426 if (src->is_bound()) {
1427 int offset = src->pos() - pc_offset() - sizeof(int32_t);
1428 ASSERT(offset <= 0);
1429 emitl(offset);
1430 } else if (src->is_linked()) {
1431 emitl(src->pos());
1432 src->link_to(pc_offset() - sizeof(int32_t));
1433 } else {
1434 ASSERT(src->is_unused());
1435 int32_t current = pc_offset();
1436 emitl(current);
1437 src->link_to(current);
1438 }
1439}
1440
1441
1442void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
1443 // If there is no relocation info, emit the value of the handle efficiently
1444 // (possibly using less that 8 bytes for the value).
1445 if (mode == RelocInfo::NONE) {
1446 // There is no possible reason to store a heap pointer without relocation
1447 // info, so it must be a smi.
1448 ASSERT(value->IsSmi());
Steve Block3ce2e202009-11-05 08:53:23 +00001449 movq(dst, reinterpret_cast<int64_t>(*value), RelocInfo::NONE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001450 } else {
1451 EnsureSpace ensure_space(this);
1452 last_pc_ = pc_;
1453 ASSERT(value->IsHeapObject());
1454 ASSERT(!Heap::InNewSpace(*value));
1455 emit_rex_64(dst);
1456 emit(0xB8 | dst.low_bits());
1457 emitq(reinterpret_cast<uintptr_t>(value.location()), mode);
1458 }
1459}
1460
1461
Steve Block3ce2e202009-11-05 08:53:23 +00001462void Assembler::movsxbq(Register dst, const Operand& src) {
1463 EnsureSpace ensure_space(this);
1464 last_pc_ = pc_;
1465 emit_rex_32(dst, src);
1466 emit(0x0F);
1467 emit(0xBE);
1468 emit_operand(dst, src);
1469}
1470
1471
1472void Assembler::movsxwq(Register dst, const Operand& src) {
1473 EnsureSpace ensure_space(this);
1474 last_pc_ = pc_;
1475 emit_rex_64(dst, src);
1476 emit(0x0F);
1477 emit(0xBF);
1478 emit_operand(dst, src);
1479}
1480
1481
Steve Blocka7e24c12009-10-30 11:49:00 +00001482void Assembler::movsxlq(Register dst, Register src) {
1483 EnsureSpace ensure_space(this);
1484 last_pc_ = pc_;
1485 emit_rex_64(dst, src);
1486 emit(0x63);
1487 emit_modrm(dst, src);
1488}
1489
1490
1491void Assembler::movsxlq(Register dst, const Operand& src) {
1492 EnsureSpace ensure_space(this);
1493 last_pc_ = pc_;
1494 emit_rex_64(dst, src);
1495 emit(0x63);
1496 emit_operand(dst, src);
1497}
1498
1499
1500void Assembler::movzxbq(Register dst, const Operand& src) {
1501 EnsureSpace ensure_space(this);
1502 last_pc_ = pc_;
1503 emit_rex_64(dst, src);
1504 emit(0x0F);
1505 emit(0xB6);
1506 emit_operand(dst, src);
1507}
1508
1509
1510void Assembler::movzxbl(Register dst, const Operand& src) {
1511 EnsureSpace ensure_space(this);
1512 last_pc_ = pc_;
1513 emit_optional_rex_32(dst, src);
1514 emit(0x0F);
1515 emit(0xB6);
1516 emit_operand(dst, src);
1517}
1518
1519
Steve Block3ce2e202009-11-05 08:53:23 +00001520void Assembler::movzxwq(Register dst, const Operand& src) {
1521 EnsureSpace ensure_space(this);
1522 last_pc_ = pc_;
1523 emit_rex_64(dst, src);
1524 emit(0x0F);
1525 emit(0xB7);
1526 emit_operand(dst, src);
1527}
1528
1529
Steve Blocka7e24c12009-10-30 11:49:00 +00001530void Assembler::movzxwl(Register dst, const Operand& src) {
1531 EnsureSpace ensure_space(this);
1532 last_pc_ = pc_;
1533 emit_optional_rex_32(dst, src);
1534 emit(0x0F);
1535 emit(0xB7);
1536 emit_operand(dst, src);
1537}
1538
1539
1540void Assembler::mul(Register src) {
1541 EnsureSpace ensure_space(this);
1542 last_pc_ = pc_;
1543 emit_rex_64(src);
1544 emit(0xF7);
1545 emit_modrm(0x4, src);
1546}
1547
1548
1549void Assembler::neg(Register dst) {
1550 EnsureSpace ensure_space(this);
1551 last_pc_ = pc_;
1552 emit_rex_64(dst);
1553 emit(0xF7);
1554 emit_modrm(0x3, dst);
1555}
1556
1557
1558void Assembler::negl(Register dst) {
1559 EnsureSpace ensure_space(this);
1560 last_pc_ = pc_;
1561 emit_optional_rex_32(dst);
1562 emit(0xF7);
1563 emit_modrm(0x3, dst);
1564}
1565
1566
1567void Assembler::neg(const Operand& dst) {
1568 EnsureSpace ensure_space(this);
1569 last_pc_ = pc_;
1570 emit_rex_64(dst);
1571 emit(0xF7);
1572 emit_operand(3, dst);
1573}
1574
1575
1576void Assembler::nop() {
1577 EnsureSpace ensure_space(this);
1578 last_pc_ = pc_;
1579 emit(0x90);
1580}
1581
1582
1583void Assembler::not_(Register dst) {
1584 EnsureSpace ensure_space(this);
1585 last_pc_ = pc_;
1586 emit_rex_64(dst);
1587 emit(0xF7);
1588 emit_modrm(0x2, dst);
1589}
1590
1591
1592void Assembler::not_(const Operand& dst) {
1593 EnsureSpace ensure_space(this);
1594 last_pc_ = pc_;
1595 emit_rex_64(dst);
1596 emit(0xF7);
1597 emit_operand(2, dst);
1598}
1599
1600
1601void Assembler::nop(int n) {
1602 // The recommended muti-byte sequences of NOP instructions from the Intel 64
1603 // and IA-32 Architectures Software Developer's Manual.
1604 //
1605 // Length Assembly Byte Sequence
1606 // 2 bytes 66 NOP 66 90H
1607 // 3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
1608 // 4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
1609 // 5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
1610 // 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
1611 // 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
1612 // 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
1613 // 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 66 0F 1F 84 00 00 00 00
1614 // 00000000H] 00H
1615
1616 ASSERT(1 <= n);
1617 ASSERT(n <= 9);
1618 EnsureSpace ensure_space(this);
1619 last_pc_ = pc_;
1620 switch (n) {
1621 case 1:
1622 emit(0x90);
1623 return;
1624 case 2:
1625 emit(0x66);
1626 emit(0x90);
1627 return;
1628 case 3:
1629 emit(0x0f);
1630 emit(0x1f);
1631 emit(0x00);
1632 return;
1633 case 4:
1634 emit(0x0f);
1635 emit(0x1f);
1636 emit(0x40);
1637 emit(0x00);
1638 return;
1639 case 5:
1640 emit(0x0f);
1641 emit(0x1f);
1642 emit(0x44);
1643 emit(0x00);
1644 emit(0x00);
1645 return;
1646 case 6:
1647 emit(0x66);
1648 emit(0x0f);
1649 emit(0x1f);
1650 emit(0x44);
1651 emit(0x00);
1652 emit(0x00);
1653 return;
1654 case 7:
1655 emit(0x0f);
1656 emit(0x1f);
1657 emit(0x80);
1658 emit(0x00);
1659 emit(0x00);
1660 emit(0x00);
1661 emit(0x00);
1662 return;
1663 case 8:
1664 emit(0x0f);
1665 emit(0x1f);
1666 emit(0x84);
1667 emit(0x00);
1668 emit(0x00);
1669 emit(0x00);
1670 emit(0x00);
1671 emit(0x00);
1672 return;
1673 case 9:
1674 emit(0x66);
1675 emit(0x0f);
1676 emit(0x1f);
1677 emit(0x84);
1678 emit(0x00);
1679 emit(0x00);
1680 emit(0x00);
1681 emit(0x00);
1682 emit(0x00);
1683 return;
1684 }
1685}
1686
1687
1688void Assembler::pop(Register dst) {
1689 EnsureSpace ensure_space(this);
1690 last_pc_ = pc_;
1691 if (dst.high_bit()) {
1692 emit_rex_64(dst);
1693 }
1694 emit(0x58 | dst.low_bits());
1695}
1696
1697
1698void Assembler::pop(const Operand& dst) {
1699 EnsureSpace ensure_space(this);
1700 last_pc_ = pc_;
1701 emit_rex_64(dst); // Could be omitted in some cases.
1702 emit(0x8F);
1703 emit_operand(0, dst);
1704}
1705
1706
1707void Assembler::popfq() {
1708 EnsureSpace ensure_space(this);
1709 last_pc_ = pc_;
1710 emit(0x9D);
1711}
1712
1713
1714void Assembler::push(Register src) {
1715 EnsureSpace ensure_space(this);
1716 last_pc_ = pc_;
1717 if (src.high_bit()) {
1718 emit_rex_64(src);
1719 }
1720 emit(0x50 | src.low_bits());
1721}
1722
1723
1724void Assembler::push(const Operand& src) {
1725 EnsureSpace ensure_space(this);
1726 last_pc_ = pc_;
1727 emit_rex_64(src); // Could be omitted in some cases.
1728 emit(0xFF);
1729 emit_operand(6, src);
1730}
1731
1732
1733void Assembler::push(Immediate value) {
1734 EnsureSpace ensure_space(this);
1735 last_pc_ = pc_;
1736 if (is_int8(value.value_)) {
1737 emit(0x6A);
1738 emit(value.value_); // Emit low byte of value.
1739 } else {
1740 emit(0x68);
1741 emitl(value.value_);
1742 }
1743}
1744
1745
1746void Assembler::pushfq() {
1747 EnsureSpace ensure_space(this);
1748 last_pc_ = pc_;
1749 emit(0x9C);
1750}
1751
1752
Steve Blocka7e24c12009-10-30 11:49:00 +00001753void Assembler::rdtsc() {
1754 EnsureSpace ensure_space(this);
1755 last_pc_ = pc_;
1756 emit(0x0F);
1757 emit(0x31);
1758}
1759
1760
1761void Assembler::ret(int imm16) {
1762 EnsureSpace ensure_space(this);
1763 last_pc_ = pc_;
1764 ASSERT(is_uint16(imm16));
1765 if (imm16 == 0) {
1766 emit(0xC3);
1767 } else {
1768 emit(0xC2);
1769 emit(imm16 & 0xFF);
1770 emit((imm16 >> 8) & 0xFF);
1771 }
1772}
1773
1774
1775void Assembler::setcc(Condition cc, Register reg) {
Steve Block3ce2e202009-11-05 08:53:23 +00001776 if (cc > last_condition) {
1777 movb(reg, Immediate(cc == always ? 1 : 0));
1778 return;
1779 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001780 EnsureSpace ensure_space(this);
1781 last_pc_ = pc_;
1782 ASSERT(is_uint4(cc));
1783 if (reg.code() > 3) { // Use x64 byte registers, where different.
1784 emit_rex_32(reg);
1785 }
1786 emit(0x0F);
1787 emit(0x90 | cc);
1788 emit_modrm(0x0, reg);
1789}
1790
1791
1792void Assembler::shld(Register dst, Register src) {
1793 EnsureSpace ensure_space(this);
1794 last_pc_ = pc_;
1795 emit_rex_64(src, dst);
1796 emit(0x0F);
1797 emit(0xA5);
1798 emit_modrm(src, dst);
1799}
1800
1801
1802void Assembler::shrd(Register dst, Register src) {
1803 EnsureSpace ensure_space(this);
1804 last_pc_ = pc_;
1805 emit_rex_64(src, dst);
1806 emit(0x0F);
1807 emit(0xAD);
1808 emit_modrm(src, dst);
1809}
1810
1811
1812void Assembler::xchg(Register dst, Register src) {
1813 EnsureSpace ensure_space(this);
1814 last_pc_ = pc_;
1815 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding
1816 Register other = src.is(rax) ? dst : src;
1817 emit_rex_64(other);
1818 emit(0x90 | other.low_bits());
1819 } else {
1820 emit_rex_64(src, dst);
1821 emit(0x87);
1822 emit_modrm(src, dst);
1823 }
1824}
1825
1826
1827void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
1828 EnsureSpace ensure_space(this);
1829 last_pc_ = pc_;
1830 emit(0x48); // REX.W
1831 emit(0xA3);
1832 emitq(reinterpret_cast<uintptr_t>(dst), mode);
1833}
1834
1835
1836void Assembler::store_rax(ExternalReference ref) {
1837 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1838}
1839
1840
Steve Block3ce2e202009-11-05 08:53:23 +00001841void Assembler::testb(Register dst, Register src) {
1842 EnsureSpace ensure_space(this);
1843 last_pc_ = pc_;
1844 if (dst.code() > 3 || src.code() > 3) {
1845 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1846 emit_rex_32(dst, src);
1847 }
1848 emit(0x84);
1849 emit_modrm(dst, src);
1850}
1851
1852
Steve Blocka7e24c12009-10-30 11:49:00 +00001853void Assembler::testb(Register reg, Immediate mask) {
1854 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
1855 EnsureSpace ensure_space(this);
1856 last_pc_ = pc_;
1857 if (reg.is(rax)) {
1858 emit(0xA8);
1859 emit(mask.value_); // Low byte emitted.
1860 } else {
1861 if (reg.code() > 3) {
1862 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1863 emit_rex_32(reg);
1864 }
1865 emit(0xF6);
1866 emit_modrm(0x0, reg);
1867 emit(mask.value_); // Low byte emitted.
1868 }
1869}
1870
1871
1872void Assembler::testb(const Operand& op, Immediate mask) {
1873 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
1874 EnsureSpace ensure_space(this);
1875 last_pc_ = pc_;
1876 emit_optional_rex_32(rax, op);
1877 emit(0xF6);
1878 emit_operand(rax, op); // Operation code 0
1879 emit(mask.value_); // Low byte emitted.
1880}
1881
1882
1883void Assembler::testl(Register dst, Register src) {
1884 EnsureSpace ensure_space(this);
1885 last_pc_ = pc_;
1886 emit_optional_rex_32(dst, src);
1887 emit(0x85);
1888 emit_modrm(dst, src);
1889}
1890
1891
1892void Assembler::testl(Register reg, Immediate mask) {
1893 // testl with a mask that fits in the low byte is exactly testb.
1894 if (is_uint8(mask.value_)) {
1895 testb(reg, mask);
1896 return;
1897 }
1898 EnsureSpace ensure_space(this);
1899 last_pc_ = pc_;
1900 if (reg.is(rax)) {
1901 emit(0xA9);
1902 emit(mask);
1903 } else {
1904 emit_optional_rex_32(rax, reg);
1905 emit(0xF7);
1906 emit_modrm(0x0, reg);
1907 emit(mask);
1908 }
1909}
1910
1911
1912void Assembler::testl(const Operand& op, Immediate mask) {
1913 // testl with a mask that fits in the low byte is exactly testb.
1914 if (is_uint8(mask.value_)) {
1915 testb(op, mask);
1916 return;
1917 }
1918 EnsureSpace ensure_space(this);
1919 last_pc_ = pc_;
1920 emit_optional_rex_32(rax, op);
1921 emit(0xF7);
1922 emit_operand(rax, op); // Operation code 0
1923 emit(mask);
1924}
1925
1926
1927void Assembler::testq(const Operand& op, Register reg) {
1928 EnsureSpace ensure_space(this);
1929 last_pc_ = pc_;
1930 emit_rex_64(reg, op);
1931 emit(0x85);
1932 emit_operand(reg, op);
1933}
1934
1935
1936void Assembler::testq(Register dst, Register src) {
1937 EnsureSpace ensure_space(this);
1938 last_pc_ = pc_;
1939 emit_rex_64(dst, src);
1940 emit(0x85);
1941 emit_modrm(dst, src);
1942}
1943
1944
1945void Assembler::testq(Register dst, Immediate mask) {
1946 EnsureSpace ensure_space(this);
1947 last_pc_ = pc_;
1948 if (dst.is(rax)) {
1949 emit_rex_64();
1950 emit(0xA9);
1951 emit(mask);
1952 } else {
1953 emit_rex_64(dst);
1954 emit(0xF7);
1955 emit_modrm(0, dst);
1956 emit(mask);
1957 }
1958}
1959
1960
1961// FPU instructions
1962
1963
1964void Assembler::fld(int i) {
1965 EnsureSpace ensure_space(this);
1966 last_pc_ = pc_;
1967 emit_farith(0xD9, 0xC0, i);
1968}
1969
1970
1971void Assembler::fld1() {
1972 EnsureSpace ensure_space(this);
1973 last_pc_ = pc_;
1974 emit(0xD9);
1975 emit(0xE8);
1976}
1977
1978
1979void Assembler::fldz() {
1980 EnsureSpace ensure_space(this);
1981 last_pc_ = pc_;
1982 emit(0xD9);
1983 emit(0xEE);
1984}
1985
1986
1987void Assembler::fld_s(const Operand& adr) {
1988 EnsureSpace ensure_space(this);
1989 last_pc_ = pc_;
1990 emit_optional_rex_32(adr);
1991 emit(0xD9);
1992 emit_operand(0, adr);
1993}
1994
1995
1996void Assembler::fld_d(const Operand& adr) {
1997 EnsureSpace ensure_space(this);
1998 last_pc_ = pc_;
1999 emit_optional_rex_32(adr);
2000 emit(0xDD);
2001 emit_operand(0, adr);
2002}
2003
2004
2005void Assembler::fstp_s(const Operand& adr) {
2006 EnsureSpace ensure_space(this);
2007 last_pc_ = pc_;
2008 emit_optional_rex_32(adr);
2009 emit(0xD9);
2010 emit_operand(3, adr);
2011}
2012
2013
2014void Assembler::fstp_d(const Operand& adr) {
2015 EnsureSpace ensure_space(this);
2016 last_pc_ = pc_;
2017 emit_optional_rex_32(adr);
2018 emit(0xDD);
2019 emit_operand(3, adr);
2020}
2021
2022
Steve Block3ce2e202009-11-05 08:53:23 +00002023void Assembler::fstp(int index) {
2024 ASSERT(is_uint3(index));
2025 EnsureSpace ensure_space(this);
2026 last_pc_ = pc_;
2027 emit_farith(0xDD, 0xD8, index);
2028}
2029
2030
Steve Blocka7e24c12009-10-30 11:49:00 +00002031void Assembler::fild_s(const Operand& adr) {
2032 EnsureSpace ensure_space(this);
2033 last_pc_ = pc_;
2034 emit_optional_rex_32(adr);
2035 emit(0xDB);
2036 emit_operand(0, adr);
2037}
2038
2039
2040void Assembler::fild_d(const Operand& adr) {
2041 EnsureSpace ensure_space(this);
2042 last_pc_ = pc_;
2043 emit_optional_rex_32(adr);
2044 emit(0xDF);
2045 emit_operand(5, adr);
2046}
2047
2048
2049void Assembler::fistp_s(const Operand& adr) {
2050 EnsureSpace ensure_space(this);
2051 last_pc_ = pc_;
2052 emit_optional_rex_32(adr);
2053 emit(0xDB);
2054 emit_operand(3, adr);
2055}
2056
2057
2058void Assembler::fisttp_s(const Operand& adr) {
Steve Blockd0582a62009-12-15 09:54:21 +00002059 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00002060 EnsureSpace ensure_space(this);
2061 last_pc_ = pc_;
2062 emit_optional_rex_32(adr);
2063 emit(0xDB);
2064 emit_operand(1, adr);
2065}
2066
2067
2068void Assembler::fist_s(const Operand& adr) {
2069 EnsureSpace ensure_space(this);
2070 last_pc_ = pc_;
2071 emit_optional_rex_32(adr);
2072 emit(0xDB);
2073 emit_operand(2, adr);
2074}
2075
2076
2077void Assembler::fistp_d(const Operand& adr) {
2078 EnsureSpace ensure_space(this);
2079 last_pc_ = pc_;
2080 emit_optional_rex_32(adr);
2081 emit(0xDF);
Steve Block3ce2e202009-11-05 08:53:23 +00002082 emit_operand(7, adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002083}
2084
2085
2086void Assembler::fabs() {
2087 EnsureSpace ensure_space(this);
2088 last_pc_ = pc_;
2089 emit(0xD9);
2090 emit(0xE1);
2091}
2092
2093
2094void Assembler::fchs() {
2095 EnsureSpace ensure_space(this);
2096 last_pc_ = pc_;
2097 emit(0xD9);
2098 emit(0xE0);
2099}
2100
2101
2102void Assembler::fcos() {
2103 EnsureSpace ensure_space(this);
2104 last_pc_ = pc_;
2105 emit(0xD9);
2106 emit(0xFF);
2107}
2108
2109
2110void Assembler::fsin() {
2111 EnsureSpace ensure_space(this);
2112 last_pc_ = pc_;
2113 emit(0xD9);
2114 emit(0xFE);
2115}
2116
2117
2118void Assembler::fadd(int i) {
2119 EnsureSpace ensure_space(this);
2120 last_pc_ = pc_;
2121 emit_farith(0xDC, 0xC0, i);
2122}
2123
2124
2125void Assembler::fsub(int i) {
2126 EnsureSpace ensure_space(this);
2127 last_pc_ = pc_;
2128 emit_farith(0xDC, 0xE8, i);
2129}
2130
2131
2132void Assembler::fisub_s(const Operand& adr) {
2133 EnsureSpace ensure_space(this);
2134 last_pc_ = pc_;
2135 emit_optional_rex_32(adr);
2136 emit(0xDA);
2137 emit_operand(4, adr);
2138}
2139
2140
2141void Assembler::fmul(int i) {
2142 EnsureSpace ensure_space(this);
2143 last_pc_ = pc_;
2144 emit_farith(0xDC, 0xC8, i);
2145}
2146
2147
2148void Assembler::fdiv(int i) {
2149 EnsureSpace ensure_space(this);
2150 last_pc_ = pc_;
2151 emit_farith(0xDC, 0xF8, i);
2152}
2153
2154
2155void Assembler::faddp(int i) {
2156 EnsureSpace ensure_space(this);
2157 last_pc_ = pc_;
2158 emit_farith(0xDE, 0xC0, i);
2159}
2160
2161
2162void Assembler::fsubp(int i) {
2163 EnsureSpace ensure_space(this);
2164 last_pc_ = pc_;
2165 emit_farith(0xDE, 0xE8, i);
2166}
2167
2168
2169void Assembler::fsubrp(int i) {
2170 EnsureSpace ensure_space(this);
2171 last_pc_ = pc_;
2172 emit_farith(0xDE, 0xE0, i);
2173}
2174
2175
2176void Assembler::fmulp(int i) {
2177 EnsureSpace ensure_space(this);
2178 last_pc_ = pc_;
2179 emit_farith(0xDE, 0xC8, i);
2180}
2181
2182
2183void Assembler::fdivp(int i) {
2184 EnsureSpace ensure_space(this);
2185 last_pc_ = pc_;
2186 emit_farith(0xDE, 0xF8, i);
2187}
2188
2189
2190void Assembler::fprem() {
2191 EnsureSpace ensure_space(this);
2192 last_pc_ = pc_;
2193 emit(0xD9);
2194 emit(0xF8);
2195}
2196
2197
2198void Assembler::fprem1() {
2199 EnsureSpace ensure_space(this);
2200 last_pc_ = pc_;
2201 emit(0xD9);
2202 emit(0xF5);
2203}
2204
2205
2206void Assembler::fxch(int i) {
2207 EnsureSpace ensure_space(this);
2208 last_pc_ = pc_;
2209 emit_farith(0xD9, 0xC8, i);
2210}
2211
2212
2213void Assembler::fincstp() {
2214 EnsureSpace ensure_space(this);
2215 last_pc_ = pc_;
2216 emit(0xD9);
2217 emit(0xF7);
2218}
2219
2220
2221void Assembler::ffree(int i) {
2222 EnsureSpace ensure_space(this);
2223 last_pc_ = pc_;
2224 emit_farith(0xDD, 0xC0, i);
2225}
2226
2227
2228void Assembler::ftst() {
2229 EnsureSpace ensure_space(this);
2230 last_pc_ = pc_;
2231 emit(0xD9);
2232 emit(0xE4);
2233}
2234
2235
2236void Assembler::fucomp(int i) {
2237 EnsureSpace ensure_space(this);
2238 last_pc_ = pc_;
2239 emit_farith(0xDD, 0xE8, i);
2240}
2241
2242
2243void Assembler::fucompp() {
2244 EnsureSpace ensure_space(this);
2245 last_pc_ = pc_;
2246 emit(0xDA);
2247 emit(0xE9);
2248}
2249
2250
Steve Block3ce2e202009-11-05 08:53:23 +00002251void Assembler::fucomi(int i) {
2252 EnsureSpace ensure_space(this);
2253 last_pc_ = pc_;
2254 emit(0xDB);
2255 emit(0xE8 + i);
2256}
2257
2258
2259void Assembler::fucomip() {
2260 EnsureSpace ensure_space(this);
2261 last_pc_ = pc_;
2262 emit(0xDF);
2263 emit(0xE9);
2264}
2265
2266
Steve Blocka7e24c12009-10-30 11:49:00 +00002267void Assembler::fcompp() {
2268 EnsureSpace ensure_space(this);
2269 last_pc_ = pc_;
2270 emit(0xDE);
2271 emit(0xD9);
2272}
2273
2274
2275void Assembler::fnstsw_ax() {
2276 EnsureSpace ensure_space(this);
2277 last_pc_ = pc_;
2278 emit(0xDF);
2279 emit(0xE0);
2280}
2281
2282
2283void Assembler::fwait() {
2284 EnsureSpace ensure_space(this);
2285 last_pc_ = pc_;
2286 emit(0x9B);
2287}
2288
2289
2290void Assembler::frndint() {
2291 EnsureSpace ensure_space(this);
2292 last_pc_ = pc_;
2293 emit(0xD9);
2294 emit(0xFC);
2295}
2296
2297
2298void Assembler::fnclex() {
2299 EnsureSpace ensure_space(this);
2300 last_pc_ = pc_;
2301 emit(0xDB);
2302 emit(0xE2);
2303}
2304
2305
2306void Assembler::sahf() {
2307 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2308 // in 64-bit mode. Test CpuID.
2309 EnsureSpace ensure_space(this);
2310 last_pc_ = pc_;
2311 emit(0x9E);
2312}
2313
2314
2315void Assembler::emit_farith(int b1, int b2, int i) {
2316 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2317 ASSERT(is_uint3(i)); // illegal stack offset
2318 emit(b1);
2319 emit(b2 + i);
2320}
2321
2322// SSE 2 operations
2323
2324void Assembler::movsd(const Operand& dst, XMMRegister src) {
2325 EnsureSpace ensure_space(this);
2326 last_pc_ = pc_;
2327 emit(0xF2); // double
2328 emit_optional_rex_32(src, dst);
2329 emit(0x0F);
2330 emit(0x11); // store
2331 emit_sse_operand(src, dst);
2332}
2333
2334
Steve Block3ce2e202009-11-05 08:53:23 +00002335void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002336 EnsureSpace ensure_space(this);
2337 last_pc_ = pc_;
2338 emit(0xF2); // double
2339 emit_optional_rex_32(dst, src);
2340 emit(0x0F);
2341 emit(0x10); // load
2342 emit_sse_operand(dst, src);
2343}
2344
2345
2346void Assembler::movsd(XMMRegister dst, const Operand& src) {
2347 EnsureSpace ensure_space(this);
2348 last_pc_ = pc_;
2349 emit(0xF2); // double
2350 emit_optional_rex_32(dst, src);
2351 emit(0x0F);
2352 emit(0x10); // load
2353 emit_sse_operand(dst, src);
2354}
2355
2356
2357void Assembler::cvttss2si(Register dst, const Operand& src) {
2358 EnsureSpace ensure_space(this);
2359 last_pc_ = pc_;
2360 emit(0xF3);
2361 emit_optional_rex_32(dst, src);
2362 emit(0x0F);
2363 emit(0x2C);
2364 emit_operand(dst, src);
2365}
2366
2367
2368void Assembler::cvttsd2si(Register dst, const Operand& src) {
2369 EnsureSpace ensure_space(this);
2370 last_pc_ = pc_;
2371 emit(0xF2);
2372 emit_optional_rex_32(dst, src);
2373 emit(0x0F);
2374 emit(0x2C);
2375 emit_operand(dst, src);
2376}
2377
2378
2379void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
2380 EnsureSpace ensure_space(this);
2381 last_pc_ = pc_;
2382 emit(0xF2);
2383 emit_optional_rex_32(dst, src);
2384 emit(0x0F);
2385 emit(0x2A);
2386 emit_sse_operand(dst, src);
2387}
2388
2389
2390void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
2391 EnsureSpace ensure_space(this);
2392 last_pc_ = pc_;
2393 emit(0xF2);
2394 emit_optional_rex_32(dst, src);
2395 emit(0x0F);
2396 emit(0x2A);
2397 emit_sse_operand(dst, src);
2398}
2399
2400
2401void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
2402 EnsureSpace ensure_space(this);
2403 last_pc_ = pc_;
2404 emit(0xF2);
2405 emit_rex_64(dst, src);
2406 emit(0x0F);
2407 emit(0x2A);
2408 emit_sse_operand(dst, src);
2409}
2410
2411
2412void Assembler::addsd(XMMRegister dst, XMMRegister src) {
2413 EnsureSpace ensure_space(this);
2414 last_pc_ = pc_;
2415 emit(0xF2);
2416 emit_optional_rex_32(dst, src);
2417 emit(0x0F);
2418 emit(0x58);
2419 emit_sse_operand(dst, src);
2420}
2421
2422
2423void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
2424 EnsureSpace ensure_space(this);
2425 last_pc_ = pc_;
2426 emit(0xF2);
2427 emit_optional_rex_32(dst, src);
2428 emit(0x0F);
2429 emit(0x59);
2430 emit_sse_operand(dst, src);
2431}
2432
2433
2434void Assembler::subsd(XMMRegister dst, XMMRegister src) {
2435 EnsureSpace ensure_space(this);
2436 last_pc_ = pc_;
2437 emit(0xF2);
2438 emit_optional_rex_32(dst, src);
2439 emit(0x0F);
2440 emit(0x5C);
2441 emit_sse_operand(dst, src);
2442}
2443
2444
2445void Assembler::divsd(XMMRegister dst, XMMRegister src) {
2446 EnsureSpace ensure_space(this);
2447 last_pc_ = pc_;
2448 emit(0xF2);
2449 emit_optional_rex_32(dst, src);
2450 emit(0x0F);
2451 emit(0x5E);
2452 emit_sse_operand(dst, src);
2453}
2454
2455
2456
2457void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2458 Register ireg = { reg.code() };
2459 emit_operand(ireg, adr);
2460}
2461
2462
2463void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2464 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2465}
2466
2467void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
2468 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2469}
2470
2471
2472// Relocation information implementations
2473
2474void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2475 ASSERT(rmode != RelocInfo::NONE);
2476 // Don't record external references unless the heap will be serialized.
2477 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2478 !Serializer::enabled() &&
2479 !FLAG_debug_code) {
2480 return;
2481 }
2482 RelocInfo rinfo(pc_, rmode, data);
2483 reloc_info_writer.Write(&rinfo);
2484}
2485
2486void Assembler::RecordJSReturn() {
2487 WriteRecordedPositions();
2488 EnsureSpace ensure_space(this);
2489 RecordRelocInfo(RelocInfo::JS_RETURN);
2490}
2491
2492
2493void Assembler::RecordComment(const char* msg) {
2494 if (FLAG_debug_code) {
2495 EnsureSpace ensure_space(this);
2496 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2497 }
2498}
2499
2500
2501void Assembler::RecordPosition(int pos) {
2502 ASSERT(pos != RelocInfo::kNoPosition);
2503 ASSERT(pos >= 0);
2504 current_position_ = pos;
2505}
2506
2507
2508void Assembler::RecordStatementPosition(int pos) {
2509 ASSERT(pos != RelocInfo::kNoPosition);
2510 ASSERT(pos >= 0);
2511 current_statement_position_ = pos;
2512}
2513
2514
2515void Assembler::WriteRecordedPositions() {
2516 // Write the statement position if it is different from what was written last
2517 // time.
2518 if (current_statement_position_ != written_statement_position_) {
2519 EnsureSpace ensure_space(this);
2520 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
2521 written_statement_position_ = current_statement_position_;
2522 }
2523
2524 // Write the position if it is different from what was written last time and
2525 // also different from the written statement position.
2526 if (current_position_ != written_position_ &&
2527 current_position_ != written_statement_position_) {
2528 EnsureSpace ensure_space(this);
2529 RecordRelocInfo(RelocInfo::POSITION, current_position_);
2530 written_position_ = current_position_;
2531 }
2532}
2533
2534
Steve Block3ce2e202009-11-05 08:53:23 +00002535const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
2536 1 << RelocInfo::INTERNAL_REFERENCE |
2537 1 << RelocInfo::JS_RETURN;
Steve Blocka7e24c12009-10-30 11:49:00 +00002538
2539} } // namespace v8::internal