diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-05 19:50:13 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-05 20:34:34 -0500 |
| commit | e093c21ed880ac3eb72119be15093ee04f8ce299 (patch) | |
| tree | 9f720ebdc0ae415734b1199ed341668c69710a94 /arch/arm64/disassembler/decode.h | |
| parent | 0609276712622908254065546102381466033141 (diff) | |
Move architecture modules into the API repo
Diffstat (limited to 'arch/arm64/disassembler/decode.h')
| -rw-r--r-- | arch/arm64/disassembler/decode.h | 580 |
1 files changed, 580 insertions, 0 deletions
diff --git a/arch/arm64/disassembler/decode.h b/arch/arm64/disassembler/decode.h new file mode 100644 index 00000000..a57d0247 --- /dev/null +++ b/arch/arm64/disassembler/decode.h @@ -0,0 +1,580 @@ +#pragma once + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#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, // <Pn>.<T>[<Wm>{, #<imm>}] p12.d[w15, #15] + ACCUM_ARRAY = 15, // ZA[<Wv>, #<imm>] 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 |
