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