#ifndef _DISASSEMBLER_HPP #define _DISASSEMBLER_HPP class DisasCallback { public: /* Mov with Immediate value */ virtual void MoviI64(unsigned int reg_idx, uint64_t imm, bool bit64) = 0; /* Deposit (i.e. distination register won't be changed) with Immediate value */ virtual void DepositI64(unsigned int rd_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64) = 0; virtual void DepositReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0; virtual void DepositZeroI64(unsigned int rd_idx, uint64_t imm, unsigned int pos, unsigned int len, bool bit64) = 0; virtual void DepositZeroReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0; /* Mov between registers */ virtual void MovReg(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0; /* Conditional mov between registers */ virtual void CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool bit64) = 0; /* Add/Sub with Immediate value */ virtual void AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) = 0; virtual void SubI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) = 0; /* Add/Sub/Mul/Div between registers */ virtual void AddReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0; virtual void SubReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0; virtual void MulReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool dst64, bool src64) = 0; virtual void Mul2Reg(unsigned int rh_idx, unsigned int rl_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign) = 0; //64bit * 64bit virtual void DivReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool bit64) = 0; virtual void ShiftReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, unsigned int shift_type, bool bit64) = 0; /* Add/Sub with carry flag between registers */ virtual void AddcReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0; virtual void SubcReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0; /* AND/OR/EOR/Shift ... with Immediate value */ virtual void AndI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool setflags, bool bit64) = 0; virtual void OrrI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool bit64) = 0; virtual void EorI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t wmask, bool bit64) = 0; virtual void ShiftI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int shift_type, unsigned int shift_amount, bool bit64) = 0; /* AND/OR/EOR/BIC/NOT... between registers */ virtual void AndReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0; virtual void OrrReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool bit64) = 0; virtual void EorReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool bit64) = 0; virtual void BicReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0; virtual void NotReg(unsigned int rd_idx, unsigned int rm_idx, bool bit64) = 0; virtual void ExtendReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int extend_type, bool bit64) = 0; /* Load/Store */ virtual void LoadReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool is_sign, bool extend, bool post, bool bit64) = 0; virtual void LoadRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool is_sign, bool extend) = 0; virtual void StoreReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool is_sign, bool extend, bool post, bool bit64) = 0; virtual void StoreRegI64(unsigned int rd_idx, unsigned int ad_idx, int size, bool is_sign, bool extend) = 0; virtual void _LoadReg(unsigned int rd_idx, uint64_t addr, int size, bool is_sign, bool extend) = 0; virtual void _StoreReg(unsigned int rd_idx, uint64_t addr, int size, bool is_sign, bool extend) = 0; /* Bitfield Signed/Unsigned Extract... with Immediate value */ virtual void SExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0; virtual void UExtractI64(unsigned int rd_idx, unsigned int rn_idx, unsigned int pos, unsigned int len, bool bit64) = 0; /* Signed Extend from 32bit */ virtual void SExt32(unsigned int rd_idx, unsigned int rn_idx) = 0; /* Reverse bit order */ virtual void RevBit(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0; /* Reverse byte order per 16bit */ virtual void RevByte16(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0; /* Reverse byte order per 32bit */ virtual void RevByte32(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0; /* Reverse byte order per 64bit */ virtual void RevByte64(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0; /* Count Leading Zeros */ virtual void CntLeadZero(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0; /* Count Leading Signed bits */ virtual void CntLeadSign(unsigned int rd_idx, unsigned int rn_idx, bool bit64) = 0; /* Conditional compare... with Immediate value */ virtual void CondCmpI64(unsigned int rn_idx, unsigned int imm, unsigned int nzcv, unsigned int cond, unsigned int op, bool bit64) = 0; /* Conditional compare... between registers */ virtual void CondCmpReg(unsigned int rn_idx, unsigned int rm_idx, unsigned int nzcv, unsigned int cond, unsigned int op, bool bit64) = 0; /* Go to Immediate address */ virtual void BranchI64(uint64_t imm) = 0; /* Conditional Branch with Immediate value and jump to Immediate address */ virtual void BranchCondiI64(unsigned int cond, unsigned int rt_idx, uint64_t imm, uint64_t addr, bool bit64) = 0; /* Conditional Branch with NZCV flags */ virtual void BranchFlag(unsigned int cond, uint64_t addr) = 0; /* Set PC with reg */ virtual void SetPCReg(unsigned int rt_idx) = 0; /* Super Visor Call */ virtual void SVC(unsigned int svc_num) = 0; /* Breakpoint exception */ virtual void BRK(unsigned int memo) = 0; /* Read/Write Sysreg */ virtual void ReadWriteSysReg(unsigned int rd_idx, int offset, bool read) = 0; /* Read/Write NZCV */ virtual void ReadWriteNZCV(unsigned int rd_idx, bool read) = 0; /* Fp Mov between registers */ virtual void FMovReg(unsigned int fd_idx, unsigned int fn_idx, int type) = 0; /* Fp Mov between registers (float <-> int)*/ virtual void FMovConv(unsigned int rd_idx, unsigned int rn_idx, int type, bool itof) = 0; /* ####### Vector ####### */ /* AND/OR/EOR/BIC/NOT ... between vector registers */ virtual void AndVecReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx) = 0; virtual void OrrVecReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx) = 0; virtual void EorVecReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx) = 0; virtual void BicVecReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx) = 0; virtual void NotVecReg(unsigned int rd_idx, unsigned int rm_idx) = 0; /* Load/Store for vector */ virtual void LoadVecReg(unsigned int vd_idx, int element, unsigned int rn_idx, int size) = 0; virtual void StoreVecReg(unsigned int rd_idx, int element, unsigned int vn_idx, int size) = 0; /* Load/Store for FP */ virtual void LoadFpReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool post, bool bit64) = 0; virtual void StoreFpReg(unsigned int rd_idx, unsigned int base_idx, unsigned int rm_idx, int size, bool post, bool bit64) = 0; /* Load/Store for FP */ virtual void LoadFpRegI64(unsigned int fd_idx, unsigned int ad_idx, int size) = 0; virtual void StoreFpRegI64(unsigned int fd_idx, unsigned int ad_idx, int size) = 0; /* Read Vector register to FP regsiter */ virtual void ReadVecReg(unsigned int fd_idx, unsigned int vn_idx, unsigned int index, int size) = 0; /* Read Vector register to general register */ virtual void ReadVecElem(unsigned int rd_idx, unsigned int vn_idx, unsigned int index, int size) = 0; /* Write general register value tot Vector register */ virtual void WriteVecElem(unsigned int vd_idx, unsigned int rn_idx, unsigned int index, int size) = 0; /* Duplicate an immediate value to vector register */ virtual void DupVecImmI32(unsigned int vd_idx, uint32_t imm, int size, int dstsize) = 0; virtual void DupVecImmI64(unsigned int vd_idx, uint64_t imm, int size, int dstsize) = 0; /* Duplicate an element of vector register to new one */ virtual void DupVecReg(unsigned int vd_idx, unsigned int vn_idx, unsigned int index, int size, int dstsize) = 0; /* Duplicate an general register into vector register */ virtual void DupVecRegFromGen(unsigned int vd_idx, unsigned int rn_idx, int size, int dstsize) = 0; /* Compare Bit wise equal */ virtual void CompareEqualVec(unsigned int vd_idx, unsigned int vn_idx, unsigned int vm_idx, int index, int size) = 0; /* Compare Bit wise test bits nonzero */ virtual void CompareTestBitsVec(unsigned int vd_idx, unsigned int vn_idx, unsigned int vm_idx, int index, int size) = 0; }; namespace Disassembler { //logical ops with shifted registers enum ShiftType { ShiftType_LSL = 0, ShiftType_LSR, ShiftType_ASR, ShiftType_ROR }; enum ExtendType { ExtendType_UXTB = 0, ExtendType_UXTH, ExtendType_UXTW, ExtendType_UXTX, ExtendType_SXTB, ExtendType_SXTH, ExtendType_SXTW, ExtendType_SXTX, }; enum CondType { CondType_EQ = 0, CondType_NE, CondType_CSHS, CondType_CCLO, CondType_MI, CondType_PL, CondType_VS, CondType_VC, CondType_HI, CondType_LS, CondType_GE, CondType_LT, CondType_GT, CondType_LE, CondType_AL, CondType_NV }; #define CP_REG_ARM64 0x6000000000000000ULL #define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000 #define CP_REG_ARM_COPROC_SHIFT 16 #define CP_REG_ARM64_SYSREG (0x0013 << CP_REG_ARM_COPROC_SHIFT) #define CP_REG_ARM64_SYSREG_OP0_MASK 0x000000000000c000 #define CP_REG_ARM64_SYSREG_OP0_SHIFT 14 #define CP_REG_ARM64_SYSREG_OP1_MASK 0x0000000000003800 #define CP_REG_ARM64_SYSREG_OP1_SHIFT 11 #define CP_REG_ARM64_SYSREG_CRN_MASK 0x0000000000000780 #define CP_REG_ARM64_SYSREG_CRN_SHIFT 7 #define CP_REG_ARM64_SYSREG_CRM_MASK 0x0000000000000078 #define CP_REG_ARM64_SYSREG_CRM_SHIFT 3 #define CP_REG_ARM64_SYSREG_OP2_MASK 0x0000000000000007 #define CP_REG_ARM64_SYSREG_OP2_SHIFT 0 #define CP_REG_ARM64_SYSREG_CP (CP_REG_ARM64_SYSREG >> CP_REG_ARM_COPROC_SHIFT) #define CP_REG_AA64_SHIFT 28 #define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT) #define CP_ANY 0xff #define ARM_CP_SPECIAL 0x0001 #define ARM_CP_CONST 0x0002 #define ARM_CP_64BIT 0x0004 #define ARM_CP_SUPPRESS_TB_END 0x0008 #define ARM_CP_OVERRIDE 0x0010 #define ARM_CP_ALIAS 0x0020 #define ARM_CP_IO 0x0040 #define ARM_CP_NO_RAW 0x0080 #define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100) #define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200) #define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300) #define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400) #define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500) #define ARM_LAST_SPECIAL ARM_CP_DC_ZVA #define ARM_CP_FPU 0x1000 #define ARM_CP_SVE 0x2000 #define ARM_CP_SENTINEL 0xffff #define ARM_CP_FLAG_MASK 0x30ff enum { ARM_CP_STATE_AA32 = 0, ARM_CP_STATE_AA64 = 1, ARM_CP_STATE_BOTH = 2, }; enum { ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */ ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */ }; #define PL3_R 0x80 #define PL3_W 0x40 #define PL2_R (0x20 | PL3_R) #define PL2_W (0x10 | PL3_W) #define PL1_R (0x08 | PL2_R) #define PL1_W (0x04 | PL2_W) #define PL0_R (0x02 | PL1_R) #define PL0_W (0x01 | PL1_W) #define PL3_RW (PL3_R | PL3_W) #define PL2_RW (PL2_R | PL2_W) #define PL1_RW (PL1_R | PL1_W) #define PL0_RW (PL0_R | PL0_W) #define ENCODE_SYSTEM_REG(cp, crn, crm, op0, op1, op2) \ (CP_REG_AA64_MASK | \ ((cp) << CP_REG_ARM_COPROC_SHIFT) | \ ((op0) << CP_REG_ARM64_SYSREG_OP0_SHIFT) | \ ((op1) << CP_REG_ARM64_SYSREG_OP1_SHIFT) | \ ((crn) << CP_REG_ARM64_SYSREG_CRN_SHIFT) | \ ((crm) << CP_REG_ARM64_SYSREG_CRM_SHIFT) | \ ((op2) << CP_REG_ARM64_SYSREG_OP2_SHIFT)) typedef void A64DecodeFn(uint32_t insn, DisasCallback *cb); class A64SysRegInfo { public: std::string name; uint8_t cp; uint8_t crn; uint8_t crm; uint8_t opc0; uint8_t opc1; uint8_t opc2; int access; int state; int type; int offset; A64SysRegInfo (std::string _name, int _state, uint8_t _cp, uint8_t _opc0, uint8_t _opc1, uint8_t _opc2, uint8_t _crn, uint8_t _crm, int _o) : name(_name), state(_state), cp(_cp), crn(_crn), crm(_crm), opc0(_opc0), opc1(_opc1), opc2(_opc2), offset(_o) {} A64SysRegInfo (std::string _name, int _state, uint8_t _opc0, uint8_t _opc1, uint8_t _opc2, uint8_t _crn, uint8_t _crm, int _o) : name(_name), state(_state), opc0(_opc0), opc1(_opc1), opc2(_opc2), crn(_crn), crm(_crm), offset(_o) {} A64SysRegInfo (int _type) : type(_type) {} }; typedef struct AArch64DecodeTable { uint32_t pattern; uint32_t mask; A64DecodeFn *disas_fn; } A64DecodeTable; void DisasA64(uint32_t insn, DisasCallback *cb); void Init(); }; #endif