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