| /* |
| * Copyright (C) 2008-2017 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64)) |
| |
| #include "AssemblerBuffer.h" |
| #include "AssemblerCommon.h" |
| #include "JITCompilationEffort.h" |
| #include <limits.h> |
| #include <stdint.h> |
| #include <wtf/Assertions.h> |
| #include <wtf/Vector.h> |
| |
| namespace JSC { |
| |
| inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; } |
| |
| namespace X86Registers { |
| |
| #define FOR_EACH_CPU_REGISTER(V) \ |
| FOR_EACH_CPU_GPREGISTER(V) \ |
| FOR_EACH_CPU_SPECIAL_REGISTER(V) \ |
| FOR_EACH_CPU_FPREGISTER(V) |
| |
| // The following are defined as pairs of the following value: |
| // 1. type of the storage needed to save the register value by the JIT probe. |
| // 2. name of the register. |
| #define FOR_EACH_CPU_GPREGISTER(V) \ |
| V(void*, eax) \ |
| V(void*, ecx) \ |
| V(void*, edx) \ |
| V(void*, ebx) \ |
| V(void*, esp) \ |
| V(void*, ebp) \ |
| V(void*, esi) \ |
| V(void*, edi) \ |
| FOR_EACH_X86_64_CPU_GPREGISTER(V) |
| |
| #define FOR_EACH_CPU_SPECIAL_REGISTER(V) \ |
| V(void*, eip) \ |
| V(void*, eflags) \ |
| |
| // Note: the JITs only stores double values in the FP registers. |
| #define FOR_EACH_CPU_FPREGISTER(V) \ |
| V(double, xmm0) \ |
| V(double, xmm1) \ |
| V(double, xmm2) \ |
| V(double, xmm3) \ |
| V(double, xmm4) \ |
| V(double, xmm5) \ |
| V(double, xmm6) \ |
| V(double, xmm7) \ |
| FOR_EACH_X86_64_CPU_FPREGISTER(V) |
| |
| #if CPU(X86) |
| |
| #define FOR_EACH_X86_64_CPU_GPREGISTER(V) // Nothing to add. |
| #define FOR_EACH_X86_64_CPU_FPREGISTER(V) // Nothing to add. |
| |
| #elif CPU(X86_64) |
| |
| #define FOR_EACH_X86_64_CPU_GPREGISTER(V) \ |
| V(void*, r8) \ |
| V(void*, r9) \ |
| V(void*, r10) \ |
| V(void*, r11) \ |
| V(void*, r12) \ |
| V(void*, r13) \ |
| V(void*, r14) \ |
| V(void*, r15) |
| |
| #define FOR_EACH_X86_64_CPU_FPREGISTER(V) \ |
| V(double, xmm8) \ |
| V(double, xmm9) \ |
| V(double, xmm10) \ |
| V(double, xmm11) \ |
| V(double, xmm12) \ |
| V(double, xmm13) \ |
| V(double, xmm14) \ |
| V(double, xmm15) |
| |
| #endif // CPU(X86_64) |
| |
| typedef enum { |
| #define DECLARE_REGISTER(_type, _regName) _regName, |
| FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER) |
| #undef DECLARE_REGISTER |
| } RegisterID; |
| |
| typedef enum { |
| #define DECLARE_REGISTER(_type, _regName) _regName, |
| FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER) |
| #undef DECLARE_REGISTER |
| } XMMRegisterID; |
| |
| } // namespace X86Register |
| |
| class X86Assembler { |
| public: |
| typedef X86Registers::RegisterID RegisterID; |
| |
| static constexpr RegisterID firstRegister() { return X86Registers::eax; } |
| static constexpr RegisterID lastRegister() |
| { |
| #if CPU(X86_64) |
| return X86Registers::r15; |
| #else |
| return X86Registers::edi; |
| #endif |
| } |
| |
| typedef X86Registers::XMMRegisterID XMMRegisterID; |
| typedef XMMRegisterID FPRegisterID; |
| |
| static constexpr FPRegisterID firstFPRegister() { return X86Registers::xmm0; } |
| static constexpr FPRegisterID lastFPRegister() |
| { |
| #if CPU(X86_64) |
| return X86Registers::xmm15; |
| #else |
| return X86Registers::xmm7; |
| #endif |
| } |
| |
| typedef enum { |
| ConditionO, |
| ConditionNO, |
| ConditionB, |
| ConditionAE, |
| ConditionE, |
| ConditionNE, |
| ConditionBE, |
| ConditionA, |
| ConditionS, |
| ConditionNS, |
| ConditionP, |
| ConditionNP, |
| ConditionL, |
| ConditionGE, |
| ConditionLE, |
| ConditionG, |
| |
| ConditionC = ConditionB, |
| ConditionNC = ConditionAE, |
| } Condition; |
| |
| private: |
| // OneByteOpcodeID defines the bytecode for 1 byte instruction. It also contains the prefixes |
| // for two bytes instructions. |
| // TwoByteOpcodeID, ThreeByteOpcodeID define the opcodes for the multibytes instructions. |
| // |
| // The encoding for each instruction can be found in the Intel Architecture Manual in the appendix |
| // "Opcode Map." |
| // |
| // Each opcode can have a suffix describing the type of argument. The full list of suffixes is |
| // in the "Key to Abbreviations" section of the "Opcode Map". |
| // The most common argument types are: |
| // -E: The argument is either a GPR or a memory address. |
| // -G: The argument is a GPR. |
| // -I: The argument is an immediate. |
| // The most common sizes are: |
| // -v: 32 or 64bit depending on the operand-size attribute. |
| // -z: 32bit in both 32bit and 64bit mode. Common for immediate values. |
| typedef enum { |
| OP_ADD_EbGb = 0x00, |
| OP_ADD_EvGv = 0x01, |
| OP_ADD_GvEv = 0x03, |
| OP_ADD_EAXIv = 0x05, |
| OP_OR_EvGb = 0x08, |
| OP_OR_EvGv = 0x09, |
| OP_OR_GvEv = 0x0B, |
| OP_OR_EAXIv = 0x0D, |
| OP_2BYTE_ESCAPE = 0x0F, |
| OP_AND_EvGb = 0x20, |
| OP_AND_EvGv = 0x21, |
| OP_AND_GvEv = 0x23, |
| OP_SUB_EvGb = 0x28, |
| OP_SUB_EvGv = 0x29, |
| OP_SUB_GvEv = 0x2B, |
| OP_SUB_EAXIv = 0x2D, |
| PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E, |
| OP_XOR_EvGb = 0x30, |
| OP_XOR_EvGv = 0x31, |
| OP_XOR_GvEv = 0x33, |
| OP_XOR_EAXIv = 0x35, |
| OP_CMP_EvGv = 0x39, |
| OP_CMP_GvEv = 0x3B, |
| OP_CMP_EAXIv = 0x3D, |
| #if CPU(X86_64) |
| PRE_REX = 0x40, |
| #endif |
| OP_PUSH_EAX = 0x50, |
| OP_POP_EAX = 0x58, |
| #if CPU(X86_64) |
| OP_MOVSXD_GvEv = 0x63, |
| #endif |
| PRE_GS = 0x65, |
| PRE_OPERAND_SIZE = 0x66, |
| PRE_SSE_66 = 0x66, |
| PRE_SSE_f3 = 0xF3, |
| OP_PUSH_Iz = 0x68, |
| OP_IMUL_GvEvIz = 0x69, |
| OP_GROUP1_EbIb = 0x80, |
| OP_GROUP1_EvIz = 0x81, |
| OP_GROUP1_EvIb = 0x83, |
| OP_TEST_EbGb = 0x84, |
| OP_TEST_EvGv = 0x85, |
| OP_XCHG_EvGb = 0x86, |
| OP_XCHG_EvGv = 0x87, |
| OP_MOV_EbGb = 0x88, |
| OP_MOV_EvGv = 0x89, |
| OP_MOV_GvEv = 0x8B, |
| OP_LEA = 0x8D, |
| OP_GROUP1A_Ev = 0x8F, |
| OP_NOP = 0x90, |
| OP_XCHG_EAX = 0x90, |
| OP_CDQ = 0x99, |
| OP_MOV_EAXOv = 0xA1, |
| OP_MOV_OvEAX = 0xA3, |
| OP_TEST_ALIb = 0xA8, |
| OP_TEST_EAXIv = 0xA9, |
| OP_MOV_EAXIv = 0xB8, |
| OP_GROUP2_EvIb = 0xC1, |
| OP_RET = 0xC3, |
| OP_GROUP11_EvIb = 0xC6, |
| OP_GROUP11_EvIz = 0xC7, |
| OP_INT3 = 0xCC, |
| OP_GROUP2_Ev1 = 0xD1, |
| OP_GROUP2_EvCL = 0xD3, |
| OP_ESCAPE_D9 = 0xD9, |
| OP_ESCAPE_DD = 0xDD, |
| OP_CALL_rel32 = 0xE8, |
| OP_JMP_rel32 = 0xE9, |
| PRE_LOCK = 0xF0, |
| PRE_SSE_F2 = 0xF2, |
| PRE_SSE_F3 = 0xF3, |
| OP_HLT = 0xF4, |
| OP_GROUP3_Eb = 0xF6, |
| OP_GROUP3_EbIb = 0xF6, |
| OP_GROUP3_Ev = 0xF7, |
| OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. |
| OP_GROUP5_Ev = 0xFF, |
| } OneByteOpcodeID; |
| |
| typedef enum { |
| OP2_UD2 = 0xB, |
| OP2_MOVSD_VsdWsd = 0x10, |
| OP2_MOVSD_WsdVsd = 0x11, |
| OP2_MOVSS_VsdWsd = 0x10, |
| OP2_MOVSS_WsdVsd = 0x11, |
| OP2_MOVAPD_VpdWpd = 0x28, |
| OP2_MOVAPS_VpdWpd = 0x28, |
| OP2_CVTSI2SD_VsdEd = 0x2A, |
| OP2_CVTTSD2SI_GdWsd = 0x2C, |
| OP2_CVTTSS2SI_GdWsd = 0x2C, |
| OP2_UCOMISD_VsdWsd = 0x2E, |
| OP2_3BYTE_ESCAPE_3A = 0x3A, |
| OP2_CMOVCC = 0x40, |
| OP2_ADDSD_VsdWsd = 0x58, |
| OP2_MULSD_VsdWsd = 0x59, |
| OP2_CVTSD2SS_VsdWsd = 0x5A, |
| OP2_CVTSS2SD_VsdWsd = 0x5A, |
| OP2_SUBSD_VsdWsd = 0x5C, |
| OP2_DIVSD_VsdWsd = 0x5E, |
| OP2_MOVMSKPD_VdEd = 0x50, |
| OP2_SQRTSD_VsdWsd = 0x51, |
| OP2_ANDPS_VpdWpd = 0x54, |
| OP2_ANDNPD_VpdWpd = 0x55, |
| OP2_ORPS_VpdWpd = 0x56, |
| OP2_XORPD_VpdWpd = 0x57, |
| OP2_MOVD_VdEd = 0x6E, |
| OP2_MOVD_EdVd = 0x7E, |
| OP2_MOVD_Md = 0xD6, |
| OP2_JCC_rel32 = 0x80, |
| OP_SETCC = 0x90, |
| OP2_3BYTE_ESCAPE_AE = 0xAE, |
| OP2_IMUL_GvEv = 0xAF, |
| OP2_CMPXCHGb = 0xB0, |
| OP2_CMPXCHG = 0xB1, |
| OP2_MOVZX_GvEb = 0xB6, |
| OP2_BSF = 0xBC, |
| OP2_TZCNT = 0xBC, |
| OP2_BSR = 0xBD, |
| OP2_LZCNT = 0xBD, |
| OP2_MOVSX_GvEb = 0xBE, |
| OP2_MOVZX_GvEw = 0xB7, |
| OP2_MOVSX_GvEw = 0xBF, |
| OP2_XADDb = 0xC0, |
| OP2_XADD = 0xC1, |
| OP2_PEXTRW_GdUdIb = 0xC5, |
| OP2_PSLLQ_UdqIb = 0x73, |
| OP2_PSRLQ_UdqIb = 0x73, |
| OP2_POR_VdqWdq = 0XEB, |
| } TwoByteOpcodeID; |
| |
| typedef enum { |
| OP3_ROUNDSS_VssWssIb = 0x0A, |
| OP3_ROUNDSD_VsdWsdIb = 0x0B, |
| OP3_MFENCE = 0xF0, |
| } ThreeByteOpcodeID; |
| |
| struct VexPrefix { |
| enum : uint8_t { |
| TwoBytes = 0xC5, |
| ThreeBytes = 0xC4 |
| }; |
| }; |
| enum class VexImpliedBytes : uint8_t { |
| TwoBytesOp = 1, |
| ThreeBytesOp38 = 2, |
| ThreeBytesOp3A = 3 |
| }; |
| |
| TwoByteOpcodeID cmovcc(Condition cond) |
| { |
| return (TwoByteOpcodeID)(OP2_CMOVCC + cond); |
| } |
| |
| TwoByteOpcodeID jccRel32(Condition cond) |
| { |
| return (TwoByteOpcodeID)(OP2_JCC_rel32 + cond); |
| } |
| |
| TwoByteOpcodeID setccOpcode(Condition cond) |
| { |
| return (TwoByteOpcodeID)(OP_SETCC + cond); |
| } |
| |
| typedef enum { |
| GROUP1_OP_ADD = 0, |
| GROUP1_OP_OR = 1, |
| GROUP1_OP_ADC = 2, |
| GROUP1_OP_AND = 4, |
| GROUP1_OP_SUB = 5, |
| GROUP1_OP_XOR = 6, |
| GROUP1_OP_CMP = 7, |
| |
| GROUP1A_OP_POP = 0, |
| |
| GROUP2_OP_ROL = 0, |
| GROUP2_OP_ROR = 1, |
| GROUP2_OP_RCL = 2, |
| GROUP2_OP_RCR = 3, |
| |
| GROUP2_OP_SHL = 4, |
| GROUP2_OP_SHR = 5, |
| GROUP2_OP_SAR = 7, |
| |
| GROUP3_OP_TEST = 0, |
| GROUP3_OP_NOT = 2, |
| GROUP3_OP_NEG = 3, |
| GROUP3_OP_DIV = 6, |
| GROUP3_OP_IDIV = 7, |
| |
| GROUP5_OP_CALLN = 2, |
| GROUP5_OP_JMPN = 4, |
| GROUP5_OP_PUSH = 6, |
| |
| GROUP11_MOV = 0, |
| |
| GROUP14_OP_PSLLQ = 6, |
| GROUP14_OP_PSRLQ = 2, |
| |
| ESCAPE_D9_FSTP_singleReal = 3, |
| ESCAPE_DD_FSTP_doubleReal = 3, |
| } GroupOpcodeID; |
| |
| class X86InstructionFormatter; |
| public: |
| |
| X86Assembler() |
| : m_indexOfLastWatchpoint(INT_MIN) |
| , m_indexOfTailOfLastWatchpoint(INT_MIN) |
| { |
| } |
| |
| AssemblerBuffer& buffer() { return m_formatter.m_buffer; } |
| |
| // Stack operations: |
| |
| void push_r(RegisterID reg) |
| { |
| m_formatter.oneByteOp(OP_PUSH_EAX, reg); |
| } |
| |
| void pop_r(RegisterID reg) |
| { |
| m_formatter.oneByteOp(OP_POP_EAX, reg); |
| } |
| |
| void push_i32(int imm) |
| { |
| m_formatter.oneByteOp(OP_PUSH_Iz); |
| m_formatter.immediate32(imm); |
| } |
| |
| void push_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_PUSH, base, offset); |
| } |
| |
| void pop_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP1A_Ev, GROUP1A_OP_POP, base, offset); |
| } |
| |
| // Arithmetic operations: |
| |
| #if !CPU(X86_64) |
| void adcl_im(int imm, const void* addr) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_ADC, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_ADC, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #endif |
| |
| void addl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_ADD_EvGv, src, dst); |
| } |
| |
| void addl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset); |
| } |
| |
| void addl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, index, scale, offset); |
| } |
| |
| #if !CPU(X86_64) |
| void addl_mr(const void* addr, RegisterID dst) |
| { |
| m_formatter.oneByteOpAddr(OP_ADD_GvEv, dst, bitwise_cast<uint32_t>(addr)); |
| } |
| #endif |
| |
| void addl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_ADD_EvGv, src, base, offset); |
| } |
| |
| void addl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_ADD_EvGv, src, base, index, scale, offset); |
| } |
| |
| void addb_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp8(OP_ADD_EbGb, src, base, offset); |
| } |
| |
| void addb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp8(OP_ADD_EbGb, src, base, index, scale, offset); |
| } |
| |
| void addw_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp8(OP_ADD_EvGv, src, base, offset); |
| } |
| |
| void addw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp8(OP_ADD_EvGv, src, base, index, scale, offset); |
| } |
| |
| void addl_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_ADD_EAXIv); |
| else |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void addl_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void addl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void addb_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp8(OP_GROUP1_EbIb, GROUP1_OP_ADD, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void addb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp8(OP_GROUP1_EbIb, GROUP1_OP_ADD, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void addw_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp8(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp8(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void addw_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp8(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp8(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, index, scale, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| #if CPU(X86_64) |
| void addq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst); |
| } |
| |
| void addq_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_ADD_GvEv, dst, base, offset); |
| } |
| |
| void addq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_ADD_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void addq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_ADD_EvGv, src, base, offset); |
| } |
| |
| void addq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_ADD_EvGv, src, base, index, scale, offset); |
| } |
| |
| void addq_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_ADD_EAXIv); |
| else |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void addq_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void addq_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #else |
| void addl_im(int imm, const void* addr) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_ADD, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_ADD, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #endif |
| |
| void andl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_AND_EvGv, src, dst); |
| } |
| |
| void andl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_AND_GvEv, dst, base, offset); |
| } |
| |
| void andl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_AND_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void andl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_AND_EvGv, src, base, offset); |
| } |
| |
| void andl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_AND_EvGv, src, base, index, scale, offset); |
| } |
| |
| void andw_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| andl_rm(src, offset, base); |
| } |
| |
| void andw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| andl_rm(src, offset, base, index, scale); |
| } |
| |
| void andb_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_AND_EvGb, src, base, offset); |
| } |
| |
| void andb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_AND_EvGb, src, base, index, scale, offset); |
| } |
| |
| void andl_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void andl_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void andl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void andw_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, base, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void andw_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, base, index, scale, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void andb_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_AND, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void andb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_AND, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| #if CPU(X86_64) |
| void andq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_AND_EvGv, src, dst); |
| } |
| |
| void andq_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void andq_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_AND_GvEv, dst, base, offset); |
| } |
| |
| void andq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_AND_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void andq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_AND_EvGv, src, base, offset); |
| } |
| |
| void andq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_AND_EvGv, src, base, index, scale, offset); |
| } |
| |
| void andq_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void andq_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #else |
| void andl_im(int imm, const void* addr) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_AND, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_AND, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #endif |
| |
| void dec_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP1_OP_OR, dst); |
| } |
| |
| #if CPU(X86_64) |
| void decq_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP5_Ev, GROUP1_OP_OR, dst); |
| } |
| #endif // CPU(X86_64) |
| |
| // Only used for testing purposes. |
| void illegalInstruction() |
| { |
| m_formatter.twoByteOp(OP2_UD2); |
| } |
| |
| void inc_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP1_OP_ADD, dst); |
| } |
| |
| #if CPU(X86_64) |
| void incq_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP5_Ev, GROUP1_OP_ADD, dst); |
| } |
| |
| void incq_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_GROUP5_Ev, GROUP1_OP_ADD, base, offset); |
| } |
| |
| void incq_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_GROUP5_Ev, GROUP1_OP_ADD, base, index, scale, offset); |
| } |
| #endif // CPU(X86_64) |
| |
| void negl_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, dst); |
| } |
| |
| #if CPU(X86_64) |
| void negq_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NEG, dst); |
| } |
| |
| void negq_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NEG, base, offset); |
| } |
| |
| void negq_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NEG, base, index, scale, offset); |
| } |
| #endif |
| |
| void negl_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, base, offset); |
| } |
| |
| void negl_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, base, index, scale, offset); |
| } |
| |
| void negw_m(int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| negl_m(offset, base); |
| } |
| |
| void negw_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| negl_m(offset, base, index, scale); |
| } |
| |
| void negb_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Eb, GROUP3_OP_NEG, base, offset); |
| } |
| |
| void negb_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Eb, GROUP3_OP_NEG, base, index, scale, offset); |
| } |
| |
| void notl_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst); |
| } |
| |
| void notl_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, base, offset); |
| } |
| |
| void notl_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, base, index, scale, offset); |
| } |
| |
| void notw_m(int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| notl_m(offset, base); |
| } |
| |
| void notw_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| notl_m(offset, base, index, scale); |
| } |
| |
| void notb_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Eb, GROUP3_OP_NOT, base, offset); |
| } |
| |
| void notb_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Eb, GROUP3_OP_NOT, base, index, scale, offset); |
| } |
| |
| #if CPU(X86_64) |
| void notq_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NOT, dst); |
| } |
| |
| void notq_m(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NOT, base, offset); |
| } |
| |
| void notq_m(int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NOT, base, index, scale, offset); |
| } |
| #endif |
| |
| void orl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_OR_EvGv, src, dst); |
| } |
| |
| void orl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset); |
| } |
| |
| void orl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_OR_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void orl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_OR_EvGv, src, base, offset); |
| } |
| |
| void orl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_OR_EvGv, src, base, index, scale, offset); |
| } |
| |
| void orw_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| orl_rm(src, offset, base); |
| } |
| |
| void orw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| orl_rm(src, offset, base, index, scale); |
| } |
| |
| void orb_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_OR_EvGb, src, base, offset); |
| } |
| |
| void orb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_OR_EvGb, src, base, index, scale, offset); |
| } |
| |
| void orl_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_OR_EAXIv); |
| else |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void orl_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void orl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void orw_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, base, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void orw_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, base, index, scale, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void orb_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_OR, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void orb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_OR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| #if CPU(X86_64) |
| void orq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_OR_EvGv, src, dst); |
| } |
| |
| void orq_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_OR_GvEv, dst, base, offset); |
| } |
| |
| void orq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_OR_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void orq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_OR_EvGv, src, base, offset); |
| } |
| |
| void orq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_OR_EvGv, src, base, index, scale, offset); |
| } |
| |
| void orq_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void orq_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void orq_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_OR_EAXIv); |
| else |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #else |
| void orl_im(int imm, const void* addr) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_OR, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_OR, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void orl_rm(RegisterID src, const void* addr) |
| { |
| m_formatter.oneByteOpAddr(OP_OR_EvGv, src, bitwise_cast<uint32_t>(addr)); |
| } |
| #endif |
| |
| void subl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_SUB_EvGv, src, dst); |
| } |
| |
| void subl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset); |
| } |
| |
| void subl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void subl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_SUB_EvGv, src, base, offset); |
| } |
| |
| void subl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_SUB_EvGv, src, base, index, scale, offset); |
| } |
| |
| void subw_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_SUB_EvGv, src, base, offset); |
| } |
| |
| void subw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_SUB_EvGv, src, base, index, scale, offset); |
| } |
| |
| void subb_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_SUB_EvGb, src, base, offset); |
| } |
| |
| void subb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_SUB_EvGb, src, base, index, scale, offset); |
| } |
| |
| void subl_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_SUB_EAXIv); |
| else |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void subl_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void subl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void subw_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void subw_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, index, scale, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void subb_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_SUB, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void subb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_SUB, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| #if CPU(X86_64) |
| void subq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst); |
| } |
| |
| void subq_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_SUB_GvEv, dst, base, offset); |
| } |
| |
| void subq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_SUB_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void subq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_SUB_EvGv, src, base, offset); |
| } |
| |
| void subq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_SUB_EvGv, src, base, index, scale, offset); |
| } |
| |
| void subq_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_SUB_EAXIv); |
| else |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void subq_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void subq_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #else |
| void subl_im(int imm, const void* addr) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_SUB, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_SUB, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #endif |
| |
| void xorl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_XOR_EvGv, src, dst); |
| } |
| |
| void xorl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_XOR_GvEv, dst, base, offset); |
| } |
| |
| void xorl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_XOR_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void xorl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_XOR_EvGv, src, base, offset); |
| } |
| |
| void xorl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_XOR_EvGv, src, base, index, scale, offset); |
| } |
| |
| void xorl_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void xorl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void xorw_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| xorl_rm(src, offset, base); |
| } |
| |
| void xorw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| xorl_rm(src, offset, base, index, scale); |
| } |
| |
| void xorw_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void xorw_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, index, scale, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void xorb_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_XOR_EvGb, src, base, offset); |
| } |
| |
| void xorb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_XOR_EvGb, src, base, index, scale, offset); |
| } |
| |
| void xorb_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_XOR, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void xorb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_XOR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void xorl_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_XOR_EAXIv); |
| else |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| #if CPU(X86_64) |
| void xorq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst); |
| } |
| |
| void xorq_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_XOR_EAXIv); |
| else |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void xorq_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void xorq_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void xorq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_XOR_EvGv, src, base, offset); |
| } |
| |
| void xorq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_XOR_EvGv, src, base, index, scale, offset); |
| } |
| |
| void xorq_mr(int offset, RegisterID base, RegisterID dest) |
| { |
| m_formatter.oneByteOp64(OP_XOR_GvEv, dest, base, offset); |
| } |
| |
| void xorq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dest) |
| { |
| m_formatter.oneByteOp64(OP_XOR_GvEv, dest, base, index, scale, offset); |
| } |
| #endif |
| |
| void lzcnt_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.prefix(PRE_SSE_F3); |
| m_formatter.twoByteOp(OP2_LZCNT, dst, src); |
| } |
| |
| void lzcnt_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.prefix(PRE_SSE_F3); |
| m_formatter.twoByteOp(OP2_LZCNT, dst, base, offset); |
| } |
| |
| #if CPU(X86_64) |
| void lzcntq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.prefix(PRE_SSE_F3); |
| m_formatter.twoByteOp64(OP2_LZCNT, dst, src); |
| } |
| |
| void lzcntq_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.prefix(PRE_SSE_F3); |
| m_formatter.twoByteOp64(OP2_LZCNT, dst, base, offset); |
| } |
| #endif |
| |
| void bsr_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_BSR, dst, src); |
| } |
| |
| void bsr_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_BSR, dst, base, offset); |
| } |
| |
| #if CPU(X86_64) |
| void bsrq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp64(OP2_BSR, dst, src); |
| } |
| |
| void bsrq_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp64(OP2_BSR, dst, base, offset); |
| } |
| #endif |
| |
| void tzcnt_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.prefix(PRE_SSE_F3); |
| m_formatter.twoByteOp(OP2_TZCNT, dst, src); |
| } |
| |
| #if CPU(X86_64) |
| void tzcntq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.prefix(PRE_SSE_F3); |
| m_formatter.twoByteOp64(OP2_TZCNT, dst, src); |
| } |
| #endif |
| |
| void bsf_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_BSF, dst, src); |
| } |
| |
| #if CPU(X86_64) |
| void bsfq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp64(OP2_BSF, dst, src); |
| } |
| #endif |
| |
| private: |
| template<GroupOpcodeID op> |
| void shiftInstruction32(int imm, RegisterID dst) |
| { |
| if (imm == 1) |
| m_formatter.oneByteOp(OP_GROUP2_Ev1, op, dst); |
| else { |
| m_formatter.oneByteOp(OP_GROUP2_EvIb, op, dst); |
| m_formatter.immediate8(imm); |
| } |
| } |
| public: |
| |
| void sarl_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction32<GROUP2_OP_SAR>(imm, dst); |
| } |
| |
| void sarl_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst); |
| } |
| |
| void shrl_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction32<GROUP2_OP_SHR>(imm, dst); |
| } |
| |
| void shrl_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst); |
| } |
| |
| void shll_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction32<GROUP2_OP_SHL>(imm, dst); |
| } |
| |
| void shll_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst); |
| } |
| |
| void rorl_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction32<GROUP2_OP_ROR>(imm, dst); |
| } |
| |
| void rorl_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_ROR, dst); |
| } |
| |
| void roll_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction32<GROUP2_OP_ROL>(imm, dst); |
| } |
| |
| void roll_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_ROL, dst); |
| } |
| |
| #if CPU(X86_64) |
| private: |
| template<GroupOpcodeID op> |
| void shiftInstruction64(int imm, RegisterID dst) |
| { |
| if (imm == 1) |
| m_formatter.oneByteOp64(OP_GROUP2_Ev1, op, dst); |
| else { |
| m_formatter.oneByteOp64(OP_GROUP2_EvIb, op, dst); |
| m_formatter.immediate8(imm); |
| } |
| } |
| public: |
| void sarq_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst); |
| } |
| |
| void sarq_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction64<GROUP2_OP_SAR>(imm, dst); |
| } |
| |
| void shrq_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction64<GROUP2_OP_SHR>(imm, dst); |
| } |
| |
| void shrq_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst); |
| } |
| |
| void shlq_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction64<GROUP2_OP_SHL>(imm, dst); |
| } |
| |
| void shlq_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst); |
| } |
| |
| void rorq_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction64<GROUP2_OP_ROR>(imm, dst); |
| } |
| |
| void rorq_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_ROR, dst); |
| } |
| |
| void rolq_i8r(int imm, RegisterID dst) |
| { |
| shiftInstruction64<GROUP2_OP_ROL>(imm, dst); |
| } |
| |
| void rolq_CLr(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_ROL, dst); |
| } |
| #endif // CPU(X86_64) |
| |
| void imull_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src); |
| } |
| |
| #if CPU(X86_64) |
| void imulq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp64(OP2_IMUL_GvEv, dst, src); |
| } |
| #endif // CPU(X86_64) |
| |
| void imull_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, base, offset); |
| } |
| |
| void imull_i32r(RegisterID src, int32_t value, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src); |
| m_formatter.immediate32(value); |
| } |
| |
| void divl_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_DIV, dst); |
| } |
| |
| void idivl_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst); |
| } |
| |
| #if CPU(X86_64) |
| void divq_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_DIV, dst); |
| } |
| |
| void idivq_r(RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst); |
| } |
| #endif // CPU(X86_64) |
| |
| // Comparisons: |
| |
| void cmpl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_CMP_EvGv, src, dst); |
| } |
| |
| void cmpl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset); |
| } |
| |
| void cmpl_mr(int offset, RegisterID base, RegisterID src) |
| { |
| m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset); |
| } |
| |
| void cmpl_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_CMP_EAXIv); |
| else |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void cmpl_ir_force32(int imm, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); |
| m_formatter.immediate32(imm); |
| } |
| |
| void cmpl_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void cmpb_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void cmpb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| #if CPU(X86) |
| void cmpb_im(int imm, const void* addr) |
| { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EbIb, GROUP1_OP_CMP, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } |
| #endif |
| |
| void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void cmpl_im_force32(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| #if CPU(X86_64) |
| void cmpq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst); |
| } |
| |
| void cmpq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, offset); |
| } |
| |
| void cmpq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, index, scale, offset); |
| } |
| |
| void cmpq_mr(int offset, RegisterID base, RegisterID src) |
| { |
| m_formatter.oneByteOp64(OP_CMP_GvEv, src, base, offset); |
| } |
| |
| void cmpq_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_CMP_EAXIv); |
| else |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void cmpq_im(int imm, int offset, RegisterID base) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| |
| void cmpq_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #else |
| void cmpl_rm(RegisterID reg, const void* addr) |
| { |
| m_formatter.oneByteOpAddr(OP_CMP_EvGv, reg, bitwise_cast<uint32_t>(addr)); |
| } |
| |
| void cmpl_im(int imm, const void* addr) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_CMP, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_CMP, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate32(imm); |
| } |
| } |
| #endif |
| |
| void cmpw_ir(int imm, RegisterID dst) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset); |
| } |
| |
| void cmpw_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| if (CAN_SIGN_EXTEND_8_32(imm)) { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } else { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset); |
| m_formatter.immediate16(imm); |
| } |
| } |
| |
| void testl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_TEST_EvGv, src, dst); |
| } |
| |
| void testl_i32r(int imm, RegisterID dst) |
| { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_TEST_EAXIv); |
| else |
| m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst); |
| m_formatter.immediate32(imm); |
| } |
| |
| void testl_i32m(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| void testb_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp8(OP_TEST_EbGb, src, dst); |
| } |
| |
| void testb_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void testb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| #if CPU(X86) |
| void testb_im(int imm, const void* addr) |
| { |
| m_formatter.oneByteOpAddr(OP_GROUP3_EbIb, GROUP3_OP_TEST, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } |
| #endif |
| |
| void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| #if CPU(X86_64) |
| void testq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst); |
| } |
| |
| void testq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_TEST_EvGv, src, base, offset); |
| } |
| |
| void testq_i32r(int imm, RegisterID dst) |
| { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_TEST_EAXIv); |
| else |
| m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst); |
| m_formatter.immediate32(imm); |
| } |
| |
| void testq_i32m(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| void testq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| #endif |
| |
| void testw_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_TEST_EvGv, src, dst); |
| } |
| |
| void testb_i8r(int imm, RegisterID dst) |
| { |
| if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_TEST_ALIb); |
| else |
| m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst); |
| m_formatter.immediate8(imm); |
| } |
| |
| void setCC_r(Condition cond, RegisterID dst) |
| { |
| m_formatter.twoByteOp8(setccOpcode(cond), (GroupOpcodeID)0, dst); |
| } |
| |
| void sete_r(RegisterID dst) |
| { |
| m_formatter.twoByteOp8(setccOpcode(ConditionE), (GroupOpcodeID)0, dst); |
| } |
| |
| void setz_r(RegisterID dst) |
| { |
| sete_r(dst); |
| } |
| |
| void setne_r(RegisterID dst) |
| { |
| m_formatter.twoByteOp8(setccOpcode(ConditionNE), (GroupOpcodeID)0, dst); |
| } |
| |
| void setnz_r(RegisterID dst) |
| { |
| setne_r(dst); |
| } |
| |
| void setnp_r(RegisterID dst) |
| { |
| m_formatter.twoByteOp8(setccOpcode(ConditionNP), (GroupOpcodeID)0, dst); |
| } |
| |
| void setp_r(RegisterID dst) |
| { |
| m_formatter.twoByteOp8(setccOpcode(ConditionP), (GroupOpcodeID)0, dst); |
| } |
| |
| // Various move ops: |
| |
| void cdq() |
| { |
| m_formatter.oneByteOp(OP_CDQ); |
| } |
| |
| #if CPU(X86_64) |
| void cqo() |
| { |
| m_formatter.oneByteOp64(OP_CDQ); |
| } |
| #endif |
| |
| void fstps(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_ESCAPE_D9, ESCAPE_D9_FSTP_singleReal, base, offset); |
| } |
| |
| void fstpl(int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_ESCAPE_DD, ESCAPE_DD_FSTP_doubleReal, base, offset); |
| } |
| |
| void xchgl_rr(RegisterID src, RegisterID dst) |
| { |
| if (src == X86Registers::eax) |
| m_formatter.oneByteOp(OP_XCHG_EAX, dst); |
| else if (dst == X86Registers::eax) |
| m_formatter.oneByteOp(OP_XCHG_EAX, src); |
| else |
| m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst); |
| } |
| |
| void xchgb_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_XCHG_EvGb, src, base, offset); |
| } |
| |
| void xchgb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_XCHG_EvGb, src, base, index, scale, offset); |
| } |
| |
| void xchgw_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_XCHG_EvGv, src, base, offset); |
| } |
| |
| void xchgw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_XCHG_EvGv, src, base, index, scale, offset); |
| } |
| |
| void xchgl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_XCHG_EvGv, src, base, offset); |
| } |
| |
| void xchgl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_XCHG_EvGv, src, base, index, scale, offset); |
| } |
| |
| #if CPU(X86_64) |
| void xchgq_rr(RegisterID src, RegisterID dst) |
| { |
| if (src == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_XCHG_EAX, dst); |
| else if (dst == X86Registers::eax) |
| m_formatter.oneByteOp64(OP_XCHG_EAX, src); |
| else |
| m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst); |
| } |
| |
| void xchgq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_XCHG_EvGv, src, base, offset); |
| } |
| |
| void xchgq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_XCHG_EvGv, src, base, index, scale, offset); |
| } |
| #endif |
| |
| void movl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_MOV_EvGv, src, dst); |
| } |
| |
| void movl_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset); |
| } |
| |
| void movl_rm_disp32(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset); |
| } |
| |
| void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset); |
| } |
| |
| void movl_mEAX(const void* addr) |
| { |
| m_formatter.oneByteOp(OP_MOV_EAXOv); |
| #if CPU(X86_64) |
| m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); |
| #else |
| m_formatter.immediate32(reinterpret_cast<int>(addr)); |
| #endif |
| } |
| |
| void movl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset); |
| } |
| |
| void movl_mr_disp32(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset); |
| } |
| |
| void movl_mr_disp8(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp_disp8(OP_MOV_GvEv, dst, base, offset); |
| } |
| |
| void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void movl_i32r(int imm, RegisterID dst) |
| { |
| m_formatter.oneByteOp(OP_MOV_EAXIv, dst); |
| m_formatter.immediate32(imm); |
| } |
| |
| void movl_i32m(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| void movl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| #if !CPU(X86_64) |
| void movb_i8m(int imm, const void* addr) |
| { |
| ASSERT(-128 <= imm && imm < 128); |
| m_formatter.oneByteOpAddr(OP_GROUP11_EvIb, GROUP11_MOV, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate8(imm); |
| } |
| #endif |
| |
| void movb_i8m(int imm, int offset, RegisterID base) |
| { |
| ASSERT(-128 <= imm && imm < 128); |
| m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| void movb_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| ASSERT(-128 <= imm && imm < 128); |
| m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, index, scale, offset); |
| m_formatter.immediate8(imm); |
| } |
| |
| #if !CPU(X86_64) |
| void movb_rm(RegisterID src, const void* addr) |
| { |
| m_formatter.oneByteOpAddr(OP_MOV_EbGb, src, bitwise_cast<uint32_t>(addr)); |
| } |
| #endif |
| |
| void movb_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp8(OP_MOV_EbGb, src, base, offset); |
| } |
| |
| void movb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp8(OP_MOV_EbGb, src, base, index, scale, offset); |
| } |
| |
| void movw_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| |
| // FIXME: We often use oneByteOp8 for 16-bit operations. It's not clear that this is |
| // necessary. https://bugs.webkit.org/show_bug.cgi?id=153433 |
| m_formatter.oneByteOp8(OP_MOV_EvGv, src, base, offset); |
| } |
| |
| void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp8(OP_MOV_EvGv, src, base, index, scale, offset); |
| } |
| |
| void movw_im(int imm, int offset, RegisterID base) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset); |
| m_formatter.immediate16(imm); |
| } |
| |
| void movw_im(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.prefix(PRE_OPERAND_SIZE); |
| m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset); |
| m_formatter.immediate16(imm); |
| } |
| |
| void movl_EAXm(const void* addr) |
| { |
| m_formatter.oneByteOp(OP_MOV_OvEAX); |
| #if CPU(X86_64) |
| m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); |
| #else |
| m_formatter.immediate32(reinterpret_cast<int>(addr)); |
| #endif |
| } |
| |
| void movl_mr(uint32_t addr, RegisterID dst) |
| { |
| m_formatter.oneByteOpAddr(OP_MOV_GvEv, dst, addr); |
| } |
| |
| #if CPU(X86_64) |
| void movq_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst); |
| } |
| |
| void movq_rm(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, offset); |
| } |
| |
| void movq_rm_disp32(RegisterID src, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, src, base, offset); |
| } |
| |
| void movq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset); |
| } |
| |
| void movq_mEAX(const void* addr) |
| { |
| m_formatter.oneByteOp64(OP_MOV_EAXOv); |
| m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); |
| } |
| |
| void movq_EAXm(const void* addr) |
| { |
| m_formatter.oneByteOp64(OP_MOV_OvEAX); |
| m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); |
| } |
| |
| void movq_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset); |
| } |
| |
| void movq_mr_disp32(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, dst, base, offset); |
| } |
| |
| void movq_mr_disp8(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.oneByteOp64_disp8(OP_MOV_GvEv, dst, base, offset); |
| } |
| |
| void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset); |
| } |
| |
| void movq_mr(uint32_t addr, RegisterID dst) |
| { |
| m_formatter.oneByteOp64Addr(OP_MOV_GvEv, dst, addr); |
| } |
| |
| void movq_i32m(int imm, int offset, RegisterID base) |
| { |
| m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| void movq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) |
| { |
| m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset); |
| m_formatter.immediate32(imm); |
| } |
| |
| void movq_i64r(int64_t imm, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_MOV_EAXIv, dst); |
| m_formatter.immediate64(imm); |
| } |
| |
| void mov_i32r(int32_t imm, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, dst); |
| m_formatter.immediate32(imm); |
| } |
| |
| void movsxd_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src); |
| } |
| #else |
| void movl_mr(const void* addr, RegisterID dst) |
| { |
| if (dst == X86Registers::eax) |
| movl_mEAX(addr); |
| else |
| m_formatter.oneByteOpAddr(OP_MOV_GvEv, dst, bitwise_cast<uint32_t>(addr)); |
| } |
| |
| void movl_rm(RegisterID src, const void* addr) |
| { |
| if (src == X86Registers::eax) |
| movl_EAXm(addr); |
| else |
| m_formatter.oneByteOpAddr(OP_MOV_EvGv, src, bitwise_cast<uint32_t>(addr)); |
| } |
| |
| void movl_i32m(int imm, const void* addr) |
| { |
| m_formatter.oneByteOpAddr(OP_GROUP11_EvIz, GROUP11_MOV, bitwise_cast<uint32_t>(addr)); |
| m_formatter.immediate32(imm); |
| } |
| #endif |
| |
| void movzwl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset); |
| } |
| |
| void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset); |
| } |
| |
| void movswl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, offset); |
| } |
| |
| void movswl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, index, scale, offset); |
| } |
| |
| void movzbl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, offset); |
| } |
| |
| void movzbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, index, scale, offset); |
| } |
| |
| #if !CPU(X86_64) |
| void movzbl_mr(const void* address, RegisterID dst) |
| { |
| m_formatter.twoByteOpAddr(OP2_MOVZX_GvEb, dst, bitwise_cast<uint32_t>(address)); |
| } |
| #endif |
| |
| void movsbl_mr(int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, offset); |
| } |
| |
| void movsbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, index, scale, offset); |
| } |
| |
| void movzbl_rr(RegisterID src, RegisterID dst) |
| { |
| // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register |
| // is in the range ESP-EDI, and the src would not have required a REX). Unneeded |
| // REX prefixes are defined to be silently ignored by the processor. |
| m_formatter.twoByteOp8(OP2_MOVZX_GvEb, dst, src); |
| } |
| |
| void movsbl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp8(OP2_MOVSX_GvEb, dst, src); |
| } |
| |
| void movzwl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp8(OP2_MOVZX_GvEw, dst, src); |
| } |
| |
| void movswl_rr(RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp8(OP2_MOVSX_GvEw, dst, src); |
| } |
| |
| void cmovl_rr(Condition cond, RegisterID src, RegisterID dst) |
| { |
| m_formatter.twoByteOp(cmovcc(cond), dst, src); |
| } |
| |
| void cmovl_mr(Condition cond, int offset, RegisterID base, RegisterID dst) |
| { |
| m_formatter.twoByteOp(cmovcc(cond), dst, base, offset); |
| } |
| |
| void cmovl_mr(Condition cond, int offset, RegisterID base, RegisterID index, int scale, RegisterID dst) |
| { |
| m_formatter.twoByteOp(cmovcc(cond), dst, base, index, scale, offset); |
| } |
| |
| void cmovel_rr(RegisterID src, RegisterID dst) |
|