1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=79:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Copyright (C) 2008 Apple Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * 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.
28 * ***** END LICENSE BLOCK ***** */
30 #ifndef X86Assembler_h
31 #define X86Assembler_h
33 #include "assembler/wtf/Platform.h"
35 #if ENABLE_ASSEMBLER && (WTF_CPU_X86 || WTF_CPU_X86_64)
37 #include "AssemblerBuffer.h"
39 #include "assembler/wtf/Assertions.h"
42 #include "methodjit/Logging.h"
45 #ifdef JS_METHODJIT_SPEW
46 # define MAYBE_PAD (isOOLPath ? "> " : "")
47 # define PRETTY_PRINT_OFFSET(os) (((os)<0)?"-":""), (((os)<0)?-(os):(os))
48 # define FIXME_INSN_PRINTING \
50 js::JaegerSpew(js::JSpew_Insns, \
51 ISPFX "FIXME insn printing %s:%d\n", \
52 __FILE__, __LINE__); \
56 # define FIXME_INSN_PRINTING ((void) 0)
57 # define PRETTY_PRINT_OFFSET(os) "", 0
63 inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; }
65 namespace X86Registers {
99 static const char* nameFPReg(XMMRegisterID fpreg)
101 static const char* xmmnames[8]
102 = { "%xmm0", "%xmm1", "%xmm2", "%xmm3",
103 "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
104 int off = (XMMRegisterID)fpreg - (XMMRegisterID)xmm0;
105 return (off < 0 || off > 7) ? "%xmm?" : xmmnames[off];
108 static const char* nameIReg(int szB, RegisterID reg)
110 static const char* r64names[16]
111 = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
112 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" };
113 static const char* r32names[16]
114 = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
115 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
116 static const char* r16names[16]
117 = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
118 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" };
119 static const char* r8names[16]
120 = { "%al", "%cl", "%dl", "%bl", "%ah/spl", "%ch/bpl", "%dh/sil", "%bh/dil",
121 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" };
122 int off = (RegisterID)reg - (RegisterID)eax;
123 const char** tab = r64names;
125 case 1: tab = r8names; break;
126 case 2: tab = r16names; break;
127 case 4: tab = r32names; break;
129 return (off < 0 || off > 15) ? "%r???" : tab[off];
132 static const char* nameIReg(RegisterID reg)
135 return nameIReg(8, reg);
137 return nameIReg(4, reg);
141 } /* namespace X86Registers */
146 typedef X86Registers::RegisterID RegisterID;
147 typedef X86Registers::XMMRegisterID XMMRegisterID;
148 typedef XMMRegisterID FPRegisterID;
168 ConditionC = ConditionB,
169 ConditionNC = ConditionAE
172 static const char* nameCC(Condition cc)
174 static const char* names[16]
175 = { "o ", "no", "b ", "ae", "e ", "ne", "be", "a ",
176 "s ", "ns", "p ", "np", "l ", "ge", "le", "g " };
178 return (ix < 0 || ix > 15) ? "??" : names[ix];
187 OP_2BYTE_ESCAPE = 0x0F,
188 OP_3BYTE_ESCAPE = 0x3A,
193 PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
208 OP_MOVSXD_GvEv = 0x63,
210 PRE_OPERAND_SIZE = 0x66,
213 OP_IMUL_GvEvIz = 0x69,
214 OP_GROUP1_EbIb = 0x80,
215 OP_GROUP1_EvIz = 0x81,
216 OP_GROUP1_EvIb = 0x83,
223 OP_GROUP1A_Ev = 0x8F,
228 OP_GROUP2_EvIb = 0xC1,
230 OP_GROUP11_EvIb = 0xC6,
231 OP_GROUP11_EvIz = 0xC7,
233 OP_GROUP2_Ev1 = 0xD1,
234 OP_GROUP2_EvCL = 0xD3,
235 OP_CALL_rel32 = 0xE8,
240 OP_GROUP3_EbIb = 0xF6,
242 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
247 OP2_MOVSD_VsdWsd = 0x10,
248 OP2_MOVSD_WsdVsd = 0x11,
249 OP2_UNPCKLPS_VsdWsd = 0x14,
250 OP2_CVTSI2SD_VsdEd = 0x2A,
251 OP2_CVTTSD2SI_GdWsd = 0x2C,
252 OP2_UCOMISD_VsdWsd = 0x2E,
253 OP2_ADDSD_VsdWsd = 0x58,
254 OP2_MULSD_VsdWsd = 0x59,
255 OP2_CVTSS2SD_VsdEd = 0x5A,
256 OP2_CVTSD2SS_VsdEd = 0x5A,
257 OP2_SUBSD_VsdWsd = 0x5C,
258 OP2_DIVSD_VsdWsd = 0x5E,
259 OP2_SQRTSD_VsdWsd = 0x51,
260 OP2_XORPD_VpdWpd = 0x57,
261 OP2_MOVD_VdEd = 0x6E,
262 OP2_PSRLDQ_Vd = 0x73,
263 OP2_MOVD_EdVd = 0x7E,
264 OP2_JCC_rel32 = 0x80,
266 OP2_IMUL_GvEv = 0xAF,
267 OP2_MOVSX_GvEb = 0xBE,
268 OP2_MOVSX_GvEw = 0xBF,
269 OP2_MOVZX_GvEb = 0xB6,
270 OP2_MOVZX_GvEw = 0xB7,
271 OP2_PEXTRW_GdUdIb = 0xC5
275 OP3_PINSRD_VsdWsd = 0x22
278 TwoByteOpcodeID jccRel32(Condition cond)
280 return (TwoByteOpcodeID)(OP2_JCC_rel32 + cond);
283 TwoByteOpcodeID setccOpcode(Condition cond)
285 return (TwoByteOpcodeID)(OP_SETCC + cond);
315 class X86InstructionFormatter;
318 #ifdef JS_METHODJIT_SPEW
323 friend class X86Assembler;
324 friend class X86InstructionFormatter;
341 friend class X86Assembler;
342 friend class X86InstructionFormatter;
350 bool isUsed() const { return m_used; }
351 void used() { m_used = true; }
352 bool isValid() const { return m_offset != -1; }
358 ASSERT(m_offset == offset);
361 signed int m_offset : 31;
366 #ifdef JS_METHODJIT_SPEW
372 size_t size() const { return m_formatter.size(); }
373 unsigned char *buffer() const { return m_formatter.buffer(); }
374 bool oom() const { return m_formatter.oom(); }
378 void push_r(RegisterID reg)
380 js::JaegerSpew(js::JSpew_Insns,
381 IPFX "push %s\n", MAYBE_PAD, nameIReg(reg));
382 m_formatter.oneByteOp(OP_PUSH_EAX, reg);
385 void pop_r(RegisterID reg)
387 js::JaegerSpew(js::JSpew_Insns,
388 IPFX "pop %s\n", MAYBE_PAD, nameIReg(reg));
389 m_formatter.oneByteOp(OP_POP_EAX, reg);
392 void push_i32(int imm)
394 js::JaegerSpew(js::JSpew_Insns,
395 IPFX "pushl %s$0x%x\n", MAYBE_PAD,
396 PRETTY_PRINT_OFFSET(imm));
397 m_formatter.oneByteOp(OP_PUSH_Iz);
398 m_formatter.immediate32(imm);
401 void push_m(int offset, RegisterID base)
403 js::JaegerSpew(js::JSpew_Insns,
404 IPFX "push %s0x%x(%s)\n", MAYBE_PAD,
405 PRETTY_PRINT_OFFSET(offset), nameIReg(base));
406 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_PUSH, base, offset);
409 void pop_m(int offset, RegisterID base)
412 m_formatter.oneByteOp(OP_GROUP1A_Ev, GROUP1A_OP_POP, base, offset);
415 // Arithmetic operations:
418 void adcl_im(int imm, void* addr)
421 if (CAN_SIGN_EXTEND_8_32(imm)) {
422 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr);
423 m_formatter.immediate8(imm);
425 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADC, addr);
426 m_formatter.immediate32(imm);
431 void addl_rr(RegisterID src, RegisterID dst)
433 js::JaegerSpew(js::JSpew_Insns,
434 IPFX "addl %s, %s\n", MAYBE_PAD,
435 nameIReg(4,src), nameIReg(4,dst));
436 m_formatter.oneByteOp(OP_ADD_EvGv, src, dst);
439 void addl_mr(int offset, RegisterID base, RegisterID dst)
442 m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset);
445 void addl_rm(RegisterID src, int offset, RegisterID base)
448 m_formatter.oneByteOp(OP_ADD_EvGv, src, base, offset);
451 void addl_ir(int imm, RegisterID dst)
453 js::JaegerSpew(js::JSpew_Insns,
454 IPFX "addl $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4,dst));
455 if (CAN_SIGN_EXTEND_8_32(imm)) {
456 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
457 m_formatter.immediate8(imm);
459 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
460 m_formatter.immediate32(imm);
464 void addl_im(int imm, int offset, RegisterID base)
466 js::JaegerSpew(js::JSpew_Insns,
467 IPFX "addl %d, %s0x%x(%s)\n", MAYBE_PAD,
468 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(8,base));
469 if (CAN_SIGN_EXTEND_8_32(imm)) {
470 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
471 m_formatter.immediate8(imm);
473 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
474 m_formatter.immediate32(imm);
479 void addq_rr(RegisterID src, RegisterID dst)
482 m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst);
485 void addq_ir(int imm, RegisterID dst)
487 js::JaegerSpew(js::JSpew_Insns,
488 IPFX "addq $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
489 if (CAN_SIGN_EXTEND_8_32(imm)) {
490 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
491 m_formatter.immediate8(imm);
493 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
494 m_formatter.immediate32(imm);
498 void addq_im(int imm, int offset, RegisterID base)
500 js::JaegerSpew(js::JSpew_Insns,
501 IPFX "addq $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
502 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(8,base));
503 if (CAN_SIGN_EXTEND_8_32(imm)) {
504 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
505 m_formatter.immediate8(imm);
507 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
508 m_formatter.immediate32(imm);
512 void addl_im(int imm, void* addr)
515 if (CAN_SIGN_EXTEND_8_32(imm)) {
516 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
517 m_formatter.immediate8(imm);
519 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
520 m_formatter.immediate32(imm);
525 void andl_rr(RegisterID src, RegisterID dst)
527 js::JaegerSpew(js::JSpew_Insns,
528 IPFX "andl %s, %s\n", MAYBE_PAD,
529 nameIReg(4,src), nameIReg(4,dst));
530 m_formatter.oneByteOp(OP_AND_EvGv, src, dst);
533 void andl_mr(int offset, RegisterID base, RegisterID dst)
536 m_formatter.oneByteOp(OP_AND_GvEv, dst, base, offset);
539 void andl_rm(RegisterID src, int offset, RegisterID base)
542 m_formatter.oneByteOp(OP_AND_EvGv, src, base, offset);
545 void andl_ir(int imm, RegisterID dst)
547 js::JaegerSpew(js::JSpew_Insns,
548 IPFX "andl $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4,dst));
549 if (CAN_SIGN_EXTEND_8_32(imm)) {
550 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
551 m_formatter.immediate8(imm);
553 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
554 m_formatter.immediate32(imm);
558 void andl_im(int imm, int offset, RegisterID base)
561 if (CAN_SIGN_EXTEND_8_32(imm)) {
562 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, base, offset);
563 m_formatter.immediate8(imm);
565 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, base, offset);
566 m_formatter.immediate32(imm);
571 void andq_rr(RegisterID src, RegisterID dst)
573 js::JaegerSpew(js::JSpew_Insns,
574 IPFX "andq %s, %s\n", MAYBE_PAD,
575 nameIReg(8,src), nameIReg(8,dst));
576 m_formatter.oneByteOp64(OP_AND_EvGv, src, dst);
579 void andq_mr(int offset, RegisterID base, RegisterID dst)
581 js::JaegerSpew(js::JSpew_Insns,
582 IPFX "andq %s0x%x(%s), %s\n", MAYBE_PAD,
583 PRETTY_PRINT_OFFSET(offset), nameIReg(8,base), nameIReg(8,dst));
584 m_formatter.oneByteOp64(OP_AND_GvEv, dst, base, offset);
587 void orq_mr(int offset, RegisterID base, RegisterID dst)
589 js::JaegerSpew(js::JSpew_Insns,
590 IPFX "orq %s0x%x(%s), %s\n", MAYBE_PAD,
591 PRETTY_PRINT_OFFSET(offset), nameIReg(8,base), nameIReg(8,dst));
592 m_formatter.oneByteOp64(OP_OR_GvEv, dst, base, offset);
595 void andq_ir(int imm, RegisterID dst)
597 js::JaegerSpew(js::JSpew_Insns,
598 IPFX "andq $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
599 if (CAN_SIGN_EXTEND_8_32(imm)) {
600 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
601 m_formatter.immediate8(imm);
603 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
604 m_formatter.immediate32(imm);
608 void andl_im(int imm, void* addr)
611 if (CAN_SIGN_EXTEND_8_32(imm)) {
612 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr);
613 m_formatter.immediate8(imm);
615 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, addr);
616 m_formatter.immediate32(imm);
621 void negl_r(RegisterID dst)
623 js::JaegerSpew(js::JSpew_Insns,
624 IPFX "negl %s\n", MAYBE_PAD, nameIReg(4,dst));
625 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, dst);
628 void negl_m(int offset, RegisterID base)
631 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, base, offset);
634 void notl_r(RegisterID dst)
636 js::JaegerSpew(js::JSpew_Insns,
637 IPFX "notl %s\n", MAYBE_PAD, nameIReg(4,dst));
638 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
641 void notl_m(int offset, RegisterID base)
644 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, base, offset);
647 void orl_rr(RegisterID src, RegisterID dst)
649 js::JaegerSpew(js::JSpew_Insns,
650 IPFX "orl %s, %s\n", MAYBE_PAD,
651 nameIReg(4,src), nameIReg(4,dst));
652 m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
655 void orl_mr(int offset, RegisterID base, RegisterID dst)
658 m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset);
661 void orl_rm(RegisterID src, int offset, RegisterID base)
664 m_formatter.oneByteOp(OP_OR_EvGv, src, base, offset);
667 void orl_ir(int imm, RegisterID dst)
669 js::JaegerSpew(js::JSpew_Insns,
670 IPFX "orl $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4,dst));
671 if (CAN_SIGN_EXTEND_8_32(imm)) {
672 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
673 m_formatter.immediate8(imm);
675 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
676 m_formatter.immediate32(imm);
680 void orl_im(int imm, int offset, RegisterID base)
683 if (CAN_SIGN_EXTEND_8_32(imm)) {
684 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, base, offset);
685 m_formatter.immediate8(imm);
687 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, base, offset);
688 m_formatter.immediate32(imm);
693 void orq_rr(RegisterID src, RegisterID dst)
695 js::JaegerSpew(js::JSpew_Insns,
696 IPFX "orq %s, %s\n", MAYBE_PAD,
697 nameIReg(8,src), nameIReg(8,dst));
698 m_formatter.oneByteOp64(OP_OR_EvGv, src, dst);
701 void orq_ir(int imm, RegisterID dst)
703 js::JaegerSpew(js::JSpew_Insns,
704 IPFX "orq $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
705 if (CAN_SIGN_EXTEND_8_32(imm)) {
706 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
707 m_formatter.immediate8(imm);
709 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
710 m_formatter.immediate32(imm);
714 void notq_r(RegisterID dst)
716 js::JaegerSpew(js::JSpew_Insns,
717 IPFX "notq %s\n", MAYBE_PAD, nameIReg(8,dst));
718 m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
721 void orl_im(int imm, void* addr)
724 if (CAN_SIGN_EXTEND_8_32(imm)) {
725 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr);
726 m_formatter.immediate8(imm);
728 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, addr);
729 m_formatter.immediate32(imm);
734 void subl_rr(RegisterID src, RegisterID dst)
736 js::JaegerSpew(js::JSpew_Insns,
737 IPFX "subl %s, %s\n", MAYBE_PAD,
738 nameIReg(4,src), nameIReg(4,dst));
739 m_formatter.oneByteOp(OP_SUB_EvGv, src, dst);
742 void subl_mr(int offset, RegisterID base, RegisterID dst)
745 m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset);
748 void subl_rm(RegisterID src, int offset, RegisterID base)
751 m_formatter.oneByteOp(OP_SUB_EvGv, src, base, offset);
754 void subl_ir(int imm, RegisterID dst)
756 js::JaegerSpew(js::JSpew_Insns,
757 IPFX "subl $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
758 if (CAN_SIGN_EXTEND_8_32(imm)) {
759 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
760 m_formatter.immediate8(imm);
762 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
763 m_formatter.immediate32(imm);
767 void subl_im(int imm, int offset, RegisterID base)
769 js::JaegerSpew(js::JSpew_Insns,
770 IPFX "subl $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
771 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(4, base));
772 if (CAN_SIGN_EXTEND_8_32(imm)) {
773 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset);
774 m_formatter.immediate8(imm);
776 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset);
777 m_formatter.immediate32(imm);
782 void subq_rr(RegisterID src, RegisterID dst)
785 m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst);
788 void subq_ir(int imm, RegisterID dst)
790 js::JaegerSpew(js::JSpew_Insns,
791 IPFX "subq $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
792 if (CAN_SIGN_EXTEND_8_32(imm)) {
793 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
794 m_formatter.immediate8(imm);
796 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
797 m_formatter.immediate32(imm);
801 void subl_im(int imm, void* addr)
804 if (CAN_SIGN_EXTEND_8_32(imm)) {
805 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
806 m_formatter.immediate8(imm);
808 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr);
809 m_formatter.immediate32(imm);
814 void xorl_rr(RegisterID src, RegisterID dst)
816 js::JaegerSpew(js::JSpew_Insns,
817 IPFX "xorl %s, %s\n", MAYBE_PAD,
818 nameIReg(4,src), nameIReg(4,dst));
819 m_formatter.oneByteOp(OP_XOR_EvGv, src, dst);
822 void xorl_mr(int offset, RegisterID base, RegisterID dst)
825 m_formatter.oneByteOp(OP_XOR_GvEv, dst, base, offset);
828 void xorl_rm(RegisterID src, int offset, RegisterID base)
831 m_formatter.oneByteOp(OP_XOR_EvGv, src, base, offset);
834 void xorl_im(int imm, int offset, RegisterID base)
837 if (CAN_SIGN_EXTEND_8_32(imm)) {
838 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, offset);
839 m_formatter.immediate8(imm);
841 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, offset);
842 m_formatter.immediate32(imm);
846 void xorl_ir(int imm, RegisterID dst)
848 js::JaegerSpew(js::JSpew_Insns,
849 IPFX "xorl %d, %s\n", MAYBE_PAD,
850 imm, nameIReg(4,dst));
851 if (CAN_SIGN_EXTEND_8_32(imm)) {
852 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
853 m_formatter.immediate8(imm);
855 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
856 m_formatter.immediate32(imm);
861 void xorq_rr(RegisterID src, RegisterID dst)
863 js::JaegerSpew(js::JSpew_Insns,
864 IPFX "xorq %s, %s\n", MAYBE_PAD,
865 nameIReg(8,src), nameIReg(8, dst));
866 m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
869 void xorq_ir(int imm, RegisterID dst)
871 js::JaegerSpew(js::JSpew_Insns,
872 IPFX "xorq %d, %s\n", MAYBE_PAD,
873 imm, nameIReg(8,dst));
874 if (CAN_SIGN_EXTEND_8_32(imm)) {
875 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
876 m_formatter.immediate8(imm);
878 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
879 m_formatter.immediate32(imm);
884 void sarl_i8r(int imm, RegisterID dst)
886 js::JaegerSpew(js::JSpew_Insns,
887 IPFX "sarl $%d, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
889 m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
891 m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
892 m_formatter.immediate8(imm);
896 void sarl_CLr(RegisterID dst)
898 js::JaegerSpew(js::JSpew_Insns,
899 IPFX "sarl %%cl, %s\n", MAYBE_PAD, nameIReg(4, dst));
900 m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
903 void shrl_i8r(int imm, RegisterID dst)
906 m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
908 m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHR, dst);
909 m_formatter.immediate8(imm);
913 void shrl_CLr(RegisterID dst)
915 m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst);
918 void shll_i8r(int imm, RegisterID dst)
920 js::JaegerSpew(js::JSpew_Insns,
921 IPFX "shll $%d, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
923 m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
925 m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
926 m_formatter.immediate8(imm);
930 void shll_CLr(RegisterID dst)
932 js::JaegerSpew(js::JSpew_Insns,
933 IPFX "shll %%cl, %s\n", MAYBE_PAD, nameIReg(4, dst));
934 m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
938 void sarq_CLr(RegisterID dst)
941 m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
944 void sarq_i8r(int imm, RegisterID dst)
946 js::JaegerSpew(js::JSpew_Insns,
947 IPFX "sarq $%d, %s\n", MAYBE_PAD, imm, nameIReg(8, dst));
949 m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
951 m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
952 m_formatter.immediate8(imm);
956 void shlq_i8r(int imm, RegisterID dst)
958 js::JaegerSpew(js::JSpew_Insns,
959 IPFX "shlq $%d, %s\n", MAYBE_PAD, imm, nameIReg(8, dst));
961 m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
963 m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
964 m_formatter.immediate8(imm);
969 void imull_rr(RegisterID src, RegisterID dst)
971 js::JaegerSpew(js::JSpew_Insns,
972 IPFX "imull %s, %s\n", MAYBE_PAD, nameIReg(4,src), nameIReg(4, dst));
973 m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
976 void imull_mr(int offset, RegisterID base, RegisterID dst)
979 m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, base, offset);
982 void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
985 m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src);
986 m_formatter.immediate32(value);
989 void idivl_r(RegisterID dst)
991 js::JaegerSpew(js::JSpew_Insns,
992 IPFX "idivl %s\n", MAYBE_PAD,
994 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst);
999 void cmpl_rr(RegisterID src, RegisterID dst)
1001 js::JaegerSpew(js::JSpew_Insns,
1002 IPFX "cmpl %s, %s\n", MAYBE_PAD,
1003 nameIReg(4, src), nameIReg(4, dst));
1004 m_formatter.oneByteOp(OP_CMP_EvGv, src, dst);
1007 void cmpl_rm(RegisterID src, int offset, RegisterID base)
1009 js::JaegerSpew(js::JSpew_Insns,
1010 IPFX "cmpl %s, %s0x%x(%s)\n", MAYBE_PAD,
1011 nameIReg(4, src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1012 m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset);
1015 void cmpl_mr(int offset, RegisterID base, RegisterID src)
1017 js::JaegerSpew(js::JSpew_Insns,
1018 IPFX "cmpl %s0x%x(%s), %s\n", MAYBE_PAD,
1019 PRETTY_PRINT_OFFSET(offset), nameIReg(4, base), nameIReg(src));
1020 m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset);
1023 void cmpl_ir(int imm, RegisterID dst)
1025 js::JaegerSpew(js::JSpew_Insns,
1026 IPFX "cmpl $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
1027 if (CAN_SIGN_EXTEND_8_32(imm)) {
1028 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
1029 m_formatter.immediate8(imm);
1031 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
1032 m_formatter.immediate32(imm);
1036 void cmpl_ir_force32(int imm, RegisterID dst)
1038 js::JaegerSpew(js::JSpew_Insns,
1039 IPFX "cmpl $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
1040 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
1041 m_formatter.immediate32(imm);
1044 void cmpl_im(int imm, int offset, RegisterID base)
1046 js::JaegerSpew(js::JSpew_Insns,
1047 IPFX "cmpl $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1048 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(4,base));
1049 if (CAN_SIGN_EXTEND_8_32(imm)) {
1050 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
1051 m_formatter.immediate8(imm);
1053 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
1054 m_formatter.immediate32(imm);
1058 void cmpb_im(int imm, int offset, RegisterID base)
1060 m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, offset);
1061 m_formatter.immediate8(imm);
1064 void cmpb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1066 m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, index, scale, offset);
1067 m_formatter.immediate8(imm);
1070 void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1072 js::JaegerSpew(js::JSpew_Insns,
1073 IPFX "cmpl %d, %d(%s,%s,%d)\n", MAYBE_PAD,
1074 imm, offset, nameIReg(4,base), nameIReg(4,index), scale);
1075 if (CAN_SIGN_EXTEND_8_32(imm)) {
1076 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
1077 m_formatter.immediate8(imm);
1079 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
1080 m_formatter.immediate32(imm);
1084 void cmpl_im_force32(int imm, int offset, RegisterID base)
1086 FIXME_INSN_PRINTING;
1087 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
1088 m_formatter.immediate32(imm);
1092 void cmpq_rr(RegisterID src, RegisterID dst)
1094 js::JaegerSpew(js::JSpew_Insns,
1095 IPFX "cmpq %s, %s\n", MAYBE_PAD,
1096 nameIReg(8, src), nameIReg(8, dst));
1097 m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst);
1100 void cmpq_rm(RegisterID src, int offset, RegisterID base)
1102 js::JaegerSpew(js::JSpew_Insns,
1103 IPFX "cmpq %s, %d(%s)\n", MAYBE_PAD,
1104 nameIReg(8, src), offset, nameIReg(8, base));
1105 m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, offset);
1108 void cmpq_mr(int offset, RegisterID base, RegisterID src)
1110 js::JaegerSpew(js::JSpew_Insns,
1111 IPFX "cmpq %d(%s), %s\n", MAYBE_PAD,
1112 offset, nameIReg(8, base), nameIReg(8, src));
1113 m_formatter.oneByteOp64(OP_CMP_GvEv, src, base, offset);
1116 void cmpq_ir(int imm, RegisterID dst)
1118 js::JaegerSpew(js::JSpew_Insns,
1119 IPFX "cmpq %d, %s\n", MAYBE_PAD,
1120 imm, nameIReg(8, dst));
1121 if (CAN_SIGN_EXTEND_8_32(imm)) {
1122 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
1123 m_formatter.immediate8(imm);
1125 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
1126 m_formatter.immediate32(imm);
1130 void cmpq_im(int imm, int offset, RegisterID base)
1132 FIXME_INSN_PRINTING;
1133 if (CAN_SIGN_EXTEND_8_32(imm)) {
1134 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
1135 m_formatter.immediate8(imm);
1137 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
1138 m_formatter.immediate32(imm);
1142 void cmpq_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1144 FIXME_INSN_PRINTING;
1145 if (CAN_SIGN_EXTEND_8_32(imm)) {
1146 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
1147 m_formatter.immediate8(imm);
1149 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
1150 m_formatter.immediate32(imm);
1154 void cmpl_rm(RegisterID reg, void* addr)
1156 FIXME_INSN_PRINTING;
1157 m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr);
1160 void cmpl_im(int imm, void* addr)
1162 FIXME_INSN_PRINTING;
1163 if (CAN_SIGN_EXTEND_8_32(imm)) {
1164 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
1165 m_formatter.immediate8(imm);
1167 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
1168 m_formatter.immediate32(imm);
1173 void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1175 FIXME_INSN_PRINTING;
1176 m_formatter.prefix(PRE_OPERAND_SIZE);
1177 m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset);
1180 void cmpw_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1182 FIXME_INSN_PRINTING;
1183 if (CAN_SIGN_EXTEND_8_32(imm)) {
1184 m_formatter.prefix(PRE_OPERAND_SIZE);
1185 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
1186 m_formatter.immediate8(imm);
1188 m_formatter.prefix(PRE_OPERAND_SIZE);
1189 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
1190 m_formatter.immediate16(imm);
1194 void testl_rr(RegisterID src, RegisterID dst)
1196 js::JaegerSpew(js::JSpew_Insns,
1197 IPFX "testl %s, %s\n", MAYBE_PAD,
1198 nameIReg(4,src), nameIReg(4,dst));
1199 m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
1202 void testl_i32r(int imm, RegisterID dst)
1204 js::JaegerSpew(js::JSpew_Insns,
1205 IPFX "testl $0x%x, %s\n", MAYBE_PAD,
1206 imm, nameIReg(dst));
1207 m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
1208 m_formatter.immediate32(imm);
1211 void testl_i32m(int imm, int offset, RegisterID base)
1213 js::JaegerSpew(js::JSpew_Insns,
1214 IPFX "testl $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1215 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1216 m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
1217 m_formatter.immediate32(imm);
1220 void testb_im(int imm, int offset, RegisterID base)
1222 m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset);
1223 m_formatter.immediate8(imm);
1226 void testb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1228 m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, index, scale, offset);
1229 m_formatter.immediate8(imm);
1232 void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1234 FIXME_INSN_PRINTING;
1235 m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
1236 m_formatter.immediate32(imm);
1240 void testq_rr(RegisterID src, RegisterID dst)
1242 js::JaegerSpew(js::JSpew_Insns,
1243 IPFX "testq %s, %s\n", MAYBE_PAD,
1244 nameIReg(8,src), nameIReg(8,dst));
1245 m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst);
1248 void testq_i32r(int imm, RegisterID dst)
1250 FIXME_INSN_PRINTING;
1251 m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
1252 m_formatter.immediate32(imm);
1255 void testq_i32m(int imm, int offset, RegisterID base)
1257 js::JaegerSpew(js::JSpew_Insns,
1258 IPFX "testq $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1259 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1260 m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
1261 m_formatter.immediate32(imm);
1264 void testq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1266 FIXME_INSN_PRINTING;
1267 m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
1268 m_formatter.immediate32(imm);
1272 void testw_rr(RegisterID src, RegisterID dst)
1274 FIXME_INSN_PRINTING;
1275 m_formatter.prefix(PRE_OPERAND_SIZE);
1276 m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
1279 void testb_i8r(int imm, RegisterID dst)
1281 js::JaegerSpew(js::JSpew_Insns,
1282 IPFX "testb $0x%x, %s\n", MAYBE_PAD,
1283 imm, nameIReg(1,dst));
1284 m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst);
1285 m_formatter.immediate8(imm);
1288 void setCC_r(Condition cond, RegisterID dst)
1290 js::JaegerSpew(js::JSpew_Insns,
1291 IPFX "set%s %s\n", MAYBE_PAD,
1292 nameCC(cond), nameIReg(1,dst));
1293 m_formatter.twoByteOp8(setccOpcode(cond), (GroupOpcodeID)0, dst);
1296 void sete_r(RegisterID dst)
1298 FIXME_INSN_PRINTING;
1299 m_formatter.twoByteOp8(setccOpcode(ConditionE), (GroupOpcodeID)0, dst);
1302 void setz_r(RegisterID dst)
1304 FIXME_INSN_PRINTING;
1308 void setne_r(RegisterID dst)
1310 FIXME_INSN_PRINTING;
1311 m_formatter.twoByteOp8(setccOpcode(ConditionNE), (GroupOpcodeID)0, dst);
1314 void setnz_r(RegisterID dst)
1316 FIXME_INSN_PRINTING;
1320 // Various move ops:
1324 js::JaegerSpew(js::JSpew_Insns,
1325 IPFX "cdq \n", MAYBE_PAD);
1326 m_formatter.oneByteOp(OP_CDQ);
1329 void xchgl_rr(RegisterID src, RegisterID dst)
1331 js::JaegerSpew(js::JSpew_Insns,
1332 IPFX "xchgl %s, %s\n", MAYBE_PAD,
1333 nameIReg(4,src), nameIReg(4,dst));
1334 m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
1338 void xchgq_rr(RegisterID src, RegisterID dst)
1340 js::JaegerSpew(js::JSpew_Insns,
1341 IPFX "xchgq %s, %s\n", MAYBE_PAD,
1342 nameIReg(8,src), nameIReg(8,dst));
1343 m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
1347 void movl_rr(RegisterID src, RegisterID dst)
1349 js::JaegerSpew(js::JSpew_Insns,
1350 IPFX "movl %s, %s\n", MAYBE_PAD,
1351 nameIReg(4,src), nameIReg(4,dst));
1352 m_formatter.oneByteOp(OP_MOV_EvGv, src, dst);
1355 void movw_rm(RegisterID src, int offset, RegisterID base)
1357 js::JaegerSpew(js::JSpew_Insns,
1358 IPFX "movw %s, %s0x%x(%s)\n", MAYBE_PAD,
1359 nameIReg(2,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1360 m_formatter.prefix(PRE_OPERAND_SIZE);
1361 m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
1364 void movl_rm(RegisterID src, int offset, RegisterID base)
1366 js::JaegerSpew(js::JSpew_Insns,
1367 IPFX "movl %s, %s0x%x(%s)\n", MAYBE_PAD,
1368 nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1369 m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
1372 void movl_rm_disp32(RegisterID src, int offset, RegisterID base)
1374 FIXME_INSN_PRINTING;
1375 m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset);
1378 void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1380 js::JaegerSpew(js::JSpew_Insns,
1381 IPFX "movw %s, %d(%s,%s,%d)\n", MAYBE_PAD,
1382 nameIReg(2, src), offset, nameIReg(base), nameIReg(index), scale);
1383 m_formatter.prefix(PRE_OPERAND_SIZE);
1384 m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
1387 void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1389 js::JaegerSpew(js::JSpew_Insns,
1390 IPFX "movl %s, %d(%s,%s,%d)\n", MAYBE_PAD,
1391 nameIReg(4, src), offset, nameIReg(base), nameIReg(index), scale);
1392 m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
1395 void movl_mEAX(void* addr)
1397 FIXME_INSN_PRINTING;
1398 m_formatter.oneByteOp(OP_MOV_EAXOv);
1400 m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1402 m_formatter.immediate32(reinterpret_cast<int>(addr));
1406 void movl_mr(int offset, RegisterID base, RegisterID dst)
1408 js::JaegerSpew(js::JSpew_Insns,
1409 IPFX "movl %s0x%x(%s), %s\n", MAYBE_PAD,
1410 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1411 m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset);
1414 void movl_mr_disp32(int offset, RegisterID base, RegisterID dst)
1416 FIXME_INSN_PRINTING;
1417 m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
1420 void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1422 js::JaegerSpew(js::JSpew_Insns,
1423 IPFX "movl %d(%s,%s,%d), %s\n", MAYBE_PAD,
1424 offset, nameIReg(base), nameIReg(index), scale, nameIReg(4, dst));
1425 m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset);
1428 void movl_i32r(int imm, RegisterID dst)
1430 js::JaegerSpew(js::JSpew_Insns,
1431 IPFX "movl $0x%x, %s\n", MAYBE_PAD,
1432 imm, nameIReg(dst));
1433 m_formatter.oneByteOp(OP_MOV_EAXIv, dst);
1434 m_formatter.immediate32(imm);
1437 void movb_i8m(int imm, int offset, RegisterID base)
1439 js::JaegerSpew(js::JSpew_Insns,
1440 IPFX "movb $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1441 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1442 m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, offset);
1443 m_formatter.immediate8(imm);
1446 void movb_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1448 js::JaegerSpew(js::JSpew_Insns,
1449 IPFX "movb $0x%x, %d(%s,%s,%d)\n", MAYBE_PAD,
1450 imm, offset, nameIReg(base), nameIReg(index), scale);
1451 m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, index, scale, offset);
1452 m_formatter.immediate8(imm);
1455 void movw_i16m(int imm, int offset, RegisterID base)
1457 js::JaegerSpew(js::JSpew_Insns,
1458 IPFX "movw $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1459 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1460 m_formatter.prefix(PRE_OPERAND_SIZE);
1461 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
1462 m_formatter.immediate16(imm);
1465 void movl_i32m(int imm, int offset, RegisterID base)
1467 js::JaegerSpew(js::JSpew_Insns,
1468 IPFX "movl $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1469 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1470 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
1471 m_formatter.immediate32(imm);
1474 void movw_i16m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1476 js::JaegerSpew(js::JSpew_Insns,
1477 IPFX "movw $0x%x, %d(%s,%s,%d)\n", MAYBE_PAD,
1478 imm, offset, nameIReg(base), nameIReg(index), scale);
1479 m_formatter.prefix(PRE_OPERAND_SIZE);
1480 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
1481 m_formatter.immediate16(imm);
1484 void movl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1486 js::JaegerSpew(js::JSpew_Insns,
1487 IPFX "movl $0x%x, %d(%s,%s,%d)\n", MAYBE_PAD,
1488 imm, offset, nameIReg(base), nameIReg(index), scale);
1489 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
1490 m_formatter.immediate32(imm);
1493 void movl_EAXm(void* addr)
1495 FIXME_INSN_PRINTING;
1496 m_formatter.oneByteOp(OP_MOV_OvEAX);
1498 m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1500 m_formatter.immediate32(reinterpret_cast<int>(addr));
1505 void movq_rr(RegisterID src, RegisterID dst)
1507 js::JaegerSpew(js::JSpew_Insns,
1508 IPFX "movq %s, %s\n", MAYBE_PAD,
1509 nameIReg(8,src), nameIReg(8,dst));
1510 m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst);
1513 void movq_rm(RegisterID src, int offset, RegisterID base)
1515 js::JaegerSpew(js::JSpew_Insns,
1516 IPFX "movq %s, %s0x%x(%s)\n", MAYBE_PAD,
1517 nameIReg(8,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1518 m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, offset);
1521 void movq_rm_disp32(RegisterID src, int offset, RegisterID base)
1523 FIXME_INSN_PRINTING;
1524 m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, src, base, offset);
1527 void movq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1529 js::JaegerSpew(js::JSpew_Insns,
1530 IPFX "movq %s, %s0x%x(%s)\n", MAYBE_PAD,
1531 nameIReg(8,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1532 m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
1535 void movq_mEAX(void* addr)
1537 FIXME_INSN_PRINTING;
1538 m_formatter.oneByteOp64(OP_MOV_EAXOv);
1539 m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1542 void movq_EAXm(void* addr)
1544 FIXME_INSN_PRINTING;
1545 m_formatter.oneByteOp64(OP_MOV_OvEAX);
1546 m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1549 void movq_mr(int offset, RegisterID base, RegisterID dst)
1551 js::JaegerSpew(js::JSpew_Insns,
1552 IPFX "movq %s0x%x(%s), %s\n", MAYBE_PAD,
1553 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(8,dst));
1554 m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset);
1557 void movq_mr_disp32(int offset, RegisterID base, RegisterID dst)
1559 FIXME_INSN_PRINTING;
1560 m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, dst, base, offset);
1563 void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1565 js::JaegerSpew(js::JSpew_Insns,
1566 IPFX "movq %s0x%x(%s), %s\n", MAYBE_PAD,
1567 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(8,dst));
1568 m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
1571 void leaq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1573 js::JaegerSpew(js::JSpew_Insns,
1574 IPFX "leaq %d(%s,%s,%d), %s\n", MAYBE_PAD,
1575 offset, nameIReg(base), nameIReg(index), scale, nameIReg(8,dst)),
1576 m_formatter.oneByteOp64(OP_LEA, dst, base, index, scale, offset);
1579 void movq_i32m(int imm, int offset, RegisterID base)
1581 js::JaegerSpew(js::JSpew_Insns,
1582 IPFX "movq $%d, %s0x%x(%s)\n", MAYBE_PAD,
1583 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1584 m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
1585 m_formatter.immediate32(imm);
1588 void movq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1590 js::JaegerSpew(js::JSpew_Insns,
1591 IPFX "movq $%d, %s0x%x(%s)\n", MAYBE_PAD,
1592 imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1593 m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
1594 m_formatter.immediate32(imm);
1597 void movq_i64r(int64_t imm, RegisterID dst)
1599 js::JaegerSpew(js::JSpew_Insns,
1600 IPFX "movabsq $0x%llx, %s\n", MAYBE_PAD,
1601 (unsigned long long int)imm, nameIReg(8,dst));
1602 m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
1603 m_formatter.immediate64(imm);
1606 void movsxd_rr(RegisterID src, RegisterID dst)
1608 js::JaegerSpew(js::JSpew_Insns,
1609 IPFX "movsxd %s, %s\n", MAYBE_PAD,
1610 nameIReg(4, src), nameIReg(8, dst));
1611 m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src);
1616 void movl_rm(RegisterID src, void* addr)
1618 FIXME_INSN_PRINTING;
1619 if (src == X86Registers::eax)
1622 m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
1625 void movl_mr(void* addr, RegisterID dst)
1627 js::JaegerSpew(js::JSpew_Insns,
1628 IPFX "movl 0(%p), %s\n", MAYBE_PAD,
1629 addr, nameIReg(4, dst));
1630 if (dst == X86Registers::eax)
1633 m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
1636 void movl_i32m(int imm, void* addr)
1638 FIXME_INSN_PRINTING;
1639 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
1640 m_formatter.immediate32(imm);
1644 void movb_rm(RegisterID src, int offset, RegisterID base)
1646 js::JaegerSpew(js::JSpew_Insns,
1647 IPFX "movb %s, %s0x%x(%s)\n", MAYBE_PAD,
1648 nameIReg(1, src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1649 m_formatter.oneByteOp8(OP_MOV_EbGv, src, base, offset);
1652 void movb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1654 js::JaegerSpew(js::JSpew_Insns,
1655 IPFX "movb %s, %d(%s,%s,%d)\n", MAYBE_PAD,
1656 nameIReg(1, src), offset, nameIReg(base), nameIReg(index), scale);
1657 m_formatter.oneByteOp8(OP_MOV_EbGv, src, base, index, scale, offset);
1660 void movzbl_mr(int offset, RegisterID base, RegisterID dst)
1662 js::JaegerSpew(js::JSpew_Insns,
1663 IPFX "movzbl %s0x%x(%s), %s\n", MAYBE_PAD,
1664 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1665 m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, offset);
1668 void movzbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1670 js::JaegerSpew(js::JSpew_Insns,
1671 IPFX "movzbl %d(%s,%s,%d), %s\n", MAYBE_PAD,
1672 offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1673 m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, index, scale, offset);
1676 void movxbl_mr(int offset, RegisterID base, RegisterID dst)
1678 js::JaegerSpew(js::JSpew_Insns,
1679 IPFX "movxbl %s0x%x(%s), %s\n", MAYBE_PAD,
1680 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1681 m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, offset);
1684 void movxbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1686 js::JaegerSpew(js::JSpew_Insns,
1687 IPFX "movxbl %d(%s,%s,%d), %s\n", MAYBE_PAD,
1688 offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1689 m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, index, scale, offset);
1692 void movzwl_mr(int offset, RegisterID base, RegisterID dst)
1694 js::JaegerSpew(js::JSpew_Insns,
1695 IPFX "movzwl %s0x%x(%s), %s\n", MAYBE_PAD,
1696 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1697 m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset);
1700 void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1702 js::JaegerSpew(js::JSpew_Insns,
1703 IPFX "movzwl %d(%s,%s,%d), %s\n", MAYBE_PAD,
1704 offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1705 m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset);
1708 void movxwl_mr(int offset, RegisterID base, RegisterID dst)
1710 js::JaegerSpew(js::JSpew_Insns,
1711 IPFX "movxwl %s0x%x(%s), %s\n", MAYBE_PAD,
1712 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1713 m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, offset);
1716 void movxwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1718 js::JaegerSpew(js::JSpew_Insns,
1719 IPFX "movxwl %d(%s,%s,%d), %s\n", MAYBE_PAD,
1720 offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1721 m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, index, scale, offset);
1724 void movzbl_rr(RegisterID src, RegisterID dst)
1726 // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
1727 // is in the range ESP-EDI, and the src would not have required a REX). Unneeded
1728 // REX prefixes are defined to be silently ignored by the processor.
1729 js::JaegerSpew(js::JSpew_Insns,
1730 IPFX "movzbl %s, %s\n", MAYBE_PAD,
1731 nameIReg(4,src), nameIReg(4,dst));
1732 m_formatter.twoByteOp8(OP2_MOVZX_GvEb, dst, src);
1735 void leal_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1737 js::JaegerSpew(js::JSpew_Insns,
1738 IPFX "leal %d(%s,%s,%d), %s\n", MAYBE_PAD,
1739 offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1740 m_formatter.oneByteOp(OP_LEA, dst, base, index, scale, offset);
1743 void leal_mr(int offset, RegisterID base, RegisterID dst)
1745 js::JaegerSpew(js::JSpew_Insns,
1746 IPFX "leal %s0x%x(%s), %s\n", MAYBE_PAD,
1747 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
1748 m_formatter.oneByteOp(OP_LEA, dst, base, offset);
1751 void leaq_mr(int offset, RegisterID base, RegisterID dst)
1753 js::JaegerSpew(js::JSpew_Insns,
1754 IPFX "leaq %s0x%x(%s), %s\n", MAYBE_PAD,
1755 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(8,dst));
1756 m_formatter.oneByteOp64(OP_LEA, dst, base, offset);
1764 m_formatter.oneByteOp(OP_CALL_rel32);
1765 JmpSrc r = m_formatter.immediateRel32();
1766 js::JaegerSpew(js::JSpew_Insns,
1767 IPFX "call ((%d))\n", MAYBE_PAD, r.m_offset);
1771 JmpSrc call(RegisterID dst)
1773 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
1774 JmpSrc r = JmpSrc(m_formatter.size());
1775 js::JaegerSpew(js::JSpew_Insns,
1776 IPFX "call *%s\n", MAYBE_PAD, nameIReg(dst));
1780 void call_m(int offset, RegisterID base)
1782 FIXME_INSN_PRINTING;
1783 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, base, offset);
1788 m_formatter.oneByteOp(OP_JMP_rel32);
1789 JmpSrc r = m_formatter.immediateRel32();
1790 js::JaegerSpew(js::JSpew_Insns,
1791 IPFX "jmp ((%d))\n", MAYBE_PAD, r.m_offset);
1795 // Return a JmpSrc so we have a label to the jump, so we can use this
1796 // To make a tail recursive call on x86-64. The MacroAssembler
1797 // really shouldn't wrap this as a Jump, since it can't be linked. :-/
1798 JmpSrc jmp_r(RegisterID dst)
1800 js::JaegerSpew(js::JSpew_Insns,
1801 IPFX "jmp ((%s))\n", MAYBE_PAD,
1803 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
1804 return JmpSrc(m_formatter.size());
1807 void jmp_m(int offset, RegisterID base)
1809 FIXME_INSN_PRINTING;
1810 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
1813 void jmp_m(int offset, RegisterID base, RegisterID index, int scale) {
1814 js::JaegerSpew(js::JSpew_Insns,
1815 IPFX "jmp ((%d(%s,%s,%d)))\n", MAYBE_PAD,
1816 offset, nameIReg(base), nameIReg(index), scale);
1817 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, index, scale, offset);
1822 return jCC(ConditionNE);
1827 // printing done by jne()
1833 FIXME_INSN_PRINTING;
1834 m_formatter.twoByteOp(jccRel32(ConditionE));
1835 return m_formatter.immediateRel32();
1840 // printing done by je()
1846 FIXME_INSN_PRINTING;
1847 m_formatter.twoByteOp(jccRel32(ConditionL));
1848 return m_formatter.immediateRel32();
1853 FIXME_INSN_PRINTING;
1854 m_formatter.twoByteOp(jccRel32(ConditionB));
1855 return m_formatter.immediateRel32();
1860 FIXME_INSN_PRINTING;
1861 m_formatter.twoByteOp(jccRel32(ConditionLE));
1862 return m_formatter.immediateRel32();
1867 FIXME_INSN_PRINTING;
1868 m_formatter.twoByteOp(jccRel32(ConditionBE));
1869 return m_formatter.immediateRel32();
1874 FIXME_INSN_PRINTING;
1875 m_formatter.twoByteOp(jccRel32(ConditionGE));
1876 return m_formatter.immediateRel32();
1881 FIXME_INSN_PRINTING;
1882 m_formatter.twoByteOp(jccRel32(ConditionG));
1883 return m_formatter.immediateRel32();
1888 FIXME_INSN_PRINTING;
1889 m_formatter.twoByteOp(jccRel32(ConditionA));
1890 return m_formatter.immediateRel32();
1895 FIXME_INSN_PRINTING;
1896 m_formatter.twoByteOp(jccRel32(ConditionAE));
1897 return m_formatter.immediateRel32();
1902 FIXME_INSN_PRINTING;
1903 m_formatter.twoByteOp(jccRel32(ConditionO));
1904 return m_formatter.immediateRel32();
1909 return jCC(ConditionP);
1914 FIXME_INSN_PRINTING;
1915 m_formatter.twoByteOp(jccRel32(ConditionS));
1916 return m_formatter.immediateRel32();
1919 JmpSrc jCC(Condition cond)
1921 m_formatter.twoByteOp(jccRel32(cond));
1922 JmpSrc r = m_formatter.immediateRel32();
1923 js::JaegerSpew(js::JSpew_Insns,
1924 IPFX "j%s ((%d))\n", MAYBE_PAD,
1925 nameCC(cond), r.m_offset);
1931 void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
1933 js::JaegerSpew(js::JSpew_Insns,
1934 IPFX "addsd %s, %s\n", MAYBE_PAD,
1935 nameFPReg(src), nameFPReg(dst));
1936 m_formatter.prefix(PRE_SSE_F2);
1937 m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
1940 void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1942 js::JaegerSpew(js::JSpew_Insns,
1943 IPFX "addsd %s0x%x(%s), %s\n", MAYBE_PAD,
1944 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
1945 m_formatter.prefix(PRE_SSE_F2);
1946 m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
1949 void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
1951 js::JaegerSpew(js::JSpew_Insns,
1952 IPFX "cvtps2pd %s, %s\n", MAYBE_PAD,
1953 nameFPReg(src), nameFPReg(dst));
1954 m_formatter.prefix(PRE_SSE_F3);
1955 m_formatter.twoByteOp(OP2_CVTSS2SD_VsdEd, (RegisterID)dst, (RegisterID)src);
1958 void cvtsd2ss_rr(XMMRegisterID src, XMMRegisterID dst)
1960 js::JaegerSpew(js::JSpew_Insns,
1961 IPFX "cvtps2pd %s, %s\n", MAYBE_PAD,
1962 nameFPReg(src), nameFPReg(dst));
1963 m_formatter.prefix(PRE_SSE_F2);
1964 m_formatter.twoByteOp(OP2_CVTSD2SS_VsdEd, (RegisterID)dst, (RegisterID)src);
1967 void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
1969 js::JaegerSpew(js::JSpew_Insns,
1970 IPFX "cvtsi2sd %s, %s\n", MAYBE_PAD,
1971 nameIReg(src), nameFPReg(dst));
1972 m_formatter.prefix(PRE_SSE_F2);
1973 m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
1977 void cvtsq2sd_rr(RegisterID src, XMMRegisterID dst)
1979 js::JaegerSpew(js::JSpew_Insns,
1980 IPFX "cvtsq2sd %s, %s\n", MAYBE_PAD,
1981 nameIReg(src), nameFPReg(dst));
1982 m_formatter.prefix(PRE_SSE_F2);
1983 m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
1987 void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
1989 js::JaegerSpew(js::JSpew_Insns,
1990 IPFX "cvtsi2sd %s0x%x(%s), %s\n", MAYBE_PAD,
1991 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
1992 m_formatter.prefix(PRE_SSE_F2);
1993 m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
1997 void cvtsi2sd_mr(void* address, XMMRegisterID dst)
1999 js::JaegerSpew(js::JSpew_Insns,
2000 IPFX "cvtsi2sd %p, %s\n", MAYBE_PAD,
2001 address, nameFPReg(dst));
2002 m_formatter.prefix(PRE_SSE_F2);
2003 m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address);
2007 void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
2009 js::JaegerSpew(js::JSpew_Insns,
2010 IPFX "cvttsd2si %s, %s\n", MAYBE_PAD,
2011 nameFPReg(src), nameIReg(dst));
2012 m_formatter.prefix(PRE_SSE_F2);
2013 m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
2016 void unpcklps_rr(XMMRegisterID src, XMMRegisterID dst)
2018 js::JaegerSpew(js::JSpew_Insns,
2019 IPFX "unpcklps %s, %s\n", MAYBE_PAD,
2020 nameFPReg(src), nameFPReg(dst));
2021 m_formatter.twoByteOp(OP2_UNPCKLPS_VsdWsd, (RegisterID)dst, (RegisterID)src);
2024 void movd_rr(RegisterID src, XMMRegisterID dst)
2026 js::JaegerSpew(js::JSpew_Insns,
2027 IPFX "movd %s, %s\n", MAYBE_PAD,
2028 nameIReg(src), nameFPReg(dst));
2029 m_formatter.prefix(PRE_SSE_66);
2030 m_formatter.twoByteOp(OP2_MOVD_VdEd, (RegisterID)dst, src);
2033 void psrldq_rr(XMMRegisterID dest, int shift)
2035 js::JaegerSpew(js::JSpew_Insns,
2036 IPFX "pslldq %s, %d\n", MAYBE_PAD,
2037 nameFPReg(dest), shift);
2038 m_formatter.prefix(PRE_SSE_66);
2039 m_formatter.twoByteOp(OP2_PSRLDQ_Vd, (RegisterID)3, (RegisterID)dest);
2040 m_formatter.immediate8(shift);
2043 void movd_rr(XMMRegisterID src, RegisterID dst)
2045 js::JaegerSpew(js::JSpew_Insns,
2046 IPFX "movd %s, %s\n", MAYBE_PAD,
2047 nameFPReg(src), nameIReg(dst));
2048 m_formatter.prefix(PRE_SSE_66);
2049 m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
2053 void movq_rr(XMMRegisterID src, RegisterID dst)
2055 js::JaegerSpew(js::JSpew_Insns,
2056 IPFX "movq %s, %s\n", MAYBE_PAD,
2057 nameFPReg(src), nameIReg(dst));
2058 m_formatter.prefix(PRE_SSE_66);
2059 m_formatter.twoByteOp64(OP2_MOVD_EdVd, (RegisterID)src, dst);
2062 void movq_rr(RegisterID src, XMMRegisterID dst)
2064 js::JaegerSpew(js::JSpew_Insns,
2065 IPFX "movq %s, %s\n", MAYBE_PAD,
2066 nameIReg(src), nameFPReg(dst));
2067 m_formatter.prefix(PRE_SSE_66);
2068 m_formatter.twoByteOp64(OP2_MOVD_VdEd, (RegisterID)dst, src);
2072 void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
2074 js::JaegerSpew(js::JSpew_Insns,
2075 IPFX "movsd %s, %s0x%x(%s)\n", MAYBE_PAD,
2076 nameFPReg(src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
2077 m_formatter.prefix(PRE_SSE_F2);
2078 m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
2081 void movss_rm(XMMRegisterID src, int offset, RegisterID base)
2083 js::JaegerSpew(js::JSpew_Insns,
2084 IPFX "movss %s, %s0x%x(%s)\n", MAYBE_PAD,
2085 nameFPReg(src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
2086 m_formatter.prefix(PRE_SSE_F3);
2087 m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
2090 void movss_mr(int offset, RegisterID base, XMMRegisterID dst)
2092 js::JaegerSpew(js::JSpew_Insns,
2093 IPFX "movss %s0x%x(%s), %s\n", MAYBE_PAD,
2094 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2095 m_formatter.prefix(PRE_SSE_F3);
2096 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
2099 void movsd_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
2101 js::JaegerSpew(js::JSpew_Insns,
2102 IPFX "movsd %s, %d(%s,%s,%d)\n", MAYBE_PAD,
2103 nameFPReg(src), offset, nameIReg(base), nameIReg(index), scale);
2104 m_formatter.prefix(PRE_SSE_F2);
2105 m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
2108 void movss_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
2110 js::JaegerSpew(js::JSpew_Insns,
2111 IPFX "movss %s, %d(%s,%s,%d)\n", MAYBE_PAD,
2112 nameFPReg(src), offset, nameIReg(base), nameIReg(index), scale);
2113 m_formatter.prefix(PRE_SSE_F3);
2114 m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
2117 void movss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
2119 js::JaegerSpew(js::JSpew_Insns,
2120 IPFX "movss %d(%s,%s,%d), %s\n", MAYBE_PAD,
2121 offset, nameIReg(base), nameIReg(index), scale, nameFPReg(dst));
2122 m_formatter.prefix(PRE_SSE_F3);
2123 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, index, scale, offset);
2126 void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2128 js::JaegerSpew(js::JSpew_Insns,
2129 IPFX "movsd %s0x%x(%s), %s\n", MAYBE_PAD,
2130 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2131 m_formatter.prefix(PRE_SSE_F2);
2132 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
2135 void movsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
2137 js::JaegerSpew(js::JSpew_Insns,
2138 IPFX "movsd %d(%s,%s,%d), %s\n", MAYBE_PAD,
2139 offset, nameIReg(base), nameIReg(index), scale, nameFPReg(dst));
2140 m_formatter.prefix(PRE_SSE_F2);
2141 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, index, scale, offset);
2144 void movsd_rr(XMMRegisterID src, XMMRegisterID dst)
2146 js::JaegerSpew(js::JSpew_Insns,
2147 IPFX "movsd %s, %s\n", MAYBE_PAD,
2148 nameFPReg(src), nameFPReg(dst));
2149 m_formatter.prefix(PRE_SSE_F2);
2150 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2154 void movsd_mr(const void* address, XMMRegisterID dst)
2156 js::JaegerSpew(js::JSpew_Insns,
2157 IPFX "movsd %p, %s\n", MAYBE_PAD,
2158 address, nameFPReg(dst));
2159 m_formatter.prefix(PRE_SSE_F2);
2160 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
2164 void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
2166 js::JaegerSpew(js::JSpew_Insns,
2167 IPFX "mulsd %s, %s\n", MAYBE_PAD,
2168 nameFPReg(src), nameFPReg(dst));
2169 m_formatter.prefix(PRE_SSE_F2);
2170 m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2173 void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2175 js::JaegerSpew(js::JSpew_Insns,
2176 IPFX "mulsd %s0x%x(%s), %s\n", MAYBE_PAD,
2177 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2178 m_formatter.prefix(PRE_SSE_F2);
2179 m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset);
2182 void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
2184 FIXME_INSN_PRINTING;
2185 m_formatter.prefix(PRE_SSE_66);
2186 m_formatter.twoByteOp(OP2_PEXTRW_GdUdIb, (RegisterID)dst, (RegisterID)src);
2187 m_formatter.immediate8(whichWord);
2190 void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
2192 js::JaegerSpew(js::JSpew_Insns,
2193 IPFX "subsd %s, %s\n", MAYBE_PAD,
2194 nameFPReg(src), nameFPReg(dst));
2195 m_formatter.prefix(PRE_SSE_F2);
2196 m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2199 void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2201 js::JaegerSpew(js::JSpew_Insns,
2202 IPFX "subsd %s0x%x(%s), %s\n", MAYBE_PAD,
2203 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2204 m_formatter.prefix(PRE_SSE_F2);
2205 m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset);
2208 void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst)
2210 js::JaegerSpew(js::JSpew_Insns,
2211 IPFX "ucomisd %s, %s\n", MAYBE_PAD,
2212 nameFPReg(src), nameFPReg(dst));
2213 m_formatter.prefix(PRE_SSE_66);
2214 m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2217 void ucomisd_mr(int offset, RegisterID base, XMMRegisterID dst)
2219 js::JaegerSpew(js::JSpew_Insns,
2220 IPFX "ucomisd %s0x%x(%s), %s\n", MAYBE_PAD,
2221 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2222 m_formatter.prefix(PRE_SSE_66);
2223 m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, base, offset);
2226 void divsd_rr(XMMRegisterID src, XMMRegisterID dst)
2228 js::JaegerSpew(js::JSpew_Insns,
2229 IPFX "divsd %s, %s\n", MAYBE_PAD,
2230 nameFPReg(src), nameFPReg(dst));
2231 m_formatter.prefix(PRE_SSE_F2);
2232 m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2235 void divsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2237 js::JaegerSpew(js::JSpew_Insns,
2238 IPFX "divsd %s0x%x(%s), %s\n", MAYBE_PAD,
2239 PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2240 m_formatter.prefix(PRE_SSE_F2);
2241 m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, base, offset);
2244 void xorpd_rr(XMMRegisterID src, XMMRegisterID dst)
2246 js::JaegerSpew(js::JSpew_Insns,
2247 IPFX "xorpd %s, %s\n", MAYBE_PAD,
2248 nameFPReg(src), nameFPReg(dst));
2249 m_formatter.prefix(PRE_SSE_66);
2250 m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
2253 void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
2255 js::JaegerSpew(js::JSpew_Insns,
2256 IPFX "sqrtsd %s, %s\n", MAYBE_PAD,
2257 nameFPReg(src), nameFPReg(dst));
2258 m_formatter.prefix(PRE_SSE_F2);
2259 m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2262 void pinsrd_rr(RegisterID src, XMMRegisterID dst)
2264 js::JaegerSpew(js::JSpew_Insns,
2265 IPFX "pinsrd $1, %s, %s\n", MAYBE_PAD,
2266 nameIReg(src), nameFPReg(dst));
2267 m_formatter.prefix(PRE_SSE_66);
2268 m_formatter.threeByteOp(OP3_PINSRD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2269 m_formatter.immediate8(0x01); // the $1
2272 // Misc instructions:
2276 js::JaegerSpew(js::JSpew_Insns, IPFX "int3\n", MAYBE_PAD);
2277 m_formatter.oneByteOp(OP_INT3);
2282 js::JaegerSpew(js::JSpew_Insns, IPFX "ret\n", MAYBE_PAD);
2283 m_formatter.oneByteOp(OP_RET);
2286 void predictNotTaken()
2288 FIXME_INSN_PRINTING;
2289 m_formatter.prefix(PRE_PREDICT_BRANCH_NOT_TAKEN);
2295 js::JaegerSpew(js::JSpew_Insns, IPFX "pusha\n", MAYBE_PAD);
2296 m_formatter.oneByteOp(OP_PUSHA);
2301 js::JaegerSpew(js::JSpew_Insns, IPFX "popa\n", MAYBE_PAD);
2302 m_formatter.oneByteOp(OP_POPA);
2306 // Assembler admin methods:
2310 JmpDst r = JmpDst(m_formatter.size());
2311 js::JaegerSpew(js::JSpew_Insns,
2312 IPFX "#label ((%d))\n", MAYBE_PAD, r.m_offset);
2316 static JmpDst labelFor(JmpSrc jump, intptr_t offset = 0)
2318 FIXME_INSN_PRINTING;
2319 return JmpDst(jump.m_offset + offset);
2322 JmpDst align(int alignment)
2324 FIXME_INSN_PRINTING;
2325 while (!m_formatter.isAligned(alignment))
2326 m_formatter.oneByteOp(OP_HLT);
2331 // Linking & patching:
2333 // 'link' and 'patch' methods are for use on unprotected code - such as the code
2334 // within the AssemblerBuffer, and code being patched by the patch buffer. Once
2335 // code has been finalized it is (platform support permitting) within a non-
2336 // writable region of memory; to modify the code in an execute-only execuable
2337 // pool the 'repatch' and 'relink' methods should be used.
2339 void linkJump(JmpSrc from, JmpDst to)
2341 ASSERT(from.m_offset != -1);
2342 ASSERT(to.m_offset != -1);
2344 js::JaegerSpew(js::JSpew_Insns,
2345 IPFX "##link ((%d)) jumps to ((%d))\n", MAYBE_PAD,
2346 from.m_offset, to.m_offset);
2347 char* code = reinterpret_cast<char*>(m_formatter.data());
2348 setRel32(code + from.m_offset, code + to.m_offset);
2351 static void linkJump(void* code, JmpSrc from, void* to)
2353 ASSERT(from.m_offset != -1);
2355 js::JaegerSpew(js::JSpew_Insns,
2356 ISPFX "##link ((%d)) jumps to ((%p))\n",
2358 setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
2361 static void linkCall(void* code, JmpSrc from, void* to)
2363 ASSERT(from.m_offset != -1);
2365 FIXME_INSN_PRINTING;
2366 setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
2369 static void linkPointer(void* code, JmpDst where, void* value)
2371 ASSERT(where.m_offset != -1);
2373 FIXME_INSN_PRINTING;
2374 setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
2377 static void relinkJump(void* from, void* to)
2379 js::JaegerSpew(js::JSpew_Insns,
2380 ISPFX "##relinkJump ((from=%p)) ((to=%p))\n",
2385 static bool canRelinkJump(void* from, void* to)
2387 intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
2388 return (offset == static_cast<int32_t>(offset));
2391 static void relinkCall(void* from, void* to)
2393 js::JaegerSpew(js::JSpew_Insns,
2394 ISPFX "##relinkCall ((from=%p)) ((to=%p))\n",
2399 static void repatchInt32(void* where, int32_t value)
2401 js::JaegerSpew(js::JSpew_Insns,
2402 ISPFX "##relinkInt32 ((where=%p)) ((value=%d))\n",
2404 setInt32(where, value);
2407 static void repatchPointer(void* where, void* value)
2409 js::JaegerSpew(js::JSpew_Insns,
2410 ISPFX "##repatchPtr ((where=%p)) ((value=%p))\n",
2412 setPointer(where, value);
2415 static void repatchLoadPtrToLEA(void* where)
2417 js::JaegerSpew(js::JSpew_Insns,
2418 ISPFX "##repatchLoadPtrToLEA ((where=%p))\n",
2422 // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
2423 // Skip over the prefix byte.
2424 where = reinterpret_cast<char*>(where) + 1;
2426 *reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_LEA);
2429 static void repatchLEAToLoadPtr(void* where)
2431 js::JaegerSpew(js::JSpew_Insns,
2432 ISPFX "##repatchLEAToLoadPtr ((where=%p))\n",
2435 // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
2436 // Skip over the prefix byte.
2437 where = reinterpret_cast<char*>(where) + 1;
2439 *reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_MOV_GvEv);
2442 static unsigned getCallReturnOffset(JmpSrc call)
2444 ASSERT(call.m_offset >= 0);
2445 return call.m_offset;
2448 static void* getRelocatedAddress(void* code, JmpSrc jump)
2450 ASSERT(jump.m_offset != -1);
2452 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
2455 static void* getRelocatedAddress(void* code, JmpDst destination)
2457 ASSERT(destination.m_offset != -1);
2459 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
2462 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
2464 return dst.m_offset - src.m_offset;
2467 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
2469 return dst.m_offset - src.m_offset;
2472 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
2474 return dst.m_offset - src.m_offset;
2477 void* executableCopy(ExecutablePool* allocator)
2479 void* copy = m_formatter.executableCopy(allocator);
2483 void* executableCopy(void* buffer)
2485 if (m_formatter.oom())
2487 return memcpy(buffer, m_formatter.buffer(), size());
2492 static void setPointer(void* where, void* value)
2494 js::JaegerSpew(js::JSpew_Insns,
2495 ISPFX "##setPtr ((where=%p)) ((value=%p))\n", where, value);
2496 reinterpret_cast<void**>(where)[-1] = value;
2499 static void setInt32(void* where, int32_t value)
2501 reinterpret_cast<int32_t*>(where)[-1] = value;
2504 static void setRel32(void* from, void* to)
2506 intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
2507 ASSERT(offset == static_cast<int32_t>(offset));
2508 #define JS_CRASH(x) *(int *)x = 0
2509 if (offset != static_cast<int32_t>(offset))
2513 js::JaegerSpew(js::JSpew_Insns,
2514 ISPFX "##setRel32 ((from=%p)) ((to=%p))\n", from, to);
2515 setInt32(from, offset);
2518 class X86InstructionFormatter {
2520 static const int maxInstructionSize = 16;
2524 // Legacy prefix bytes:
2526 // These are emmitted prior to the instruction.
2528 void prefix(OneByteOpcodeID pre)
2530 m_buffer.putByte(pre);
2533 // Word-sized operands / no operand instruction formatters.
2535 // In addition to the opcode, the following operand permutations are supported:
2536 // * None - instruction takes no operands.
2537 // * One register - the low three bits of the RegisterID are added into the opcode.
2538 // * Two registers - encode a register form ModRm (for all ModRm formats, the reg field is passed first, and a GroupOpcodeID may be passed in its place).
2539 // * Three argument ModRM - a register, and a register and an offset describing a memory operand.
2540 // * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.
2542 // For 32-bit x86 targets, the address operand may also be provided as a void*.
2543 // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used.
2545 // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F).
2547 void oneByteOp(OneByteOpcodeID opcode)
2549 m_buffer.ensureSpace(maxInstructionSize);
2550 m_buffer.putByteUnchecked(opcode);
2553 void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)
2555 m_buffer.ensureSpace(maxInstructionSize);
2556 emitRexIfNeeded(0, 0, reg);
2557 m_buffer.putByteUnchecked(opcode + (reg & 7));
2560 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm)
2562 m_buffer.ensureSpace(maxInstructionSize);
2563 emitRexIfNeeded(reg, 0, rm);
2564 m_buffer.putByteUnchecked(opcode);
2565 registerModRM(reg, rm);
2568 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2570 m_buffer.ensureSpace(maxInstructionSize);
2571 emitRexIfNeeded(reg, 0, base);
2572 m_buffer.putByteUnchecked(opcode);
2573 memoryModRM(reg, base, offset);
2576 void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2578 m_buffer.ensureSpace(maxInstructionSize);
2579 emitRexIfNeeded(reg, 0, base);
2580 m_buffer.putByteUnchecked(opcode);
2581 memoryModRM_disp32(reg, base, offset);
2584 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2586 m_buffer.ensureSpace(maxInstructionSize);
2587 emitRexIfNeeded(reg, index, base);
2588 m_buffer.putByteUnchecked(opcode);
2589 memoryModRM(reg, base, index, scale, offset);
2593 void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
2595 m_buffer.ensureSpace(maxInstructionSize);
2596 m_buffer.putByteUnchecked(opcode);
2597 memoryModRM(reg, address);
2601 void twoByteOp(TwoByteOpcodeID opcode)
2603 m_buffer.ensureSpace(maxInstructionSize);
2604 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2605 m_buffer.putByteUnchecked(opcode);
2608 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm)
2610 m_buffer.ensureSpace(maxInstructionSize);
2611 emitRexIfNeeded(reg, 0, rm);
2612 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2613 m_buffer.putByteUnchecked(opcode);
2614 registerModRM(reg, rm);
2617 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset)
2619 m_buffer.ensureSpace(maxInstructionSize);
2620 emitRexIfNeeded(reg, 0, base);
2621 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2622 m_buffer.putByteUnchecked(opcode);
2623 memoryModRM(reg, base, offset);
2626 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2628 m_buffer.ensureSpace(maxInstructionSize);
2629 emitRexIfNeeded(reg, index, base);
2630 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2631 m_buffer.putByteUnchecked(opcode);
2632 memoryModRM(reg, base, index, scale, offset);
2636 void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address)
2638 m_buffer.ensureSpace(maxInstructionSize);
2639 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2640 m_buffer.putByteUnchecked(opcode);
2641 memoryModRM(reg, address);
2645 void threeByteOp(ThreeByteOpcodeID opcode, int reg, RegisterID rm)
2647 m_buffer.ensureSpace(maxInstructionSize);
2648 emitRexIfNeeded(reg, 0, rm);
2649 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2650 m_buffer.putByteUnchecked(OP_3BYTE_ESCAPE);
2651 m_buffer.putByteUnchecked(opcode);
2652 registerModRM(reg, rm);
2656 // Quad-word-sized operands:
2658 // Used to format 64-bit operantions, planting a REX.w prefix.
2659 // When planting d64 or f64 instructions, not requiring a REX.w prefix,
2660 // the normal (non-'64'-postfixed) formatters should be used.
2662 void oneByteOp64(OneByteOpcodeID opcode)
2664 m_buffer.ensureSpace(maxInstructionSize);
2666 m_buffer.putByteUnchecked(opcode);
2669 void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg)
2671 m_buffer.ensureSpace(maxInstructionSize);
2672 emitRexW(0, 0, reg);
2673 m_buffer.putByteUnchecked(opcode + (reg & 7));
2676 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm)
2678 m_buffer.ensureSpace(maxInstructionSize);
2679 emitRexW(reg, 0, rm);
2680 m_buffer.putByteUnchecked(opcode);
2681 registerModRM(reg, rm);
2684 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2686 m_buffer.ensureSpace(maxInstructionSize);
2687 emitRexW(reg, 0, base);
2688 m_buffer.putByteUnchecked(opcode);
2689 memoryModRM(reg, base, offset);
2692 void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2694 m_buffer.ensureSpace(maxInstructionSize);
2695 emitRexW(reg, 0, base);
2696 m_buffer.putByteUnchecked(opcode);
2697 memoryModRM_disp32(reg, base, offset);
2700 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2702 m_buffer.ensureSpace(maxInstructionSize);
2703 emitRexW(reg, index, base);
2704 m_buffer.putByteUnchecked(opcode);
2705 memoryModRM(reg, base, index, scale, offset);
2708 void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
2710 m_buffer.ensureSpace(maxInstructionSize);
2711 emitRexW(reg, 0, rm);
2712 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2713 m_buffer.putByteUnchecked(opcode);
2714 registerModRM(reg, rm);
2720 // These methods format byte operations. Byte operations differ from the normal
2721 // formatters in the circumstances under which they will decide to emit REX prefixes.
2722 // These should be used where any register operand signifies a byte register.
2724 // The disctinction is due to the handling of register numbers in the range 4..7 on
2725 // x86-64. These register numbers may either represent the second byte of the first
2726 // four registers (ah..bh) or the first byte of the second four registers (spl..dil).
2728 // Since ah..bh cannot be used in all permutations of operands (specifically cannot
2729 // be accessed where a REX prefix is present), these are likely best treated as
2730 // deprecated. In order to ensure the correct registers spl..dil are selected a
2731 // REX prefix will be emitted for any byte register operand in the range 4..15.
2733 // These formatters may be used in instructions where a mix of operand sizes, in which
2734 // case an unnecessary REX will be emitted, for example:
2736 // In this case a REX will be planted since edi is 7 (and were this a byte operand
2737 // a REX would be required to specify dil instead of bh). Unneeded REX prefixes will
2738 // be silently ignored by the processor.
2740 // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex()
2741 // is provided to check byte register operands.
2743 void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
2746 ASSERT(!byteRegRequiresRex(rm));
2748 m_buffer.ensureSpace(maxInstructionSize);
2749 emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
2750 m_buffer.putByteUnchecked(opcode);
2751 registerModRM(groupOp, rm);
2754 void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2757 ASSERT(!byteRegRequiresRex(reg));
2759 m_buffer.ensureSpace(maxInstructionSize);
2760 emitRexIf(byteRegRequiresRex(reg), reg, 0, base);
2761 m_buffer.putByteUnchecked(opcode);
2762 memoryModRM(reg, base, offset);
2765 void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2768 ASSERT(!byteRegRequiresRex(reg));
2770 m_buffer.ensureSpace(maxInstructionSize);
2771 emitRexIf(byteRegRequiresRex(reg), reg, index, base);
2772 m_buffer.putByteUnchecked(opcode);
2773 memoryModRM(reg, base, index, scale, offset);
2776 void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
2778 m_buffer.ensureSpace(maxInstructionSize);
2779 emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);
2780 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2781 m_buffer.putByteUnchecked(opcode);
2782 registerModRM(reg, rm);
2785 void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
2787 m_buffer.ensureSpace(maxInstructionSize);
2788 emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
2789 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2790 m_buffer.putByteUnchecked(opcode);
2791 registerModRM(groupOp, rm);
2796 // An immedaite should be appended where appropriate after an op has been emitted.
2797 // The writes are unchecked since the opcode formatters above will have ensured space.
2799 void immediate8(int imm)
2801 m_buffer.putByteUnchecked(imm);
2804 void immediate16(int imm)
2806 m_buffer.putShortUnchecked(imm);
2809 void immediate32(int imm)
2811 m_buffer.putIntUnchecked(imm);
2814 void immediate64(int64_t imm)
2816 m_buffer.putInt64Unchecked(imm);
2819 JmpSrc immediateRel32()
2821 m_buffer.putIntUnchecked(0);
2822 return JmpSrc(m_buffer.size());
2825 // Administrative methods:
2827 size_t size() const { return m_buffer.size(); }
2828 unsigned char *buffer() const { return m_buffer.buffer(); }
2829 bool oom() const { return m_buffer.oom(); }
2830 bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
2831 void* data() const { return m_buffer.data(); }
2832 void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
2836 // Internals; ModRm and REX formatters.
2838 // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
2839 inline bool byteRegRequiresRex(int reg)
2841 return (reg >= X86Registers::esp);
2844 static const RegisterID noBase = X86Registers::ebp;
2845 static const RegisterID hasSib = X86Registers::esp;
2846 static const RegisterID noIndex = X86Registers::esp;
2848 static const RegisterID noBase2 = X86Registers::r13;
2849 static const RegisterID hasSib2 = X86Registers::r12;
2851 // Registers r8 & above require a REX prefixe.
2852 inline bool regRequiresRex(int reg)
2854 return (reg >= X86Registers::r8);
2857 // Format a REX prefix byte.
2858 inline void emitRex(bool w, int r, int x, int b)
2860 m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));
2863 // Used to plant a REX byte with REX.w set (for 64-bit operations).
2864 inline void emitRexW(int r, int x, int b)
2866 emitRex(true, r, x, b);
2869 // Used for operations with byte operands - use byteRegRequiresRex() to check register operands,
2870 // regRequiresRex() to check other registers (i.e. address base & index).
2872 // NB: WebKit's use of emitRexIf() is limited such that the reqRequiresRex() checks are
2873 // not needed. SpiderMonkey extends oneByteOp8 functionality such that r, x, and b can
2875 inline void emitRexIf(bool condition, int r, int x, int b)
2877 if (condition || regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b))
2878 emitRex(false, r, x, b);
2881 // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above).
2882 inline void emitRexIfNeeded(int r, int x, int b)
2884 emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b);
2887 // No REX prefix bytes on 32-bit x86.
2888 inline bool regRequiresRex(int) { return false; }
2889 inline void emitRexIf(bool, int, int, int) {}
2890 inline void emitRexIfNeeded(int, int, int) {}
2900 void putModRm(ModRmMode mode, int reg, RegisterID rm)
2902 m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7));
2905 void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale)
2907 ASSERT(mode != ModRmRegister);
2909 putModRm(mode, reg, hasSib);
2910 m_buffer.putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7));
2913 void registerModRM(int reg, RegisterID rm)
2915 putModRm(ModRmRegister, reg, rm);
2918 void memoryModRM(int reg, RegisterID base, int offset)
2920 // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
2922 if ((base == hasSib) || (base == hasSib2)) {
2924 if (base == hasSib) {
2926 if (!offset) // No need to check if the base is noBase, since we know it is hasSib!
2927 putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0);
2928 else if (CAN_SIGN_EXTEND_8_32(offset)) {
2929 putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0);
2930 m_buffer.putByteUnchecked(offset);
2932 putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
2933 m_buffer.putIntUnchecked(offset);
2937 if (!offset && (base != noBase) && (base != noBase2))
2939 if (!offset && (base != noBase))
2941 putModRm(ModRmMemoryNoDisp, reg, base);
2942 else if (CAN_SIGN_EXTEND_8_32(offset)) {
2943 putModRm(ModRmMemoryDisp8, reg, base);
2944 m_buffer.putByteUnchecked(offset);
2946 putModRm(ModRmMemoryDisp32, reg, base);
2947 m_buffer.putIntUnchecked(offset);
2952 void memoryModRM_disp32(int reg, RegisterID base, int offset)
2954 // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
2956 if ((base == hasSib) || (base == hasSib2)) {
2958 if (base == hasSib) {
2960 putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
2961 m_buffer.putIntUnchecked(offset);
2963 putModRm(ModRmMemoryDisp32, reg, base);
2964 m_buffer.putIntUnchecked(offset);
2968 void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)
2970 ASSERT(index != noIndex);
2973 if (!offset && (base != noBase) && (base != noBase2))
2975 if (!offset && (base != noBase))
2977 putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale);
2978 else if (CAN_SIGN_EXTEND_8_32(offset)) {
2979 putModRmSib(ModRmMemoryDisp8, reg, base, index, scale);
2980 m_buffer.putByteUnchecked(offset);
2982 putModRmSib(ModRmMemoryDisp32, reg, base, index, scale);
2983 m_buffer.putIntUnchecked(offset);
2988 void memoryModRM(int reg, const void* address)
2990 // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
2991 putModRm(ModRmMemoryNoDisp, reg, noBase);
2992 m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));
2996 AssemblerBuffer m_buffer;
3002 #endif // ENABLE(ASSEMBLER) && CPU(X86)
3004 #endif // X86Assembler_h