📄 x86assembler.h
字号:
/* * Copyright (C) 2008 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. */#ifndef X86Assembler_h#define X86Assembler_h#include <wtf/Platform.h>#if ENABLE(ASSEMBLER) && (PLATFORM(X86) || PLATFORM(X86_64))#include "AssemblerBuffer.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; }#if PLATFORM(X86_64)inline bool CAN_SIGN_EXTEND_32_64(intptr_t value) { return value == (intptr_t)(int32_t)value; }inline bool CAN_SIGN_EXTEND_U32_64(intptr_t value) { return value == (intptr_t)(uint32_t)value; }#define REPTACH_OFFSET_CALL_R11 3#endifnamespace X86 { typedef enum { eax, ecx, edx, ebx, esp, ebp, esi, edi,#if PLATFORM(X86_64) r8, r9, r10, r11, r12, r13, r14, r15,#endif } RegisterID; typedef enum { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, } XMMRegisterID;}class X86Assembler {public: typedef X86::RegisterID RegisterID; typedef X86::XMMRegisterID XMMRegisterID; typedef enum { ConditionO, ConditionNO, ConditionB, ConditionAE, ConditionE, ConditionNE, ConditionBE, ConditionA, ConditionS, ConditionNS, ConditionP, ConditionNP, ConditionL, ConditionGE, ConditionLE, ConditionG, ConditionC = ConditionB, ConditionNC = ConditionAE, } Condition;private: typedef enum { OP_ADD_EvGv = 0x01, OP_ADD_GvEv = 0x03, OP_OR_EvGv = 0x09, OP_OR_GvEv = 0x0B, OP_2BYTE_ESCAPE = 0x0F, OP_AND_EvGv = 0x21, OP_SUB_EvGv = 0x29, OP_SUB_GvEv = 0x2B, PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E, OP_XOR_EvGv = 0x31, OP_CMP_EvGv = 0x39, OP_CMP_GvEv = 0x3B,#if PLATFORM(X86_64) PRE_REX = 0x40,#endif OP_PUSH_EAX = 0x50, OP_POP_EAX = 0x58,#if PLATFORM(X86_64) OP_MOVSXD_GvEv = 0x63,#endif PRE_OPERAND_SIZE = 0x66, PRE_SSE_66 = 0x66, OP_PUSH_Iz = 0x68, OP_IMUL_GvEvIz = 0x69, OP_GROUP1_EvIz = 0x81, OP_GROUP1_EvIb = 0x83, OP_TEST_EvGv = 0x85, OP_XCHG_EvGv = 0x87, OP_MOV_EvGv = 0x89, OP_MOV_GvEv = 0x8B, OP_LEA = 0x8D, OP_GROUP1A_Ev = 0x8F, OP_CDQ = 0x99, OP_MOV_EAXOv = 0xA1, OP_MOV_OvEAX = 0xA3, OP_MOV_EAXIv = 0xB8, OP_GROUP2_EvIb = 0xC1, OP_RET = 0xC3, OP_GROUP11_EvIz = 0xC7, OP_INT3 = 0xCC, OP_GROUP2_Ev1 = 0xD1, OP_GROUP2_EvCL = 0xD3, OP_CALL_rel32 = 0xE8, OP_JMP_rel32 = 0xE9, PRE_SSE_F2 = 0xF2, OP_HLT = 0xF4, 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_MOVSD_VsdWsd = 0x10, OP2_MOVSD_WsdVsd = 0x11, OP2_CVTSI2SD_VsdEd = 0x2A, OP2_CVTTSD2SI_GdWsd = 0x2C, OP2_UCOMISD_VsdWsd = 0x2E, OP2_ADDSD_VsdWsd = 0x58, OP2_MULSD_VsdWsd = 0x59, OP2_SUBSD_VsdWsd = 0x5C, OP2_MOVD_VdEd = 0x6E, OP2_MOVD_EdVd = 0x7E, OP2_JCC_rel32 = 0x80, OP_SETCC = 0x90, OP2_IMUL_GvEv = 0xAF, OP2_MOVZX_GvEb = 0xB6, OP2_MOVZX_GvEw = 0xB7, OP2_PEXTRW_GdUdIb = 0xC5, } TwoByteOpcodeID; 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_AND = 4, GROUP1_OP_SUB = 5, GROUP1_OP_XOR = 6, GROUP1_OP_CMP = 7, GROUP1A_OP_POP = 0, GROUP2_OP_SHL = 4, GROUP2_OP_SAR = 7, GROUP3_OP_TEST = 0, GROUP3_OP_NOT = 2, GROUP3_OP_IDIV = 7, GROUP5_OP_CALLN = 2, GROUP5_OP_JMPN = 4, GROUP5_OP_PUSH = 6, GROUP11_MOV = 0, } GroupOpcodeID; class X86InstructionFormatter;public: class JmpSrc { friend class X86Assembler; friend class X86InstructionFormatter; public: JmpSrc() : m_offset(-1) { } private: JmpSrc(int offset) : m_offset(offset) { } int m_offset; }; class JmpDst { friend class X86Assembler; friend class X86InstructionFormatter; public: JmpDst() : m_offset(-1) , m_used(false) { } bool isUsed() const { return m_used; } void used() { m_used = true; } private: JmpDst(int offset) : m_offset(offset) , m_used(false) { ASSERT(m_offset == offset); } int m_offset : 31; bool m_used : 1; }; X86Assembler() { } size_t size() const { return m_formatter.size(); } // 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: 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_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 { 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); } }#if PLATFORM(X86_64) void addq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst); } 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 { m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst); m_formatter.immediate32(imm); } }#else void addl_im(int imm, void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr); m_formatter.immediate8(imm); } else { m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr); m_formatter.immediate32(imm); } }#endif void andl_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp(OP_AND_EvGv, src, dst); } 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); } }#if PLATFORM(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); } }#endif void notl_r(RegisterID dst) { m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst); } 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_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 { m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst); m_formatter.immediate32(imm); } }#if PLATFORM(X86_64) void orq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_OR_EvGv, src, dst); } 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 { m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, dst); m_formatter.immediate32(imm); } }#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_ir(int imm, RegisterID dst) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -