mirror of
https://github.com/RKX1209/nsemu.git
synced 2025-04-02 10:31:49 -04:00
305 lines
14 KiB
C++
305 lines
14 KiB
C++
#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
|