/*---------------------------------------------------------------*/
/*--- begin host_arm64_defs.h ---*/
/*---------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2013-2013 OpenWorks
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_ARM64_DEFS_H
#define __VEX_HOST_ARM64_DEFS_H
#include "libvex_basictypes.h"
#include "libvex.h" // VexArch
#include "host_generic_regs.h" // HReg
//ZZ extern UInt arm_hwcaps;
/* --------- Registers. --------- */
//ZZ /* The usual HReg abstraction.
//ZZ There are 16 general purpose regs.
//ZZ */
extern void ppHRegARM64 ( HReg );
extern HReg hregARM64_X0 ( void );
extern HReg hregARM64_X1 ( void );
extern HReg hregARM64_X2 ( void );
extern HReg hregARM64_X3 ( void );
extern HReg hregARM64_X4 ( void );
extern HReg hregARM64_X5 ( void );
extern HReg hregARM64_X6 ( void );
extern HReg hregARM64_X7 ( void );
//ZZ extern HReg hregARM_R8 ( void );
extern HReg hregARM64_X9 ( void );
extern HReg hregARM64_X10 ( void );
extern HReg hregARM64_X11 ( void );
extern HReg hregARM64_X12 ( void );
extern HReg hregARM64_X13 ( void );
extern HReg hregARM64_X14 ( void );
extern HReg hregARM64_X15 ( void );
extern HReg hregARM64_X21 ( void );
extern HReg hregARM64_X22 ( void );
extern HReg hregARM64_X23 ( void );
extern HReg hregARM64_X24 ( void );
extern HReg hregARM64_X25 ( void );
extern HReg hregARM64_X26 ( void );
extern HReg hregARM64_X27 ( void );
extern HReg hregARM64_X28 ( void );
extern HReg hregARM64_D8 ( void );
extern HReg hregARM64_D9 ( void );
extern HReg hregARM64_D10 ( void );
extern HReg hregARM64_D11 ( void );
extern HReg hregARM64_D12 ( void );
extern HReg hregARM64_D13 ( void );
extern HReg hregARM64_Q16 ( void );
extern HReg hregARM64_Q17 ( void );
extern HReg hregARM64_Q18 ( void );
/* Number of registers used arg passing in function calls */
#define ARM64_N_ARGREGS 8 /* x0 .. x7 */
/* --------- Condition codes. --------- */
typedef
enum {
ARM64cc_EQ = 0, /* equal : Z=1 */
ARM64cc_NE = 1, /* not equal : Z=0 */
ARM64cc_CS = 2, /* >=u (higher or same) : C=1 */
ARM64cc_CC = 3, /* <u (lower) : C=0 */
ARM64cc_MI = 4, /* minus (negative) : N=1 */
ARM64cc_PL = 5, /* plus (zero or +ve) : N=0 */
ARM64cc_VS = 6, /* overflow : V=1 */
ARM64cc_VC = 7, /* no overflow : V=0 */
ARM64cc_HI = 8, /* >u (higher) : C=1 && Z=0 */
ARM64cc_LS = 9, /* <=u (lower or same) : !(C=1 && Z=0) */
ARM64cc_GE = 10, /* >=s (signed greater or equal) : N=V */
ARM64cc_LT = 11, /* <s (signed less than) : !(N=V) */
ARM64cc_GT = 12, /* >s (signed greater) : Z=0 && N=V */
ARM64cc_LE = 13, /* <=s (signed less or equal) : !(Z=0 && N=V) */
ARM64cc_AL = 14, /* always (unconditional) */
ARM64cc_NV = 15 /* in 64-bit mode also means "always" */
}
ARM64CondCode;
/* --------- Memory address expressions (amodes). --------- */
typedef
enum {
ARM64am_RI9=10, /* reg + simm9 */
ARM64am_RI12, /* reg + uimm12 * szB (iow, scaled by access size) */
ARM64am_RR /* reg1 + reg2 */
}
ARM64AModeTag;
typedef
struct {
ARM64AModeTag tag;
union {
struct {
HReg reg;
Int simm9; /* -256 .. +255 */
} RI9;
struct {
HReg reg;
UInt uimm12; /* 0 .. 4095 */
UChar szB; /* 1, 2, 4, 8 (16 ?) */
} RI12;
struct {
HReg base;
HReg index;
} RR;
} ARM64am;
}
ARM64AMode;
extern ARM64AMode* ARM64AMode_RI9 ( HReg reg, Int simm9 );
extern ARM64AMode* ARM64AMode_RI12 ( HReg reg, Int uimm12, UChar szB );
extern ARM64AMode* ARM64AMode_RR ( HReg base, HReg index );
/* --------- Reg or uimm12 or (uimm12 << 12) operands --------- */
typedef
enum {
ARM64riA_I12=20, /* uimm12 << 0 or 12 only */
ARM64riA_R /* reg */
}
ARM64RIATag;
typedef
struct {
ARM64RIATag tag;
union {
struct {
UShort imm12; /* 0 .. 4095 */
UChar shift; /* 0 or 12 only */
} I12;
struct {
HReg reg;
} R;
} ARM64riA;
}
ARM64RIA;
extern ARM64RIA* ARM64RIA_I12 ( UShort imm12, UChar shift );
extern ARM64RIA* ARM64RIA_R ( HReg );
/* --------- Reg or "bitfield" (logic immediate) operands --------- */
typedef
enum {
ARM64riL_I13=6, /* wierd-o bitfield immediate, 13 bits in total */
ARM64riL_R /* reg */
}
ARM64RILTag;
typedef
struct {
ARM64RILTag tag;
union {
struct {
UChar bitN; /* 0 .. 1 */
UChar immR; /* 0 .. 63 */
UChar immS; /* 0 .. 63 */
} I13;
struct {
HReg reg;
} R;
} ARM64riL;
}
ARM64RIL;
extern ARM64RIL* ARM64RIL_I13 ( UChar bitN, UChar immR, UChar immS );
extern ARM64RIL* ARM64RIL_R ( HReg );
/* --------------- Reg or uimm6 operands --------------- */
typedef
enum {
ARM64ri6_I6=30, /* uimm6, 1 .. 63 only */
ARM64ri6_R /* reg */
}
ARM64RI6Tag;
typedef
struct {
ARM64RI6Tag tag;
union {
struct {
UInt imm6; /* 1 .. 63 */
} I6;
struct {
HReg reg;
} R;
} ARM64ri6;
}
ARM64RI6;
extern ARM64RI6* ARM64RI6_I6 ( UInt imm6 );
extern ARM64RI6* ARM64RI6_R ( HReg );
/* --------------------- Instructions --------------------- */
typedef
enum {
ARM64lo_AND=40,
ARM64lo_OR,
ARM64lo_XOR
}
ARM64LogicOp;
typedef
enum {
ARM64sh_SHL=50,
ARM64sh_SHR,
ARM64sh_SAR
}
ARM64ShiftOp;
typedef
enum {
ARM64un_NEG=60,
ARM64un_NOT,
ARM64un_CLZ,
}
ARM64UnaryOp;
typedef
enum {
ARM64mul_PLAIN=70, /* lo64(64 * 64) */
ARM64mul_ZX, /* hi64(64 *u 64) */
ARM64mul_SX /* hi64(64 *s 64) */
}
ARM64MulOp;
typedef
/* These characterise an integer-FP conversion, but don't imply any
particular direction. */
enum {
ARM64cvt_F32_I32S=80,
ARM64cvt_F64_I32S,
ARM64cvt_F32_I64S,
ARM64cvt_F64_I64S,
ARM64cvt_F32_I32U,
ARM64cvt_F64_I32U,
ARM64cvt_F32_I64U,
ARM64cvt_F64_I64U,
ARM64cvt_INVALID
}
ARM64CvtOp;
typedef
enum {
ARM64fpb_ADD=100,
ARM64fpb_SUB,
ARM64fpb_MUL,
ARM64fpb_DIV,
ARM64fpb_INVALID
}
ARM64FpBinOp;
typedef
enum {
ARM64fpu_NEG=110,
ARM64fpu_ABS,
ARM64fpu_SQRT,
ARM64fpu_RINT,
ARM64fpu_INVALID
}
ARM64FpUnaryOp;
typedef
enum {
ARM64vecb_ADD64x2=120,
ARM64vecb_ADD32x4,
ARM64vecb_ADD16x8,
ARM64vecb_ADD8x16,
ARM64vecb_SUB64x2,
ARM64vecb_SUB32x4,
ARM64vecb_SUB16x8,
ARM64vecb_SUB8x16,
ARM64vecb_MUL32x4,
ARM64vecb_MUL16x8,
ARM64vecb_MUL8x16,
ARM64vecb_FADD64x2,
ARM64vecb_FSUB64x2,
ARM64vecb_FMUL64x2,
ARM64vecb_FDIV64x2,
ARM64vecb_FADD32x4,
ARM64vecb_FSUB32x4,
ARM64vecb_FMUL32x4,
ARM64vecb_FDIV32x4,
ARM64vecb_UMAX32x4,
ARM64vecb_UMAX16x8,
ARM64vecb_UMAX8x16,
ARM64vecb_UMIN32x4,
ARM64vecb_UMIN16x8,
ARM64vecb_UMIN8x16,
ARM64vecb_UMULL32x2,
ARM64vecb_UMULL16x4,
ARM64vecb_UMULL8x8,
ARM64vecb_SMAX32x4,
ARM64vecb_SMAX16x8,
ARM64vecb_SMAX8x16,
ARM64vecb_SMIN32x4,
ARM64vecb_SMIN16x8,
ARM64vecb_SMIN8x16,
ARM64vecb_AND,
ARM64vecb_ORR,
ARM64vecb_XOR,
ARM64vecb_CMEQ64x2,
ARM64vecb_CMEQ32x4,
ARM64vecb_CMEQ16x8,
ARM64vecb_CMEQ8x16,
ARM64vecb_CMHI64x2, /* >u */
ARM64vecb_CMHI32x4,
ARM64vecb_CMHI16x8,
ARM64vecb_CMHI8x16,
ARM64vecb_CMGT64x2, /* >s */
ARM64vecb_CMGT32x4,
ARM64vecb_CMGT16x8,
ARM64vecb_CMGT8x16,
ARM64vecb_FCMEQ64x2,
ARM64vecb_FCMEQ32x4,
ARM64vecb_FCMGE64x2,
ARM64vecb_FCMGE32x4,
ARM64vecb_FCMGT64x2,
ARM64vecb_FCMGT32x4,
ARM64vecb_TBL1,
ARM64vecb_INVALID
}
ARM64VecBinOp;
typedef
enum {
ARM64vecu_FNEG64x2=300,
ARM64vecu_FNEG32x4,
ARM64vecu_FABS64x2,
ARM64vecu_FABS32x4,
ARM64vecu_VMOVL8U,
ARM64vecu_VMOVL16U,
ARM64vecu_VMOVL32U,
ARM64vecu_VMOVL8S,
ARM64vecu_VMOVL16S,
ARM64vecu_VMOVL32S,
ARM64vecu_NOT,
ARM64vecu_CNT,
ARM64vecu_UADDLV8x16,
ARM64vecu_UADDLV16x8,
ARM64vecu_UADDLV32x4,
ARM64vecu_SADDLV8x16,
ARM64vecu_SADDLV16x8,
ARM64vecu_SADDLV32x4,
ARM64vecu_INVALID
}
ARM64VecUnaryOp;
typedef
enum {
ARM64vecsh_USHR64x2=350,
ARM64vecsh_USHR32x4,
ARM64vecsh_USHR16x8,
ARM64vecsh_USHR8x16,
ARM64vecsh_SSHR64x2,
ARM64vecsh_SSHR32x4,
ARM64vecsh_SSHR16x8,
ARM64vecsh_SSHR8x16,
ARM64vecsh_SHL64x2,
ARM64vecsh_SHL32x4,
ARM64vecsh_SHL16x8,
ARM64vecsh_SHL8x16,
ARM64vecsh_INVALID
}
ARM64VecShiftOp;
//ZZ extern const HChar* showARMVfpUnaryOp ( ARMVfpUnaryOp op );
//ZZ
//ZZ typedef
//ZZ enum {
//ZZ ARMneon_VAND=90,
//ZZ ARMneon_VORR,
//ZZ ARMneon_VXOR,
//ZZ ARMneon_VADD,
//ZZ ARMneon_VADDFP,
//ZZ ARMneon_VRHADDS,
//ZZ ARMneon_VRHADDU,
//ZZ ARMneon_VPADDFP,
//ZZ ARMneon_VABDFP,
//ZZ ARMneon_VSUB,
//ZZ ARMneon_VSUBFP,
//ZZ ARMneon_VMAXU,
//ZZ ARMneon_VMAXS,
//ZZ ARMneon_VMAXF,
//ZZ ARMneon_VMINU,
//ZZ ARMneon_VMINS,
//ZZ ARMneon_VMINF,
//ZZ ARMneon_VQADDU,
//ZZ ARMneon_VQADDS,
//ZZ ARMneon_VQSUBU,
//ZZ ARMneon_VQSUBS,
//ZZ ARMneon_VCGTU,
//ZZ ARMneon_VCGTS,
//ZZ ARMneon_VCGEU,
//ZZ ARMneon_VCGES,
//ZZ ARMneon_VCGTF,
//ZZ ARMneon_VCGEF,
//ZZ ARMneon_VCEQ,
//ZZ ARMneon_VCEQF,
//ZZ ARMneon_VEXT,
//ZZ ARMneon_VMUL,
//ZZ ARMneon_VMULFP,
//ZZ ARMneon_VMULLU,
//ZZ ARMneon_VMULLS,
//ZZ ARMneon_VMULP,
//ZZ ARMneon_VMULLP,
//ZZ ARMneon_VQDMULH,
//ZZ ARMneon_VQRDMULH,
//ZZ ARMneon_VPADD,
//ZZ ARMneon_VPMINU,
//ZZ ARMneon_VPMINS,
//ZZ ARMneon_VPMINF,
//ZZ ARMneon_VPMAXU,
//ZZ ARMneon_VPMAXS,
//ZZ ARMneon_VPMAXF,
//ZZ ARMneon_VTBL,
//ZZ ARMneon_VQDMULL,
//ZZ ARMneon_VRECPS,
//ZZ ARMneon_VRSQRTS,
//ZZ /* ... */
//ZZ }
//ZZ ARMNeonBinOp;
//ZZ
//ZZ typedef
//ZZ enum {
//ZZ ARMneon_VSHL=150,
//ZZ ARMneon_VSAL, /* Yah, not SAR but SAL */
//ZZ ARMneon_VQSHL,
//ZZ ARMneon_VQSAL
//ZZ }
//ZZ ARMNeonShiftOp;
//ZZ
//ZZ typedef
//ZZ enum {
//ZZ ARMneon_COPY=160,
//ZZ ARMneon_COPYLU,
//ZZ ARMneon_COPYLS,
//ZZ ARMneon_COPYN,
//ZZ ARMneon_COPYQNSS,
//ZZ ARMneon_COPYQNUS,
//ZZ ARMneon_COPYQNUU,
//ZZ ARMneon_NOT,
//ZZ ARMneon_EQZ,
//ZZ ARMneon_DUP,
//ZZ ARMneon_PADDLS,
//ZZ ARMneon_PADDLU,
//ZZ ARMneon_CNT,
//ZZ ARMneon_CLZ,
//ZZ ARMneon_CLS,
//ZZ ARMneon_VCVTxFPxINT,
//ZZ ARMneon_VQSHLNSS,
//ZZ ARMneon_VQSHLNUU,
//ZZ ARMneon_VQSHLNUS,
//ZZ ARMneon_VCVTFtoU,
//ZZ ARMneon_VCVTFtoS,
//ZZ ARMneon_VCVTUtoF,
//ZZ ARMneon_VCVTStoF,
//ZZ ARMneon_VCVTFtoFixedU,
//ZZ ARMneon_VCVTFtoFixedS,
//ZZ ARMneon_VCVTFixedUtoF,
//ZZ ARMneon_VCVTFixedStoF,
//ZZ ARMneon_VCVTF16toF32,
//ZZ ARMneon_VCVTF32toF16,
//ZZ ARMneon_REV16,
//ZZ ARMneon_REV32,
//ZZ ARMneon_REV64,
//ZZ ARMneon_ABS,
//ZZ ARMneon_VNEGF,
//ZZ ARMneon_VRECIP,
//ZZ ARMneon_VRECIPF,
//ZZ ARMneon_VABSFP,
//ZZ ARMneon_VRSQRTEFP,
//ZZ ARMneon_VRSQRTE
//ZZ /* ... */
//ZZ }
//ZZ ARMNeonUnOp;
//ZZ
//ZZ typedef
//ZZ enum {
//ZZ ARMneon_SETELEM=200,
//ZZ ARMneon_GETELEMU,
//ZZ ARMneon_GETELEMS,
//ZZ ARMneon_VDUP,
//ZZ }
//ZZ ARMNeonUnOpS;
//ZZ
//ZZ typedef
//ZZ enum {
//ZZ ARMneon_TRN=210,
//ZZ ARMneon_ZIP,
//ZZ ARMneon_UZP
//ZZ /* ... */
//ZZ }
//ZZ ARMNeonDualOp;
//ZZ
//ZZ extern const HChar* showARMNeonBinOp ( ARMNeonBinOp op );
//ZZ extern const HChar* showARMNeonUnOp ( ARMNeonUnOp op );
//ZZ extern const HChar* showARMNeonUnOpS ( ARMNeonUnOpS op );
//ZZ extern const HChar* showARMNeonShiftOp ( ARMNeonShiftOp op );
//ZZ extern const HChar* showARMNeonDualOp ( ARMNeonDualOp op );
//ZZ extern const HChar* showARMNeonBinOpDataType ( ARMNeonBinOp op );
//ZZ extern const HChar* showARMNeonUnOpDataType ( ARMNeonUnOp op );
//ZZ extern const HChar* showARMNeonUnOpSDataType ( ARMNeonUnOpS op );
//ZZ extern const HChar* showARMNeonShiftOpDataType ( ARMNeonShiftOp op );
//ZZ extern const HChar* showARMNeonDualOpDataType ( ARMNeonDualOp op );
typedef
enum {
/* baseline */
ARM64in_Arith=1220,
ARM64in_Cmp,
ARM64in_Logic,
ARM64in_Test,
ARM64in_Shift,
ARM64in_Unary,
ARM64in_MovI, /* int reg-reg move */
ARM64in_Imm64,
ARM64in_LdSt64,
ARM64in_LdSt32, /* w/ ZX loads */
ARM64in_LdSt16, /* w/ ZX loads */
ARM64in_LdSt8, /* w/ ZX loads */
ARM64in_XDirect, /* direct transfer to GA */
ARM64in_XIndir, /* indirect transfer to GA */
ARM64in_XAssisted, /* assisted transfer to GA */
ARM64in_CSel,
ARM64in_Call,
ARM64in_AddToSP, /* move SP by small, signed constant */
ARM64in_FromSP, /* move SP to integer register */
ARM64in_Mul,
ARM64in_LdrEX,
ARM64in_StrEX,
ARM64in_MFence,
//ZZ ARMin_CLREX,
/* ARM64in_V*: scalar ops involving vector registers */
ARM64in_VLdStS, /* 32-bit FP load/store, with imm offset */
ARM64in_VLdStD, /* 64-bit FP load/store, with imm offset */
ARM64in_VLdStQ,
ARM64in_VCvtI2F,
ARM64in_VCvtF2I,
ARM64in_VCvtSD,
ARM64in_VUnaryD,
ARM64in_VUnaryS,
ARM64in_VBinD,
ARM64in_VBinS,
ARM64in_VCmpD,
ARM64in_VCmpS,
ARM64in_FPCR,
/* ARM64in_V*V: vector ops on vector registers */
ARM64in_VBinV,
ARM64in_VUnaryV,
ARM64in_VNarrowV,
ARM64in_VShiftImmV,
//ZZ ARMin_VAluS,
//ZZ ARMin_VCMovD,
//ZZ ARMin_VCMovS,
//ZZ ARMin_VXferD,
//ZZ ARMin_VXferS,
//ZZ ARMin_VCvtID,
//ZZ /* Neon */
//ZZ ARMin_NLdStD,
//ZZ ARMin_NUnary,
//ZZ ARMin_NUnaryS,
//ZZ ARMin_NDual,
//ZZ ARMin_NBinary,
//ZZ ARMin_NBinaryS,
//ZZ ARMin_NShift,
//ZZ ARMin_NShl64, // special case 64-bit shift of Dreg by immediate
ARM64in_VImmQ,
ARM64in_VDfromX, /* Move an Xreg to a Dreg */
ARM64in_VQfromXX, /* Move 2 Xregs to a Qreg */
ARM64in_VXfromQ, /* Move half a Qreg to an Xreg */
ARM64in_VMov, /* vector reg-reg move, 16, 8 or 4 bytes */
/* infrastructure */
ARM64in_EvCheck, /* Event check */
//ZZ ARMin_ProfInc /* 64-bit profile counter increment */
}
ARM64InstrTag;
/* Destinations are on the LEFT (first operand) */
typedef
struct {
ARM64InstrTag tag;
union {
/* --- INTEGER INSTRUCTIONS --- */
/* 64 bit ADD/SUB reg, reg or uimm12<<{0,12} */
struct {
HReg dst;
HReg argL;
ARM64RIA* argR;
Bool isAdd;
} Arith;
/* 64 or 32 bit CMP reg, reg or aimm (SUB and set flags) */
struct {
HReg argL;
ARM64RIA* argR;
Bool is64;
} Cmp;
/* 64 bit AND/OR/XOR reg, reg or bitfield-immediate */
struct {
HReg dst;
HReg argL;
ARM64RIL* argR;
ARM64LogicOp op;
} Logic;
/* 64 bit TST reg, reg or bimm (AND and set flags) */
struct {
HReg argL;
ARM64RIL* argR;
} Test;
/* 64 bit SHL/SHR/SAR, 2nd arg is reg or imm */
struct {
HReg dst;
HReg argL;
ARM64RI6* argR;
ARM64ShiftOp op;
} Shift;
/* NOT/NEG/CLZ, 64 bit only */
struct {
HReg dst;
HReg src;
ARM64UnaryOp op;
} Unary;
/* MOV dst, src -- reg-reg move for integer registers */
struct {
HReg dst;
HReg src;
} MovI;
/* Pseudo-insn; make a 64-bit immediate */
struct {
HReg dst;
ULong imm64;
} Imm64;
/* 64-bit load or store */
struct {
Bool isLoad;
HReg rD;
ARM64AMode* amode;
} LdSt64;
/* zx-32-to-64-bit load, or 32-bit store */
struct {
Bool isLoad;
HReg rD;
ARM64AMode* amode;
} LdSt32;
/* zx-16-to-64-bit load, or 16-bit store */
struct {
Bool isLoad;
HReg rD;
ARM64AMode* amode;
} LdSt16;
/* zx-8-to-64-bit load, or 8-bit store */
struct {
Bool isLoad;
HReg rD;
ARM64AMode* amode;
} LdSt8;
/* Update the guest PC value, then exit requesting to chain
to it. May be conditional. Urr, use of Addr64 implicitly
assumes that wordsize(guest) == wordsize(host). */
struct {
Addr64 dstGA; /* next guest address */
ARM64AMode* amPC; /* amode in guest state for PC */
ARM64CondCode cond; /* can be ARM64cc_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;
ARM64AMode* amPC;
ARM64CondCode cond; /* can be ARM64cc_AL */
} XIndir;
/* Assisted transfer to a guest address, most general case.
Not chainable. May be conditional. */
struct {
HReg dstGA;
ARM64AMode* amPC;
ARM64CondCode cond; /* can be ARM64cc_AL */
IRJumpKind jk;
} XAssisted;
/* CSEL: dst = if cond then argL else argR. cond may be anything. */
struct {
HReg dst;
HReg argL;
HReg argR;
ARM64CondCode cond;
} CSel;
/* Pseudo-insn. Call target (an absolute address), on given
condition (which could be ARM64cc_AL). */
struct {
RetLoc rloc; /* where the return value will be */
HWord target;
ARM64CondCode cond;
Int nArgRegs; /* # regs carrying args: 0 .. 8 */
} Call;
/* move SP by small, signed constant */
struct {
Int simm; /* needs to be 0 % 16 and in the range -4095
.. 4095 inclusive */
} AddToSP;
/* move SP to integer register */
struct {
HReg dst;
} FromSP;
/* Integer multiply, with 3 variants:
(PLAIN) lo64(64 * 64)
(ZX) hi64(64 *u 64)
(SX) hi64(64 *s 64)
*/
struct {
HReg dst;
HReg argL;
HReg argR;
ARM64MulOp op;
} Mul;
/* LDXR{,H,B} x2, [x4] */
struct {
Int szB; /* 1, 2, 4 or 8 */
} LdrEX;
/* STXR{,H,B} w0, x2, [x4] */
struct {
Int szB; /* 1, 2, 4 or 8 */
} StrEX;
/* Mem fence. An insn which fences all loads and stores as
much as possible before continuing. On ARM64 we emit the
sequence "dsb sy ; dmb sy ; isb sy", which is probably
total nuclear overkill, but better safe than sorry. */
struct {
} MFence;
//ZZ /* A CLREX instruction. */
//ZZ struct {
//ZZ } CLREX;
/* --- INSTRUCTIONS INVOLVING VECTOR REGISTERS --- */
/* 32-bit Fp load/store */
struct {
Bool isLoad;
HReg sD;
HReg rN;
UInt uimm12; /* 0 .. 16380 inclusive, 0 % 4 */
} VLdStS;
/* 64-bit Fp load/store */
struct {
Bool isLoad;
HReg dD;
HReg rN;
UInt uimm12; /* 0 .. 32760 inclusive, 0 % 8 */
} VLdStD;
/* 128-bit Vector load/store. */
struct {
Bool isLoad;
HReg rQ; // data
HReg rN; // address
} VLdStQ;
/* Scalar conversion of int to float. */
struct {
ARM64CvtOp how;
HReg rD; // dst, a D or S register
HReg rS; // src, a W or X register
} VCvtI2F;
/* Scalar conversion of float to int, w/ specified RM. */
struct {
ARM64CvtOp how;
HReg rD; // dst, a W or X register
HReg rS; // src, a D or S register
UChar armRM; // ARM encoded RM:
// 00=nearest, 01=+inf, 10=-inf, 11=zero
} VCvtF2I;
/* Convert between 32-bit and 64-bit FP values (both
ways). (FCVT) */
struct {
Bool sToD; /* True: F32->F64. False: F64->F32 */
HReg dst;
HReg src;
} VCvtSD;
/* 64-bit FP unary */
struct {
ARM64FpUnaryOp op;
HReg dst;
HReg src;
} VUnaryD;
/* 32-bit FP unary */
struct {
ARM64FpUnaryOp op;
HReg dst;
HReg src;
} VUnaryS;
/* 64-bit FP binary arithmetic */
struct {
ARM64FpBinOp op;
HReg dst;
HReg argL;
HReg argR;
} VBinD;
/* 32-bit FP binary arithmetic */
struct {
ARM64FpBinOp op;
HReg dst;
HReg argL;
HReg argR;
} VBinS;
/* 64-bit FP compare */
struct {
HReg argL;
HReg argR;
} VCmpD;
/* 32-bit FP compare */
struct {
HReg argL;
HReg argR;
} VCmpS;
/* Move a 32-bit value to/from the FPCR */
struct {
Bool toFPCR;
HReg iReg;
} FPCR;
/* binary vector operation on vector registers */
struct {
ARM64VecBinOp op;
HReg dst;
HReg argL;
HReg argR;
} VBinV;
/* unary vector operation on vector registers */
struct {
ARM64VecUnaryOp op;
HReg dst;
HReg arg;
} VUnaryV;
/* vector narrowing, Q -> Q. Result goes in the bottom half
of dst and the top half is zeroed out. Iow is XTN. */
struct {
UInt dszBlg2; // 0: 16to8_x8 1: 32to16_x4 2: 64to32_x2
HReg dst; // Q reg
HReg src; // Q reg
} VNarrowV;
/* Vector shift by immediate. |amt| needs to be > 0 and <
implied lane size of |op|. Zero shifts and out of range
shifts are not allowed. */
struct {
ARM64VecShiftOp op;
HReg dst;
HReg src;
UInt amt;
} VShiftImmV;
//ZZ /* 32-bit FP binary arithmetic */
//ZZ struct {
//ZZ ARMVfpOp op;
//ZZ HReg dst;
//ZZ HReg argL;
//ZZ HReg argR;
//ZZ } VAluS;
//ZZ /* 64-bit FP mov src to dst on the given condition, which may
//ZZ not be ARMcc_AL. */
//ZZ struct {
//ZZ ARMCondCode cond;
//ZZ HReg dst;
//ZZ HReg src;
//ZZ } VCMovD;
//ZZ /* 32-bit FP mov src to dst on the given condition, which may
//ZZ not be ARMcc_AL. */
//ZZ struct {
//ZZ ARMCondCode cond;
//ZZ HReg dst;
//ZZ HReg src;
//ZZ } VCMovS;
//ZZ /* Transfer a VFP D reg to/from two integer registers (VMOV) */
//ZZ struct {
//ZZ Bool toD;
//ZZ HReg dD;
//ZZ HReg rHi;
//ZZ HReg rLo;
//ZZ } VXferD;
//ZZ /* Transfer a VFP S reg to/from an integer register (VMOV) */
//ZZ struct {
//ZZ Bool toS;
//ZZ HReg fD;
//ZZ HReg rLo;
//ZZ } VXferS;
//ZZ /* Convert between 32-bit ints and 64-bit FP values (both ways
//ZZ and both signednesses). (FSITOD, FUITOD, FTOSID, FTOUID) */
//ZZ struct {
//ZZ Bool iToD; /* True: I32->F64. False: F64->I32 */
//ZZ Bool syned; /* True: I32 is signed. False: I32 is unsigned */
//ZZ HReg dst;
//ZZ HReg src;
//ZZ } VCvtID;
//ZZ /* Neon data processing instruction: 3 registers of the same
//ZZ length */
//ZZ struct {
//ZZ ARMNeonBinOp op;
//ZZ HReg dst;
//ZZ HReg argL;
//ZZ HReg argR;
//ZZ UInt size;
//ZZ Bool Q;
//ZZ } NBinary;
//ZZ struct {
//ZZ ARMNeonBinOp op;
//ZZ ARMNRS* dst;
//ZZ ARMNRS* argL;
//ZZ ARMNRS* argR;
//ZZ UInt size;
//ZZ Bool Q;
//ZZ } NBinaryS;
//ZZ struct {
//ZZ ARMNeonShiftOp op;
//ZZ HReg dst;
//ZZ HReg argL;
//ZZ HReg argR;
//ZZ UInt size;
//ZZ Bool Q;
//ZZ } NShift;
//ZZ struct {
//ZZ HReg dst;
//ZZ HReg src;
//ZZ UInt amt; /* 1..63 only */
//ZZ } NShl64;
//ZZ struct {
//ZZ Bool isLoad;
//ZZ HReg dD;
//ZZ ARMAModeN *amode;
//ZZ } NLdStD
//ZZ struct {
//ZZ ARMNeonUnOpS op;
//ZZ ARMNRS* dst;
//ZZ ARMNRS* src;
//ZZ UInt size;
//ZZ Bool Q;
//ZZ } NUnaryS;
//ZZ struct {
//ZZ ARMNeonUnOp op;
//ZZ HReg dst;
//ZZ HReg src;
//ZZ UInt size;
//ZZ Bool Q;
//ZZ } NUnary;
//ZZ /* Takes two arguments and modifies them both. */
//ZZ struct {
//ZZ ARMNeonDualOp op;
//ZZ HReg arg1;
//ZZ HReg arg2;
//ZZ UInt size;
//ZZ Bool Q;
//ZZ } NDual;
struct {
HReg rQ;
UShort imm; /* Same 1-bit-per-byte encoding as IR */
} VImmQ;
struct {
HReg rD;
HReg rX;
} VDfromX;
struct {
HReg rQ;
HReg rXhi;
HReg rXlo;
} VQfromXX;
struct {
HReg rX;
HReg rQ;
UInt laneNo; /* either 0 or 1 */
} VXfromQ;
/* MOV dst, src -- reg-reg move for vector registers */
struct {
UInt szB; // 16=mov qD,qS; 8=mov dD,dS; 4=mov sD,sS
HReg dst;
HReg src;
} VMov;
struct {
ARM64AMode* amCounter;
ARM64AMode* amFailAddr;
} EvCheck;
//ZZ struct {
//ZZ /* No fields. The address of the counter to inc is
//ZZ installed later, post-translation, by patching it in,
//ZZ as it is not known at translation time. */
//ZZ } ProfInc;
} ARM64in;
}
ARM64Instr;
//ZZ
extern ARM64Instr* ARM64Instr_Arith ( HReg, HReg, ARM64RIA*, Bool isAdd );
extern ARM64Instr* ARM64Instr_Cmp ( HReg, ARM64RIA*, Bool is64 );
extern ARM64Instr* ARM64Instr_Logic ( HReg, HReg, ARM64RIL*, ARM64LogicOp );
extern ARM64Instr* ARM64Instr_Test ( HReg, ARM64RIL* );
extern ARM64Instr* ARM64Instr_Shift ( HReg, HReg, ARM64RI6*, ARM64ShiftOp );
extern ARM64Instr* ARM64Instr_Unary ( HReg, HReg, ARM64UnaryOp );
//ZZ extern ARMInstr* ARMInstr_CmpOrTst ( Bool isCmp, HReg, ARMRI84* );
extern ARM64Instr* ARM64Instr_MovI ( HReg, HReg );
extern ARM64Instr* ARM64Instr_Imm64 ( HReg, ULong );
extern ARM64Instr* ARM64Instr_LdSt64 ( Bool isLoad, HReg, ARM64AMode* );
extern ARM64Instr* ARM64Instr_LdSt32 ( Bool isLoad, HReg, ARM64AMode* );
extern ARM64Instr* ARM64Instr_LdSt16 ( Bool isLoad, HReg, ARM64AMode* );
extern ARM64Instr* ARM64Instr_LdSt8 ( Bool isLoad, HReg, ARM64AMode* );
//ZZ extern ARMInstr* ARMInstr_Ld8S ( ARMCondCode, HReg, ARMAMode2* );
extern ARM64Instr* ARM64Instr_XDirect ( Addr64 dstGA, ARM64AMode* amPC,
ARM64CondCode cond, Bool toFastEP );
extern ARM64Instr* ARM64Instr_XIndir ( HReg dstGA, ARM64AMode* amPC,
ARM64CondCode cond );
extern ARM64Instr* ARM64Instr_XAssisted ( HReg dstGA, ARM64AMode* amPC,
ARM64CondCode cond, IRJumpKind jk );
extern ARM64Instr* ARM64Instr_CSel ( HReg dst, HReg argL, HReg argR,
ARM64CondCode cond );
extern ARM64Instr* ARM64Instr_Call ( ARM64CondCode, HWord, Int nArgRegs,
RetLoc rloc );
extern ARM64Instr* ARM64Instr_AddToSP ( Int simm );
extern ARM64Instr* ARM64Instr_FromSP ( HReg dst );
extern ARM64Instr* ARM64Instr_Mul ( HReg dst, HReg argL, HReg argR,
ARM64MulOp op );
extern ARM64Instr* ARM64Instr_LdrEX ( Int szB );
extern ARM64Instr* ARM64Instr_StrEX ( Int szB );
extern ARM64Instr* ARM64Instr_MFence ( void );
//ZZ extern ARMInstr* ARMInstr_CLREX ( void );
extern ARM64Instr* ARM64Instr_VLdStS ( Bool isLoad, HReg sD, HReg rN,
UInt uimm12 /* 0 .. 16380, 0 % 4 */ );
extern ARM64Instr* ARM64Instr_VLdStD ( Bool isLoad, HReg dD, HReg rN,
UInt uimm12 /* 0 .. 32760, 0 % 8 */ );
extern ARM64Instr* ARM64Instr_VLdStQ ( Bool isLoad, HReg rQ, HReg rN );
extern ARM64Instr* ARM64Instr_VCvtI2F ( ARM64CvtOp how, HReg rD, HReg rS );
extern ARM64Instr* ARM64Instr_VCvtF2I ( ARM64CvtOp how, HReg rD, HReg rS,
UChar armRM );
extern ARM64Instr* ARM64Instr_VCvtSD ( Bool sToD, HReg dst, HReg src );
extern ARM64Instr* ARM64Instr_VUnaryD ( ARM64FpUnaryOp op, HReg dst, HReg src );
extern ARM64Instr* ARM64Instr_VUnaryS ( ARM64FpUnaryOp op, HReg dst, HReg src );
extern ARM64Instr* ARM64Instr_VBinD ( ARM64FpBinOp op, HReg, HReg, HReg );
extern ARM64Instr* ARM64Instr_VBinS ( ARM64FpBinOp op, HReg, HReg, HReg );
extern ARM64Instr* ARM64Instr_VCmpD ( HReg argL, HReg argR );
extern ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR );
extern ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg );
extern ARM64Instr* ARM64Instr_VBinV ( ARM64VecBinOp op, HReg, HReg, HReg );
extern ARM64Instr* ARM64Instr_VUnaryV ( ARM64VecUnaryOp op, HReg, HReg );
extern ARM64Instr* ARM64Instr_VNarrowV ( UInt dszBlg2, HReg dst, HReg src );
extern ARM64Instr* ARM64Instr_VShiftImmV ( ARM64VecShiftOp op,
HReg dst, HReg src, UInt amt );
//ZZ extern ARMInstr* ARMInstr_VAluS ( ARMVfpOp op, HReg, HReg, HReg );
//ZZ extern ARMInstr* ARMInstr_VCMovD ( ARMCondCode, HReg dst, HReg src );
//ZZ extern ARMInstr* ARMInstr_VCMovS ( ARMCondCode, HReg dst, HReg src );
//ZZ extern ARMInstr* ARMInstr_VXferD ( Bool toD, HReg dD, HReg rHi, HReg rLo );
//ZZ extern ARMInstr* ARMInstr_VXferS ( Bool toS, HReg fD, HReg rLo );
//ZZ extern ARMInstr* ARMInstr_VCvtID ( Bool iToD, Bool syned,
//ZZ HReg dst, HReg src );
//ZZ extern ARMInstr* ARMInstr_NLdStD ( Bool isLoad, HReg, ARMAModeN* );
//ZZ extern ARMInstr* ARMInstr_NUnary ( ARMNeonUnOp, HReg, HReg, UInt, Bool );
//ZZ extern ARMInstr* ARMInstr_NUnaryS ( ARMNeonUnOpS, ARMNRS*, ARMNRS*,
//ZZ UInt, Bool );
//ZZ extern ARMInstr* ARMInstr_NDual ( ARMNeonDualOp, HReg, HReg, UInt, Bool );
//ZZ extern ARMInstr* ARMInstr_NBinary ( ARMNeonBinOp, HReg, HReg, HReg,
//ZZ UInt, Bool );
//ZZ extern ARMInstr* ARMInstr_NShift ( ARMNeonShiftOp, HReg, HReg, HReg,
//ZZ UInt, Bool );
//ZZ extern ARMInstr* ARMInstr_NShl64 ( HReg, HReg, UInt );
extern ARM64Instr* ARM64Instr_VImmQ ( HReg, UShort );
extern ARM64Instr* ARM64Instr_VDfromX ( HReg rD, HReg rX );
extern ARM64Instr* ARM64Instr_VQfromXX( HReg rQ, HReg rXhi, HReg rXlo );
extern ARM64Instr* ARM64Instr_VXfromQ ( HReg rX, HReg rQ, UInt laneNo );
extern ARM64Instr* ARM64Instr_VMov ( UInt szB, HReg dst, HReg src );
extern ARM64Instr* ARM64Instr_EvCheck ( ARM64AMode* amCounter,
ARM64AMode* amFailAddr );
//ZZ extern ARMInstr* ARMInstr_ProfInc ( void );
extern void ppARM64Instr ( ARM64Instr* );
/* Some functions that insulate the register allocator from details
of the underlying instruction set. */
extern void getRegUsage_ARM64Instr ( HRegUsage*, ARM64Instr*, Bool );
extern void mapRegs_ARM64Instr ( HRegRemap*, ARM64Instr*, Bool );
extern Bool isMove_ARM64Instr ( ARM64Instr*, HReg*, HReg* );
extern Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
UChar* buf, Int nbuf, ARM64Instr* 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_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
extern void genReload_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
extern void getAllocableRegs_ARM64 ( Int*, HReg** );
extern HInstrArray* iselSB_ARM64 ( 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_ARM64 ( void );
/* Perform a chaining and unchaining of an XDirect jump. */
extern VexInvalRange chainXDirect_ARM64 ( void* place_to_chain,
void* disp_cp_chain_me_EXPECTED,
void* place_to_jump_to );
extern VexInvalRange unchainXDirect_ARM64 ( void* place_to_unchain,
void* place_to_jump_to_EXPECTED,
void* disp_cp_chain_me );
//ZZ /* Patch the counter location into an existing ProfInc point. */
//ZZ extern VexInvalRange patchProfInc_ARM ( void* place_to_patch,
//ZZ ULong* location_of_counter );
#endif /* ndef __VEX_HOST_ARM64_DEFS_H */
/*---------------------------------------------------------------*/
/*--- end host_arm64_defs.h ---*/
/*---------------------------------------------------------------*/