| /*---------------------------------------------------------------*/ |
| /*--- begin host_arm_defs.h ---*/ |
| /*---------------------------------------------------------------*/ |
| |
| /* |
| This file is part of Valgrind, a dynamic binary instrumentation |
| framework. |
| |
| Copyright (C) 2004-2012 OpenWorks LLP |
| info@open-works.net |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License as |
| published by the Free Software Foundation; either version 2 of the |
| License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301, USA. |
| |
| The GNU General Public License is contained in the file COPYING. |
| */ |
| |
| #ifndef __VEX_HOST_ARM_DEFS_H |
| #define __VEX_HOST_ARM_DEFS_H |
| |
| #include "libvex_basictypes.h" |
| #include "libvex.h" // VexArch |
| #include "host_generic_regs.h" // HReg |
| |
| extern UInt arm_hwcaps; |
| |
| |
| /* --------- Registers. --------- */ |
| |
| /* The usual HReg abstraction. |
| There are 16 general purpose regs. |
| */ |
| |
| extern void ppHRegARM ( HReg ); |
| |
| extern HReg hregARM_R0 ( void ); |
| extern HReg hregARM_R1 ( void ); |
| extern HReg hregARM_R2 ( void ); |
| extern HReg hregARM_R3 ( void ); |
| extern HReg hregARM_R4 ( void ); |
| extern HReg hregARM_R5 ( void ); |
| extern HReg hregARM_R6 ( void ); |
| extern HReg hregARM_R7 ( void ); |
| extern HReg hregARM_R8 ( void ); |
| extern HReg hregARM_R9 ( void ); |
| extern HReg hregARM_R10 ( void ); |
| extern HReg hregARM_R11 ( void ); |
| extern HReg hregARM_R12 ( void ); |
| extern HReg hregARM_R13 ( void ); |
| extern HReg hregARM_R14 ( void ); |
| extern HReg hregARM_R15 ( void ); |
| extern HReg hregARM_D8 ( void ); |
| extern HReg hregARM_D9 ( void ); |
| extern HReg hregARM_D10 ( void ); |
| extern HReg hregARM_D11 ( void ); |
| extern HReg hregARM_D12 ( void ); |
| extern HReg hregARM_S26 ( void ); |
| extern HReg hregARM_S27 ( void ); |
| extern HReg hregARM_S28 ( void ); |
| extern HReg hregARM_S29 ( void ); |
| extern HReg hregARM_S30 ( void ); |
| extern HReg hregARM_Q8 ( void ); |
| extern HReg hregARM_Q9 ( void ); |
| extern HReg hregARM_Q10 ( void ); |
| extern HReg hregARM_Q11 ( void ); |
| extern HReg hregARM_Q12 ( void ); |
| extern HReg hregARM_Q13 ( void ); |
| extern HReg hregARM_Q14 ( void ); |
| extern HReg hregARM_Q15 ( void ); |
| |
| /* Number of registers used arg passing in function calls */ |
| #define ARM_N_ARGREGS 4 /* r0, r1, r2, r3 */ |
| |
| |
| /* --------- Condition codes. --------- */ |
| |
| typedef |
| enum { |
| ARMcc_EQ = 0, /* equal : Z=1 */ |
| ARMcc_NE = 1, /* not equal : Z=0 */ |
| |
| ARMcc_HS = 2, /* >=u (higher or same) : C=1 */ |
| ARMcc_LO = 3, /* <u (lower) : C=0 */ |
| |
| ARMcc_MI = 4, /* minus (negative) : N=1 */ |
| ARMcc_PL = 5, /* plus (zero or +ve) : N=0 */ |
| |
| ARMcc_VS = 6, /* overflow : V=1 */ |
| ARMcc_VC = 7, /* no overflow : V=0 */ |
| |
| ARMcc_HI = 8, /* >u (higher) : C=1 && Z=0 */ |
| ARMcc_LS = 9, /* <=u (lower or same) : C=0 || Z=1 */ |
| |
| ARMcc_GE = 10, /* >=s (signed greater or equal) : N=V */ |
| ARMcc_LT = 11, /* <s (signed less than) : N!=V */ |
| |
| ARMcc_GT = 12, /* >s (signed greater) : Z=0 && N=V */ |
| ARMcc_LE = 13, /* <=s (signed less or equal) : Z=1 || N!=V */ |
| |
| ARMcc_AL = 14, /* always (unconditional) */ |
| ARMcc_NV = 15 /* never (basically undefined meaning), deprecated */ |
| } |
| ARMCondCode; |
| |
| extern const HChar* showARMCondCode ( ARMCondCode ); |
| |
| |
| |
| /* --------- Memory address expressions (amodes). --------- */ |
| |
| /* --- Addressing Mode 1 --- */ |
| typedef |
| enum { |
| ARMam1_RI=1, /* reg +/- imm12 */ |
| ARMam1_RRS /* reg1 + (reg2 << 0, 1 2 or 3) */ |
| } |
| ARMAMode1Tag; |
| |
| typedef |
| struct { |
| ARMAMode1Tag tag; |
| union { |
| struct { |
| HReg reg; |
| Int simm13; /* -4095 .. +4095 */ |
| } RI; |
| struct { |
| HReg base; |
| HReg index; |
| UInt shift; /* 0, 1 2 or 3 */ |
| } RRS; |
| } ARMam1; |
| } |
| ARMAMode1; |
| |
| extern ARMAMode1* ARMAMode1_RI ( HReg reg, Int simm13 ); |
| extern ARMAMode1* ARMAMode1_RRS ( HReg base, HReg index, UInt shift ); |
| |
| extern void ppARMAMode1 ( ARMAMode1* ); |
| |
| |
| /* --- Addressing Mode 2 --- */ |
| typedef |
| enum { |
| ARMam2_RI=3, /* reg +/- imm8 */ |
| ARMam2_RR /* reg1 + reg2 */ |
| } |
| ARMAMode2Tag; |
| |
| typedef |
| struct { |
| ARMAMode2Tag tag; |
| union { |
| struct { |
| HReg reg; |
| Int simm9; /* -255 .. 255 */ |
| } RI; |
| struct { |
| HReg base; |
| HReg index; |
| } RR; |
| } ARMam2; |
| } |
| ARMAMode2; |
| |
| extern ARMAMode2* ARMAMode2_RI ( HReg reg, Int simm9 ); |
| extern ARMAMode2* ARMAMode2_RR ( HReg base, HReg index ); |
| |
| extern void ppARMAMode2 ( ARMAMode2* ); |
| |
| |
| /* --- Addressing Mode suitable for VFP --- */ |
| /* The simm11 is encoded as 8 bits + 1 sign bit, |
| so can only be 0 % 4. */ |
| typedef |
| struct { |
| HReg reg; |
| Int simm11; /* -1020, -1016 .. 1016, 1020 */ |
| } |
| ARMAModeV; |
| |
| extern ARMAModeV* mkARMAModeV ( HReg reg, Int simm11 ); |
| |
| extern void ppARMAModeV ( ARMAModeV* ); |
| |
| /* --- Addressing Mode suitable for Neon --- */ |
| typedef |
| enum { |
| ARMamN_R=5, |
| ARMamN_RR |
| /* ... */ |
| } |
| ARMAModeNTag; |
| |
| typedef |
| struct { |
| ARMAModeNTag tag; |
| union { |
| struct { |
| HReg rN; |
| HReg rM; |
| } RR; |
| struct { |
| HReg rN; |
| } R; |
| /* ... */ |
| } ARMamN; |
| } |
| ARMAModeN; |
| |
| extern ARMAModeN* mkARMAModeN_RR ( HReg, HReg ); |
| extern ARMAModeN* mkARMAModeN_R ( HReg ); |
| extern void ppARMAModeN ( ARMAModeN* ); |
| |
| /* --------- Reg or imm-8x4 operands --------- */ |
| /* a.k.a (a very restricted form of) Shifter Operand, |
| in the ARM parlance. */ |
| |
| typedef |
| enum { |
| ARMri84_I84=7, /* imm8 `ror` (2 * imm4) */ |
| ARMri84_R /* reg */ |
| } |
| ARMRI84Tag; |
| |
| typedef |
| struct { |
| ARMRI84Tag tag; |
| union { |
| struct { |
| UShort imm8; |
| UShort imm4; |
| } I84; |
| struct { |
| HReg reg; |
| } R; |
| } ARMri84; |
| } |
| ARMRI84; |
| |
| extern ARMRI84* ARMRI84_I84 ( UShort imm8, UShort imm4 ); |
| extern ARMRI84* ARMRI84_R ( HReg ); |
| |
| extern void ppARMRI84 ( ARMRI84* ); |
| |
| |
| /* --------- Reg or imm5 operands --------- */ |
| typedef |
| enum { |
| ARMri5_I5=9, /* imm5, 1 .. 31 only (no zero!) */ |
| ARMri5_R /* reg */ |
| } |
| ARMRI5Tag; |
| |
| typedef |
| struct { |
| ARMRI5Tag tag; |
| union { |
| struct { |
| UInt imm5; |
| } I5; |
| struct { |
| HReg reg; |
| } R; |
| } ARMri5; |
| } |
| ARMRI5; |
| |
| extern ARMRI5* ARMRI5_I5 ( UInt imm5 ); |
| extern ARMRI5* ARMRI5_R ( HReg ); |
| |
| extern void ppARMRI5 ( ARMRI5* ); |
| |
| /* -------- Neon Immediate operand -------- */ |
| |
| /* imm8 = abcdefgh, B = NOT(b); |
| |
| type | value (64bit binary) |
| -----+------------------------------------------------------------------------- |
| 0 | 00000000 00000000 00000000 abcdefgh 00000000 00000000 00000000 abcdefgh |
| 1 | 00000000 00000000 abcdefgh 00000000 00000000 00000000 abcdefgh 00000000 |
| 2 | 00000000 abcdefgh 00000000 00000000 00000000 abcdefgh 00000000 00000000 |
| 3 | abcdefgh 00000000 00000000 00000000 abcdefgh 00000000 00000000 00000000 |
| 4 | 00000000 abcdefgh 00000000 abcdefgh 00000000 abcdefgh 00000000 abcdefgh |
| 5 | abcdefgh 00000000 abcdefgh 00000000 abcdefgh 00000000 abcdefgh 00000000 |
| 6 | abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh |
| 7 | 00000000 00000000 abcdefgh 11111111 00000000 00000000 abcdefgh 11111111 |
| 8 | 00000000 abcdefgh 11111111 11111111 00000000 abcdefgh 11111111 11111111 |
| 9 | aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh |
| 10 | aBbbbbbc defgh000 00000000 00000000 aBbbbbbc defgh000 00000000 00000000 |
| -----+------------------------------------------------------------------------- |
| |
| Type 10 is: |
| (-1)^S * 2^exp * mantissa |
| where S = a, exp = UInt(B:c:d) - 3, mantissa = (16 + UInt(e:f:g:h)) / 16 |
| */ |
| |
| typedef |
| struct { |
| UInt type; |
| UInt imm8; |
| } |
| ARMNImm; |
| |
| extern ARMNImm* ARMNImm_TI ( UInt type, UInt imm8 ); |
| extern ULong ARMNImm_to_Imm64 ( ARMNImm* ); |
| extern ARMNImm* Imm64_to_ARMNImm ( ULong ); |
| |
| extern void ppARMNImm ( ARMNImm* ); |
| |
| /* ------ Neon Register or Scalar Operand ------ */ |
| |
| typedef |
| enum { |
| ARMNRS_Reg=11, |
| ARMNRS_Scalar |
| } |
| ARMNRS_tag; |
| |
| typedef |
| struct { |
| ARMNRS_tag tag; |
| HReg reg; |
| UInt index; |
| } |
| ARMNRS; |
| |
| extern ARMNRS* mkARMNRS(ARMNRS_tag, HReg reg, UInt index); |
| extern void ppARMNRS ( ARMNRS* ); |
| |
| /* --------- Instructions. --------- */ |
| |
| /* --------- */ |
| typedef |
| enum { |
| ARMalu_ADD=20, /* plain 32-bit add */ |
| ARMalu_ADDS, /* 32-bit add, and set the flags */ |
| ARMalu_ADC, /* 32-bit add with carry */ |
| ARMalu_SUB, /* plain 32-bit subtract */ |
| ARMalu_SUBS, /* 32-bit subtract, and set the flags */ |
| ARMalu_SBC, /* 32-bit subtract with carry */ |
| ARMalu_AND, |
| ARMalu_BIC, |
| ARMalu_OR, |
| ARMalu_XOR |
| } |
| ARMAluOp; |
| |
| extern const HChar* showARMAluOp ( ARMAluOp op ); |
| |
| |
| typedef |
| enum { |
| ARMsh_SHL=40, |
| ARMsh_SHR, |
| ARMsh_SAR |
| } |
| ARMShiftOp; |
| |
| extern const HChar* showARMShiftOp ( ARMShiftOp op ); |
| |
| |
| typedef |
| enum { |
| ARMun_NEG=50, |
| ARMun_NOT, |
| ARMun_CLZ |
| } |
| ARMUnaryOp; |
| |
| extern const HChar* showARMUnaryOp ( ARMUnaryOp op ); |
| |
| |
| typedef |
| enum { |
| ARMmul_PLAIN=60, |
| ARMmul_ZX, |
| ARMmul_SX |
| } |
| ARMMulOp; |
| |
| extern const HChar* showARMMulOp ( ARMMulOp op ); |
| |
| |
| typedef |
| enum { |
| ARMvfp_ADD=70, |
| ARMvfp_SUB, |
| ARMvfp_MUL, |
| ARMvfp_DIV |
| } |
| ARMVfpOp; |
| |
| extern const HChar* showARMVfpOp ( ARMVfpOp op ); |
| |
| |
| typedef |
| enum { |
| ARMvfpu_COPY=80, |
| ARMvfpu_NEG, |
| ARMvfpu_ABS, |
| ARMvfpu_SQRT |
| } |
| ARMVfpUnaryOp; |
| |
| extern const HChar* showARMVfpUnaryOp ( ARMVfpUnaryOp op ); |
| |
| typedef |
| enum { |
| ARMneon_VAND=90, |
| ARMneon_VORR, |
| ARMneon_VXOR, |
| ARMneon_VADD, |
| ARMneon_VADDFP, |
| ARMneon_VRHADDS, |
| ARMneon_VRHADDU, |
| ARMneon_VPADDFP, |
| ARMneon_VABDFP, |
| ARMneon_VSUB, |
| ARMneon_VSUBFP, |
| ARMneon_VMAXU, |
| ARMneon_VMAXS, |
| ARMneon_VMAXF, |
| ARMneon_VMINU, |
| ARMneon_VMINS, |
| ARMneon_VMINF, |
| ARMneon_VQADDU, |
| ARMneon_VQADDS, |
| ARMneon_VQSUBU, |
| ARMneon_VQSUBS, |
| ARMneon_VCGTU, |
| ARMneon_VCGTS, |
| ARMneon_VCGEU, |
| ARMneon_VCGES, |
| ARMneon_VCGTF, |
| ARMneon_VCGEF, |
| ARMneon_VCEQ, |
| ARMneon_VCEQF, |
| ARMneon_VEXT, |
| ARMneon_VMUL, |
| ARMneon_VMULFP, |
| ARMneon_VMULLU, |
| ARMneon_VMULLS, |
| ARMneon_VMULP, |
| ARMneon_VMULLP, |
| ARMneon_VQDMULH, |
| ARMneon_VQRDMULH, |
| ARMneon_VPADD, |
| ARMneon_VPMINU, |
| ARMneon_VPMINS, |
| ARMneon_VPMINF, |
| ARMneon_VPMAXU, |
| ARMneon_VPMAXS, |
| ARMneon_VPMAXF, |
| ARMneon_VTBL, |
| ARMneon_VQDMULL, |
| ARMneon_VRECPS, |
| ARMneon_VRSQRTS, |
| /* ... */ |
| } |
| ARMNeonBinOp; |
| |
| typedef |
| enum { |
| ARMneon_VSHL=150, |
| ARMneon_VSAL, /* Yah, not SAR but SAL */ |
| ARMneon_VQSHL, |
| ARMneon_VQSAL |
| } |
| ARMNeonShiftOp; |
| |
| typedef |
| enum { |
| ARMneon_COPY=160, |
| ARMneon_COPYLU, |
| ARMneon_COPYLS, |
| ARMneon_COPYN, |
| ARMneon_COPYQNSS, |
| ARMneon_COPYQNUS, |
| ARMneon_COPYQNUU, |
| ARMneon_NOT, |
| ARMneon_EQZ, |
| ARMneon_DUP, |
| ARMneon_PADDLS, |
| ARMneon_PADDLU, |
| ARMneon_CNT, |
| ARMneon_CLZ, |
| ARMneon_CLS, |
| ARMneon_VCVTxFPxINT, |
| ARMneon_VQSHLNSS, |
| ARMneon_VQSHLNUU, |
| ARMneon_VQSHLNUS, |
| ARMneon_VCVTFtoU, |
| ARMneon_VCVTFtoS, |
| ARMneon_VCVTUtoF, |
| ARMneon_VCVTStoF, |
| ARMneon_VCVTFtoFixedU, |
| ARMneon_VCVTFtoFixedS, |
| ARMneon_VCVTFixedUtoF, |
| ARMneon_VCVTFixedStoF, |
| ARMneon_VCVTF16toF32, |
| ARMneon_VCVTF32toF16, |
| ARMneon_REV16, |
| ARMneon_REV32, |
| ARMneon_REV64, |
| ARMneon_ABS, |
| ARMneon_VNEGF, |
| ARMneon_VRECIP, |
| ARMneon_VRECIPF, |
| ARMneon_VABSFP, |
| ARMneon_VRSQRTEFP, |
| ARMneon_VRSQRTE |
| /* ... */ |
| } |
| ARMNeonUnOp; |
| |
| typedef |
| enum { |
| ARMneon_SETELEM=200, |
| ARMneon_GETELEMU, |
| ARMneon_GETELEMS, |
| ARMneon_VDUP, |
| } |
| ARMNeonUnOpS; |
| |
| typedef |
| enum { |
| ARMneon_TRN=210, |
| ARMneon_ZIP, |
| ARMneon_UZP |
| /* ... */ |
| } |
| ARMNeonDualOp; |
| |
| extern const HChar* showARMNeonBinOp ( ARMNeonBinOp op ); |
| extern const HChar* showARMNeonUnOp ( ARMNeonUnOp op ); |
| extern const HChar* showARMNeonUnOpS ( ARMNeonUnOpS op ); |
| extern const HChar* showARMNeonShiftOp ( ARMNeonShiftOp op ); |
| extern const HChar* showARMNeonDualOp ( ARMNeonDualOp op ); |
| extern const HChar* showARMNeonBinOpDataType ( ARMNeonBinOp op ); |
| extern const HChar* showARMNeonUnOpDataType ( ARMNeonUnOp op ); |
| extern const HChar* showARMNeonUnOpSDataType ( ARMNeonUnOpS op ); |
| extern const HChar* showARMNeonShiftOpDataType ( ARMNeonShiftOp op ); |
| extern const HChar* showARMNeonDualOpDataType ( ARMNeonDualOp op ); |
| |
| typedef |
| enum { |
| /* baseline */ |
| ARMin_Alu=220, |
| ARMin_Shift, |
| ARMin_Unary, |
| ARMin_CmpOrTst, |
| ARMin_Mov, |
| ARMin_Imm32, |
| ARMin_LdSt32, |
| ARMin_LdSt16, |
| ARMin_LdSt8U, |
| ARMin_Ld8S, |
| ARMin_XDirect, /* direct transfer to GA */ |
| ARMin_XIndir, /* indirect transfer to GA */ |
| ARMin_XAssisted, /* assisted transfer to GA */ |
| ARMin_CMov, |
| ARMin_Call, |
| ARMin_Mul, |
| ARMin_LdrEX, |
| ARMin_StrEX, |
| /* vfp */ |
| ARMin_VLdStD, |
| ARMin_VLdStS, |
| ARMin_VAluD, |
| ARMin_VAluS, |
| ARMin_VUnaryD, |
| ARMin_VUnaryS, |
| ARMin_VCmpD, |
| ARMin_VCMovD, |
| ARMin_VCMovS, |
| ARMin_VCvtSD, |
| ARMin_VXferD, |
| ARMin_VXferS, |
| ARMin_VCvtID, |
| ARMin_FPSCR, |
| ARMin_MFence, |
| ARMin_CLREX, |
| /* Neon */ |
| ARMin_NLdStQ, |
| ARMin_NLdStD, |
| ARMin_NUnary, |
| ARMin_NUnaryS, |
| ARMin_NDual, |
| ARMin_NBinary, |
| ARMin_NBinaryS, |
| ARMin_NShift, |
| ARMin_NShl64, // special case 64-bit shift of Dreg by immediate |
| ARMin_NeonImm, |
| ARMin_NCMovQ, |
| /* This is not a NEON instruction. Actually there is no corresponding |
| instruction in ARM instruction set at all. We need this one to |
| generate spill/reload of 128-bit registers since current register |
| allocator demands them to consist of no more than two instructions. |
| We will split this instruction into 2 or 3 ARM instructions on the |
| emiting phase. |
| NOTE: source and destination registers should be different! */ |
| ARMin_Add32, |
| ARMin_EvCheck, /* Event check */ |
| ARMin_ProfInc /* 64-bit profile counter increment */ |
| } |
| ARMInstrTag; |
| |
| /* Destinations are on the LEFT (first operand) */ |
| |
| typedef |
| struct { |
| ARMInstrTag tag; |
| union { |
| /* ADD/SUB/AND/OR/XOR, vanilla ALU op */ |
| struct { |
| ARMAluOp op; |
| HReg dst; |
| HReg argL; |
| ARMRI84* argR; |
| } Alu; |
| /* SHL/SHR/SAR, 2nd arg is reg or imm */ |
| struct { |
| ARMShiftOp op; |
| HReg dst; |
| HReg argL; |
| ARMRI5* argR; |
| } Shift; |
| /* NOT/NEG/CLZ */ |
| struct { |
| ARMUnaryOp op; |
| HReg dst; |
| HReg src; |
| } Unary; |
| /* CMP/TST; subtract/and, discard result, set NZCV */ |
| struct { |
| Bool isCmp; |
| HReg argL; |
| ARMRI84* argR; |
| } CmpOrTst; |
| /* MOV dst, src -- reg-reg (or reg-imm8x4) move */ |
| struct { |
| HReg dst; |
| ARMRI84* src; |
| } Mov; |
| /* Pseudo-insn; make a 32-bit immediate */ |
| struct { |
| HReg dst; |
| UInt imm32; |
| } Imm32; |
| /* 32-bit load or store, may be conditional */ |
| struct { |
| ARMCondCode cc; /* ARMcc_NV is not allowed */ |
| Bool isLoad; |
| HReg rD; |
| ARMAMode1* amode; |
| } LdSt32; |
| /* 16-bit load or store, may be conditional */ |
| struct { |
| ARMCondCode cc; /* ARMcc_NV is not allowed */ |
| Bool isLoad; |
| Bool signedLoad; |
| HReg rD; |
| ARMAMode2* amode; |
| } LdSt16; |
| /* 8-bit (unsigned) load or store, may be conditional */ |
| struct { |
| ARMCondCode cc; /* ARMcc_NV is not allowed */ |
| Bool isLoad; |
| HReg rD; |
| ARMAMode1* amode; |
| } LdSt8U; |
| /* 8-bit signed load, may be conditional */ |
| struct { |
| ARMCondCode cc; /* ARMcc_NV is not allowed */ |
| HReg rD; |
| ARMAMode2* amode; |
| } Ld8S; |
| /* Update the guest R15T value, then exit requesting to chain |
| to it. May be conditional. Urr, use of Addr32 implicitly |
| assumes that wordsize(guest) == wordsize(host). */ |
| struct { |
| Addr32 dstGA; /* next guest address */ |
| ARMAMode1* amR15T; /* amode in guest state for R15T */ |
| ARMCondCode cond; /* can be ARMcc_AL */ |
| Bool toFastEP; /* chain to the slow or fast point? */ |
| } XDirect; |
| /* Boring transfer to a guest address not known at JIT time. |
| Not chainable. May be conditional. */ |
| struct { |
| HReg dstGA; |
| ARMAMode1* amR15T; |
| ARMCondCode cond; /* can be ARMcc_AL */ |
| } XIndir; |
| /* Assisted transfer to a guest address, most general case. |
| Not chainable. May be conditional. */ |
| struct { |
| HReg dstGA; |
| ARMAMode1* amR15T; |
| ARMCondCode cond; /* can be ARMcc_AL */ |
| IRJumpKind jk; |
| } XAssisted; |
| /* Mov src to dst on the given condition, which may not |
| be ARMcc_AL. */ |
| struct { |
| ARMCondCode cond; |
| HReg dst; |
| ARMRI84* src; |
| } CMov; |
| /* Pseudo-insn. Call target (an absolute address), on given |
| condition (which could be ARMcc_AL). */ |
| struct { |
| ARMCondCode cond; |
| HWord target; |
| Int nArgRegs; /* # regs carrying args: 0 .. 4 */ |
| RetLoc rloc; /* where the return value will be */ |
| } Call; |
| /* (PLAIN) 32 * 32 -> 32: r0 = r2 * r3 |
| (ZX) 32 *u 32 -> 64: r1:r0 = r2 *u r3 |
| (SX) 32 *s 32 -> 64: r1:r0 = r2 *s r3 |
| Why hardwired registers? Because the ARM ARM specifies |
| (eg for straight MUL) the result (Rd) and the left arg (Rm) |
| may not be the same register. That's not a constraint we |
| can enforce in the register allocator (without mucho extra |
| complexity). Hence hardwire it. At least using caller-saves |
| registers, which are less likely to be in use. */ |
| struct { |
| ARMMulOp op; |
| } Mul; |
| /* LDREX{,H,B} r2, [r4] and |
| LDREXD r2, r3, [r4] (on LE hosts, transferred value is r3:r2) |
| Again, hardwired registers since this is not performance |
| critical, and there are possibly constraints on the |
| registers that we can't express in the register allocator.*/ |
| struct { |
| Int szB; /* 1, 2, 4 or 8 */ |
| } LdrEX; |
| /* STREX{,H,B} r0, r2, [r4] and |
| STREXD r0, r2, r3, [r4] (on LE hosts, transferred value is r3:r2) |
| r0 = SC( [r4] = r2 ) (8, 16, 32 bit transfers) |
| r0 = SC( [r4] = r3:r2) (64 bit transfers) |
| Ditto comment re fixed registers. */ |
| struct { |
| Int szB; /* 1, 2, 4 or 8 */ |
| } StrEX; |
| /* VFP INSTRUCTIONS */ |
| /* 64-bit Fp load/store */ |
| struct { |
| Bool isLoad; |
| HReg dD; |
| ARMAModeV* amode; |
| } VLdStD; |
| /* 32-bit Fp load/store */ |
| struct { |
| Bool isLoad; |
| HReg fD; |
| ARMAModeV* amode; |
| } VLdStS; |
| /* 64-bit FP binary arithmetic */ |
| struct { |
| ARMVfpOp op; |
| HReg dst; |
| HReg argL; |
| HReg argR; |
| } VAluD; |
| /* 32-bit FP binary arithmetic */ |
| struct { |
| ARMVfpOp op; |
| HReg dst; |
| HReg argL; |
| HReg argR; |
| } VAluS; |
| /* 64-bit FP unary, also reg-reg move */ |
| struct { |
| ARMVfpUnaryOp op; |
| HReg dst; |
| HReg src; |
| } VUnaryD; |
| /* 32-bit FP unary, also reg-reg move */ |
| struct { |
| ARMVfpUnaryOp op; |
| HReg dst; |
| HReg src; |
| } VUnaryS; |
| /* 64-bit FP compare and move results to CPSR (FCMPD;FMSTAT) */ |
| struct { |
| HReg argL; |
| HReg argR; |
| } VCmpD; |
| /* 64-bit FP mov src to dst on the given condition, which may |
| not be ARMcc_AL. */ |
| struct { |
| ARMCondCode cond; |
| HReg dst; |
| HReg src; |
| } VCMovD; |
| /* 32-bit FP mov src to dst on the given condition, which may |
| not be ARMcc_AL. */ |
| struct { |
| ARMCondCode cond; |
| HReg dst; |
| HReg src; |
| } VCMovS; |
| /* Convert between 32-bit and 64-bit FP values (both ways). |
| (FCVTSD, FCVTDS) */ |
| struct { |
| Bool sToD; /* True: F32->F64. False: F64->F32 */ |
| HReg dst; |
| HReg src; |
| } VCvtSD; |
| /* Transfer a VFP D reg to/from two integer registers (VMOV) */ |
| struct { |
| Bool toD; |
| HReg dD; |
| HReg rHi; |
| HReg rLo; |
| } VXferD; |
| /* Transfer a VFP S reg to/from an integer register (VMOV) */ |
| struct { |
| Bool toS; |
| HReg fD; |
| HReg rLo; |
| } VXferS; |
| /* Convert between 32-bit ints and 64-bit FP values (both ways |
| and both signednesses). (FSITOD, FUITOD, FTOSID, FTOUID) */ |
| struct { |
| Bool iToD; /* True: I32->F64. False: F64->I32 */ |
| Bool syned; /* True: I32 is signed. False: I32 is unsigned */ |
| HReg dst; |
| HReg src; |
| } VCvtID; |
| /* Move a 32-bit value to/from the FPSCR (FMXR, FMRX) */ |
| struct { |
| Bool toFPSCR; |
| HReg iReg; |
| } FPSCR; |
| /* Mem fence. An insn which fences all loads and stores as |
| much as possible before continuing. On ARM we emit the |
| sequence |
| mcr 15,0,r0,c7,c10,4 (DSB) |
| mcr 15,0,r0,c7,c10,5 (DMB) |
| mcr 15,0,r0,c7,c5,4 (ISB) |
| which is probably total overkill, but better safe than |
| sorry. |
| */ |
| struct { |
| } MFence; |
| /* A CLREX instruction. */ |
| struct { |
| } CLREX; |
| /* Neon data processing instruction: 3 registers of the same |
| length */ |
| struct { |
| ARMNeonBinOp op; |
| HReg dst; |
| HReg argL; |
| HReg argR; |
| UInt size; |
| Bool Q; |
| } NBinary; |
| struct { |
| ARMNeonBinOp op; |
| ARMNRS* dst; |
| ARMNRS* argL; |
| ARMNRS* argR; |
| UInt size; |
| Bool Q; |
| } NBinaryS; |
| struct { |
| ARMNeonShiftOp op; |
| HReg dst; |
| HReg argL; |
| HReg argR; |
| UInt size; |
| Bool Q; |
| } NShift; |
| struct { |
| HReg dst; |
| HReg src; |
| UInt amt; /* 1..63 only */ |
| } NShl64; |
| struct { |
| Bool isLoad; |
| HReg dQ; |
| ARMAModeN *amode; |
| } NLdStQ; |
| struct { |
| Bool isLoad; |
| HReg dD; |
| ARMAModeN *amode; |
| } NLdStD; |
| struct { |
| ARMNeonUnOpS op; |
| ARMNRS* dst; |
| ARMNRS* src; |
| UInt size; |
| Bool Q; |
| } NUnaryS; |
| struct { |
| ARMNeonUnOp op; |
| HReg dst; |
| HReg src; |
| UInt size; |
| Bool Q; |
| } NUnary; |
| /* Takes two arguments and modifies them both. */ |
| struct { |
| ARMNeonDualOp op; |
| HReg arg1; |
| HReg arg2; |
| UInt size; |
| Bool Q; |
| } NDual; |
| struct { |
| HReg dst; |
| ARMNImm* imm; |
| } NeonImm; |
| /* 128-bit Neon move src to dst on the given condition, which |
| may not be ARMcc_AL. */ |
| struct { |
| ARMCondCode cond; |
| HReg dst; |
| HReg src; |
| } NCMovQ; |
| struct { |
| /* Note: rD != rN */ |
| HReg rD; |
| HReg rN; |
| UInt imm32; |
| } Add32; |
| struct { |
| ARMAMode1* amCounter; |
| ARMAMode1* amFailAddr; |
| } EvCheck; |
| struct { |
| /* No fields. The address of the counter to inc is |
| installed later, post-translation, by patching it in, |
| as it is not known at translation time. */ |
| } ProfInc; |
| } ARMin; |
| } |
| ARMInstr; |
| |
| |
| extern ARMInstr* ARMInstr_Alu ( ARMAluOp, HReg, HReg, ARMRI84* ); |
| extern ARMInstr* ARMInstr_Shift ( ARMShiftOp, HReg, HReg, ARMRI5* ); |
| extern ARMInstr* ARMInstr_Unary ( ARMUnaryOp, HReg, HReg ); |
| extern ARMInstr* ARMInstr_CmpOrTst ( Bool isCmp, HReg, ARMRI84* ); |
| extern ARMInstr* ARMInstr_Mov ( HReg, ARMRI84* ); |
| extern ARMInstr* ARMInstr_Imm32 ( HReg, UInt ); |
| extern ARMInstr* ARMInstr_LdSt32 ( ARMCondCode, |
| Bool isLoad, HReg, ARMAMode1* ); |
| extern ARMInstr* ARMInstr_LdSt16 ( ARMCondCode, |
| Bool isLoad, Bool signedLoad, |
| HReg, ARMAMode2* ); |
| extern ARMInstr* ARMInstr_LdSt8U ( ARMCondCode, |
| Bool isLoad, HReg, ARMAMode1* ); |
| extern ARMInstr* ARMInstr_Ld8S ( ARMCondCode, HReg, ARMAMode2* ); |
| extern ARMInstr* ARMInstr_XDirect ( Addr32 dstGA, ARMAMode1* amR15T, |
| ARMCondCode cond, Bool toFastEP ); |
| extern ARMInstr* ARMInstr_XIndir ( HReg dstGA, ARMAMode1* amR15T, |
| ARMCondCode cond ); |
| extern ARMInstr* ARMInstr_XAssisted ( HReg dstGA, ARMAMode1* amR15T, |
| ARMCondCode cond, IRJumpKind jk ); |
| extern ARMInstr* ARMInstr_CMov ( ARMCondCode, HReg dst, ARMRI84* src ); |
| extern ARMInstr* ARMInstr_Call ( ARMCondCode, HWord, Int nArgRegs, |
| RetLoc rloc ); |
| extern ARMInstr* ARMInstr_Mul ( ARMMulOp op ); |
| extern ARMInstr* ARMInstr_LdrEX ( Int szB ); |
| extern ARMInstr* ARMInstr_StrEX ( Int szB ); |
| extern ARMInstr* ARMInstr_VLdStD ( Bool isLoad, HReg, ARMAModeV* ); |
| extern ARMInstr* ARMInstr_VLdStS ( Bool isLoad, HReg, ARMAModeV* ); |
| extern ARMInstr* ARMInstr_VAluD ( ARMVfpOp op, HReg, HReg, HReg ); |
| extern ARMInstr* ARMInstr_VAluS ( ARMVfpOp op, HReg, HReg, HReg ); |
| extern ARMInstr* ARMInstr_VUnaryD ( ARMVfpUnaryOp, HReg dst, HReg src ); |
| extern ARMInstr* ARMInstr_VUnaryS ( ARMVfpUnaryOp, HReg dst, HReg src ); |
| extern ARMInstr* ARMInstr_VCmpD ( HReg argL, HReg argR ); |
| extern ARMInstr* ARMInstr_VCMovD ( ARMCondCode, HReg dst, HReg src ); |
| extern ARMInstr* ARMInstr_VCMovS ( ARMCondCode, HReg dst, HReg src ); |
| extern ARMInstr* ARMInstr_VCvtSD ( Bool sToD, HReg dst, HReg src ); |
| extern ARMInstr* ARMInstr_VXferD ( Bool toD, HReg dD, HReg rHi, HReg rLo ); |
| extern ARMInstr* ARMInstr_VXferS ( Bool toS, HReg fD, HReg rLo ); |
| extern ARMInstr* ARMInstr_VCvtID ( Bool iToD, Bool syned, |
| HReg dst, HReg src ); |
| extern ARMInstr* ARMInstr_FPSCR ( Bool toFPSCR, HReg iReg ); |
| extern ARMInstr* ARMInstr_MFence ( void ); |
| extern ARMInstr* ARMInstr_CLREX ( void ); |
| extern ARMInstr* ARMInstr_NLdStQ ( Bool isLoad, HReg, ARMAModeN* ); |
| extern ARMInstr* ARMInstr_NLdStD ( Bool isLoad, HReg, ARMAModeN* ); |
| extern ARMInstr* ARMInstr_NUnary ( ARMNeonUnOp, HReg, HReg, UInt, Bool ); |
| extern ARMInstr* ARMInstr_NUnaryS ( ARMNeonUnOpS, ARMNRS*, ARMNRS*, |
| UInt, Bool ); |
| extern ARMInstr* ARMInstr_NDual ( ARMNeonDualOp, HReg, HReg, UInt, Bool ); |
| extern ARMInstr* ARMInstr_NBinary ( ARMNeonBinOp, HReg, HReg, HReg, |
| UInt, Bool ); |
| extern ARMInstr* ARMInstr_NShift ( ARMNeonShiftOp, HReg, HReg, HReg, |
| UInt, Bool ); |
| extern ARMInstr* ARMInstr_NShl64 ( HReg, HReg, UInt ); |
| extern ARMInstr* ARMInstr_NeonImm ( HReg, ARMNImm* ); |
| extern ARMInstr* ARMInstr_NCMovQ ( ARMCondCode, HReg, HReg ); |
| extern ARMInstr* ARMInstr_Add32 ( HReg rD, HReg rN, UInt imm32 ); |
| extern ARMInstr* ARMInstr_EvCheck ( ARMAMode1* amCounter, |
| ARMAMode1* amFailAddr ); |
| extern ARMInstr* ARMInstr_ProfInc ( void ); |
| |
| extern void ppARMInstr ( ARMInstr* ); |
| |
| |
| /* Some functions that insulate the register allocator from details |
| of the underlying instruction set. */ |
| extern void getRegUsage_ARMInstr ( HRegUsage*, ARMInstr*, Bool ); |
| extern void mapRegs_ARMInstr ( HRegRemap*, ARMInstr*, Bool ); |
| extern Bool isMove_ARMInstr ( ARMInstr*, HReg*, HReg* ); |
| extern Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc, |
| UChar* buf, Int nbuf, ARMInstr* i, |
| Bool mode64, |
| void* disp_cp_chain_me_to_slowEP, |
| void* disp_cp_chain_me_to_fastEP, |
| void* disp_cp_xindir, |
| void* disp_cp_xassisted ); |
| |
| extern void genSpill_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2, |
| HReg rreg, Int offset, Bool ); |
| extern void genReload_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2, |
| HReg rreg, Int offset, Bool ); |
| |
| extern void getAllocableRegs_ARM ( Int*, HReg** ); |
| extern HInstrArray* iselSB_ARM ( IRSB*, |
| VexArch, |
| VexArchInfo*, |
| VexAbiInfo*, |
| Int offs_Host_EvC_Counter, |
| Int offs_Host_EvC_FailAddr, |
| Bool chainingAllowed, |
| Bool addProfInc, |
| Addr64 max_ga ); |
| |
| /* How big is an event check? This is kind of a kludge because it |
| depends on the offsets of host_EvC_FAILADDR and |
| host_EvC_COUNTER. */ |
| extern Int evCheckSzB_ARM ( void ); |
| |
| /* Perform a chaining and unchaining of an XDirect jump. */ |
| extern VexInvalRange chainXDirect_ARM ( void* place_to_chain, |
| void* disp_cp_chain_me_EXPECTED, |
| void* place_to_jump_to ); |
| |
| extern VexInvalRange unchainXDirect_ARM ( void* place_to_unchain, |
| void* place_to_jump_to_EXPECTED, |
| void* disp_cp_chain_me ); |
| |
| /* Patch the counter location into an existing ProfInc point. */ |
| extern VexInvalRange patchProfInc_ARM ( void* place_to_patch, |
| ULong* location_of_counter ); |
| |
| |
| #endif /* ndef __VEX_HOST_ARM_DEFS_H */ |
| |
| /*---------------------------------------------------------------*/ |
| /*--- end host_arm_defs.h ---*/ |
| /*---------------------------------------------------------------*/ |