1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the
16 // - Neither the name of Sun Microsystems or the names of contributors may
17 // be used to endorse or promote products derived from this software without
18 // specific prior written permission.
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
33 // The original source code covered by the above license above has been modified
34 // significantly by Google Inc.
35 // Copyright 2012 the V8 project authors. All rights reserved.
39 #if V8_TARGET_ARCH_IA32
41 #include "src/base/cpu.h"
42 #include "src/disassembler.h"
43 #include "src/macro-assembler.h"
44 #include "src/serialize.h"
49 // -----------------------------------------------------------------------------
50 // Implementation of CpuFeatures
52 void CpuFeatures::ProbeImpl(bool cross_compile) {
54 CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
55 CHECK(cpu.has_cmov()); // CMOV support is mandatory.
57 // Only use statically determined features for cross compile (snapshot).
58 if (cross_compile) return;
60 if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1;
61 if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
65 void CpuFeatures::PrintTarget() { }
66 void CpuFeatures::PrintFeatures() { }
69 // -----------------------------------------------------------------------------
70 // Implementation of Displacement
72 void Displacement::init(Label* L, Type type) {
73 DCHECK(!L->is_bound());
77 DCHECK(next > 0); // Displacements must be at positions > 0
79 // Ensure that we _never_ overflow the next field.
80 DCHECK(NextField::is_valid(Assembler::kMaximalBufferSize));
81 data_ = NextField::encode(next) | TypeField::encode(type);
85 // -----------------------------------------------------------------------------
86 // Implementation of RelocInfo
89 const int RelocInfo::kApplyMask =
90 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
91 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
92 1 << RelocInfo::DEBUG_BREAK_SLOT | 1 << RelocInfo::CODE_AGE_SEQUENCE;
95 bool RelocInfo::IsCodedSpecially() {
96 // The deserializer needs to know whether a pointer is specially coded. Being
97 // specially coded on IA32 means that it is a relative address, as used by
98 // branch instructions. These are also the ones that need changing when a
100 return (1 << rmode_) & kApplyMask;
104 bool RelocInfo::IsInConstantPool() {
109 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
110 // Patch the code at the current address with the supplied instructions.
111 for (int i = 0; i < instruction_count; i++) {
112 *(pc_ + i) = *(instructions + i);
115 // Indicate that code has changed.
116 CpuFeatures::FlushICache(pc_, instruction_count);
120 // Patch the code at the current PC with a call to the target address.
121 // Additional guard int3 instructions can be added if required.
122 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
123 // Call instruction takes up 5 bytes and int3 takes up one byte.
124 static const int kCallCodeSize = 5;
125 int code_size = kCallCodeSize + guard_bytes;
127 // Create a code patcher.
128 CodePatcher patcher(pc_, code_size);
130 // Add a label for checking the size of the code used for returning.
132 Label check_codesize;
133 patcher.masm()->bind(&check_codesize);
137 patcher.masm()->call(target, RelocInfo::NONE32);
139 // Check that the size of the code generated is as expected.
140 DCHECK_EQ(kCallCodeSize,
141 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
143 // Add the requested number of int3 instructions after the call.
144 DCHECK_GE(guard_bytes, 0);
145 for (int i = 0; i < guard_bytes; i++) {
146 patcher.masm()->int3();
151 // -----------------------------------------------------------------------------
152 // Implementation of Operand
154 Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
156 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
159 if (base.is(esp)) set_sib(times_1, esp, base);
160 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
163 if (base.is(esp)) set_sib(times_1, esp, base);
168 if (base.is(esp)) set_sib(times_1, esp, base);
169 set_dispr(disp, rmode);
174 Operand::Operand(Register base,
178 RelocInfo::Mode rmode) {
179 DCHECK(!index.is(esp)); // illegal addressing mode
180 // [base + index*scale + disp/r]
181 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
182 // [base + index*scale]
184 set_sib(scale, index, base);
185 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
186 // [base + index*scale + disp8]
188 set_sib(scale, index, base);
191 // [base + index*scale + disp/r]
193 set_sib(scale, index, base);
194 set_dispr(disp, rmode);
199 Operand::Operand(Register index,
202 RelocInfo::Mode rmode) {
203 DCHECK(!index.is(esp)); // illegal addressing mode
204 // [index*scale + disp/r]
206 set_sib(scale, index, ebp);
207 set_dispr(disp, rmode);
211 Operand::Operand(const Operand& operand, int32_t offset) {
212 DCHECK(operand.len_ >= 1);
213 // Operand encodes REX ModR/M [SIB] [Disp].
214 byte modrm = operand.buf_[0];
215 DCHECK(modrm < 0xC0); // Disallow mode 3 (register target).
216 bool has_sib = ((modrm & 0x07) == 0x04);
217 byte mode = modrm & 0xC0;
218 int disp_offset = has_sib ? 2 : 1;
219 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
220 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
222 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
223 int32_t disp_value = 0;
224 if (mode == 0x80 || is_baseless) {
225 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
226 disp_value = *BitCast<const int32_t*>(&operand.buf_[disp_offset]);
227 } else if (mode == 0x40) {
228 // Mode 1: Byte displacement.
229 disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
232 // Write new operand with same registers, but with modified displacement.
233 DCHECK(offset >= 0 ? disp_value + offset >= disp_value
234 : disp_value + offset < disp_value); // No overflow.
235 disp_value += offset;
236 if (!is_int8(disp_value) || is_baseless) {
237 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
238 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
239 len_ = disp_offset + 4;
240 Memory::int32_at(&buf_[disp_offset]) = disp_value;
241 } else if (disp_value != 0 || (base_reg == 0x05)) {
242 // Need 8 bits of displacement.
243 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
244 len_ = disp_offset + 1;
245 buf_[disp_offset] = static_cast<byte>(disp_value);
247 // Need no displacement.
248 buf_[0] = (modrm & 0x3f); // Mode 0.
252 buf_[1] = operand.buf_[1];
257 bool Operand::is_reg(Register reg) const {
258 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
259 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
263 bool Operand::is_reg_only() const {
264 return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only.
268 Register Operand::reg() const {
269 DCHECK(is_reg_only());
270 return Register::from_code(buf_[0] & 0x07);
274 // -----------------------------------------------------------------------------
275 // Implementation of Assembler.
277 // Emit a single byte. Must always be inlined.
282 #ifdef GENERATED_CODE_COVERAGE
283 static void InitCoverageLog();
286 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
287 : AssemblerBase(isolate, buffer, buffer_size),
288 positions_recorder_(this) {
289 // Clear the buffer in debug mode unless it was provided by the
290 // caller in which case we can't be sure it's okay to overwrite
291 // existing code in it; see CodePatcher::CodePatcher(...).
294 memset(buffer_, 0xCC, buffer_size_); // int3
298 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
300 #ifdef GENERATED_CODE_COVERAGE
306 void Assembler::GetCode(CodeDesc* desc) {
307 // Finalize code (at this point overflow() may be true, but the gap ensures
308 // that we are still not overlapping instructions and relocation info).
309 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
310 // Set up code descriptor.
311 desc->buffer = buffer_;
312 desc->buffer_size = buffer_size_;
313 desc->instr_size = pc_offset();
314 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
319 void Assembler::Align(int m) {
320 DCHECK(IsPowerOf2(m));
322 int addr = pc_offset();
323 Nop((m - (addr & mask)) & mask);
327 bool Assembler::IsNop(Address addr) {
329 while (*a == 0x66) a++;
330 if (*a == 0x90) return true;
331 if (a[0] == 0xf && a[1] == 0x1f) return true;
336 void Assembler::Nop(int bytes) {
337 EnsureSpace ensure_space(this);
339 // Multi byte nops from http://support.amd.com/us/Processor_TechDocs/40546.pdf
401 void Assembler::CodeTargetAlign() {
402 Align(16); // Preferred alignment of jump targets on ia32.
406 void Assembler::cpuid() {
407 EnsureSpace ensure_space(this);
413 void Assembler::pushad() {
414 EnsureSpace ensure_space(this);
419 void Assembler::popad() {
420 EnsureSpace ensure_space(this);
425 void Assembler::pushfd() {
426 EnsureSpace ensure_space(this);
431 void Assembler::popfd() {
432 EnsureSpace ensure_space(this);
437 void Assembler::push(const Immediate& x) {
438 EnsureSpace ensure_space(this);
449 void Assembler::push_imm32(int32_t imm32) {
450 EnsureSpace ensure_space(this);
456 void Assembler::push(Register src) {
457 EnsureSpace ensure_space(this);
458 EMIT(0x50 | src.code());
462 void Assembler::push(const Operand& src) {
463 EnsureSpace ensure_space(this);
465 emit_operand(esi, src);
469 void Assembler::pop(Register dst) {
470 DCHECK(reloc_info_writer.last_pc() != NULL);
471 EnsureSpace ensure_space(this);
472 EMIT(0x58 | dst.code());
476 void Assembler::pop(const Operand& dst) {
477 EnsureSpace ensure_space(this);
479 emit_operand(eax, dst);
483 void Assembler::enter(const Immediate& size) {
484 EnsureSpace ensure_space(this);
491 void Assembler::leave() {
492 EnsureSpace ensure_space(this);
497 void Assembler::mov_b(Register dst, const Operand& src) {
498 CHECK(dst.is_byte_register());
499 EnsureSpace ensure_space(this);
501 emit_operand(dst, src);
505 void Assembler::mov_b(const Operand& dst, int8_t imm8) {
506 EnsureSpace ensure_space(this);
508 emit_operand(eax, dst);
513 void Assembler::mov_b(const Operand& dst, Register src) {
514 CHECK(src.is_byte_register());
515 EnsureSpace ensure_space(this);
517 emit_operand(src, dst);
521 void Assembler::mov_w(Register dst, const Operand& src) {
522 EnsureSpace ensure_space(this);
525 emit_operand(dst, src);
529 void Assembler::mov_w(const Operand& dst, Register src) {
530 EnsureSpace ensure_space(this);
533 emit_operand(src, dst);
537 void Assembler::mov_w(const Operand& dst, int16_t imm16) {
538 EnsureSpace ensure_space(this);
541 emit_operand(eax, dst);
542 EMIT(static_cast<int8_t>(imm16 & 0xff));
543 EMIT(static_cast<int8_t>(imm16 >> 8));
547 void Assembler::mov(Register dst, int32_t imm32) {
548 EnsureSpace ensure_space(this);
549 EMIT(0xB8 | dst.code());
554 void Assembler::mov(Register dst, const Immediate& x) {
555 EnsureSpace ensure_space(this);
556 EMIT(0xB8 | dst.code());
561 void Assembler::mov(Register dst, Handle<Object> handle) {
562 EnsureSpace ensure_space(this);
563 EMIT(0xB8 | dst.code());
568 void Assembler::mov(Register dst, const Operand& src) {
569 EnsureSpace ensure_space(this);
571 emit_operand(dst, src);
575 void Assembler::mov(Register dst, Register src) {
576 EnsureSpace ensure_space(this);
578 EMIT(0xC0 | src.code() << 3 | dst.code());
582 void Assembler::mov(const Operand& dst, const Immediate& x) {
583 EnsureSpace ensure_space(this);
585 emit_operand(eax, dst);
590 void Assembler::mov(const Operand& dst, Handle<Object> handle) {
591 EnsureSpace ensure_space(this);
593 emit_operand(eax, dst);
598 void Assembler::mov(const Operand& dst, Register src) {
599 EnsureSpace ensure_space(this);
601 emit_operand(src, dst);
605 void Assembler::movsx_b(Register dst, const Operand& src) {
606 EnsureSpace ensure_space(this);
609 emit_operand(dst, src);
613 void Assembler::movsx_w(Register dst, const Operand& src) {
614 EnsureSpace ensure_space(this);
617 emit_operand(dst, src);
621 void Assembler::movzx_b(Register dst, const Operand& src) {
622 EnsureSpace ensure_space(this);
625 emit_operand(dst, src);
629 void Assembler::movzx_w(Register dst, const Operand& src) {
630 EnsureSpace ensure_space(this);
633 emit_operand(dst, src);
637 void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
638 EnsureSpace ensure_space(this);
639 // Opcode: 0f 40 + cc /r.
642 emit_operand(dst, src);
646 void Assembler::cld() {
647 EnsureSpace ensure_space(this);
652 void Assembler::rep_movs() {
653 EnsureSpace ensure_space(this);
659 void Assembler::rep_stos() {
660 EnsureSpace ensure_space(this);
666 void Assembler::stos() {
667 EnsureSpace ensure_space(this);
672 void Assembler::xchg(Register dst, Register src) {
673 EnsureSpace ensure_space(this);
674 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
675 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
678 EMIT(0xC0 | src.code() << 3 | dst.code());
683 void Assembler::xchg(Register dst, const Operand& src) {
684 EnsureSpace ensure_space(this);
686 emit_operand(dst, src);
690 void Assembler::adc(Register dst, int32_t imm32) {
691 EnsureSpace ensure_space(this);
692 emit_arith(2, Operand(dst), Immediate(imm32));
696 void Assembler::adc(Register dst, const Operand& src) {
697 EnsureSpace ensure_space(this);
699 emit_operand(dst, src);
703 void Assembler::add(Register dst, const Operand& src) {
704 EnsureSpace ensure_space(this);
706 emit_operand(dst, src);
710 void Assembler::add(const Operand& dst, Register src) {
711 EnsureSpace ensure_space(this);
713 emit_operand(src, dst);
717 void Assembler::add(const Operand& dst, const Immediate& x) {
718 DCHECK(reloc_info_writer.last_pc() != NULL);
719 EnsureSpace ensure_space(this);
720 emit_arith(0, dst, x);
724 void Assembler::and_(Register dst, int32_t imm32) {
725 and_(dst, Immediate(imm32));
729 void Assembler::and_(Register dst, const Immediate& x) {
730 EnsureSpace ensure_space(this);
731 emit_arith(4, Operand(dst), x);
735 void Assembler::and_(Register dst, const Operand& src) {
736 EnsureSpace ensure_space(this);
738 emit_operand(dst, src);
742 void Assembler::and_(const Operand& dst, const Immediate& x) {
743 EnsureSpace ensure_space(this);
744 emit_arith(4, dst, x);
748 void Assembler::and_(const Operand& dst, Register src) {
749 EnsureSpace ensure_space(this);
751 emit_operand(src, dst);
755 void Assembler::cmpb(const Operand& op, int8_t imm8) {
756 EnsureSpace ensure_space(this);
757 if (op.is_reg(eax)) {
761 emit_operand(edi, op); // edi == 7
767 void Assembler::cmpb(const Operand& op, Register reg) {
768 CHECK(reg.is_byte_register());
769 EnsureSpace ensure_space(this);
771 emit_operand(reg, op);
775 void Assembler::cmpb(Register reg, const Operand& op) {
776 CHECK(reg.is_byte_register());
777 EnsureSpace ensure_space(this);
779 emit_operand(reg, op);
783 void Assembler::cmpw(const Operand& op, Immediate imm16) {
784 DCHECK(imm16.is_int16());
785 EnsureSpace ensure_space(this);
788 emit_operand(edi, op);
793 void Assembler::cmp(Register reg, int32_t imm32) {
794 EnsureSpace ensure_space(this);
795 emit_arith(7, Operand(reg), Immediate(imm32));
799 void Assembler::cmp(Register reg, Handle<Object> handle) {
800 EnsureSpace ensure_space(this);
801 emit_arith(7, Operand(reg), Immediate(handle));
805 void Assembler::cmp(Register reg, const Operand& op) {
806 EnsureSpace ensure_space(this);
808 emit_operand(reg, op);
812 void Assembler::cmp(const Operand& op, const Immediate& imm) {
813 EnsureSpace ensure_space(this);
814 emit_arith(7, op, imm);
818 void Assembler::cmp(const Operand& op, Handle<Object> handle) {
819 EnsureSpace ensure_space(this);
820 emit_arith(7, op, Immediate(handle));
824 void Assembler::cmpb_al(const Operand& op) {
825 EnsureSpace ensure_space(this);
826 EMIT(0x38); // CMP r/m8, r8
827 emit_operand(eax, op); // eax has same code as register al.
831 void Assembler::cmpw_ax(const Operand& op) {
832 EnsureSpace ensure_space(this);
834 EMIT(0x39); // CMP r/m16, r16
835 emit_operand(eax, op); // eax has same code as register ax.
839 void Assembler::dec_b(Register dst) {
840 CHECK(dst.is_byte_register());
841 EnsureSpace ensure_space(this);
843 EMIT(0xC8 | dst.code());
847 void Assembler::dec_b(const Operand& dst) {
848 EnsureSpace ensure_space(this);
850 emit_operand(ecx, dst);
854 void Assembler::dec(Register dst) {
855 EnsureSpace ensure_space(this);
856 EMIT(0x48 | dst.code());
860 void Assembler::dec(const Operand& dst) {
861 EnsureSpace ensure_space(this);
863 emit_operand(ecx, dst);
867 void Assembler::cdq() {
868 EnsureSpace ensure_space(this);
873 void Assembler::idiv(const Operand& src) {
874 EnsureSpace ensure_space(this);
876 emit_operand(edi, src);
880 void Assembler::div(const Operand& src) {
881 EnsureSpace ensure_space(this);
883 emit_operand(esi, src);
887 void Assembler::imul(Register reg) {
888 EnsureSpace ensure_space(this);
890 EMIT(0xE8 | reg.code());
894 void Assembler::imul(Register dst, const Operand& src) {
895 EnsureSpace ensure_space(this);
898 emit_operand(dst, src);
902 void Assembler::imul(Register dst, Register src, int32_t imm32) {
903 imul(dst, Operand(src), imm32);
907 void Assembler::imul(Register dst, const Operand& src, int32_t imm32) {
908 EnsureSpace ensure_space(this);
909 if (is_int8(imm32)) {
911 emit_operand(dst, src);
915 emit_operand(dst, src);
921 void Assembler::inc(Register dst) {
922 EnsureSpace ensure_space(this);
923 EMIT(0x40 | dst.code());
927 void Assembler::inc(const Operand& dst) {
928 EnsureSpace ensure_space(this);
930 emit_operand(eax, dst);
934 void Assembler::lea(Register dst, const Operand& src) {
935 EnsureSpace ensure_space(this);
937 emit_operand(dst, src);
941 void Assembler::mul(Register src) {
942 EnsureSpace ensure_space(this);
944 EMIT(0xE0 | src.code());
948 void Assembler::neg(Register dst) {
949 EnsureSpace ensure_space(this);
951 EMIT(0xD8 | dst.code());
955 void Assembler::neg(const Operand& dst) {
956 EnsureSpace ensure_space(this);
958 emit_operand(ebx, dst);
962 void Assembler::not_(Register dst) {
963 EnsureSpace ensure_space(this);
965 EMIT(0xD0 | dst.code());
969 void Assembler::not_(const Operand& dst) {
970 EnsureSpace ensure_space(this);
972 emit_operand(edx, dst);
976 void Assembler::or_(Register dst, int32_t imm32) {
977 EnsureSpace ensure_space(this);
978 emit_arith(1, Operand(dst), Immediate(imm32));
982 void Assembler::or_(Register dst, const Operand& src) {
983 EnsureSpace ensure_space(this);
985 emit_operand(dst, src);
989 void Assembler::or_(const Operand& dst, const Immediate& x) {
990 EnsureSpace ensure_space(this);
991 emit_arith(1, dst, x);
995 void Assembler::or_(const Operand& dst, Register src) {
996 EnsureSpace ensure_space(this);
998 emit_operand(src, dst);
1002 void Assembler::rcl(Register dst, uint8_t imm8) {
1003 EnsureSpace ensure_space(this);
1004 DCHECK(is_uint5(imm8)); // illegal shift count
1007 EMIT(0xD0 | dst.code());
1010 EMIT(0xD0 | dst.code());
1016 void Assembler::rcr(Register dst, uint8_t imm8) {
1017 EnsureSpace ensure_space(this);
1018 DCHECK(is_uint5(imm8)); // illegal shift count
1021 EMIT(0xD8 | dst.code());
1024 EMIT(0xD8 | dst.code());
1030 void Assembler::ror(Register dst, uint8_t imm8) {
1031 EnsureSpace ensure_space(this);
1032 DCHECK(is_uint5(imm8)); // illegal shift count
1035 EMIT(0xC8 | dst.code());
1038 EMIT(0xC8 | dst.code());
1044 void Assembler::ror_cl(Register dst) {
1045 EnsureSpace ensure_space(this);
1047 EMIT(0xC8 | dst.code());
1051 void Assembler::sar(const Operand& dst, uint8_t imm8) {
1052 EnsureSpace ensure_space(this);
1053 DCHECK(is_uint5(imm8)); // illegal shift count
1056 emit_operand(edi, dst);
1059 emit_operand(edi, dst);
1065 void Assembler::sar_cl(const Operand& dst) {
1066 EnsureSpace ensure_space(this);
1068 emit_operand(edi, dst);
1072 void Assembler::sbb(Register dst, const Operand& src) {
1073 EnsureSpace ensure_space(this);
1075 emit_operand(dst, src);
1079 void Assembler::shld(Register dst, const Operand& src) {
1080 EnsureSpace ensure_space(this);
1083 emit_operand(dst, src);
1087 void Assembler::shl(const Operand& dst, uint8_t imm8) {
1088 EnsureSpace ensure_space(this);
1089 DCHECK(is_uint5(imm8)); // illegal shift count
1092 emit_operand(esp, dst);
1095 emit_operand(esp, dst);
1101 void Assembler::shl_cl(const Operand& dst) {
1102 EnsureSpace ensure_space(this);
1104 emit_operand(esp, dst);
1108 void Assembler::shrd(Register dst, const Operand& src) {
1109 EnsureSpace ensure_space(this);
1112 emit_operand(dst, src);
1116 void Assembler::shr(const Operand& dst, uint8_t imm8) {
1117 EnsureSpace ensure_space(this);
1118 DCHECK(is_uint5(imm8)); // illegal shift count
1121 emit_operand(ebp, dst);
1124 emit_operand(ebp, dst);
1130 void Assembler::shr_cl(const Operand& dst) {
1131 EnsureSpace ensure_space(this);
1133 emit_operand(ebp, dst);
1137 void Assembler::sub(const Operand& dst, const Immediate& x) {
1138 EnsureSpace ensure_space(this);
1139 emit_arith(5, dst, x);
1143 void Assembler::sub(Register dst, const Operand& src) {
1144 EnsureSpace ensure_space(this);
1146 emit_operand(dst, src);
1150 void Assembler::sub(const Operand& dst, Register src) {
1151 EnsureSpace ensure_space(this);
1153 emit_operand(src, dst);
1157 void Assembler::test(Register reg, const Immediate& imm) {
1158 if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
1159 test_b(reg, imm.x_);
1163 EnsureSpace ensure_space(this);
1164 // This is not using emit_arith because test doesn't support
1165 // sign-extension of 8-bit operands.
1170 EMIT(0xC0 | reg.code());
1176 void Assembler::test(Register reg, const Operand& op) {
1177 EnsureSpace ensure_space(this);
1179 emit_operand(reg, op);
1183 void Assembler::test_b(Register reg, const Operand& op) {
1184 CHECK(reg.is_byte_register());
1185 EnsureSpace ensure_space(this);
1187 emit_operand(reg, op);
1191 void Assembler::test(const Operand& op, const Immediate& imm) {
1192 if (op.is_reg_only()) {
1193 test(op.reg(), imm);
1196 if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
1197 return test_b(op, imm.x_);
1199 EnsureSpace ensure_space(this);
1201 emit_operand(eax, op);
1206 void Assembler::test_b(Register reg, uint8_t imm8) {
1207 EnsureSpace ensure_space(this);
1208 // Only use test against byte for registers that have a byte
1209 // variant: eax, ebx, ecx, and edx.
1213 } else if (reg.is_byte_register()) {
1214 emit_arith_b(0xF6, 0xC0, reg, imm8);
1217 EMIT(0xC0 | reg.code());
1223 void Assembler::test_b(const Operand& op, uint8_t imm8) {
1224 if (op.is_reg_only()) {
1225 test_b(op.reg(), imm8);
1228 EnsureSpace ensure_space(this);
1230 emit_operand(eax, op);
1235 void Assembler::xor_(Register dst, int32_t imm32) {
1236 EnsureSpace ensure_space(this);
1237 emit_arith(6, Operand(dst), Immediate(imm32));
1241 void Assembler::xor_(Register dst, const Operand& src) {
1242 EnsureSpace ensure_space(this);
1244 emit_operand(dst, src);
1248 void Assembler::xor_(const Operand& dst, Register src) {
1249 EnsureSpace ensure_space(this);
1251 emit_operand(src, dst);
1255 void Assembler::xor_(const Operand& dst, const Immediate& x) {
1256 EnsureSpace ensure_space(this);
1257 emit_arith(6, dst, x);
1261 void Assembler::bt(const Operand& dst, Register src) {
1262 EnsureSpace ensure_space(this);
1265 emit_operand(src, dst);
1269 void Assembler::bts(const Operand& dst, Register src) {
1270 EnsureSpace ensure_space(this);
1273 emit_operand(src, dst);
1277 void Assembler::bsr(Register dst, const Operand& src) {
1278 EnsureSpace ensure_space(this);
1281 emit_operand(dst, src);
1285 void Assembler::hlt() {
1286 EnsureSpace ensure_space(this);
1291 void Assembler::int3() {
1292 EnsureSpace ensure_space(this);
1297 void Assembler::nop() {
1298 EnsureSpace ensure_space(this);
1303 void Assembler::ret(int imm16) {
1304 EnsureSpace ensure_space(this);
1305 DCHECK(is_uint16(imm16));
1311 EMIT((imm16 >> 8) & 0xFF);
1316 // Labels refer to positions in the (to be) generated code.
1317 // There are bound, linked, and unused labels.
1319 // Bound labels refer to known positions in the already
1320 // generated code. pos() is the position the label refers to.
1322 // Linked labels refer to unknown positions in the code
1323 // to be generated; pos() is the position of the 32bit
1324 // Displacement of the last instruction using the label.
1327 void Assembler::print(Label* L) {
1328 if (L->is_unused()) {
1329 PrintF("unused label\n");
1330 } else if (L->is_bound()) {
1331 PrintF("bound label to %d\n", L->pos());
1332 } else if (L->is_linked()) {
1334 PrintF("unbound label");
1335 while (l.is_linked()) {
1336 Displacement disp = disp_at(&l);
1337 PrintF("@ %d ", l.pos());
1343 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1348 void Assembler::bind_to(Label* L, int pos) {
1349 EnsureSpace ensure_space(this);
1350 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1351 while (L->is_linked()) {
1352 Displacement disp = disp_at(L);
1353 int fixup_pos = L->pos();
1354 if (disp.type() == Displacement::CODE_RELATIVE) {
1355 // Relative to Code* heap object pointer.
1356 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1358 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1359 DCHECK(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1361 // Relative address, relative to point after address.
1362 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1363 long_at_put(fixup_pos, imm32);
1367 while (L->is_near_linked()) {
1368 int fixup_pos = L->near_link_pos();
1369 int offset_to_next =
1370 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
1371 DCHECK(offset_to_next <= 0);
1372 // Relative address, relative to point after address.
1373 int disp = pos - fixup_pos - sizeof(int8_t);
1374 CHECK(0 <= disp && disp <= 127);
1375 set_byte_at(fixup_pos, disp);
1376 if (offset_to_next < 0) {
1377 L->link_to(fixup_pos + offset_to_next, Label::kNear);
1386 void Assembler::bind(Label* L) {
1387 EnsureSpace ensure_space(this);
1388 DCHECK(!L->is_bound()); // label can only be bound once
1389 bind_to(L, pc_offset());
1393 void Assembler::call(Label* L) {
1394 positions_recorder()->WriteRecordedPositions();
1395 EnsureSpace ensure_space(this);
1396 if (L->is_bound()) {
1397 const int long_size = 5;
1398 int offs = L->pos() - pc_offset();
1400 // 1110 1000 #32-bit disp.
1402 emit(offs - long_size);
1404 // 1110 1000 #32-bit disp.
1406 emit_disp(L, Displacement::OTHER);
1411 void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
1412 positions_recorder()->WriteRecordedPositions();
1413 EnsureSpace ensure_space(this);
1414 DCHECK(!RelocInfo::IsCodeTarget(rmode));
1416 if (RelocInfo::IsRuntimeEntry(rmode)) {
1417 emit(reinterpret_cast<uint32_t>(entry), rmode);
1419 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1424 int Assembler::CallSize(const Operand& adr) {
1425 // Call size is 1 (opcode) + adr.len_ (operand).
1426 return 1 + adr.len_;
1430 void Assembler::call(const Operand& adr) {
1431 positions_recorder()->WriteRecordedPositions();
1432 EnsureSpace ensure_space(this);
1434 emit_operand(edx, adr);
1438 int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
1439 return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
1443 void Assembler::call(Handle<Code> code,
1444 RelocInfo::Mode rmode,
1445 TypeFeedbackId ast_id) {
1446 positions_recorder()->WriteRecordedPositions();
1447 EnsureSpace ensure_space(this);
1448 DCHECK(RelocInfo::IsCodeTarget(rmode)
1449 || rmode == RelocInfo::CODE_AGE_SEQUENCE);
1451 emit(code, rmode, ast_id);
1455 void Assembler::jmp(Label* L, Label::Distance distance) {
1456 EnsureSpace ensure_space(this);
1457 if (L->is_bound()) {
1458 const int short_size = 2;
1459 const int long_size = 5;
1460 int offs = L->pos() - pc_offset();
1462 if (is_int8(offs - short_size)) {
1463 // 1110 1011 #8-bit disp.
1465 EMIT((offs - short_size) & 0xFF);
1467 // 1110 1001 #32-bit disp.
1469 emit(offs - long_size);
1471 } else if (distance == Label::kNear) {
1475 // 1110 1001 #32-bit disp.
1477 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1482 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1483 EnsureSpace ensure_space(this);
1484 DCHECK(!RelocInfo::IsCodeTarget(rmode));
1486 if (RelocInfo::IsRuntimeEntry(rmode)) {
1487 emit(reinterpret_cast<uint32_t>(entry), rmode);
1489 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1494 void Assembler::jmp(const Operand& adr) {
1495 EnsureSpace ensure_space(this);
1497 emit_operand(esp, adr);
1501 void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1502 EnsureSpace ensure_space(this);
1503 DCHECK(RelocInfo::IsCodeTarget(rmode));
1509 void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
1510 EnsureSpace ensure_space(this);
1511 DCHECK(0 <= cc && static_cast<int>(cc) < 16);
1512 if (L->is_bound()) {
1513 const int short_size = 2;
1514 const int long_size = 6;
1515 int offs = L->pos() - pc_offset();
1517 if (is_int8(offs - short_size)) {
1518 // 0111 tttn #8-bit disp
1520 EMIT((offs - short_size) & 0xFF);
1522 // 0000 1111 1000 tttn #32-bit disp
1525 emit(offs - long_size);
1527 } else if (distance == Label::kNear) {
1531 // 0000 1111 1000 tttn #32-bit disp
1532 // Note: could eliminate cond. jumps to this jump if condition
1533 // is the same however, seems to be rather unlikely case.
1536 emit_disp(L, Displacement::OTHER);
1541 void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
1542 EnsureSpace ensure_space(this);
1543 DCHECK((0 <= cc) && (static_cast<int>(cc) < 16));
1544 // 0000 1111 1000 tttn #32-bit disp.
1547 if (RelocInfo::IsRuntimeEntry(rmode)) {
1548 emit(reinterpret_cast<uint32_t>(entry), rmode);
1550 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1555 void Assembler::j(Condition cc, Handle<Code> code) {
1556 EnsureSpace ensure_space(this);
1557 // 0000 1111 1000 tttn #32-bit disp
1560 emit(code, RelocInfo::CODE_TARGET);
1564 // FPU instructions.
1566 void Assembler::fld(int i) {
1567 EnsureSpace ensure_space(this);
1568 emit_farith(0xD9, 0xC0, i);
1572 void Assembler::fstp(int i) {
1573 EnsureSpace ensure_space(this);
1574 emit_farith(0xDD, 0xD8, i);
1578 void Assembler::fld1() {
1579 EnsureSpace ensure_space(this);
1585 void Assembler::fldpi() {
1586 EnsureSpace ensure_space(this);
1592 void Assembler::fldz() {
1593 EnsureSpace ensure_space(this);
1599 void Assembler::fldln2() {
1600 EnsureSpace ensure_space(this);
1606 void Assembler::fld_s(const Operand& adr) {
1607 EnsureSpace ensure_space(this);
1609 emit_operand(eax, adr);
1613 void Assembler::fld_d(const Operand& adr) {
1614 EnsureSpace ensure_space(this);
1616 emit_operand(eax, adr);
1620 void Assembler::fstp_s(const Operand& adr) {
1621 EnsureSpace ensure_space(this);
1623 emit_operand(ebx, adr);
1627 void Assembler::fst_s(const Operand& adr) {
1628 EnsureSpace ensure_space(this);
1630 emit_operand(edx, adr);
1634 void Assembler::fstp_d(const Operand& adr) {
1635 EnsureSpace ensure_space(this);
1637 emit_operand(ebx, adr);
1641 void Assembler::fst_d(const Operand& adr) {
1642 EnsureSpace ensure_space(this);
1644 emit_operand(edx, adr);
1648 void Assembler::fild_s(const Operand& adr) {
1649 EnsureSpace ensure_space(this);
1651 emit_operand(eax, adr);
1655 void Assembler::fild_d(const Operand& adr) {
1656 EnsureSpace ensure_space(this);
1658 emit_operand(ebp, adr);
1662 void Assembler::fistp_s(const Operand& adr) {
1663 EnsureSpace ensure_space(this);
1665 emit_operand(ebx, adr);
1669 void Assembler::fisttp_s(const Operand& adr) {
1670 DCHECK(IsEnabled(SSE3));
1671 EnsureSpace ensure_space(this);
1673 emit_operand(ecx, adr);
1677 void Assembler::fisttp_d(const Operand& adr) {
1678 DCHECK(IsEnabled(SSE3));
1679 EnsureSpace ensure_space(this);
1681 emit_operand(ecx, adr);
1685 void Assembler::fist_s(const Operand& adr) {
1686 EnsureSpace ensure_space(this);
1688 emit_operand(edx, adr);
1692 void Assembler::fistp_d(const Operand& adr) {
1693 EnsureSpace ensure_space(this);
1695 emit_operand(edi, adr);
1699 void Assembler::fabs() {
1700 EnsureSpace ensure_space(this);
1706 void Assembler::fchs() {
1707 EnsureSpace ensure_space(this);
1713 void Assembler::fcos() {
1714 EnsureSpace ensure_space(this);
1720 void Assembler::fsin() {
1721 EnsureSpace ensure_space(this);
1727 void Assembler::fptan() {
1728 EnsureSpace ensure_space(this);
1734 void Assembler::fyl2x() {
1735 EnsureSpace ensure_space(this);
1741 void Assembler::f2xm1() {
1742 EnsureSpace ensure_space(this);
1748 void Assembler::fscale() {
1749 EnsureSpace ensure_space(this);
1755 void Assembler::fninit() {
1756 EnsureSpace ensure_space(this);
1762 void Assembler::fadd(int i) {
1763 EnsureSpace ensure_space(this);
1764 emit_farith(0xDC, 0xC0, i);
1768 void Assembler::fadd_i(int i) {
1769 EnsureSpace ensure_space(this);
1770 emit_farith(0xD8, 0xC0, i);
1774 void Assembler::fsub(int i) {
1775 EnsureSpace ensure_space(this);
1776 emit_farith(0xDC, 0xE8, i);
1780 void Assembler::fsub_i(int i) {
1781 EnsureSpace ensure_space(this);
1782 emit_farith(0xD8, 0xE0, i);
1786 void Assembler::fisub_s(const Operand& adr) {
1787 EnsureSpace ensure_space(this);
1789 emit_operand(esp, adr);
1793 void Assembler::fmul_i(int i) {
1794 EnsureSpace ensure_space(this);
1795 emit_farith(0xD8, 0xC8, i);
1799 void Assembler::fmul(int i) {
1800 EnsureSpace ensure_space(this);
1801 emit_farith(0xDC, 0xC8, i);
1805 void Assembler::fdiv(int i) {
1806 EnsureSpace ensure_space(this);
1807 emit_farith(0xDC, 0xF8, i);
1811 void Assembler::fdiv_i(int i) {
1812 EnsureSpace ensure_space(this);
1813 emit_farith(0xD8, 0xF0, i);
1817 void Assembler::faddp(int i) {
1818 EnsureSpace ensure_space(this);
1819 emit_farith(0xDE, 0xC0, i);
1823 void Assembler::fsubp(int i) {
1824 EnsureSpace ensure_space(this);
1825 emit_farith(0xDE, 0xE8, i);
1829 void Assembler::fsubrp(int i) {
1830 EnsureSpace ensure_space(this);
1831 emit_farith(0xDE, 0xE0, i);
1835 void Assembler::fmulp(int i) {
1836 EnsureSpace ensure_space(this);
1837 emit_farith(0xDE, 0xC8, i);
1841 void Assembler::fdivp(int i) {
1842 EnsureSpace ensure_space(this);
1843 emit_farith(0xDE, 0xF8, i);
1847 void Assembler::fprem() {
1848 EnsureSpace ensure_space(this);
1854 void Assembler::fprem1() {
1855 EnsureSpace ensure_space(this);
1861 void Assembler::fxch(int i) {
1862 EnsureSpace ensure_space(this);
1863 emit_farith(0xD9, 0xC8, i);
1867 void Assembler::fincstp() {
1868 EnsureSpace ensure_space(this);
1874 void Assembler::ffree(int i) {
1875 EnsureSpace ensure_space(this);
1876 emit_farith(0xDD, 0xC0, i);
1880 void Assembler::ftst() {
1881 EnsureSpace ensure_space(this);
1887 void Assembler::fucomp(int i) {
1888 EnsureSpace ensure_space(this);
1889 emit_farith(0xDD, 0xE8, i);
1893 void Assembler::fucompp() {
1894 EnsureSpace ensure_space(this);
1900 void Assembler::fucomi(int i) {
1901 EnsureSpace ensure_space(this);
1907 void Assembler::fucomip() {
1908 EnsureSpace ensure_space(this);
1914 void Assembler::fcompp() {
1915 EnsureSpace ensure_space(this);
1921 void Assembler::fnstsw_ax() {
1922 EnsureSpace ensure_space(this);
1928 void Assembler::fwait() {
1929 EnsureSpace ensure_space(this);
1934 void Assembler::frndint() {
1935 EnsureSpace ensure_space(this);
1941 void Assembler::fnclex() {
1942 EnsureSpace ensure_space(this);
1948 void Assembler::sahf() {
1949 EnsureSpace ensure_space(this);
1954 void Assembler::setcc(Condition cc, Register reg) {
1955 DCHECK(reg.is_byte_register());
1956 EnsureSpace ensure_space(this);
1959 EMIT(0xC0 | reg.code());
1963 void Assembler::cvttss2si(Register dst, const Operand& src) {
1964 EnsureSpace ensure_space(this);
1968 emit_operand(dst, src);
1972 void Assembler::cvttsd2si(Register dst, const Operand& src) {
1973 EnsureSpace ensure_space(this);
1977 emit_operand(dst, src);
1981 void Assembler::cvtsd2si(Register dst, XMMRegister src) {
1982 EnsureSpace ensure_space(this);
1986 emit_sse_operand(dst, src);
1990 void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
1991 EnsureSpace ensure_space(this);
1995 emit_sse_operand(dst, src);
1999 void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2000 EnsureSpace ensure_space(this);
2004 emit_sse_operand(dst, src);
2008 void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
2009 EnsureSpace ensure_space(this);
2013 emit_sse_operand(dst, src);
2017 void Assembler::addsd(XMMRegister dst, XMMRegister src) {
2018 EnsureSpace ensure_space(this);
2022 emit_sse_operand(dst, src);
2026 void Assembler::addsd(XMMRegister dst, const Operand& src) {
2027 EnsureSpace ensure_space(this);
2031 emit_sse_operand(dst, src);
2035 void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
2036 EnsureSpace ensure_space(this);
2040 emit_sse_operand(dst, src);
2044 void Assembler::mulsd(XMMRegister dst, const Operand& src) {
2045 EnsureSpace ensure_space(this);
2049 emit_sse_operand(dst, src);
2053 void Assembler::subsd(XMMRegister dst, XMMRegister src) {
2054 EnsureSpace ensure_space(this);
2058 emit_sse_operand(dst, src);
2062 void Assembler::divsd(XMMRegister dst, XMMRegister src) {
2063 EnsureSpace ensure_space(this);
2067 emit_sse_operand(dst, src);
2071 void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2072 EnsureSpace ensure_space(this);
2076 emit_sse_operand(dst, src);
2080 void Assembler::xorpd(XMMRegister dst, const Operand& src) {
2081 EnsureSpace ensure_space(this);
2085 emit_sse_operand(dst, src);
2089 void Assembler::andps(XMMRegister dst, const Operand& src) {
2090 EnsureSpace ensure_space(this);
2093 emit_sse_operand(dst, src);
2097 void Assembler::orps(XMMRegister dst, const Operand& src) {
2098 EnsureSpace ensure_space(this);
2101 emit_sse_operand(dst, src);
2105 void Assembler::xorps(XMMRegister dst, const Operand& src) {
2106 EnsureSpace ensure_space(this);
2109 emit_sse_operand(dst, src);
2113 void Assembler::addps(XMMRegister dst, const Operand& src) {
2114 EnsureSpace ensure_space(this);
2117 emit_sse_operand(dst, src);
2121 void Assembler::subps(XMMRegister dst, const Operand& src) {
2122 EnsureSpace ensure_space(this);
2125 emit_sse_operand(dst, src);
2129 void Assembler::mulps(XMMRegister dst, const Operand& src) {
2130 EnsureSpace ensure_space(this);
2133 emit_sse_operand(dst, src);
2137 void Assembler::divps(XMMRegister dst, const Operand& src) {
2138 EnsureSpace ensure_space(this);
2141 emit_sse_operand(dst, src);
2145 void Assembler::addpd(XMMRegister dst, const Operand& src) {
2146 EnsureSpace ensure_space(this);
2150 emit_sse_operand(dst, src);
2154 void Assembler::subpd(XMMRegister dst, const Operand& src) {
2155 EnsureSpace ensure_space(this);
2159 emit_sse_operand(dst, src);
2163 void Assembler::mulpd(XMMRegister dst, const Operand& src) {
2164 EnsureSpace ensure_space(this);
2168 emit_sse_operand(dst, src);
2172 void Assembler::divpd(XMMRegister dst, const Operand& src) {
2173 EnsureSpace ensure_space(this);
2177 emit_sse_operand(dst, src);
2181 void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2182 EnsureSpace ensure_space(this);
2186 emit_sse_operand(dst, src);
2190 void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
2191 EnsureSpace ensure_space(this);
2195 emit_sse_operand(dst, src);
2199 void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2200 EnsureSpace ensure_space(this);
2204 emit_sse_operand(dst, src);
2208 void Assembler::andpd(XMMRegister dst, const Operand& src) {
2209 EnsureSpace ensure_space(this);
2213 emit_sse_operand(dst, src);
2217 void Assembler::orpd(XMMRegister dst, XMMRegister src) {
2218 EnsureSpace ensure_space(this);
2222 emit_sse_operand(dst, src);
2226 void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
2227 EnsureSpace ensure_space(this);
2231 emit_sse_operand(dst, src);
2235 void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
2236 DCHECK(IsEnabled(SSE4_1));
2237 EnsureSpace ensure_space(this);
2242 emit_sse_operand(dst, src);
2243 // Mask precision exeption.
2244 EMIT(static_cast<byte>(mode) | 0x8);
2248 void Assembler::movmskpd(Register dst, XMMRegister src) {
2249 EnsureSpace ensure_space(this);
2253 emit_sse_operand(dst, src);
2257 void Assembler::movmskps(Register dst, XMMRegister src) {
2258 EnsureSpace ensure_space(this);
2261 emit_sse_operand(dst, src);
2265 void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
2266 EnsureSpace ensure_space(this);
2270 emit_sse_operand(dst, src);
2274 void Assembler::pcmpgtd(XMMRegister dst, XMMRegister src) {
2275 EnsureSpace ensure_space(this);
2279 emit_sse_operand(dst, src);
2283 void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
2284 EnsureSpace ensure_space(this);
2288 emit_sse_operand(dst, src);
2293 void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2294 EnsureSpace ensure_space(this);
2297 emit_sse_operand(dst, src);
2301 void Assembler::movups(XMMRegister dst, const Operand& src) {
2302 EnsureSpace ensure_space(this);
2305 emit_sse_operand(dst, src);
2309 void Assembler::movups(const Operand& dst, XMMRegister src) {
2310 EnsureSpace ensure_space(this);
2313 emit_sse_operand(src, dst);
2317 void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
2318 DCHECK(is_uint8(imm8));
2319 EnsureSpace ensure_space(this);
2322 emit_sse_operand(dst, src);
2327 void Assembler::shufpd(XMMRegister dst, XMMRegister src, byte imm8) {
2328 DCHECK(is_uint8(imm8));
2329 EnsureSpace ensure_space(this);
2333 emit_sse_operand(dst, src);
2338 void Assembler::movdqa(const Operand& dst, XMMRegister src) {
2339 EnsureSpace ensure_space(this);
2343 emit_sse_operand(src, dst);
2347 void Assembler::movdqa(XMMRegister dst, const Operand& src) {
2348 EnsureSpace ensure_space(this);
2352 emit_sse_operand(dst, src);
2356 void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
2357 EnsureSpace ensure_space(this);
2361 emit_sse_operand(src, dst);
2365 void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2366 EnsureSpace ensure_space(this);
2370 emit_sse_operand(dst, src);
2374 void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
2375 DCHECK(IsEnabled(SSE4_1));
2376 EnsureSpace ensure_space(this);
2381 emit_sse_operand(dst, src);
2385 void Assembler::movntdq(const Operand& dst, XMMRegister src) {
2386 EnsureSpace ensure_space(this);
2390 emit_sse_operand(src, dst);
2394 void Assembler::prefetch(const Operand& src, int level) {
2395 DCHECK(is_uint2(level));
2396 EnsureSpace ensure_space(this);
2399 // Emit hint number in Reg position of RegR/M.
2400 XMMRegister code = XMMRegister::from_code(level);
2401 emit_sse_operand(code, src);
2405 void Assembler::movsd(const Operand& dst, XMMRegister src ) {
2406 EnsureSpace ensure_space(this);
2407 EMIT(0xF2); // double
2409 EMIT(0x11); // store
2410 emit_sse_operand(src, dst);
2414 void Assembler::movsd(XMMRegister dst, const Operand& src) {
2415 EnsureSpace ensure_space(this);
2416 EMIT(0xF2); // double
2419 emit_sse_operand(dst, src);
2423 void Assembler::movss(const Operand& dst, XMMRegister src ) {
2424 EnsureSpace ensure_space(this);
2425 EMIT(0xF3); // float
2427 EMIT(0x11); // store
2428 emit_sse_operand(src, dst);
2432 void Assembler::movss(XMMRegister dst, const Operand& src) {
2433 EnsureSpace ensure_space(this);
2434 EMIT(0xF3); // float
2437 emit_sse_operand(dst, src);
2441 void Assembler::movd(XMMRegister dst, const Operand& src) {
2442 EnsureSpace ensure_space(this);
2446 emit_sse_operand(dst, src);
2450 void Assembler::movd(const Operand& dst, XMMRegister src) {
2451 EnsureSpace ensure_space(this);
2455 emit_sse_operand(src, dst);
2459 void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
2460 DCHECK(IsEnabled(SSE4_1));
2461 DCHECK(is_uint8(imm8));
2462 EnsureSpace ensure_space(this);
2467 emit_sse_operand(src, dst);
2472 void Assembler::pand(XMMRegister dst, XMMRegister src) {
2473 EnsureSpace ensure_space(this);
2477 emit_sse_operand(dst, src);
2481 void Assembler::pxor(XMMRegister dst, XMMRegister src) {
2482 EnsureSpace ensure_space(this);
2486 emit_sse_operand(dst, src);
2490 void Assembler::por(XMMRegister dst, XMMRegister src) {
2491 EnsureSpace ensure_space(this);
2495 emit_sse_operand(dst, src);
2499 void Assembler::ptest(XMMRegister dst, XMMRegister src) {
2500 DCHECK(IsEnabled(SSE4_1));
2501 EnsureSpace ensure_space(this);
2506 emit_sse_operand(dst, src);
2510 void Assembler::psllq(XMMRegister reg, int8_t shift) {
2511 EnsureSpace ensure_space(this);
2515 emit_sse_operand(esi, reg); // esi == 6
2520 void Assembler::psllq(XMMRegister dst, XMMRegister src) {
2521 EnsureSpace ensure_space(this);
2525 emit_sse_operand(dst, src);
2529 void Assembler::pslld(XMMRegister reg, int8_t shift) {
2530 EnsureSpace ensure_space(this);
2534 emit_sse_operand(esi, reg); // esi == 6
2539 void Assembler::pslld(XMMRegister dst, XMMRegister src) {
2540 EnsureSpace ensure_space(this);
2544 emit_sse_operand(dst, src);
2548 void Assembler::psrld(XMMRegister reg, int8_t shift) {
2549 EnsureSpace ensure_space(this);
2553 emit_sse_operand(edx, reg); // edx == 2
2558 void Assembler::psrld(XMMRegister dst, XMMRegister src) {
2559 EnsureSpace ensure_space(this);
2563 emit_sse_operand(dst, src);
2567 void Assembler::psrad(XMMRegister reg, int8_t shift) {
2568 EnsureSpace ensure_space(this);
2572 emit_sse_operand(esp, reg); // esp == 4
2577 void Assembler::psrad(XMMRegister dst, XMMRegister src) {
2578 EnsureSpace ensure_space(this);
2582 emit_sse_operand(dst, src);
2586 void Assembler::psrlq(XMMRegister reg, int8_t shift) {
2587 EnsureSpace ensure_space(this);
2591 emit_sse_operand(edx, reg); // edx == 2
2596 void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
2597 EnsureSpace ensure_space(this);
2601 emit_sse_operand(dst, src);
2605 void Assembler::psrldq(XMMRegister dst, int8_t shift) {
2606 EnsureSpace ensure_space(this);
2610 emit_sse_operand(ebx, dst); // ebx == 3
2615 void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
2616 EnsureSpace ensure_space(this);
2620 emit_sse_operand(dst, src);
2625 void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
2626 DCHECK(IsEnabled(SSE4_1));
2627 EnsureSpace ensure_space(this);
2632 emit_sse_operand(src, dst);
2637 void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
2638 DCHECK(IsEnabled(SSE4_1));
2639 EnsureSpace ensure_space(this);
2644 emit_sse_operand(dst, src);
2649 void Assembler::minps(XMMRegister dst, const Operand& src) {
2650 EnsureSpace ensure_space(this);
2653 emit_sse_operand(dst, src);
2657 void Assembler::maxps(XMMRegister dst, const Operand& src) {
2658 EnsureSpace ensure_space(this);
2661 emit_sse_operand(dst, src);
2665 void Assembler::minpd(XMMRegister dst, const Operand& src) {
2666 EnsureSpace ensure_space(this);
2670 emit_sse_operand(dst, src);
2674 void Assembler::maxpd(XMMRegister dst, const Operand& src) {
2675 EnsureSpace ensure_space(this);
2679 emit_sse_operand(dst, src);
2683 void Assembler::rcpps(XMMRegister dst, const Operand& src) {
2684 EnsureSpace ensure_space(this);
2687 emit_sse_operand(dst, src);
2691 void Assembler::rsqrtps(XMMRegister dst, const Operand& src) {
2692 EnsureSpace ensure_space(this);
2695 emit_sse_operand(dst, src);
2699 void Assembler::sqrtps(XMMRegister dst, const Operand& src) {
2700 EnsureSpace ensure_space(this);
2703 emit_sse_operand(dst, src);
2707 void Assembler::sqrtpd(XMMRegister dst, const Operand& src) {
2708 EnsureSpace ensure_space(this);
2712 emit_sse_operand(dst, src);
2716 void Assembler::cvtdq2ps(XMMRegister dst, const Operand& src) {
2717 EnsureSpace ensure_space(this);
2720 emit_sse_operand(dst, src);
2724 void Assembler::paddd(XMMRegister dst, const Operand& src) {
2725 EnsureSpace ensure_space(this);
2729 emit_sse_operand(dst, src);
2733 void Assembler::psubd(XMMRegister dst, const Operand& src) {
2734 EnsureSpace ensure_space(this);
2738 emit_sse_operand(dst, src);
2742 void Assembler::pmulld(XMMRegister dst, const Operand& src) {
2743 DCHECK(IsEnabled(SSE4_1));
2744 EnsureSpace ensure_space(this);
2749 emit_sse_operand(dst, src);
2753 void Assembler::pmuludq(XMMRegister dst, const Operand& src) {
2754 EnsureSpace ensure_space(this);
2758 emit_sse_operand(dst, src);
2762 void Assembler::punpackldq(XMMRegister dst, const Operand& src) {
2763 EnsureSpace ensure_space(this);
2767 emit_sse_operand(dst, src);
2771 void Assembler::cvtps2dq(XMMRegister dst, const Operand& src) {
2772 EnsureSpace ensure_space(this);
2776 emit_sse_operand(dst, src);
2780 void Assembler::cmpps(XMMRegister dst, XMMRegister src, int8_t cmp) {
2781 EnsureSpace ensure_space(this);
2784 emit_sse_operand(dst, src);
2789 void Assembler::cmpeqps(XMMRegister dst, XMMRegister src) {
2790 cmpps(dst, src, 0x0);
2794 void Assembler::cmpltps(XMMRegister dst, XMMRegister src) {
2795 cmpps(dst, src, 0x1);
2799 void Assembler::cmpleps(XMMRegister dst, XMMRegister src) {
2800 cmpps(dst, src, 0x2);
2804 void Assembler::cmpneqps(XMMRegister dst, XMMRegister src) {
2805 cmpps(dst, src, 0x4);
2809 void Assembler::cmpnltps(XMMRegister dst, XMMRegister src) {
2810 cmpps(dst, src, 0x5);
2814 void Assembler::cmpnleps(XMMRegister dst, XMMRegister src) {
2815 cmpps(dst, src, 0x6);
2819 void Assembler::insertps(XMMRegister dst, XMMRegister src, byte imm8) {
2820 DCHECK(CpuFeatures::IsSupported(SSE4_1));
2821 DCHECK(is_uint8(imm8));
2822 EnsureSpace ensure_space(this);
2827 emit_sse_operand(dst, src);
2832 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2833 Register ireg = { reg.code() };
2834 emit_operand(ireg, adr);
2838 void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2839 EMIT(0xC0 | dst.code() << 3 | src.code());
2843 void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2844 EMIT(0xC0 | dst.code() << 3 | src.code());
2848 void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
2849 EMIT(0xC0 | (dst.code() << 3) | src.code());
2853 void Assembler::Print() {
2854 Disassembler::Decode(isolate(), stdout, buffer_, pc_);
2858 void Assembler::RecordJSReturn() {
2859 positions_recorder()->WriteRecordedPositions();
2860 EnsureSpace ensure_space(this);
2861 RecordRelocInfo(RelocInfo::JS_RETURN);
2865 void Assembler::RecordDebugBreakSlot() {
2866 positions_recorder()->WriteRecordedPositions();
2867 EnsureSpace ensure_space(this);
2868 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2872 void Assembler::RecordComment(const char* msg, bool force) {
2873 if (FLAG_code_comments || force) {
2874 EnsureSpace ensure_space(this);
2875 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2880 void Assembler::GrowBuffer() {
2881 DCHECK(buffer_overflow());
2882 if (!own_buffer_) FATAL("external code buffer is too small");
2884 // Compute new buffer size.
2885 CodeDesc desc; // the new buffer
2886 desc.buffer_size = 2 * buffer_size_;
2888 // Some internal data structures overflow for very large buffers,
2889 // they must ensure that kMaximalBufferSize is not too large.
2890 if ((desc.buffer_size > kMaximalBufferSize) ||
2891 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
2892 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2895 // Set up new buffer.
2896 desc.buffer = NewArray<byte>(desc.buffer_size);
2897 desc.instr_size = pc_offset();
2898 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2900 // Clear the buffer in debug mode. Use 'int3' instructions to make
2901 // sure to get into problems if we ever run uninitialized code.
2903 memset(desc.buffer, 0xCC, desc.buffer_size);
2907 int pc_delta = desc.buffer - buffer_;
2908 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2909 MemMove(desc.buffer, buffer_, desc.instr_size);
2910 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
2914 DeleteArray(buffer_);
2915 buffer_ = desc.buffer;
2916 buffer_size_ = desc.buffer_size;
2918 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2919 reloc_info_writer.last_pc() + pc_delta);
2921 // Relocate runtime entries.
2922 for (RelocIterator it(desc); !it.done(); it.next()) {
2923 RelocInfo::Mode rmode = it.rinfo()->rmode();
2924 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2925 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2926 if (*p != 0) { // 0 means uninitialized.
2932 DCHECK(!buffer_overflow());
2936 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2937 DCHECK(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2938 DCHECK(is_uint8(imm8));
2939 DCHECK((op1 & 0x01) == 0); // should be 8bit operation
2941 EMIT(op2 | dst.code());
2946 void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2947 DCHECK((0 <= sel) && (sel <= 7));
2948 Register ireg = { sel };
2950 EMIT(0x83); // using a sign-extended 8-bit immediate.
2951 emit_operand(ireg, dst);
2953 } else if (dst.is_reg(eax)) {
2954 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2957 EMIT(0x81); // using a literal 32-bit immediate.
2958 emit_operand(ireg, dst);
2964 void Assembler::emit_operand(Register reg, const Operand& adr) {
2965 const unsigned length = adr.len_;
2968 // Emit updated ModRM byte containing the given register.
2969 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2971 // Emit the rest of the encoded operand.
2972 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2975 // Emit relocation information if necessary.
2976 if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) {
2977 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2978 RecordRelocInfo(adr.rmode_);
2979 pc_ += sizeof(int32_t);
2984 void Assembler::emit_farith(int b1, int b2, int i) {
2985 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2986 DCHECK(0 <= i && i < 8); // illegal stack offset
2992 void Assembler::db(uint8_t data) {
2993 EnsureSpace ensure_space(this);
2998 void Assembler::dd(uint32_t data) {
2999 EnsureSpace ensure_space(this);
3004 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3005 DCHECK(!RelocInfo::IsNone(rmode));
3006 // Don't record external references unless the heap will be serialized.
3007 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
3008 !serializer_enabled() && !emit_debug_code()) {
3011 RelocInfo rinfo(pc_, rmode, data, NULL);
3012 reloc_info_writer.Write(&rinfo);
3016 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
3017 // No out-of-line constant pool support.
3018 DCHECK(!FLAG_enable_ool_constant_pool);
3019 return isolate->factory()->empty_constant_pool_array();
3023 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
3024 // No out-of-line constant pool support.
3025 DCHECK(!FLAG_enable_ool_constant_pool);
3030 #ifdef GENERATED_CODE_COVERAGE
3031 static FILE* coverage_log = NULL;
3034 static void InitCoverageLog() {
3035 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
3036 if (file_name != NULL) {
3037 coverage_log = fopen(file_name, "aw+");
3042 void LogGeneratedCodeCoverage(const char* file_line) {
3043 const char* return_address = (&file_line)[-1];
3044 char* push_insn = const_cast<char*>(return_address - 12);
3045 push_insn[0] = 0xeb; // Relative branch insn.
3046 push_insn[1] = 13; // Skip over coverage insns.
3047 if (coverage_log != NULL) {
3048 fprintf(coverage_log, "%s\n", file_line);
3049 fflush(coverage_log);
3055 } } // namespace v8::internal
3057 #endif // V8_TARGET_ARCH_IA32