/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Alexander V. Astapchuk */ #ifndef _ENCODER_DEFS_H_ #define _ENCODER_DEFS_H_ // Used to isolate experimental or being tuned encoder into a separate // namespace so it can coexist with a stable one in the same bundle. #ifdef ENCODER_ISOLATE #define ENCODER_NAMESPACE_START namespace enc_ia32 { #define ENCODER_NAMESPACE_END }; #else #define ENCODER_NAMESPACE_START #define ENCODER_NAMESPACE_END #endif #include <assert.h> #include "enc_defs_ext.h" #ifndef COUNTOF /** * Number of items in an array. */ #define COUNTOF(a) (sizeof(a)/sizeof(a[0])) #endif #ifdef _EM64T_ /** * A stack pointer of default platform's size. */ #define REG_STACK RegName_RSP /** * A max GP register (with a highest index number) */ #define REG_MAX RegName_R15 /** * Total number of GP registers including stack pointer. */ #define MAX_REGS 15 #else #define REG_STACK RegName_ESP #define REG_MAX RegName_EDI #define MAX_REGS 8 #endif ENCODER_NAMESPACE_START /** * A number of bytes 'eaten' by an ordinary PUSH/POP. */ #define STACK_SLOT_SIZE (sizeof(void*)) /** * A recommended by Intel Arch Manual aligment for instructions that * are targets for jmps. */ #define JMP_TARGET_ALIGMENT (16) /** * A maximum possible size of native instruction. */ #define MAX_NATIVE_INST_SIZE (15) /** * The enum OpndKind describes an operand's location - memory, immediate or a register. * It can be used as a bit mask. */ typedef enum OpndKind { /** * A change must be balanced with at least the following places: * Ia32::Constraint-s use the OpndKind as a mask * encoder.cpp & encoder_master_info.cpp uses OpndKind as an index for hashing * - perhaps there are much more places * * NOTE: an MMXReg kind is incompatible with the current constraints framework, * as it's not encoded as a mask. */ OpndKind_Null=0, OpndKind_GPReg = 0x01, OpndKind_MinRegKind = OpndKind_GPReg, OpndKind_SReg = 0x02, #ifdef _HAVE_MMX_ OpndKind_MMXReg = 0x03, #endif OpndKind_FPReg = 0x04, OpndKind_XMMReg = 0x08, OpndKind_OtherReg = 0x10, OpndKind_StatusReg = OpndKind_OtherReg, OpndKind_MaxRegKind = OpndKind_StatusReg, // a max existing kind of register OpndKind_MaxReg, // -'- + 1 to be used in array defs // OpndKind_Immediate = 0x20, OpndKind_Imm=OpndKind_Immediate, OpndKind_Memory = 0x40, OpndKind_Mem=OpndKind_Memory, // OpndKind_Reg = 0x1F, OpndKind_Any = 0x7F, // syntetic constants. Normally not used anywhere, but are used for // human-readable showing under the debugger OpndKind_GPReg_Mem = OpndKind_GPReg|OpndKind_Mem, #ifdef _HAVE_MMX_ OpndKind_MMXReg_Mem = OpndKind_MMXReg|OpndKind_Mem, #endif OpndKind_XMMReg_Mem = OpndKind_XMMReg|OpndKind_Mem, } OpndKind; /** * Defines type of extention allowed for particular operand. * For example imul r32,r_m32,imm8 sign extend imm8 before performing multiplication. * To satisfy instruction constraints immediate operand should be either OpndExt_Signed * or OpndExt_Any. */ typedef enum OpndExt { OpndExt_None = 0x0, OpndExt_Signed = 0x1, OpndExt_Zero = 0x2, OpndExt_Any = 0x3, }OpndExt; /** * enum OpndRole defines the role of an operand in an instruction * Can be used as mask to combine def and use. The complete def+use * info can be combined in 2 bits which is used, say in Encoder::OpndRole. */ //TODO: this duplicates an Role used in the Ia32::Inst. That duplicate enum should be removed. typedef enum OpndRole { OpndRole_Null=0, OpndRole_Use=0x1, OpndRole_Def=0x2, OpndRole_UseDef=OpndRole_Use|OpndRole_Def, OpndRole_All=0xffff, } OpndRole; #define REGNAME(k,s,i) ( ((k & OpndKind_Any)<<24) | ((s & OpndSize_Any)<<16) | (i&0xFF) ) // Gregory - // It is critical that all register indexes (3rd number) inside of the // following table go in ascending order. That is R8 goes after // RDI. It is necessary for decoder when extending registers from RAX-RDI // to R8-R15 by simply adding 8 to the index on EM64T architecture typedef enum RegName { RegName_Null = 0, #ifdef _EM64T_ /* An index part of the RegName-s for RAX-RDI, EAX-ESI, AX-SI and AL-BH is the same as the index used during instructions encoding. The same rule applies for XMM regsters for IA32. For new EM64T registers (both GP and XMM) the index need to be corrected to obtain the index used in processor's instructions. */ RegName_RAX = REGNAME(OpndKind_GPReg,OpndSize_64,0), RegName_RCX = REGNAME(OpndKind_GPReg,OpndSize_64,1), RegName_RDX = REGNAME(OpndKind_GPReg,OpndSize_64,2), RegName_RBX = REGNAME(OpndKind_GPReg,OpndSize_64,3), RegName_RSP = REGNAME(OpndKind_GPReg,OpndSize_64,4), RegName_RBP = REGNAME(OpndKind_GPReg,OpndSize_64,5), RegName_RSI = REGNAME(OpndKind_GPReg,OpndSize_64,6), RegName_RDI = REGNAME(OpndKind_GPReg,OpndSize_64,7), RegName_R8 = REGNAME(OpndKind_GPReg,OpndSize_64,8), RegName_R9 = REGNAME(OpndKind_GPReg,OpndSize_64,9), RegName_R10 = REGNAME(OpndKind_GPReg,OpndSize_64,10), RegName_R11 = REGNAME(OpndKind_GPReg,OpndSize_64,11), RegName_R12 = REGNAME(OpndKind_GPReg,OpndSize_64,12), RegName_R13 = REGNAME(OpndKind_GPReg,OpndSize_64,13), RegName_R14 = REGNAME(OpndKind_GPReg,OpndSize_64,14), RegName_R15 = REGNAME(OpndKind_GPReg,OpndSize_64,15), #endif //~_EM64T_ RegName_EAX=REGNAME(OpndKind_GPReg,OpndSize_32,0), RegName_ECX=REGNAME(OpndKind_GPReg,OpndSize_32,1), RegName_EDX=REGNAME(OpndKind_GPReg,OpndSize_32,2), RegName_EBX=REGNAME(OpndKind_GPReg,OpndSize_32,3), RegName_ESP=REGNAME(OpndKind_GPReg,OpndSize_32,4), RegName_EBP=REGNAME(OpndKind_GPReg,OpndSize_32,5), RegName_ESI=REGNAME(OpndKind_GPReg,OpndSize_32,6), RegName_EDI=REGNAME(OpndKind_GPReg,OpndSize_32,7), #ifdef _EM64T_ RegName_R8D = REGNAME(OpndKind_GPReg,OpndSize_32,8), RegName_R9D = REGNAME(OpndKind_GPReg,OpndSize_32,9), RegName_R10D = REGNAME(OpndKind_GPReg,OpndSize_32,10), RegName_R11D = REGNAME(OpndKind_GPReg,OpndSize_32,11), RegName_R12D = REGNAME(OpndKind_GPReg,OpndSize_32,12), RegName_R13D = REGNAME(OpndKind_GPReg,OpndSize_32,13), RegName_R14D = REGNAME(OpndKind_GPReg,OpndSize_32,14), RegName_R15D = REGNAME(OpndKind_GPReg,OpndSize_32,15), #endif //~_EM64T_ RegName_AX=REGNAME(OpndKind_GPReg,OpndSize_16,0), RegName_CX=REGNAME(OpndKind_GPReg,OpndSize_16,1), RegName_DX=REGNAME(OpndKind_GPReg,OpndSize_16,2), RegName_BX=REGNAME(OpndKind_GPReg,OpndSize_16,3), RegName_SP=REGNAME(OpndKind_GPReg,OpndSize_16,4), RegName_BP=REGNAME(OpndKind_GPReg,OpndSize_16,5), RegName_SI=REGNAME(OpndKind_GPReg,OpndSize_16,6), RegName_DI=REGNAME(OpndKind_GPReg,OpndSize_16,7), #ifdef _EM64T_ RegName_R8S = REGNAME(OpndKind_GPReg,OpndSize_16,8), RegName_R9S = REGNAME(OpndKind_GPReg,OpndSize_16,9), RegName_R10S = REGNAME(OpndKind_GPReg,OpndSize_16,10), RegName_R11S = REGNAME(OpndKind_GPReg,OpndSize_16,11), RegName_R12S = REGNAME(OpndKind_GPReg,OpndSize_16,12), RegName_R13S = REGNAME(OpndKind_GPReg,OpndSize_16,13), RegName_R14S = REGNAME(OpndKind_GPReg,OpndSize_16,14), RegName_R15S = REGNAME(OpndKind_GPReg,OpndSize_16,15), #endif //~_EM64T_ RegName_AL=REGNAME(OpndKind_GPReg,OpndSize_8,0), RegName_CL=REGNAME(OpndKind_GPReg,OpndSize_8,1), RegName_DL=REGNAME(OpndKind_GPReg,OpndSize_8,2), RegName_BL=REGNAME(OpndKind_GPReg,OpndSize_8,3), // FIXME: Used in enc_tabl.cpp // AH is not accessible on EM64T, instead encoded register is SPL, so decoded // register will return incorrect enum RegName_AH=REGNAME(OpndKind_GPReg,OpndSize_8,4), #if !defined(_EM64T_) RegName_CH=REGNAME(OpndKind_GPReg,OpndSize_8,5), RegName_DH=REGNAME(OpndKind_GPReg,OpndSize_8,6), RegName_BH=REGNAME(OpndKind_GPReg,OpndSize_8,7), #else RegName_SPL=REGNAME(OpndKind_GPReg,OpndSize_8,4), RegName_BPL=REGNAME(OpndKind_GPReg,OpndSize_8,5), RegName_SIL=REGNAME(OpndKind_GPReg,OpndSize_8,6), RegName_DIL=REGNAME(OpndKind_GPReg,OpndSize_8,7), RegName_R8L=REGNAME(OpndKind_GPReg,OpndSize_8,8), RegName_R9L=REGNAME(OpndKind_GPReg,OpndSize_8,9), RegName_R10L=REGNAME(OpndKind_GPReg,OpndSize_8,10), RegName_R11L=REGNAME(OpndKind_GPReg,OpndSize_8,11), RegName_R12L=REGNAME(OpndKind_GPReg,OpndSize_8,12), RegName_R13L=REGNAME(OpndKind_GPReg,OpndSize_8,13), RegName_R14L=REGNAME(OpndKind_GPReg,OpndSize_8,14), RegName_R15L=REGNAME(OpndKind_GPReg,OpndSize_8,15), #endif RegName_ES=REGNAME(OpndKind_SReg,OpndSize_16,0), RegName_CS=REGNAME(OpndKind_SReg,OpndSize_16,1), RegName_SS=REGNAME(OpndKind_SReg,OpndSize_16,2), RegName_DS=REGNAME(OpndKind_SReg,OpndSize_16,3), RegName_FS=REGNAME(OpndKind_SReg,OpndSize_16,4), RegName_GS=REGNAME(OpndKind_SReg,OpndSize_16,5), RegName_EFLAGS=REGNAME(OpndKind_StatusReg,OpndSize_32,0), #if !defined(TESTING_ENCODER) RegName_FP0=REGNAME(OpndKind_FPReg,OpndSize_80,0), RegName_FP1=REGNAME(OpndKind_FPReg,OpndSize_80,1), RegName_FP2=REGNAME(OpndKind_FPReg,OpndSize_80,2), RegName_FP3=REGNAME(OpndKind_FPReg,OpndSize_80,3), RegName_FP4=REGNAME(OpndKind_FPReg,OpndSize_80,4), RegName_FP5=REGNAME(OpndKind_FPReg,OpndSize_80,5), RegName_FP6=REGNAME(OpndKind_FPReg,OpndSize_80,6), RegName_FP7=REGNAME(OpndKind_FPReg,OpndSize_80,7), #endif RegName_FP0S=REGNAME(OpndKind_FPReg,OpndSize_32,0), RegName_FP1S=REGNAME(OpndKind_FPReg,OpndSize_32,1), RegName_FP2S=REGNAME(OpndKind_FPReg,OpndSize_32,2), RegName_FP3S=REGNAME(OpndKind_FPReg,OpndSize_32,3), RegName_FP4S=REGNAME(OpndKind_FPReg,OpndSize_32,4), RegName_FP5S=REGNAME(OpndKind_FPReg,OpndSize_32,5), RegName_FP6S=REGNAME(OpndKind_FPReg,OpndSize_32,6), RegName_FP7S=REGNAME(OpndKind_FPReg,OpndSize_32,7), RegName_FP0D=REGNAME(OpndKind_FPReg,OpndSize_64,0), RegName_FP1D=REGNAME(OpndKind_FPReg,OpndSize_64,1), RegName_FP2D=REGNAME(OpndKind_FPReg,OpndSize_64,2), RegName_FP3D=REGNAME(OpndKind_FPReg,OpndSize_64,3), RegName_FP4D=REGNAME(OpndKind_FPReg,OpndSize_64,4), RegName_FP5D=REGNAME(OpndKind_FPReg,OpndSize_64,5), RegName_FP6D=REGNAME(OpndKind_FPReg,OpndSize_64,6), RegName_FP7D=REGNAME(OpndKind_FPReg,OpndSize_64,7), #if !defined(TESTING_ENCODER) RegName_XMM0=REGNAME(OpndKind_XMMReg,OpndSize_128,0), RegName_XMM1=REGNAME(OpndKind_XMMReg,OpndSize_128,1), RegName_XMM2=REGNAME(OpndKind_XMMReg,OpndSize_128,2), RegName_XMM3=REGNAME(OpndKind_XMMReg,OpndSize_128,3), RegName_XMM4=REGNAME(OpndKind_XMMReg,OpndSize_128,4), RegName_XMM5=REGNAME(OpndKind_XMMReg,OpndSize_128,5), RegName_XMM6=REGNAME(OpndKind_XMMReg,OpndSize_128,6), RegName_XMM7=REGNAME(OpndKind_XMMReg,OpndSize_128,7), #ifdef _EM64T_ RegName_XMM8 = REGNAME(OpndKind_XMMReg,OpndSize_128,0), RegName_XMM9 = REGNAME(OpndKind_XMMReg,OpndSize_128,1), RegName_XMM10 = REGNAME(OpndKind_XMMReg,OpndSize_128,2), RegName_XMM11 = REGNAME(OpndKind_XMMReg,OpndSize_128,3), RegName_XMM12 = REGNAME(OpndKind_XMMReg,OpndSize_128,4), RegName_XMM13 = REGNAME(OpndKind_XMMReg,OpndSize_128,5), RegName_XMM14 = REGNAME(OpndKind_XMMReg,OpndSize_128,6), RegName_XMM15 = REGNAME(OpndKind_XMMReg,OpndSize_128,7), #endif //~_EM64T_ #endif // ~TESTING_ENCODER RegName_XMM0S=REGNAME(OpndKind_XMMReg,OpndSize_32,0), RegName_XMM1S=REGNAME(OpndKind_XMMReg,OpndSize_32,1), RegName_XMM2S=REGNAME(OpndKind_XMMReg,OpndSize_32,2), RegName_XMM3S=REGNAME(OpndKind_XMMReg,OpndSize_32,3), RegName_XMM4S=REGNAME(OpndKind_XMMReg,OpndSize_32,4), RegName_XMM5S=REGNAME(OpndKind_XMMReg,OpndSize_32,5), RegName_XMM6S=REGNAME(OpndKind_XMMReg,OpndSize_32,6), RegName_XMM7S=REGNAME(OpndKind_XMMReg,OpndSize_32,7), #ifdef _EM64T_ RegName_XMM8S=REGNAME(OpndKind_XMMReg,OpndSize_32,8), RegName_XMM9S=REGNAME(OpndKind_XMMReg,OpndSize_32,9), RegName_XMM10S=REGNAME(OpndKind_XMMReg,OpndSize_32,10), RegName_XMM11S=REGNAME(OpndKind_XMMReg,OpndSize_32,11), RegName_XMM12S=REGNAME(OpndKind_XMMReg,OpndSize_32,12), RegName_XMM13S=REGNAME(OpndKind_XMMReg,OpndSize_32,13), RegName_XMM14S=REGNAME(OpndKind_XMMReg,OpndSize_32,14), RegName_XMM15S=REGNAME(OpndKind_XMMReg,OpndSize_32,15), #endif // ifdef _EM64T_ RegName_XMM0D=REGNAME(OpndKind_XMMReg,OpndSize_64,0), RegName_XMM1D=REGNAME(OpndKind_XMMReg,OpndSize_64,1), RegName_XMM2D=REGNAME(OpndKind_XMMReg,OpndSize_64,2), RegName_XMM3D=REGNAME(OpndKind_XMMReg,OpndSize_64,3), RegName_XMM4D=REGNAME(OpndKind_XMMReg,OpndSize_64,4), RegName_XMM5D=REGNAME(OpndKind_XMMReg,OpndSize_64,5), RegName_XMM6D=REGNAME(OpndKind_XMMReg,OpndSize_64,6), RegName_XMM7D=REGNAME(OpndKind_XMMReg,OpndSize_64,7), #ifdef _EM64T_ RegName_XMM8D=REGNAME(OpndKind_XMMReg,OpndSize_64,8), RegName_XMM9D=REGNAME(OpndKind_XMMReg,OpndSize_64,9), RegName_XMM10D=REGNAME(OpndKind_XMMReg,OpndSize_64,10), RegName_XMM11D=REGNAME(OpndKind_XMMReg,OpndSize_64,11), RegName_XMM12D=REGNAME(OpndKind_XMMReg,OpndSize_64,12), RegName_XMM13D=REGNAME(OpndKind_XMMReg,OpndSize_64,13), RegName_XMM14D=REGNAME(OpndKind_XMMReg,OpndSize_64,14), RegName_XMM15D=REGNAME(OpndKind_XMMReg,OpndSize_64,15), #endif // ifdef _EM64T_ #ifdef _HAVE_MMX_ RegName_MMX0=REGNAME(OpndKind_MMXReg,OpndSize_64,0), RegName_MMX1=REGNAME(OpndKind_MMXReg,OpndSize_64,1), RegName_MMX2=REGNAME(OpndKind_MMXReg,OpndSize_64,2), RegName_MMX3=REGNAME(OpndKind_MMXReg,OpndSize_64,3), RegName_MMX4=REGNAME(OpndKind_MMXReg,OpndSize_64,4), RegName_MMX5=REGNAME(OpndKind_MMXReg,OpndSize_64,5), RegName_MMX6=REGNAME(OpndKind_MMXReg,OpndSize_64,6), RegName_MMX7=REGNAME(OpndKind_MMXReg,OpndSize_64,7), #endif // _HAVE_MMX_ } RegName; #if 0 // Android x86: use mnemonics defined in enc_defs_ext.h /** * Conditional mnemonics. * The values match the 'real' (==processor's) values of the appropriate * condition values used in the opcodes. */ enum ConditionMnemonic { ConditionMnemonic_O=0, ConditionMnemonic_NO=1, ConditionMnemonic_B=2, ConditionMnemonic_NAE=ConditionMnemonic_B, ConditionMnemonic_C=ConditionMnemonic_B, ConditionMnemonic_NB=3, ConditionMnemonic_AE=ConditionMnemonic_NB, ConditionMnemonic_NC=ConditionMnemonic_NB, ConditionMnemonic_Z=4, ConditionMnemonic_E=ConditionMnemonic_Z, ConditionMnemonic_NZ=5, ConditionMnemonic_NE=ConditionMnemonic_NZ, ConditionMnemonic_BE=6, ConditionMnemonic_NA=ConditionMnemonic_BE, ConditionMnemonic_NBE=7, ConditionMnemonic_A=ConditionMnemonic_NBE, ConditionMnemonic_S=8, ConditionMnemonic_NS=9, ConditionMnemonic_P=10, ConditionMnemonic_PE=ConditionMnemonic_P, ConditionMnemonic_NP=11, ConditionMnemonic_PO=ConditionMnemonic_NP, ConditionMnemonic_L=12, ConditionMnemonic_NGE=ConditionMnemonic_L, ConditionMnemonic_NL=13, ConditionMnemonic_GE=ConditionMnemonic_NL, ConditionMnemonic_LE=14, ConditionMnemonic_NG=ConditionMnemonic_LE, ConditionMnemonic_NLE=15, ConditionMnemonic_G=ConditionMnemonic_NLE, ConditionMnemonic_Count=16 }; #define CCM(prefix,cond) Mnemonic_##prefix##cond=Mnemonic_##prefix##cc+ConditionMnemonic_##cond //========================================================================================================= enum Mnemonic { Mnemonic_NULL=0, Mnemonic_Null=Mnemonic_NULL, Mnemonic_ADC, // Add with Carry Mnemonic_ADD, // Add Mnemonic_ADDSD, // Add Scalar Double-Precision Floating-Point Values Mnemonic_ADDSS, // Add Scalar Single-Precision Floating-Point Values Mnemonic_AND, // Logical AND Mnemonic_BSF, // Bit scan forward Mnemonic_BSR, // Bit scan reverse Mnemonic_CALL, // Call Procedure Mnemonic_CMC, // Complement Carry Flag Mnemonic_CWD, Mnemonic_CDQ=Mnemonic_CWD,// Convert Word to Doubleword/Convert Doubleword to Qua T dword Mnemonic_CMOVcc, // Conditional Move CCM(CMOV,O), CCM(CMOV,NO), CCM(CMOV,B), CCM(CMOV,NAE), CCM(CMOV,C), CCM(CMOV,NB), CCM(CMOV,AE), CCM(CMOV,NC), CCM(CMOV,Z), CCM(CMOV,E), CCM(CMOV,NZ), CCM(CMOV,NE), CCM(CMOV,BE), CCM(CMOV,NA), CCM(CMOV,NBE), CCM(CMOV,A), CCM(CMOV,S), CCM(CMOV,NS), CCM(CMOV,P), CCM(CMOV,PE), CCM(CMOV,NP), CCM(CMOV,PO), CCM(CMOV,L), CCM(CMOV,NGE), CCM(CMOV,NL), CCM(CMOV,GE), CCM(CMOV,LE), CCM(CMOV,NG), CCM(CMOV,NLE), CCM(CMOV,G), Mnemonic_CMP, // Compare Two Operands Mnemonic_CMPXCHG, // Compare and exchange Mnemonic_CMPXCHG8B, // Compare and Exchange 8 Bytes Mnemonic_CMPSB, // Compare Two Bytes at DS:ESI and ES:EDI Mnemonic_CMPSW, // Compare Two Words at DS:ESI and ES:EDI Mnemonic_CMPSD, // Compare Two Doublewords at DS:ESI and ES:EDI // // double -> float Mnemonic_CVTSD2SS, // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value // double -> I_32 Mnemonic_CVTSD2SI, // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer // double [truncated] -> I_32 Mnemonic_CVTTSD2SI, // Convert with Truncation Scalar Double-Precision Floating-Point Value to Signed Doubleword Integer // // float -> double Mnemonic_CVTSS2SD, // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value // float -> I_32 Mnemonic_CVTSS2SI, // Convert Scalar Single-Precision Floating-Point Value to Doubleword Integer // float [truncated] -> I_32 Mnemonic_CVTTSS2SI, // Convert with Truncation Scalar Single-Precision Floating-Point Value to Doubleword Integer // // I_32 -> double Mnemonic_CVTSI2SD, // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value // I_32 -> float Mnemonic_CVTSI2SS, // Convert Doubleword Integer to Scalar Single-Precision Floating-Point Value Mnemonic_COMISD, // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS Mnemonic_COMISS, // Compare Scalar Ordered Single-Precision Floating-Point Values and Set EFLAGS Mnemonic_DEC, // Decrement by 1 //Mnemonic_DIV, // Unsigned Divide Mnemonic_DIVSD, // Divide Scalar Double-Precision Floating-Point Values Mnemonic_DIVSS, // Divide Scalar Single-Precision Floating-Point Values #ifdef _HAVE_MMX_ Mnemonic_EMMS, // Empty MMX Technology State #endif Mnemonic_ENTER, // ENTER-Make Stack Frame for Procedure Parameters Mnemonic_FLDCW, // Load FPU control word Mnemonic_FADDP, Mnemonic_FLDZ, Mnemonic_FADD, Mnemonic_FSUBP, Mnemonic_FSUB, Mnemonic_FISUB, Mnemonic_FMUL, Mnemonic_FMULP, Mnemonic_FDIVP, Mnemonic_FDIV, Mnemonic_FUCOMPP, Mnemonic_FRNDINT, Mnemonic_FNSTCW, // Store FPU control word Mnemonic_FSTSW, // Store FPU status word Mnemonic_FNSTSW, // Store FPU status word //Mnemonic_FDECSTP, // Decrement Stack-Top Pointer Mnemonic_FILD, // Load Integer Mnemonic_FLD, // Load Floating Point Value Mnemonic_FLDLG2, Mnemonic_FLDLN2, Mnemonic_FLD1, Mnemonic_FCLEX, // Clear Exceptions Mnemonic_FCHS, // Change sign of ST0 Mnemonic_FNCLEX, // Clear Exceptions //Mnemonic_FINCSTP, // Increment Stack-Top Pointer Mnemonic_FIST, // Store Integer Mnemonic_FISTP, // Store Integer, pop FPU stack Mnemonic_FISTTP, // Store Integer with Truncation Mnemonic_FPREM, // Partial Remainder Mnemonic_FPREM1, // Partial Remainder Mnemonic_FST, // Store Floating Point Value Mnemonic_FSTP, // Store Floating Point Value and pop the FP stack Mnemonic_FSQRT, //Computes the square root of the source value in the stack and pop the FP stack Mnemonic_FABS, //Computes the absolute value of the source value in the stack and pop the FP stack Mnemonic_FSIN, //Computes the sine of the source value in the stack and pop the FP stack Mnemonic_FCOS, //Computes the cosine of the source value in the stack and pop the FP stack Mnemonic_FPTAN, //Computes the tangent of the source value in the stack and pop the FP stack Mnemonic_FYL2X, Mnemonic_FYL2XP1, Mnemonic_F2XM1, Mnemonic_FPATAN, Mnemonic_FXCH, Mnemonic_FSCALE, Mnemonic_XCHG, Mnemonic_DIV, // Unsigned Divide Mnemonic_IDIV, // Signed Divide Mnemonic_MUL, // Unsigned Multiply Mnemonic_IMUL, // Signed Multiply Mnemonic_INC, // Increment by 1 Mnemonic_INT3, // Call break point Mnemonic_Jcc, // Jump if Condition Is Met CCM(J,O), CCM(J,NO), CCM(J,B), CCM(J,NAE), CCM(J,C), CCM(J,NB), CCM(J,AE), CCM(J,NC), CCM(J,Z), CCM(J,E), CCM(J,NZ), CCM(J,NE), CCM(J,BE), CCM(J,NA), CCM(J,NBE), CCM(J,A), CCM(J,S), CCM(J,NS), CCM(J,P), CCM(J,PE), CCM(J,NP), CCM(J,PO), CCM(J,L), CCM(J,NGE), CCM(J,NL), CCM(J,GE), CCM(J,LE), CCM(J,NG), CCM(J,NLE), CCM(J,G), Mnemonic_JMP, // Jump Mnemonic_LEA, // Load Effective Address Mnemonic_LEAVE, // High Level Procedure Exit Mnemonic_LOOP, // Loop according to ECX counter Mnemonic_LOOPE, // Loop according to ECX counter Mnemonic_LOOPNE, Mnemonic_LOOPNZ = Mnemonic_LOOPNE, // Loop according to ECX Mnemonic_LAHF, // Load Flags into AH Mnemonic_MOV, // Move Mnemonic_MOVD, // Move Double word Mnemonic_MOVQ, // Move Quadword /*Mnemonic_MOVS, // Move Data from String to String*/ // MOVS is a special case: see encoding table for more details, Mnemonic_MOVS8, Mnemonic_MOVS16, Mnemonic_MOVS32, Mnemonic_MOVS64, // Mnemonic_MOVAPD, // Move Scalar Double-Precision Floating-Point Value Mnemonic_MOVSD, // Move Scalar Double-Precision Floating-Point Value Mnemonic_MOVSS, // Move Scalar Single-Precision Floating-Point Values Mnemonic_MOVSX, // Move with Sign-Extension Mnemonic_MOVZX, // Move with Zero-Extend //Mnemonic_MUL, // Unsigned Multiply Mnemonic_MULSD, // Multiply Scalar Double-Precision Floating-Point Values Mnemonic_MULSS, // Multiply Scalar Single-Precision Floating-Point Values Mnemonic_NEG, // Two's Complement Negation Mnemonic_NOP, // No Operation Mnemonic_NOT, // One's Complement Negation Mnemonic_OR, // Logical Inclusive OR Mnemonic_PREFETCH, // prefetch #ifdef _HAVE_MMX_ Mnemonic_PADDQ, // Add Packed Quadword Integers Mnemonic_PAND, // Logical AND Mnemonic_POR, // Bitwise Logical OR Mnemonic_PSUBQ, // Subtract Packed Quadword Integers #endif Mnemonic_PXOR, // Logical Exclusive OR Mnemonic_POP, // Pop a Value from the Stack Mnemonic_POPFD, // Pop a Value of EFLAGS register from the Stack Mnemonic_PUSH, // Push Word or Doubleword Onto the Stack Mnemonic_PUSHFD, // Push EFLAGS Doubleword Onto the Stack Mnemonic_RET, // Return from Procedure Mnemonic_SETcc, // Set Byte on Condition CCM(SET,O), CCM(SET,NO), CCM(SET,B), CCM(SET,NAE), CCM(SET,C), CCM(SET,NB), CCM(SET,AE), CCM(SET,NC), CCM(SET,Z), CCM(SET,E), CCM(SET,NZ), CCM(SET,NE), CCM(SET,BE), CCM(SET,NA), CCM(SET,NBE), CCM(SET,A), CCM(SET,S), CCM(SET,NS), CCM(SET,P), CCM(SET,PE), CCM(SET,NP), CCM(SET,PO), CCM(SET,L), CCM(SET,NGE), CCM(SET,NL), CCM(SET,GE), CCM(SET,LE), CCM(SET,NG), CCM(SET,NLE), CCM(SET,G), Mnemonic_SAL, Mnemonic_SHL=Mnemonic_SAL,// Shift left Mnemonic_SAR, // Shift right Mnemonic_ROR, // Rotate right Mnemonic_RCR, // Rotate right through CARRY flag Mnemonic_ROL, // Rotate left Mnemonic_RCL, // Rotate left through CARRY flag Mnemonic_SHR, // Unsigned shift right Mnemonic_SHRD, // Double Precision Shift Right Mnemonic_SHLD, // Double Precision Shift Left Mnemonic_SBB, // Integer Subtraction with Borrow Mnemonic_SUB, // Subtract Mnemonic_SUBSD, // Subtract Scalar Double-Precision Floating-Point Values Mnemonic_SUBSS, // Subtract Scalar Single-Precision Floating-Point Values Mnemonic_TEST, // Logical Compare Mnemonic_UCOMISD, // Unordered Compare Scalar Double-Precision Floating-Point Values and Set EFLAGS Mnemonic_UCOMISS, // Unordered Compare Scalar Single-Precision Floating-Point Values and Set EFLAGS Mnemonic_XOR, // Logical Exclusive OR // // packed things, // Mnemonic_XORPD, // Bitwise Logical XOR for Double-Precision Floating-Point Values Mnemonic_XORPS, // Bitwise Logical XOR for Single-Precision Floating-Point Values Mnemonic_CVTDQ2PD, // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values Mnemonic_CVTTPD2DQ, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers Mnemonic_CVTDQ2PS, // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values Mnemonic_CVTTPS2DQ, // Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers // // String operations // Mnemonic_STD, // Set direction flag Mnemonic_CLD, // Clear direction flag Mnemonic_SCAS, // Scan string Mnemonic_STOS, // Store string // Mnemonic_WAIT, // Check pending pending unmasked floating-point exception // Mnemonic_Count }; #undef CCM #endif /** * @brief Instruction prefixes, according to arch manual. */ typedef enum InstPrefix { InstPrefix_Null = 0, // Group 1 InstPrefix_LOCK = 0xF0, InstPrefix_REPNE = 0xF2, InstPrefix_REPNZ = InstPrefix_REPNE, InstPrefix_REP = 0xF3, InstPrefix_REPZ = InstPrefix_REP, // Group 2 InstPrefix_CS = 0x2E, InstPrefix_SS = 0x36, InstPrefix_DS = 0x3E, InstPrefix_ES = 0x26, InstPrefix_FS = 0x64, InstPrefix_GS = 0x65, // InstPrefix_HintTaken = 0x3E, InstPrefix_HintNotTaken = 0x2E, // Group 3 InstPrefix_OpndSize = 0x66, // Group 4 InstPrefix_AddrSize = 0x67 } InstPrefix; inline unsigned getSizeBytes(OpndSize sz) { if (sz==OpndSize_64) { return 8; } if (sz==OpndSize_32) { return 4; } if (sz==OpndSize_16) { return 2; } if (sz==OpndSize_8) { return 1; } assert(false); return 0; } inline bool isRegKind(OpndKind kind) { return OpndKind_GPReg<= kind && kind<=OpndKind_MaxRegKind; } /** * @brief Returns #RegName for a given name. * * Name is case-insensitive. * @param regname - string name of a register * @return #RegName for the given name, or #RegName_Null if name is invalid */ RegName getRegName(const char * regname); /** * Constructs RegName from the given OpndKind, size and index. */ inline RegName getRegName(OpndKind k, OpndSize s, int idx) { return (RegName)REGNAME(k,s,idx); } /** * Extracts a bit mask with a bit set at the position of the register's index. */ inline unsigned getRegMask(RegName reg) { return 1<<(reg&0xff); } /** * @brief Extracts #RegKind from the #RegName. */ inline OpndKind getRegKind(RegName reg) { return (OpndKind)(reg>>24); } /** * @brief Extracts #OpndSize from #RegName. */ inline OpndSize getRegSize(RegName reg) { return (OpndSize)((reg>>16)&0xFF); } /** * Extracts an index from the given RegName. */ inline unsigned char getRegIndex(RegName reg) { return (unsigned char)(reg&0xFF); } /** * Returns a string name of the given RegName. The name returned is in upper-case. * Returns NULL if invalid RegName specified. */ const char * getRegNameString(RegName reg); /** * Returns string name of a given OpndSize. * Returns NULL if invalid OpndSize passed. */ const char * getOpndSizeString(OpndSize size); /** * Returns OpndSize passed by its string representation (case insensitive). * Returns OpndSize_Null if invalid string specified. * The 'sizeString' can not be NULL. */ OpndSize getOpndSize(const char * sizeString); /** * Returns string name of a given OpndKind. * Returns NULL if the passed kind is invalid. */ const char * getOpndKindString(OpndKind kind); /** * Returns OpndKind found by its string representation (case insensitive). * Returns OpndKind_Null if the name is invalid. * The 'kindString' can not be NULL. */ OpndKind getOpndKind(const char * kindString); /** * */ const char * getConditionString(ConditionMnemonic cm); /** * Constructs an RegName with the same index and kind, but with a different size from * the given RegName (i.e. getRegAlias(EAX, OpndSize_16) => AX; getRegAlias(BL, OpndSize_32) => EBX). * The constructed RegName is not checked in any way and thus may be invalid. * Note, that the aliasing does not work for at least AH,BH,CH,DH, ESI, EDI, ESP and EBP regs. */ inline RegName getAliasReg(RegName reg, OpndSize sz) { return (RegName)REGNAME(getRegKind(reg), sz, getRegIndex(reg)); } /** * brief Tests two RegName-s of the same kind for equality. * * @note Does work for 8 bit general purpose registers (AH, AL, BH, BL, etc). */ inline bool equals(RegName r0, RegName r1) { return getRegKind(r0) == getRegKind(r1) && getRegIndex(r0) == getRegIndex(r1); } ENCODER_NAMESPACE_END #endif // ifndef _ENCODER_DEFS_H_