#pragma once #include #include #include #include #include "feature_flags.h" #include "operations.h" #include "encodings_dec.h" #include "regs.h" #include "sysregs.h" #ifdef _MSC_VER #undef REG_NONE // collides with winnt's define #endif #ifdef __cplusplus #define restrict __restrict #endif /* these are used in lookup tables elsewhere, modify with caution */ enum ArrangementSpec { ARRSPEC_NONE = 0, ARRSPEC_FULL = 1, /* 128-bit v-reg unsplit, eg: REG_V0_Q0 */ /* 128 bit v-reg considered as... */ ARRSPEC_2DOUBLES = 2, /* (.2d) two 64-bit double-precision: REG_V0_D1, REG_V0_D0 */ ARRSPEC_4SINGLES = 3, /* (.4s) four 32-bit single-precision: REG_V0_S3, REG_V0_S2, REG_V0_S1, REG_V0_S0 */ ARRSPEC_8HALVES = 4, /* (.8h) eight 16-bit half-precision: REG_V0_H7, REG_V0_H6, (..., REG_V0_H0 */ ARRSPEC_16BYTES = 5, /* (.16b) sixteen 8-bit values: REG_V0_B15, REG_V0_B14, (..., REG_V0_B01 */ /* low 64-bit of v-reg considered as... */ ARRSPEC_1DOUBLE = 6, /* (.d) one 64-bit double-precision: REG_V0_D0 */ ARRSPEC_2SINGLES = 7, /* (.2s) two 32-bit single-precision: REG_V0_S1, REG_V0_S0 */ ARRSPEC_4HALVES = 8, /* (.4h) four 16-bit half-precision: REG_V0_H3, REG_V0_H2, REG_V0_H1, REG_V0_H0 */ ARRSPEC_8BYTES = 9, /* (.8b) eight 8-bit values: REG_V0_B7, REG_V0_B6, (..., REG_V0_B0 */ /* low 32-bit of v-reg considered as... */ ARRSPEC_1SINGLE = 10, /* (.s) one 32-bit single-precision: REG_V0_S0 */ ARRSPEC_2HALVES = 11, /* (.2h) two 16-bit half-precision: REG_V0_H1, REG_V0_H0 */ ARRSPEC_4BYTES = 12, /* (.4b) four 8-bit values: REG_V0_B3, REG_V0_B2, REG_V0_B1, REG_V0_B0 */ /* low 16-bit of v-reg considered as... */ ARRSPEC_1HALF = 13, /* (.h) one 16-bit half-precision: REG_V0_H0 */ /* low 8-bit of v-reg considered as... */ ARRSPEC_1BYTE = 14 /* (.b) one 8-bit byte: REG_V0_B0 */ }; enum SliceIndicator { SLICE_NONE = -1, SLICE_HORIZONTAL = 0, /* same values as read from fields32 */ SLICE_VERTICAL = 1 }; //----------------------------------------------------------------------------- // decode return values //----------------------------------------------------------------------------- #define DECODE_STATUS_OK 0 // success! the resulting named encoding is accurate #define DECODE_STATUS_RESERVED -1 // spec says this space is reserved, eg: RESERVED_36_asisdsame #define DECODE_STATUS_UNMATCHED -2 // decoding logic fell through the spec's checks #define DECODE_STATUS_UNALLOCATED \ -3 // spec says this space is unallocated, eg: UNALLOCATED_10_branch_reg #define DECODE_STATUS_UNDEFINED \ -4 // spec says this encoding is undefined, often due to a disallowed field // or a missing feature, eg: "if !HaveBF16Ext() then UNDEFINED;" #define DECODE_STATUS_END_OF_INSTRUCTION \ -5 // spec decode EndOfInstruction(), instruction executes as NOP #define DECODE_STATUS_LOST -6 // descended past checks, ie: "SEE encoding_up_higher" #define DECODE_STATUS_UNREACHABLE -7 // ran into pcode Unreachable() #define DECODE_STATUS_ASSERT_FAILED -8 // failed an assert #define DECODE_STATUS_ERROR_OPERANDS -9 //----------------------------------------------------------------------------- // floating point condition register values //----------------------------------------------------------------------------- #define FPCR_AHP ((uint64_t)1 << 26) #define FPCR_DN ((uint64_t)1 << 25) #define FPCR_FZ ((uint64_t)1 << 24) #define FPCR_RMode (uint64_t)0xC00000 // [23,22] #define FPCR_Stride (uint64_t)0x300000 // [21,20] #define FPCR_FZ16 ((uint64_t)1 << 19) #define FPCR_Len (uint64_t)0x30000 // [18:16] #define FPCR_IDE ((uint64_t)1 << 15) #define FPCR_IXE ((uint64_t)1 << 12) #define FPCR_UFE ((uint64_t)1 << 11) #define FPCR_OFE ((uint64_t)1 << 10) #define FPCR_DZE ((uint64_t)1 << 9) #define FPCR_IOE ((uint64_t)1 << 8) #define FPCR_GET_AHP(X) SLICE(X, 26, 26) #define FPCR_GET_DN(X) SLICE(X, 25, 25) #define FPCR_GET_FZ(X) SLICE(X, 24, 24) #define FPCR_GET_RMode(X) SLICE(X, 23, 22) #define FPCR_GET_Stride(X) SLICE(X, 21, 20) #define FPCR_GET_FZ16(X) SLICE(X, 19, 19) #define FPCR_GET_Len(X) SLICE(X, 18, 16) #define FPCR_GET_IDE(X) SLICE(X, 15, 15) #define FPCR_GET_IXE(X) SLICE(X, 12, 12) #define FPCR_GET_UFE(X) SLICE(X, 11, 11) #define FPCR_GET_OFE(X) SLICE(X, 10, 10) #define FPCR_GET_DZE(X) SLICE(X, 9, 9) #define FPCR_GET_IOE(X) SLICE(X, 8, 8) //----------------------------------------------------------------------------- // disassembly context (INPUT into disassembler) //----------------------------------------------------------------------------- typedef struct context_ { uint32_t insword; uint64_t address; uint64_t features0; // bitmask of ARCH_FEATURE_XXX uint64_t features1; // bitmask of ARCH_FEATURE_XXX // uint32_t exception_level; // used by AArch64.CheckSystemAccess() // uint32_t security_state; uint8_t pstate_btype; // used by BTypeCompatible_BTI() uint8_t pstate_el; uint8_t pstate_uao; bool BTypeCompatible; uint8_t BTypeNext; bool halted; // is CPU halted? used by Halted() uint64_t FPCR; // floating point control register bool EDSCR_HDE; // External Debug Status and Control Register, Halting debug enable /* specification scratchpad: ~300 possible named fields */ uint64_t A; uint64_t ADD; uint64_t AccType_NORMAL; uint64_t AccType_STREAM; uint64_t AccType_UNPRIV; uint64_t AccType_VEC; uint64_t AccType_VECSTREAM; uint64_t B; uint64_t C; uint64_t CRm; uint64_t CRn; uint64_t dst, D; uint64_t E; uint64_t H; uint64_t HCR_EL2_E2H, HCR_EL2_NV, HCR_EL2_NV1, HCR_EL2_TGE; uint64_t k; uint64_t L; uint64_t LL; uint64_t M; uint64_t N; uint64_t O; uint64_t Op0, Op3; uint64_t P; uint64_t Pd, Pdm, Pdn, Pg, Pm, Pn, Pt; uint64_t Q, Qa, Qd, Qm, Qn, Qt, Qt2; uint64_t reason, retry; uint64_t R, Ra, Rd, Rdn, Rm, Rmhi, Rn, Rs, Rt, Rt2, Rv; uint64_t s1, s2, sel1, sel2, S, Sa, Sd, Sm, Sn, St, St2; uint64_t S10; uint64_t SCTLR_EL1_UMA; uint64_t T; uint64_t U; uint64_t US; uint64_t V, Va, Vd, Vdn, Vm, Vn, Vt, Vt2; uint64_t W, Wa, Wd, Wdn, Wm, Wn, Ws, Wt, Wt2; uint64_t Xa, Xd, Xdn, Xm, Xn, Xs, Xt, Xt2; uint64_t Z, Za, Zd, Zda, Zdn, Zm, Zn, Zt; uint64_t a; uint64_t abs; uint64_t ac; uint64_t acc; uint64_t acctype; uint64_t accumulate; uint64_t alias; uint64_t amount; uint64_t and_test; uint64_t asimdimm; uint64_t b; uint64_t b40; uint64_t b5; uint64_t bit_pos; uint64_t bit_val; uint64_t branch_type; uint64_t c; uint64_t cmode; uint64_t cmp, cmph, cmpl, cmp_eq, cmp_with_zero; uint64_t comment; uint64_t comparison; uint64_t cond; /* careful! this is the pcode scratchpad .cond, NOT the .cond field of a struct InstructionOperand */ uint64_t condition; uint64_t container_size; uint64_t containers; uint64_t countop; uint64_t crc32c; uint64_t csize; uint64_t d, da, data, datasize, double_table; uint64_t dtype, dtypeh, dtypel; uint64_t d_esize; uint64_t decrypt; uint64_t destsize; uint64_t dm; uint64_t dn; uint64_t domain; uint64_t dst_index; uint64_t dst_unsigned; uint64_t dstsize; uint64_t e; uint64_t elements; uint64_t elements_per_container; uint64_t else_inc; uint64_t else_inv; uint64_t elsize; uint64_t eq; uint64_t esize; uint64_t exact; uint64_t extend; uint64_t extend_type; uint64_t f, ff; uint64_t field; uint64_t flags; uint64_t fltsize; uint64_t fpop; uint64_t fracbits; uint64_t ftype; uint64_t g; uint64_t h; uint64_t has_result; uint64_t hi; uint64_t hw; uint64_t i, i1, i2, i2h, i2l, i3h, i3l; uint64_t idxdsize; uint64_t imm; uint64_t imm1; uint64_t imm12; uint64_t imm13; uint64_t imm14; uint64_t imm16; uint64_t imm19; uint64_t imm2; uint64_t imm26; uint64_t imm3; uint64_t imm4; uint64_t imm5; uint64_t imm5b; uint64_t imm6; uint64_t imm64; uint64_t imm7; uint64_t imm8; uint64_t imm8h; uint64_t imm8l; uint64_t imm9; uint64_t imm9h; uint64_t imm9l; uint64_t immb; uint64_t immh; uint64_t immhi; uint64_t immlo; uint64_t immr; uint64_t imms; uint64_t index; uint64_t init_scale; uint64_t intsize; uint64_t int_U; uint64_t invert; uint64_t inzero; uint64_t isBefore; uint64_t is_tbl; uint64_t iszero; uint64_t ldacctype; uint64_t len; uint64_t level; uint64_t lsb; uint64_t lt; uint64_t m; uint64_t mask; uint64_t mbytes; uint64_t memop; uint64_t merging; uint64_t min; uint64_t min_EL; uint64_t minimum; uint64_t msb; uint64_t msize; uint64_t msz; uint64_t mulx_op; uint64_t n; uint64_t ne; uint64_t need_secure; uint64_t neg; uint64_t neg_i; uint64_t neg_r; uint64_t negated; uint64_t nreg; uint64_t nzcv; uint64_t nXS; uint64_t o0, o1, o2, o3; uint64_t offs_size; uint64_t offs_unsigned; uint64_t offset; uint64_t op1_neg; uint64_t op1_unsigned; uint64_t op, op0, op1, op2, op3, op4, op21, op31, op54; uint64_t op2_unsigned; uint64_t op3_neg; uint64_t opa_neg; uint64_t opc; uint64_t opc2; uint64_t opcode, opcode2; uint64_t operand; uint64_t operation_; uint64_t opt, option; uint64_t osize; uint64_t pac; uint64_t page; uint64_t pair; uint64_t pairs; uint64_t part; uint64_t part1; uint64_t pat; uint64_t pattern; uint64_t poly; uint64_t pos; uint64_t position; uint64_t postindex; uint64_t pref_hint; uint64_t prfop; uint64_t ptype; uint64_t rd; uint64_t read; uint64_t regs; uint64_t regsize; uint64_t replicate; uint64_t rmode; uint64_t rot; uint64_t round; uint64_t rounding; uint64_t rpt; uint64_t rsize; uint64_t rn_unknown, rt_unknown; uint64_t rw; uint64_t s; uint64_t s_esize; uint64_t saturating; uint64_t scale; uint64_t sel; uint64_t sel_a; uint64_t sel_b; uint64_t selem; uint64_t setflags; uint64_t sf; uint64_t sh; uint64_t shift; uint64_t shift_amount; uint64_t shift_type; uint64_t signal_all_nans; uint64_t signed_; uint64_t simm7; uint64_t size; uint64_t source_is_sp; uint64_t src_index; uint64_t src_unsigned; uint64_t srcsize; uint64_t ssize, ssz; uint64_t stacctype; uint64_t stream; uint64_t sub_i; uint64_t sub_op; uint64_t sub_r; uint64_t swsize; uint64_t sys_crm; uint64_t sys_crn; uint64_t sys_op0; uint64_t sys_op1; uint64_t sys_op2; uint64_t sz; uint64_t t, t2, tb; uint64_t tag_checked; uint64_t tag_offset; uint64_t target_level; uint64_t tmask; uint64_t tsize; uint64_t tsz; uint64_t tszh; uint64_t tszl; uint64_t types; uint64_t u0, u1; uint64_t uimm4; uint64_t uimm6; uint64_t unpriv_at_el1; uint64_t unpriv_at_el2; uint64_t uns; uint64_t unsigned_; uint64_t use_key_a; uint64_t user_access_override; uint64_t v, vertical; uint64_t wback; uint64_t wb_unknown; uint64_t wmask; uint64_t writeback; uint64_t xs; uint64_t ZAda, ZAd, ZAn, ZAt, Zk, zero_data; } context; //----------------------------------------------------------------------------- // Instruction definition (OUTPUT from disassembler) //----------------------------------------------------------------------------- enum OperandClass { // syntax example NONE = 0, // --------------------------- --------------------- IMM32 = 1, IMM64 = 2, FIMM32 = 3, STR_IMM = 4, REG = 5, MULTI_REG = 6, SYS_REG = 7, MEM_REG = 8, MEM_PRE_IDX = 9, MEM_POST_IDX = 10, MEM_OFFSET = 11, MEM_EXTENDED = 12, SME_TILE = 13, INDEXED_ELEMENT = 14, // .[{, #}] p12.d[w15, #15] ACCUM_ARRAY = 15, // ZA[, #] ZA[w13, #8] LABEL = 16, CONDITION = 17, NAME = 18, IMPLEMENTATION_SPECIFIC = 19 }; enum Condition { COND_EQ, COND_NE, COND_CS, COND_CC, COND_MI, COND_PL, COND_VS, COND_VC, COND_HI, COND_LS, COND_GE, COND_LT, COND_GT, COND_LE, COND_AL, COND_NV, END_CONDITION }; enum ShiftType { ShiftType_NONE, ShiftType_LSL, ShiftType_LSR, ShiftType_ASR, ShiftType_ROR, ShiftType_UXTW, ShiftType_SXTW, ShiftType_SXTX, ShiftType_UXTX, ShiftType_SXTB, ShiftType_SXTH, ShiftType_UXTH, ShiftType_UXTB, ShiftType_MSL, ShiftType_END, }; enum Group { GROUP_UNALLOCATED, GROUP_DATA_PROCESSING_IMM, GROUP_BRANCH_EXCEPTION_SYSTEM, GROUP_LOAD_STORE, GROUP_DATA_PROCESSING_REG, GROUP_DATA_PROCESSING_SIMD, GROUP_DATA_PROCESSING_SIMD2, END_GROUP }; enum FlagEffect { FLAGEFFECT_NONE=0, // doesn't set flags FLAGEFFECT_SETS=1, // sets flags, but unknown which type FLAGEFFECT_SETS_NORMAL=2, // sets flags after normal comparison FLAGEFFECT_SETS_FLOAT=3 // sets flags after float comparison }; #ifndef __cplusplus typedef enum SystemReg SystemReg; typedef enum OperandClass OperandClass; typedef enum Register Register; typedef enum Condition Condition; typedef enum ShiftType ShiftType; typedef enum Operation Operation; typedef enum Group Group; typedef enum ArrangementSpec ArrangementSpec; typedef enum SliceIndicator SliceIndicator; #endif #define MAX_REGISTERS 5 #define MAX_NAME 16 struct InstructionOperand { OperandClass operandClass; ArrangementSpec arrSpec; Register reg[MAX_REGISTERS]; /* for class CONDITION */ Condition cond; /* for class IMPLEMENTATION_SPECIFIC */ uint8_t implspec[MAX_REGISTERS]; /* for class SYS_REG */ SystemReg sysreg; bool laneUsed; uint32_t lane; uint64_t immediate; ShiftType shiftType; bool shiftValueUsed; uint32_t shiftValue; ShiftType extend; bool signedImm; char pred_qual; // predicate register qualifier ('z' or 'm') bool mul_vl; // whether MEM_OFFSET has the offset "mul vl" /* for class SME_TILE */ uint16_t tile; SliceIndicator slice; /* for class NAME */ char name[MAX_NAME]; }; #ifndef __cplusplus typedef struct InstructionOperand InstructionOperand; #endif #define MAX_OPERANDS 5 struct Instruction { uint32_t insword; enum ENCODING encoding; enum Operation operation; InstructionOperand operands[MAX_OPERANDS]; enum FlagEffect setflags; }; #ifndef __cplusplus typedef struct Instruction Instruction; #endif #ifdef __cplusplus extern "C" { #endif int aarch64_decompose(uint32_t instructionValue, Instruction* instr, uint64_t address); size_t get_register_size(enum Register); #ifdef __cplusplus } #endif