From e093c21ed880ac3eb72119be15093ee04f8ce299 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 5 Mar 2024 19:50:13 -0500 Subject: Move architecture modules into the API repo --- arch/arm64/disassembler/decode_scratchpad.c | 10828 ++++++++++++++++++++++++++ 1 file changed, 10828 insertions(+) create mode 100644 arch/arm64/disassembler/decode_scratchpad.c (limited to 'arch/arm64/disassembler/decode_scratchpad.c') diff --git a/arch/arm64/disassembler/decode_scratchpad.c b/arch/arm64/disassembler/decode_scratchpad.c new file mode 100644 index 00000000..0248b0ca --- /dev/null +++ b/arch/arm64/disassembler/decode_scratchpad.c @@ -0,0 +1,10828 @@ +#include "decode.h" +#include "pcode.h" +#include +#include +#include + +//----------------------------------------------------------------------------- +// registers +//----------------------------------------------------------------------------- + +// regMap[0][?][?] uses SP for R31 +// regMap[1][?][?] uses ZR for R31 +static const Register regMap[2][10][32] = { + { + { + REG_W0, + REG_W1, + REG_W2, + REG_W3, + REG_W4, + REG_W5, + REG_W6, + REG_W7, + REG_W8, + REG_W9, + REG_W10, + REG_W11, + REG_W12, + REG_W13, + REG_W14, + REG_W15, + REG_W16, + REG_W17, + REG_W18, + REG_W19, + REG_W20, + REG_W21, + REG_W22, + REG_W23, + REG_W24, + REG_W25, + REG_W26, + REG_W27, + REG_W28, + REG_W29, + REG_W30, + REG_WSP, + }, + {REG_X0, REG_X1, REG_X2, REG_X3, REG_X4, REG_X5, REG_X6, REG_X7, REG_X8, REG_X9, REG_X10, + REG_X11, REG_X12, REG_X13, REG_X14, REG_X15, REG_X16, REG_X17, REG_X18, REG_X19, + REG_X20, REG_X21, REG_X22, REG_X23, REG_X24, REG_X25, REG_X26, REG_X27, REG_X28, + REG_X29, REG_X30, REG_SP}, + {REG_V0, REG_V1, REG_V2, REG_V3, REG_V4, REG_V5, REG_V6, REG_V7, REG_V8, REG_V9, REG_V10, + REG_V11, REG_V12, REG_V13, REG_V14, REG_V15, REG_V16, REG_V17, REG_V18, REG_V19, + REG_V20, REG_V21, REG_V22, REG_V23, REG_V24, REG_V25, REG_V26, REG_V27, REG_V28, + REG_V29, REG_V30, REG_V31}, + {REG_B0, REG_B1, REG_B2, REG_B3, REG_B4, REG_B5, REG_B6, REG_B7, REG_B8, REG_B9, REG_B10, + REG_B11, REG_B12, REG_B13, REG_B14, REG_B15, REG_B16, REG_B17, REG_B18, REG_B19, + REG_B20, REG_B21, REG_B22, REG_B23, REG_B24, REG_B25, REG_B26, REG_B27, REG_B28, + REG_B29, REG_B30, REG_B31}, + {REG_H0, REG_H1, REG_H2, REG_H3, REG_H4, REG_H5, REG_H6, REG_H7, REG_H8, REG_H9, REG_H10, + REG_H11, REG_H12, REG_H13, REG_H14, REG_H15, REG_H16, REG_H17, REG_H18, REG_H19, + REG_H20, REG_H21, REG_H22, REG_H23, REG_H24, REG_H25, REG_H26, REG_H27, REG_H28, + REG_H29, REG_H30, REG_H31}, + {REG_S0, REG_S1, REG_S2, REG_S3, REG_S4, REG_S5, REG_S6, REG_S7, REG_S8, REG_S9, REG_S10, + REG_S11, REG_S12, REG_S13, REG_S14, REG_S15, REG_S16, REG_S17, REG_S18, REG_S19, + REG_S20, REG_S21, REG_S22, REG_S23, REG_S24, REG_S25, REG_S26, REG_S27, REG_S28, + REG_S29, REG_S30, REG_S31}, + {REG_D0, REG_D1, REG_D2, REG_D3, REG_D4, REG_D5, REG_D6, REG_D7, REG_D8, REG_D9, REG_D10, + REG_D11, REG_D12, REG_D13, REG_D14, REG_D15, REG_D16, REG_D17, REG_D18, REG_D19, + REG_D20, REG_D21, REG_D22, REG_D23, REG_D24, REG_D25, REG_D26, REG_D27, REG_D28, + REG_D29, REG_D30, REG_D31}, + {REG_Q0, REG_Q1, REG_Q2, REG_Q3, REG_Q4, REG_Q5, REG_Q6, REG_Q7, REG_Q8, REG_Q9, REG_Q10, + REG_Q11, REG_Q12, REG_Q13, REG_Q14, REG_Q15, REG_Q16, REG_Q17, REG_Q18, REG_Q19, + REG_Q20, REG_Q21, REG_Q22, REG_Q23, REG_Q24, REG_Q25, REG_Q26, REG_Q27, REG_Q28, + REG_Q29, REG_Q30, REG_Q31}, + {REG_Z0, REG_Z1, REG_Z2, REG_Z3, REG_Z4, REG_Z5, REG_Z6, REG_Z7, REG_Z8, REG_Z9, REG_Z10, + REG_Z11, REG_Z12, REG_Z13, REG_Z14, REG_Z15, REG_Z16, REG_Z17, REG_Z18, REG_Z19, + REG_Z20, REG_Z21, REG_Z22, REG_Z23, REG_Z24, REG_Z25, REG_Z26, REG_Z27, REG_Z28, + REG_Z29, REG_Z30, REG_Z31}, + {REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_P6, REG_P7, REG_P8, REG_P9, REG_P10, + REG_P11, REG_P12, REG_P13, REG_P14, REG_P15, REG_P16, REG_P17, REG_P18, REG_P19, + REG_P20, REG_P21, REG_P22, REG_P23, REG_P24, REG_P25, REG_P26, REG_P27, REG_P28, + REG_P29, REG_P30, REG_P31}, + }, + {{ + REG_W0, + REG_W1, + REG_W2, + REG_W3, + REG_W4, + REG_W5, + REG_W6, + REG_W7, + REG_W8, + REG_W9, + REG_W10, + REG_W11, + REG_W12, + REG_W13, + REG_W14, + REG_W15, + REG_W16, + REG_W17, + REG_W18, + REG_W19, + REG_W20, + REG_W21, + REG_W22, + REG_W23, + REG_W24, + REG_W25, + REG_W26, + REG_W27, + REG_W28, + REG_W29, + REG_W30, + REG_WZR, + }, + { + REG_X0, + REG_X1, + REG_X2, + REG_X3, + REG_X4, + REG_X5, + REG_X6, + REG_X7, + REG_X8, + REG_X9, + REG_X10, + REG_X11, + REG_X12, + REG_X13, + REG_X14, + REG_X15, + REG_X16, + REG_X17, + REG_X18, + REG_X19, + REG_X20, + REG_X21, + REG_X22, + REG_X23, + REG_X24, + REG_X25, + REG_X26, + REG_X27, + REG_X28, + REG_X29, + REG_X30, + REG_XZR, + }, + { + REG_V0, + REG_V1, + REG_V2, + REG_V3, + REG_V4, + REG_V5, + REG_V6, + REG_V7, + REG_V8, + REG_V9, + REG_V10, + REG_V11, + REG_V12, + REG_V13, + REG_V14, + REG_V15, + REG_V16, + REG_V17, + REG_V18, + REG_V19, + REG_V20, + REG_V21, + REG_V22, + REG_V23, + REG_V24, + REG_V25, + REG_V26, + REG_V27, + REG_V28, + REG_V29, + REG_V30, + REG_V31, + }, + { + REG_B0, + REG_B1, + REG_B2, + REG_B3, + REG_B4, + REG_B5, + REG_B6, + REG_B7, + REG_B8, + REG_B9, + REG_B10, + REG_B11, + REG_B12, + REG_B13, + REG_B14, + REG_B15, + REG_B16, + REG_B17, + REG_B18, + REG_B19, + REG_B20, + REG_B21, + REG_B22, + REG_B23, + REG_B24, + REG_B25, + REG_B26, + REG_B27, + REG_B28, + REG_B29, + REG_B30, + REG_B31, + }, + { + REG_H0, + REG_H1, + REG_H2, + REG_H3, + REG_H4, + REG_H5, + REG_H6, + REG_H7, + REG_H8, + REG_H9, + REG_H10, + REG_H11, + REG_H12, + REG_H13, + REG_H14, + REG_H15, + REG_H16, + REG_H17, + REG_H18, + REG_H19, + REG_H20, + REG_H21, + REG_H22, + REG_H23, + REG_H24, + REG_H25, + REG_H26, + REG_H27, + REG_H28, + REG_H29, + REG_H30, + REG_H31, + }, + { + REG_S0, + REG_S1, + REG_S2, + REG_S3, + REG_S4, + REG_S5, + REG_S6, + REG_S7, + REG_S8, + REG_S9, + REG_S10, + REG_S11, + REG_S12, + REG_S13, + REG_S14, + REG_S15, + REG_S16, + REG_S17, + REG_S18, + REG_S19, + REG_S20, + REG_S21, + REG_S22, + REG_S23, + REG_S24, + REG_S25, + REG_S26, + REG_S27, + REG_S28, + REG_S29, + REG_S30, + REG_S31, + }, + { + REG_D0, + REG_D1, + REG_D2, + REG_D3, + REG_D4, + REG_D5, + REG_D6, + REG_D7, + REG_D8, + REG_D9, + REG_D10, + REG_D11, + REG_D12, + REG_D13, + REG_D14, + REG_D15, + REG_D16, + REG_D17, + REG_D18, + REG_D19, + REG_D20, + REG_D21, + REG_D22, + REG_D23, + REG_D24, + REG_D25, + REG_D26, + REG_D27, + REG_D28, + REG_D29, + REG_D30, + REG_D31, + }, + {REG_Q0, REG_Q1, REG_Q2, REG_Q3, REG_Q4, REG_Q5, REG_Q6, REG_Q7, REG_Q8, REG_Q9, REG_Q10, + REG_Q11, REG_Q12, REG_Q13, REG_Q14, REG_Q15, REG_Q16, REG_Q17, REG_Q18, REG_Q19, + REG_Q20, REG_Q21, REG_Q22, REG_Q23, REG_Q24, REG_Q25, REG_Q26, REG_Q27, REG_Q28, + REG_Q29, REG_Q30, REG_Q31}, + {REG_Z0, REG_Z1, REG_Z2, REG_Z3, REG_Z4, REG_Z5, REG_Z6, REG_Z7, REG_Z8, REG_Z9, REG_Z10, + REG_Z11, REG_Z12, REG_Z13, REG_Z14, REG_Z15, REG_Z16, REG_Z17, REG_Z18, REG_Z19, + REG_Z20, REG_Z21, REG_Z22, REG_Z23, REG_Z24, REG_Z25, REG_Z26, REG_Z27, REG_Z28, + REG_Z29, REG_Z30, REG_Z31}, + {REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_P6, REG_P7, REG_P8, REG_P9, REG_P10, + REG_P11, REG_P12, REG_P13, REG_P14, REG_P15, REG_P16, REG_P17, REG_P18, REG_P19, + REG_P20, REG_P21, REG_P22, REG_P23, REG_P24, REG_P25, REG_P26, REG_P27, REG_P28, + REG_P29, REG_P30, REG_P31}, + }}; + +/* first coordinate into regMap */ +#define REGSET_SP 0 +#define REGSET_ZR 1 + +/* second coordinate into regMap */ +#define REG_W_BASE 0 +#define REG_X_BASE 1 +#define REG_V_BASE 2 +#define REG_B_BASE 3 +#define REG_H_BASE 4 +#define REG_S_BASE 5 +#define REG_D_BASE 6 +#define REG_Q_BASE 7 +#define REG_Z_BASE 8 +#define REG_P_BASE 9 + +/* third coordinate into regMap is [0,31] */ + +int table_wbase_xbase[2] = {REG_W_BASE, REG_X_BASE}; + +#define REG(SP_OR_ZR, REG_BASE, REG_NUM) regMap[(SP_OR_ZR)][(REG_BASE)][(REG_NUM)] + +/* prefetch operation */ +const char* prfop_lookup(unsigned prfop) +{ + switch (prfop) + { + case 0b00000: + return "pldl1keep"; + case 0b00001: + return "pldl1strm"; + case 0b00010: + return "pldl2keep"; + case 0b00011: + return "pldl2strm"; + case 0b00100: + return "pldl3keep"; + case 0b00101: + return "pldl3strm"; + case 0b00110: + return "#6"; + case 0b00111: + return "#7"; + case 0b01000: + return "plil1keep"; + case 0b01001: + return "plil1strm"; + case 0b01010: + return "plil2keep"; + case 0b01011: + return "plil2strm"; + case 0b01100: + return "plil3keep"; + case 0b01101: + return "plil3strm"; + case 0b01110: + return "#14"; + case 0b01111: + return "#15"; + case 0b10000: + return "pstl1keep"; + case 0b10001: + return "pstl1strm"; + case 0b10010: + return "pstl2keep"; + case 0b10011: + return "pstl2strm"; + case 0b10100: + return "pstl3keep"; + case 0b10101: + return "pstl3strm"; + case 0b10110: + return "#22"; + case 0b10111: + return "#23"; + case 0b11000: + return "#24"; + case 0b11001: + return "#25"; + case 0b11010: + return "#26"; + case 0b11011: + return "#27"; + case 0b11100: + return "#28"; + case 0b11101: + return "#29"; + case 0b11110: + return "#30"; + case 0b11111: + return "#31"; + default: + return "error"; + } +} + +/* prefetch operation */ +const char* prfop_lookup_4(unsigned prfop) +{ + switch (prfop) + { + case 0b0000: + return "pldl1keep"; + case 0b0001: + return "pldl1strm"; + case 0b0010: + return "pldl2keep"; + case 0b0011: + return "pldl2strm"; + case 0b0100: + return "pldl3keep"; + case 0b0101: + return "pldl3strm"; + case 0b0110: + return "#6"; + case 0b0111: + return "#7"; + case 0b1000: + return "pstl1keep"; + case 0b1001: + return "pstl1strm"; + case 0b1010: + return "pstl2keep"; + case 0b1011: + return "pstl2strm"; + case 0b1100: + return "pstl3keep"; + case 0b1101: + return "pstl3strm"; + case 0b1110: + return "#14"; + case 0b1111: + return "#15"; + default: + return "error"; + } +} + +const char* pattern_lookup(unsigned pattern, unsigned uimm5) +{ + switch (pattern & 0x1f) + { + case 0b00000: + return "pow2"; + case 0b00001: + return "vl1"; + case 0b00010: + return "vl2"; + case 0b00011: + return "vl3"; + case 0b00100: + return "vl4"; + case 0b00101: + return "vl5"; + case 0b00110: + return "vl6"; + case 0b00111: + return "vl7"; + case 0b01000: + return "vl8"; + case 0b01001: + return "vl16"; + case 0b01010: + return "vl32"; + case 0b01011: + return "vl64"; + case 0b01100: + return "vl128"; + case 0b01101: + return "vl256"; + case 0b11101: + return "mul4"; + case 0b11110: + return "mul3"; + case 0b11111: + return "all"; + default: + return "error"; + } +} + +//----------------------------------------------------------------------------- +// arrangement specifiers and lookups (usually fills in a ".", ".", "<.Tb>") +//----------------------------------------------------------------------------- + +#define _1B ARRSPEC_1BYTE +#define _1H ARRSPEC_1HALF +#define _1S ARRSPEC_1SINGLE +#define _1D ARRSPEC_1DOUBLE +#define _1Q ARRSPEC_FULL +#define _2H ARRSPEC_2HALVES +#define _2S ARRSPEC_2SINGLES +#define _2D ARRSPEC_2DOUBLES +#define _4B ARRSPEC_4BYTES +#define _4H ARRSPEC_4HALVES +#define _4S ARRSPEC_4SINGLES +#define _8B ARRSPEC_8BYTES +#define _8H ARRSPEC_8HALVES +#define _16B ARRSPEC_16BYTES + +/* arrangement specifiers +0000 x SEE Advanced SIMD modified immediate +0001 0 8B +0001 1 16B +001x 0 4H +001x 1 8H +01xx 0 2S +01xx 1 4S +1xxx x RESERVED +*/ +ArrangementSpec arr_spec_method0(uint32_t imm5, uint32_t Q) +{ + if (Q == 0) + { + if (imm5 & 1) + return _8B; + if (imm5 & 2) + return _4H; + if (imm5 & 4) + return _2S; + } + else + { + if (imm5 & 1) + return _16B; + if (imm5 & 2) + return _8H; + if (imm5 & 4) + return _4S; + if (imm5 & 8) + return _2D; + } + return ARRSPEC_NONE; +} + +ArrangementSpec arr_spec_method1(unsigned key) +{ + // 00000 RESERVED + // xxxx1 B + // xxx10 H + // xx100 S + // x1000 D + // 10000 Q + if ((key & 0b00001) == 0b00001) + return _1B; // xxxx1 B + if ((key & 0b00011) == 0b00010) + return _1H; // xxx10 H + if ((key & 0b00111) == 0b00100) + return _1S; // xx100 S + if ((key & 0b01111) == 0b01000) + return _1D; // x1000 D + if ((key & 0b11111) == 0b10000) + return _1Q; // 10000 Q + return ARRSPEC_NONE; +} + +ArrangementSpec arr_spec_method2(unsigned immh) +{ + // 0000 SEE Advanced SIMD modified immediate + if (immh == 1) + return _8H; // 0001 8H + if ((immh & 0b1110) == 0b0010) + return _4S; // 001x 4S + if ((immh & 0b1100) == 0b0100) + return _2D; // 01xx 2D + return ARRSPEC_NONE; // 1xxx RESERVED +} + +ArrangementSpec arr_spec_method3(unsigned immh, unsigned q) +{ + switch ((immh << 1) | q) + { + // 0000 x SEE Advanced SIMD modified immediate + case 0b00010: + return _8B; // 0001 0 8B + case 0b00011: + return _16B; // 0001 1 16B + case 0b00100: + case 0b00110: + return _4H; // 001x 0 4H + case 0b00101: + case 0b00111: + return _8H; // 001x 1 8H + case 0b01000: + case 0b01010: + case 0b01100: + case 0b01110: + return _2S; // 01xx 0 2S + case 0b01001: + case 0b01011: + case 0b01101: + case 0b01111: + return _4S; // 01xx 1 4S + case 0b10001: + case 0b10011: + case 0b10101: + case 0b10111: + case 0b11001: + case 0b11011: + case 0b11101: + case 0b11111: + return _2D; + default: + break; // 1xxx 1 RESERVED + } + return ARRSPEC_NONE; +} + +ArrangementSpec arr_spec_method4(unsigned imm5, unsigned q) +{ + unsigned key = (imm5 << 1) | q; + // if((key & 0b011110) == 0b000000) return RESERVED; // x0000 x RESERVED + if ((key & 0b000011) == 0b000010) + return _8B; // xxxx1 0 8B + if ((key & 0b000011) == 0b000011) + return _16B; // xxxx1 1 16B + if ((key & 0b000111) == 0b000100) + return _4H; // xxx10 0 4H + if ((key & 0b000111) == 0b000101) + return _8H; // xxx10 1 8H + if ((key & 0b001111) == 0b001000) + return _2S; // xx100 0 2S + if ((key & 0b001111) == 0b001001) + return _4S; // xx100 1 4S + // if((key & 0b011111) == 0b010000) return RESERVED; // x1000 0 RESERVED + if ((key & 0b011111) == 0b010001) + return _2D; // x1000 1 2D + return ARRSPEC_NONE; +} + +ArrangementSpec table_1s_1d[2] = {_1S, _1D}; +ArrangementSpec table_2s_4s[2] = {_2S, _4S}; +ArrangementSpec table_2s_2d[2] = {_2S, _2D}; +ArrangementSpec table_2h_4h[2] = {_2H, _4H}; +ArrangementSpec table_4h_8h[2] = {_4H, _8H}; +ArrangementSpec table_4s_2d[2] = {_4S, _2D}; +ArrangementSpec table_8b_16b[2] = {_8B, _16B}; +ArrangementSpec table_2s_r_4s_2d[4] = {_2S, ARRSPEC_NONE, _4S, _2D}; +ArrangementSpec table_2s_4s_r_2d[4] = {_2S, _4S, ARRSPEC_NONE, _2D}; +ArrangementSpec table_8h_4s_2d_1q[4] = {_8H, _4S, _2D, _1Q}; +ArrangementSpec table_4h_8h_2s_4s_1d_2d_r_r[8] = { + _4H, _8H, _2S, _4S, _1D, _2D, ARRSPEC_NONE, ARRSPEC_NONE}; +ArrangementSpec table_8b_16b_4h_8h_2s_4s_1d_2d[8] = {_8B, _16B, _4H, _8H, _2S, _4S, _1D, _2D}; +ArrangementSpec table_r_b_h_r_r_s_r_r[8] = { + ARRSPEC_NONE, _1B, _1H, ARRSPEC_NONE, ARRSPEC_NONE, _1S, ARRSPEC_NONE, ARRSPEC_NONE}; +ArrangementSpec table_r_h_s_r_r_d_r_r[8] = { + ARRSPEC_NONE, _1H, _1S, ARRSPEC_NONE, ARRSPEC_NONE, _1D, ARRSPEC_NONE, ARRSPEC_NONE}; +ArrangementSpec table_r_h_s_s_d_d_d_d[8] = { + ARRSPEC_NONE, _1H, _1S, _1S, _1D, _1D, _1D, _1D}; +ArrangementSpec table_r_b_h_h_s_s_s_s[8] = { + ARRSPEC_NONE, _1B, _1H, _1H, _1S, _1S, _1S, _1S}; +ArrangementSpec table16_r_b_h_s_d[16] = { + ARRSPEC_NONE, _1B, _1H, _1H, _1S, _1S, _1S, _1S, _1D, _1D, _1D, _1D, _1D, _1D, _1D, _1D}; + +//----------------------------------------------------------------------------- +// element size (usually to fill in a ".") +//----------------------------------------------------------------------------- + +ArrangementSpec size_spec_method0(uint8_t /*bit*/ a, uint8_t /*bit(6)*/ b) +{ + if (a == 0) + { + if ((b & 0x20) == 0) + return _1S; + if ((b & 0x30) == 0x20) + return _1H; + if ((b & 0x38) == 0x30) + return _1B; + if ((b & 0x3C) == 0x38) + return _1B; + if ((b & 0x3E) == 0x3C) + return _1B; + return 0; + } + else + { + return _1D; + } +} + +ArrangementSpec size_spec_method1(unsigned imm13) +{ + unsigned key = (((imm13 >> 12) & 1) << 6) | (imm13 & 0b111111); + + if ((key & 0b1100000) == 0b0000000) + return _1S; // 0 0xxxxx S + if ((key & 0b1110000) == 0b0100000) + return _1H; // 0 10xxxx H + if ((key & 0b1111000) == 0b0110000) + return _1B; // 0 110xxx B + if ((key & 0b1111100) == 0b0111000) + return _1B; // 0 1110xx B + if ((key & 0b1111110) == 0b0111100) + return _1B; // 0 11110x B + // if((key & 0b1111111) == 0b0111110) return "RESERVED"; // 0 111110 RESERVED + // if((key & 0b1111111) == 0b0111111) return "RESERVED"; // 0 111111 RESERVED + if ((key & 0b1000000) == 0b1000000) + return _1D; // 1 xxxxxx D + return 0; +} + +ArrangementSpec size_spec_method3(int x) +{ + if ((x & 0b01111) == 0b00000) + return ARRSPEC_NONE; // x0000 RESERVED + if ((x & 0b00001) == 0b00001) + return _1B; // xxxx1 B + if ((x & 0b00011) == 0b00010) + return _1H; // xxx10 H + if ((x & 0b00111) == 0b00100) + return _1S; // xx100 S + if ((x & 0b01111) == 0b01000) + return _1D; // x1000 D + return 0; +} + +ArrangementSpec table_b_h[2] = {_1B, _1H}; +ArrangementSpec table_s_d[2] = {_1S, _1D}; +ArrangementSpec table_b_d_h_s[4] = {_1B, _1D, _1H, _1S}; +ArrangementSpec table_b_h_s_d[4] = {_1B, _1H, _1S, _1D}; +ArrangementSpec table_d_b_h_s[4] = {_1D, _1B, _1H, _1S}; +ArrangementSpec table_q_h_s_d[4] = {_1Q, _1H, _1S, _1D}; +ArrangementSpec table_r_h_s_d[4] = {ARRSPEC_NONE, _1H, _1S, _1D}; +ArrangementSpec table_r_b_h_s[4] = {ARRSPEC_NONE, _1B, _1H, _1S}; +ArrangementSpec table_r_s_d_r[4] = {ARRSPEC_NONE, _1S, _1D, ARRSPEC_NONE}; + +//----------------------------------------------------------------------------- +// other tables +//----------------------------------------------------------------------------- + + +enum Condition table_cond[16] = {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}; +enum Condition table_cond_neg[16] = {COND_NE, COND_EQ, COND_CC, COND_CS, COND_PL, COND_MI, COND_VC, + COND_VS, COND_LS, COND_HI, COND_LT, COND_GE, COND_LE, COND_GT, COND_NV, COND_AL}; + +float table_imm8_to_float[256] = {2.000000000000000000e+00, 2.125000000000000000e+00, + 2.250000000000000000e+00, 2.375000000000000000e+00, 2.500000000000000000e+00, + 2.625000000000000000e+00, 2.750000000000000000e+00, 2.875000000000000000e+00, + 3.000000000000000000e+00, 3.125000000000000000e+00, 3.250000000000000000e+00, + 3.375000000000000000e+00, 3.500000000000000000e+00, 3.625000000000000000e+00, + 3.750000000000000000e+00, 3.875000000000000000e+00, 4.000000000000000000e+00, + 4.250000000000000000e+00, 4.500000000000000000e+00, 4.750000000000000000e+00, + 5.000000000000000000e+00, 5.250000000000000000e+00, 5.500000000000000000e+00, + 5.750000000000000000e+00, 6.000000000000000000e+00, 6.250000000000000000e+00, + 6.500000000000000000e+00, 6.750000000000000000e+00, 7.000000000000000000e+00, + 7.250000000000000000e+00, 7.500000000000000000e+00, 7.750000000000000000e+00, + 8.000000000000000000e+00, 8.500000000000000000e+00, 9.000000000000000000e+00, + 9.500000000000000000e+00, 1.000000000000000000e+01, 1.050000000000000000e+01, + 1.100000000000000000e+01, 1.150000000000000000e+01, 1.200000000000000000e+01, + 1.250000000000000000e+01, 1.300000000000000000e+01, 1.350000000000000000e+01, + 1.400000000000000000e+01, 1.450000000000000000e+01, 1.500000000000000000e+01, + 1.550000000000000000e+01, 1.600000000000000000e+01, 1.700000000000000000e+01, + 1.800000000000000000e+01, 1.900000000000000000e+01, 2.000000000000000000e+01, + 2.100000000000000000e+01, 2.200000000000000000e+01, 2.300000000000000000e+01, + 2.400000000000000000e+01, 2.500000000000000000e+01, 2.600000000000000000e+01, + 2.700000000000000000e+01, 2.800000000000000000e+01, 2.900000000000000000e+01, + 3.000000000000000000e+01, 3.100000000000000000e+01, 1.250000000000000000e-01, + 1.328125000000000000e-01, 1.406250000000000000e-01, 1.484375000000000000e-01, + 1.562500000000000000e-01, 1.640625000000000000e-01, 1.718750000000000000e-01, + 1.796875000000000000e-01, 1.875000000000000000e-01, 1.953125000000000000e-01, + 2.031250000000000000e-01, 2.109375000000000000e-01, 2.187500000000000000e-01, + 2.265625000000000000e-01, 2.343750000000000000e-01, 2.421875000000000000e-01, + 2.500000000000000000e-01, 2.656250000000000000e-01, 2.812500000000000000e-01, + 2.968750000000000000e-01, 3.125000000000000000e-01, 3.281250000000000000e-01, + 3.437500000000000000e-01, 3.593750000000000000e-01, 3.750000000000000000e-01, + 3.906250000000000000e-01, 4.062500000000000000e-01, 4.218750000000000000e-01, + 4.375000000000000000e-01, 4.531250000000000000e-01, 4.687500000000000000e-01, + 4.843750000000000000e-01, 5.000000000000000000e-01, 5.312500000000000000e-01, + 5.625000000000000000e-01, 5.937500000000000000e-01, 6.250000000000000000e-01, + 6.562500000000000000e-01, 6.875000000000000000e-01, 7.187500000000000000e-01, + 7.500000000000000000e-01, 7.812500000000000000e-01, 8.125000000000000000e-01, + 8.437500000000000000e-01, 8.750000000000000000e-01, 9.062500000000000000e-01, + 9.375000000000000000e-01, 9.687500000000000000e-01, 1.000000000000000000e+00, + 1.062500000000000000e+00, 1.125000000000000000e+00, 1.187500000000000000e+00, + 1.250000000000000000e+00, 1.312500000000000000e+00, 1.375000000000000000e+00, + 1.437500000000000000e+00, 1.500000000000000000e+00, 1.562500000000000000e+00, + 1.625000000000000000e+00, 1.687500000000000000e+00, 1.750000000000000000e+00, + 1.812500000000000000e+00, 1.875000000000000000e+00, 1.937500000000000000e+00, + -2.000000000000000000e+00, -2.125000000000000000e+00, -2.250000000000000000e+00, + -2.375000000000000000e+00, -2.500000000000000000e+00, -2.625000000000000000e+00, + -2.750000000000000000e+00, -2.875000000000000000e+00, -3.000000000000000000e+00, + -3.125000000000000000e+00, -3.250000000000000000e+00, -3.375000000000000000e+00, + -3.500000000000000000e+00, -3.625000000000000000e+00, -3.750000000000000000e+00, + -3.875000000000000000e+00, -4.000000000000000000e+00, -4.250000000000000000e+00, + -4.500000000000000000e+00, -4.750000000000000000e+00, -5.000000000000000000e+00, + -5.250000000000000000e+00, -5.500000000000000000e+00, -5.750000000000000000e+00, + -6.000000000000000000e+00, -6.250000000000000000e+00, -6.500000000000000000e+00, + -6.750000000000000000e+00, -7.000000000000000000e+00, -7.250000000000000000e+00, + -7.500000000000000000e+00, -7.750000000000000000e+00, -8.000000000000000000e+00, + -8.500000000000000000e+00, -9.000000000000000000e+00, -9.500000000000000000e+00, + -1.000000000000000000e+01, -1.050000000000000000e+01, -1.100000000000000000e+01, + -1.150000000000000000e+01, -1.200000000000000000e+01, -1.250000000000000000e+01, + -1.300000000000000000e+01, -1.350000000000000000e+01, -1.400000000000000000e+01, + -1.450000000000000000e+01, -1.500000000000000000e+01, -1.550000000000000000e+01, + -1.600000000000000000e+01, -1.700000000000000000e+01, -1.800000000000000000e+01, + -1.900000000000000000e+01, -2.000000000000000000e+01, -2.100000000000000000e+01, + -2.200000000000000000e+01, -2.300000000000000000e+01, -2.400000000000000000e+01, + -2.500000000000000000e+01, -2.600000000000000000e+01, -2.700000000000000000e+01, + -2.800000000000000000e+01, -2.900000000000000000e+01, -3.000000000000000000e+01, + -3.100000000000000000e+01, -1.250000000000000000e-01, -1.328125000000000000e-01, + -1.406250000000000000e-01, -1.484375000000000000e-01, -1.562500000000000000e-01, + -1.640625000000000000e-01, -1.718750000000000000e-01, -1.796875000000000000e-01, + -1.875000000000000000e-01, -1.953125000000000000e-01, -2.031250000000000000e-01, + -2.109375000000000000e-01, -2.187500000000000000e-01, -2.265625000000000000e-01, + -2.343750000000000000e-01, -2.421875000000000000e-01, -2.500000000000000000e-01, + -2.656250000000000000e-01, -2.812500000000000000e-01, -2.968750000000000000e-01, + -3.125000000000000000e-01, -3.281250000000000000e-01, -3.437500000000000000e-01, + -3.593750000000000000e-01, -3.750000000000000000e-01, -3.906250000000000000e-01, + -4.062500000000000000e-01, -4.218750000000000000e-01, -4.375000000000000000e-01, + -4.531250000000000000e-01, -4.687500000000000000e-01, -4.843750000000000000e-01, + -5.000000000000000000e-01, -5.312500000000000000e-01, -5.625000000000000000e-01, + -5.937500000000000000e-01, -6.250000000000000000e-01, -6.562500000000000000e-01, + -6.875000000000000000e-01, -7.187500000000000000e-01, -7.500000000000000000e-01, + -7.812500000000000000e-01, -8.125000000000000000e-01, -8.437500000000000000e-01, + -8.750000000000000000e-01, -9.062500000000000000e-01, -9.375000000000000000e-01, + -9.687500000000000000e-01, -1.000000000000000000e+00, -1.062500000000000000e+00, + -1.125000000000000000e+00, -1.187500000000000000e+00, -1.250000000000000000e+00, + -1.312500000000000000e+00, -1.375000000000000000e+00, -1.437500000000000000e+00, + -1.500000000000000000e+00, -1.562500000000000000e+00, -1.625000000000000000e+00, + -1.687500000000000000e+00, -1.750000000000000000e+00, -1.812500000000000000e+00, + -1.875000000000000000e+00, -1.937500000000000000e+00}; + +const char* reg_lookup_c[16] = {"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", + "c11", "c12", "c13", "c14", "c15"}; + +#define ABCDEFGH \ + ((ctx->a << 7) | (ctx->b << 6) | (ctx->c << 5) | (ctx->d << 4) | (ctx->e << 3) | (ctx->f << 2) | \ + (ctx->g << 1) | ctx->h) +#define IMMR ctx->immr +#define IMMS ctx->imms +#define INDEX ctx->index + +/* register operand macros */ +#define ADD_OPERAND_REG(REGSET, BASE, REGNUM) \ + instr->operands[i].operandClass = REG; \ + instr->operands[i].reg[0] = REG(REGSET, BASE, REGNUM); \ + i++; + +#define ADD_OPERAND_BT ADD_OPERAND_REG(REGSET_ZR, REG_B_BASE, ctx->t); + +#define ADD_OPERAND_DA ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->a); +#define ADD_OPERAND_DD ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); +#define ADD_OPERAND_DN ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->n); +#define ADD_OPERAND_DM ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->m); +#define ADD_OPERAND_DT ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->t); +#define ADD_OPERAND_DT1 ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->t); +#define ADD_OPERAND_DT2 ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->t2); + +#define ADD_OPERAND_HA ADD_OPERAND_REG(REGSET_ZR, REG_H_BASE, ctx->a); +#define ADD_OPERAND_HD ADD_OPERAND_REG(REGSET_ZR, REG_H_BASE, ctx->d); +#define ADD_OPERAND_HN ADD_OPERAND_REG(REGSET_ZR, REG_H_BASE, ctx->n); +#define ADD_OPERAND_HM ADD_OPERAND_REG(REGSET_ZR, REG_H_BASE, ctx->m); +#define ADD_OPERAND_HT ADD_OPERAND_REG(REGSET_ZR, REG_H_BASE, ctx->t); + +#define ADD_OPERAND_QA ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->a); +#define ADD_OPERAND_QD ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->d); +#define ADD_OPERAND_QDN ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->n); +#define ADD_OPERAND_QN ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->n); +#define ADD_OPERAND_QM ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->m); +#define ADD_OPERAND_QS ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->s); +#define ADD_OPERAND_QT ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->t); +#define ADD_OPERAND_QT1 ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->t); +#define ADD_OPERAND_QT2 ADD_OPERAND_REG(REGSET_ZR, REG_Q_BASE, ctx->t2); + +#define ADD_OPERAND_SA ADD_OPERAND_REG(REGSET_ZR, REG_S_BASE, ctx->a); +#define ADD_OPERAND_SD ADD_OPERAND_REG(REGSET_ZR, REG_S_BASE, ctx->d); +#define ADD_OPERAND_SN ADD_OPERAND_REG(REGSET_ZR, REG_S_BASE, ctx->n); +#define ADD_OPERAND_SM ADD_OPERAND_REG(REGSET_ZR, REG_S_BASE, ctx->m); +#define ADD_OPERAND_ST ADD_OPERAND_REG(REGSET_ZR, REG_S_BASE, ctx->t); +#define ADD_OPERAND_ST1 ADD_OPERAND_REG(REGSET_ZR, REG_S_BASE, ctx->t); +#define ADD_OPERAND_ST2 ADD_OPERAND_REG(REGSET_ZR, REG_S_BASE, ctx->t2); + +#define ADD_OPERAND_WA ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->a); +#define ADD_OPERAND_WD ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->d); +#define ADD_OPERAND_WDN ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->dn); +#define ADD_OPERAND_WN ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->n); +#define ADD_OPERAND_WM ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->m); +#define ADD_OPERAND_WS ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->s); +#define ADD_OPERAND_WT \ + ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->t); \ + ; +#define ADD_OPERAND_WT1 ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->t); +#define ADD_OPERAND_WT2 ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, ctx->t2); + +#define ADD_OPERAND_WS_PLUS_1 ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, (ctx->s + 1) % 32); +#define ADD_OPERAND_WT_PLUS_1 ADD_OPERAND_REG(REGSET_ZR, REG_W_BASE, (ctx->t + 1) % 32); + +#define ADD_OPERAND_WD_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->d); +#define ADD_OPERAND_WN_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->n); +#define ADD_OPERAND_WM_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->m); +#define ADD_OPERAND_WT_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->n); + +#define ADD_OPERAND_XA ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->a); +#define ADD_OPERAND_XD ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->d); +#define ADD_OPERAND_XDN ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->Rdn); +#define ADD_OPERAND_XN ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->n); +#define ADD_OPERAND_XM ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->m); +#define ADD_OPERAND_XS ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->s); +#define ADD_OPERAND_XT ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->t); +#define ADD_OPERAND_XT1 ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->t); +#define ADD_OPERAND_XT2 ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, ctx->t2); + +#define ADD_OPERAND_XS_PLUS_1 ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, (ctx->s + 1) % 32); +#define ADD_OPERAND_XT_PLUS_1 ADD_OPERAND_REG(REGSET_ZR, REG_X_BASE, (ctx->t + 1) % 32); + +#define ADD_OPERAND_XD_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->d); +#define ADD_OPERAND_XN_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->n); +#define ADD_OPERAND_XDN_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->n); +#define ADD_OPERAND_XM_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->m); +#define ADD_OPERAND_XT_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->t); +#define ADD_OPERAND_XT2_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->t2); + +#define ADD_OPERAND_ZD ADD_OPERAND_REG(REGSET_ZR, REG_Z_BASE, ctx->d); +#define ADD_OPERAND_ZM ADD_OPERAND_REG(REGSET_ZR, REG_Z_BASE, ctx->m); +#define ADD_OPERAND_ZN ADD_OPERAND_REG(REGSET_ZR, REG_Z_BASE, ctx->n); +#define ADD_OPERAND_ZT ADD_OPERAND_REG(REGSET_ZR, REG_Z_BASE, ctx->t); + +#define ADD_OPERAND_PRED_REG(REGNUM) ADD_OPERAND_REG(REGSET_ZR, REG_P_BASE, REGNUM); + +#define ADD_OPERAND_PRED_REG_T(REGNUM, ARR_SPEC) \ + ADD_OPERAND_PRED_REG(REGNUM); \ + instr->operands[i - 1].arrSpec = ARR_SPEC; + +#define ADD_OPERAND_PRED_REG_QUAL(REGNUM, QUALIFIER) \ + ADD_OPERAND_PRED_REG(REGNUM); \ + instr->operands[i - 1].pred_qual = QUALIFIER; + +/* indexed element */ +// .[{, #}] +#define ADD_INDEXED_ELEMENT(REGNUM, ARRSPEC, REGINDEX, IMM) \ + instr->operands[i].operandClass = INDEXED_ELEMENT; \ + instr->operands[i].reg[0] = REG(REGSET_ZR, REG_P_BASE, (REGNUM)); \ + instr->operands[i].arrSpec = (ARRSPEC); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, REG_W_BASE, (REGINDEX)); \ + instr->operands[i].immediate = (IMM); \ + i++ + +/* register indirect adder */ +#define ADD_OPERAND_MEM_REG(REGSET, BASE, REGNUM) \ + instr->operands[i].operandClass = MEM_REG; \ + instr->operands[i].reg[0] = REG(REGSET, BASE, REGNUM); \ + i++ + +#define ADD_OPERAND_MEM_XN_SP ADD_OPERAND_MEM_REG(REGSET_SP, REG_X_BASE, ctx->n); + +/* general register indirect + offset adder */ +// [{, #}] +#define ADD_OPERAND_MEM_REG_OFFSET(REGSET, BASE, REGNUM, OFFSET) \ + instr->operands[i].operandClass = MEM_OFFSET; \ + instr->operands[i].reg[0] = REG(REGSET, BASE, REGNUM); \ + instr->operands[i].immediate = OFFSET; \ + instr->operands[i].signedImm = 1; \ + i++; + +// [.X{, #}] +#define ADD_OPERAND_MEM_REG_OFFSET_T(REGSET, BASE, REGNUM, OFFSET, ARR_SPEC) \ + instr->operands[i].operandClass = MEM_OFFSET; \ + instr->operands[i].reg[0] = REG(REGSET, BASE, REGNUM); \ + instr->operands[i].arrSpec = ARR_SPEC; \ + instr->operands[i].immediate = OFFSET; \ + instr->operands[i].signedImm = 1; \ + i++; + +// [{, #, MUL VL}] +#define ADD_OPERAND_MEM_REG_OFFSET_VL(REGSET, BASE, REGNUM, OFFSET) \ + ADD_OPERAND_MEM_REG_OFFSET(REGSET, BASE, REGNUM, OFFSET); \ + instr->operands[i - 1].mul_vl = 1; + +/* general mem post index */ +// [], # +#define ADD_OPERAND_MEM_POST_INDEX(REGSET, BASE, REGNUM, OFFSET) \ + instr->operands[i].operandClass = MEM_POST_IDX; \ + instr->operands[i].reg[0] = REG(REGSET, BASE, REGNUM); \ + instr->operands[i].immediate = OFFSET; \ + instr->operands[i].signedImm = 1; + +// [], +#define ADD_OPERAND_MEM_POST_INDEX_REG(REGSET, BASE, REGNUM, REG_PIDX) \ + instr->operands[i].operandClass = MEM_POST_IDX; \ + instr->operands[i].reg[0] = REG(REGSET, BASE, REGNUM); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, REG_X_BASE, REG_PIDX); + +/* mem pre index */ +// [, #] +#define ADD_OPERAND_MEM_PRE_INDEX(REGSET, BASE, REGNUM, OFFSET) \ + instr->operands[i].operandClass = MEM_PRE_IDX; \ + instr->operands[i].reg[0] = REG(REGSET, BASE, REGNUM); \ + instr->operands[i].immediate = OFFSET; \ + instr->operands[i].signedImm = 1; + +/* mem extended */ +// [, ] +// [,{, LSL #0}] with optional LSL +#define ADD_OPERAND_MEM_EXTENDED(BASE, REGNUM0, REGNUM1) \ + instr->operands[i].operandClass = MEM_EXTENDED; \ + instr->operands[i].reg[0] = REG(REGSET_SP, REG_X_BASE, REGNUM0); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, BASE, REGNUM1); \ + i++; + +#define ADD_OPERAND_XN_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->n); +#define ADD_OPERAND_XM_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->m); +#define ADD_OPERAND_XT_SP ADD_OPERAND_REG(REGSET_SP, REG_X_BASE, ctx->t); + +#define ADD_OPERAND_WD_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->d); +#define ADD_OPERAND_WN_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->n); +#define ADD_OPERAND_WM_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->m); +#define ADD_OPERAND_WT_SP ADD_OPERAND_REG(REGSET_SP, REG_W_BASE, ctx->n); + +#define ADD_OPERAND_MEM_EXTENDED_T(BASE0, REGNUM0, BASE1, REGNUM1, ARR_SPEC) \ + instr->operands[i].operandClass = MEM_EXTENDED; \ + instr->operands[i].reg[0] = REG(REGSET_SP, BASE0, REGNUM0); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, BASE1, REGNUM1); \ + instr->operands[i].arrSpec = ARR_SPEC; \ + i++; + +#define ADD_OPERAND_MEM_EXTENDED_T_SHIFT( \ + BASE0, REGNUM0, SZ0, BASE1, REGNUM1, SZ1, SHIFT_TYPE, SHIFT_AMT, SHIFT_USED) \ + instr->operands[i].operandClass = MEM_EXTENDED; \ + instr->operands[i].reg[0] = REG(REGSET_SP, BASE0, REGNUM0); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, BASE1, REGNUM1); \ + instr->operands[i].arrSpec = SZ1; \ + instr->operands[i].shiftType = SHIFT_TYPE; \ + instr->operands[i].shiftValue = SHIFT_AMT; \ + instr->operands[i].shiftValueUsed = SHIFT_USED; \ + i += 1; + +/* general immediate operand adder */ +#define ADD_OPERAND_IMM32(VALUE, SIGNED) \ + instr->operands[i].operandClass = IMM32; \ + instr->operands[i].signedImm = SIGNED; \ + instr->operands[i].immediate = VALUE; \ + i++; + +#define ADD_OPERAND_IMM64(VALUE, SIGNED) \ + instr->operands[i].operandClass = IMM64; \ + instr->operands[i].signedImm = SIGNED; \ + instr->operands[i].immediate = VALUE; \ + i++; + +#define ADD_OPERAND_FLOAT32(VALUE) \ + instr->operands[i].operandClass = FIMM32; \ + *(float*)&(instr->operands[i].immediate) = VALUE; \ + i++; + +#define ADD_OPERAND_CONST ADD_OPERAND_IMM64(const_, 0) +#define ADD_OPERAND_FBITS ADD_OPERAND_IMM32(fbits, 0) +#define ADD_OPERAND_FIMM ADD_OPERAND_FLOAT32(fimm) +#define ADD_OPERAND_IMM0 ADD_OPERAND_IMM32(0, 0) +#define ADD_OPERAND_IMM1 ADD_OPERAND_IMM32(imm1, 0) +#define ADD_OPERAND_IMM2 ADD_OPERAND_IMM32(imm2, 0) +#define ADD_OPERAND_IMM6 ADD_OPERAND_IMM32(imm6, 0) +#define ADD_OPERAND_IMM8 ADD_OPERAND_IMM32(imm8, 0) +#define ADD_OPERAND_LSB ADD_OPERAND_IMM32(lsb, 0) +#define ADD_OPERAND_NZCV ADD_OPERAND_IMM32(ctx->nzcv, 0) +#define ADD_OPERAND_ROTATE ADD_OPERAND_IMM32(rotate, 0) +#define ADD_OPERAND_WIDTH ADD_OPERAND_IMM32(width, 0) + +//#define SEXT4(x) (x & 0x + +/* string immediate (like "mul #0x12") */ +#define ADD_OPERAND_STR_IMM(STRING, VALUE) \ + instr->operands[i].operandClass = STR_IMM; \ + instr->operands[i].immediate = VALUE; \ + instr->operands[i].signedImm = 0; \ + strcpy(instr->operands[i].name, STRING); \ + i++; + +/* specialized immediate operands */ +#define ADD_OPERAND_NAME(VALUE) \ + instr->operands[i].operandClass = NAME; \ + strcpy(instr->operands[i].name, VALUE); \ + i++; + +/* multi reg stuff, like {v0.b, v1.b} */ +#define ADD_OPERAND_MULTIREG_1(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + instr->operands[i].operandClass = MULTI_REG; \ + instr->operands[i].reg[0] = REG(REGSET_ZR, REG_BASE, REGNUM); \ + instr->operands[i].arrSpec = ARR_SPEC; \ + i++; + +#define ADD_OPERAND_MULTIREG_2(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + instr->operands[i].operandClass = MULTI_REG; \ + instr->operands[i].reg[0] = REG(REGSET_ZR, REG_BASE, REGNUM); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, REG_BASE, (REGNUM + 1) % 32); \ + instr->operands[i].arrSpec = ARR_SPEC; \ + i++; + +#define ADD_OPERAND_MULTIREG_3(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + instr->operands[i].operandClass = MULTI_REG; \ + instr->operands[i].reg[0] = REG(REGSET_ZR, REG_BASE, REGNUM); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, REG_BASE, (REGNUM + 1) % 32); \ + instr->operands[i].reg[2] = REG(REGSET_ZR, REG_BASE, (REGNUM + 2) % 32); \ + instr->operands[i].arrSpec = ARR_SPEC; \ + i++; + +#define ADD_OPERAND_MULTIREG_4(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + instr->operands[i].operandClass = MULTI_REG; \ + instr->operands[i].reg[0] = REG(REGSET_ZR, REG_BASE, REGNUM); \ + instr->operands[i].reg[1] = REG(REGSET_ZR, REG_BASE, (REGNUM + 1) % 32); \ + instr->operands[i].reg[2] = REG(REGSET_ZR, REG_BASE, (REGNUM + 2) % 32); \ + instr->operands[i].reg[3] = REG(REGSET_ZR, REG_BASE, (REGNUM + 3) % 32); \ + instr->operands[i].arrSpec = ARR_SPEC; \ + i++; + +#define ADD_OPERAND_MULTIREG_1_LANE(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + ADD_OPERAND_MULTIREG_1(REG_BASE, ARR_SPEC, REGNUM); \ + instr->operands[i - 1].laneUsed = 1; \ + instr->operands[i - 1].lane = ctx->index; + +#define ADD_OPERAND_MULTIREG_2_LANE(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + ADD_OPERAND_MULTIREG_2(REG_BASE, ARR_SPEC, REGNUM); \ + instr->operands[i - 1].laneUsed = 1; \ + instr->operands[i - 1].lane = ctx->index; + +#define ADD_OPERAND_MULTIREG_3_LANE(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + ADD_OPERAND_MULTIREG_3(REG_BASE, ARR_SPEC, REGNUM) \ + instr->operands[i - 1].laneUsed = 1; \ + instr->operands[i - 1].lane = ctx->index; + +#define ADD_OPERAND_MULTIREG_4_LANE(REG_BASE, ARR_SPEC, REGNUM) \ + ; \ + ADD_OPERAND_MULTIREG_4(REG_BASE, ARR_SPEC, REGNUM) \ + instr->operands[i - 1].laneUsed = 1; \ + instr->operands[i - 1].lane = ctx->index; + +/* v register plus ARRANGEMENT specifier: {1,2,4,8,16} x {b,h,s,d,q} */ +#define ADD_OPERAND_REG_T(BASE, ARR_SPEC, REGNUM) \ + instr->operands[i].operandClass = REG; \ + instr->operands[i].reg[0] = REG(REGSET_ZR, BASE, REGNUM); \ + instr->operands[i].arrSpec = ARR_SPEC; \ + i++; + +#define ADD_OPERAND_VREG_T(REGNUM, ARR_SPEC) ADD_OPERAND_REG_T(REG_V_BASE, ARR_SPEC, REGNUM) + +#define ADD_OPERAND_ZREG_T(REGNUM, ARR_SPEC) ADD_OPERAND_REG_T(REG_Z_BASE, ARR_SPEC, REGNUM) + +/* and with lane */ +#define ADD_OPERAND_VREG_T_LANE(REGNUM, ARR_SPEC, INDEX_VALUE) \ + ADD_OPERAND_VREG_T(REGNUM, ARR_SPEC) \ + instr->operands[i - 1].lane = INDEX_VALUE; \ + instr->operands[i - 1].laneUsed = 1; + +#define ADD_OPERAND_ZREG_T_LANE(REGNUM, ARR_SPEC, INDEX_VALUE) \ + ADD_OPERAND_ZREG_T(REGNUM, ARR_SPEC) \ + instr->operands[i - 1].lane = INDEX_VALUE; \ + instr->operands[i - 1].laneUsed = 1; + +/* */ +#define ADD_OPERAND_COND \ + instr->operands[i].operandClass = CONDITION; \ + instr->operands[i].cond = table_cond[ctx->condition]; \ + i++; + +#define ADD_OPERAND_COND_NEG \ + instr->operands[i].operandClass = CONDITION; \ + instr->operands[i].cond = table_cond_neg[ctx->condition]; \ + i++; + +#define ADD_OPERAND_LABEL \ + instr->operands[i].operandClass = LABEL; \ + instr->operands[i].immediate = eaddr; \ + i++; + +#define ADD_OPERAND_SYSTEMREG_IMPL_SPEC(SR) \ + instr->operands[i].operandClass = IMPLEMENTATION_SPECIFIC; \ + instr->operands[i].implspec[0] = ctx->sys_op0; \ + instr->operands[i].implspec[1] = ctx->sys_op1; \ + instr->operands[i].implspec[2] = ctx->sys_crn; \ + instr->operands[i].implspec[3] = ctx->sys_crm; \ + instr->operands[i].implspec[4] = ctx->sys_op2; \ + instr->operands[i].sysreg = (SR); \ + i++; + +#define ADD_OPERAND_SYSTEMREG(R) \ + instr->operands[i].operandClass = SYS_REG; \ + instr->operands[i].sysreg = (R); \ + i++; + +#define ADD_OPERAND_SYSTEMREG_SENSE \ + { \ + SystemReg sr = ((ctx->sys_op0 << 14) | (ctx->sys_op1 << 11) | (ctx->sys_crn << 7) | \ + (ctx->sys_crm << 3) | ctx->sys_op2); \ + const char* name = get_system_register_name(sr); \ + if (name[0]) \ + { \ + ADD_OPERAND_SYSTEMREG(sr); \ + } \ + else \ + { \ + ADD_OPERAND_SYSTEMREG_IMPL_SPEC(sr); \ + } \ + } + +#define ADD_OPERAND_PATTERN \ + if (ctx->pattern > 0b1101 && ctx->pattern < 0b11101) \ + { \ + ADD_OPERAND_IMM32(ctx->pattern, 0); \ + } \ + else \ + { \ + ADD_OPERAND_NAME(pattern_lookup(ctx->pattern, ctx->imm)); \ + } + +/* SME */ +#define ADD_OPERAND_SME_TILE(TILE_NUM, SLICE_INDICATOR, ARRSPEC, BASEREG, OFFSET) \ + instr->operands[i].operandClass = SME_TILE; \ + instr->operands[i].tile = (TILE_NUM); \ + instr->operands[i].slice = (SLICE_INDICATOR); \ + instr->operands[i].arrSpec = (ARRSPEC); \ + instr->operands[i].reg[0] = (BASEREG); \ + instr->operands[i].immediate = (OFFSET); \ + instr->operands[i].signedImm = 1; \ + i++; + +#define ADD_OPERAND_ACCUM_ARRAY(BASEREG, OFFSET) \ + instr->operands[i].operandClass = ACCUM_ARRAY; \ + instr->operands[i].reg[0] = (BASEREG); \ + instr->operands[i].immediate = (OFFSET); \ + i++; + +//----------------------------------------------------------------------------- +// register base lookups +//----------------------------------------------------------------------------- + +unsigned rwwwx_0123x_reg(int x, int r) +{ + if ((x & 0b01111) == 0b00000) + return 0; // x0000 RESERVED + if ((x & 0b00001) == 0b00001) + return REG_W_BASE; // xxxx1 W + if ((x & 0b00011) == 0b00010) + return REG_W_BASE; // xxx10 W + if ((x & 0b00111) == 0b00100) + return REG_W_BASE; // xx100 W + if ((x & 0b01111) == 0b01000) + return REG_X_BASE; // x1000 X + return 0; +} + +unsigned rbhsdq_5bit_reg(unsigned key) +{ + // if((key & 0b01111) == 0b00000) return 0; // x0000 RESERVED + if (key == 0) + return 0; // x0000 RESERVED + if ((key & 0b00001) == 0b00001) + return REG_B_BASE; // xxxx1 B + if ((key & 0b00011) == 0b00010) + return REG_H_BASE; // xxx10 H + if ((key & 0b00111) == 0b00100) + return REG_S_BASE; // xx100 S + if ((key & 0b01111) == 0b01000) + return REG_D_BASE; // xx100 D + if ((key & 0b11111) == 0b10000) + return REG_Q_BASE; // xx100 Q + return 0; +} + +unsigned wwwx_0123_reg(unsigned size) +{ + if (size == 0b11) + return REG_X_BASE; + return REG_W_BASE; +} + +unsigned sd_01_reg(int v) +{ + switch (v & 1) + { + case 0: + return REG_S_BASE; + case 1: + return REG_D_BASE; + } + return 0; +} + +// ,, +unsigned bhsd_0123_reg(int v) +{ + switch (v & 3) + { + case 0: + return REG_B_BASE; + case 1: + return REG_H_BASE; + case 2: + return REG_S_BASE; + case 3: + return REG_D_BASE; + } + return 0; +} + +unsigned rsdr_0123_reg(int v) +{ + switch (v & 3) + { + case 1: + return REG_S_BASE; + case 2: + return REG_D_BASE; + } + return 0; +} + +unsigned hsdr_0123_reg(int v) +{ + switch (v & 3) + { + case 0: + return REG_H_BASE; + case 1: + return REG_S_BASE; + case 2: + return REG_D_BASE; + default: + return 0; + } +} + +unsigned rhsd_0123_reg(int v) +{ + if (v == 1) + return REG_H_BASE; + if (v == 2) + return REG_S_BASE; + return 0; +} + +unsigned rhsd_0123x_reg(int v) +{ + // if(x & 0xE == 0) return 0; // 000x + if ((v & 0xE) == 2) + return REG_H_BASE; // 001x + if ((v & 0xC) == 4) + return REG_S_BASE; // 01xx + if ((v & 0x8) == 8) + return REG_D_BASE; // 1xxx + return 0; +} + +unsigned rbhsd_0123x_reg(int v) +{ // 0000 RESERVED + if (v == 1) + return REG_B_BASE; // 0001 B + if ((v & 0b1110) == 0b0010) + return REG_H_BASE; // 001x H + if ((v & 0b1100) == 0b0100) + return REG_S_BASE; // 01xx S + if ((v & 0b1000) == 0b1000) + return REG_D_BASE; // 1xxx D + return 0; +} + +unsigned rhsdr_0123x_reg(int v) +{ + if (v == 1) + return REG_H_BASE; + if ((v & 0b1110) == 0b0010) + return REG_S_BASE; + if ((v & 0b1100) == 0b0100) + return REG_D_BASE; + return 0; +} + +#define OPTIONAL_SHIFT_AMOUNT \ + if (!(ctx->shift_type == 1 && ctx->shift_amount == 0)) \ + { \ + instr->operands[i - 1].shiftType = ctx->shift_type; \ + instr->operands[i - 1].shiftValue = ctx->shift_amount; \ + instr->operands[i - 1].shiftValueUsed = 1; \ + } \ + else \ + { \ + instr->operands[i - 1].shiftValueUsed = 0; \ + } + +#define OPTIONAL_EXTEND_AMOUNT(SPECIAL_LSL) \ + instr->operands[i - 1].shiftType = ctx->extend_type; \ + instr->operands[i - 1].shiftValue = ctx->shift; \ + if (ctx->option == SPECIAL_LSL) \ + { \ + if (ctx->shift) \ + { \ + instr->operands[i - 1].shiftType = ShiftType_LSL; \ + instr->operands[i - 1].shiftValueUsed = 1; \ + } \ + else \ + instr->operands[i - 1].shiftType = ShiftType_NONE; \ + } \ + else \ + { \ + instr->operands[i - 1].shiftValueUsed = ctx->shift ? 1 : 0; \ + } + +#define OPTIONAL_EXTEND_AMOUNT_0 \ + instr->operands[i - 1].shiftType = ctx->extend_type; \ + instr->operands[i - 1].shiftValue = 0; \ + instr->operands[i - 1].shiftValueUsed = ctx->S ? 1 : 0; + +#define OPTIONAL_EXTEND_LSL0 \ + if (ctx->S) \ + { \ + instr->operands[i - 1].shiftType = ShiftType_LSL; \ + instr->operands[i - 1].shiftValue = 0; \ + instr->operands[i - 1].shiftValueUsed = 1; \ + } \ + else \ + instr->operands[i - 1].shiftType = ShiftType_NONE; + +#define OPTIONAL_EXTEND_AMOUNT_32(EXCEPTIONAL_REG) \ + ShiftType st = DecodeRegExtend(ctx->option); \ + if (st == ShiftType_UXTW) \ + { \ + if (EXCEPTIONAL_REG == 31 && ctx->imm3 != 0) \ + { \ + st = ShiftType_LSL; \ + } \ + } \ + instr->operands[i - 1].shiftType = st; \ + instr->operands[i - 1].shiftValue = ctx->shift; \ + if (ctx->shift) \ + { \ + instr->operands[i - 1].shiftValueUsed = 1; \ + } + +#define OPTIONAL_EXTEND_AMOUNT_64_BEHAVIOR0 \ + ShiftType st = DecodeRegExtend(ctx->option); \ + if (ctx->Rn == 31 && ctx->option == 3) \ + { \ + st = ShiftType_LSL; \ + if (ctx->imm3 == 0) \ + st = ShiftType_NONE; \ + } \ + if (st != ShiftType_NONE) \ + { \ + instr->operands[i - 1].shiftType = st; \ + instr->operands[i - 1].shiftValue = ctx->shift; \ + instr->operands[i - 1].shiftValueUsed = 1; \ + } \ + if (!ctx->shift) \ + { \ + instr->operands[i - 1].shiftValueUsed = 0; \ + } + +#define OPTIONAL_EXTEND_AMOUNT_64_BEHAVIOR1 \ + ShiftType st = DecodeRegExtend(ctx->option); \ + if ((ctx->Rd == 31 || ctx->Rn == 31) && ctx->option == 3) \ + { \ + st = ShiftType_LSL; \ + if (ctx->imm3 == 0) \ + st = ShiftType_NONE; \ + } \ + if (st != ShiftType_NONE) \ + { \ + instr->operands[i - 1].shiftType = st; \ + instr->operands[i - 1].shiftValue = ctx->shift; \ + instr->operands[i - 1].shiftValueUsed = 1; \ + } \ + if (!ctx->shift) \ + { \ + instr->operands[i - 1].shiftValueUsed = 0; \ + } + +#define LAST_OPERAND_SHIFT(SHIFT_TYPE, SHIFT_VALUE) \ + instr->operands[i - 1].shiftType = SHIFT_TYPE; \ + instr->operands[i - 1].shiftValue = SHIFT_VALUE; \ + instr->operands[i - 1].shiftValueUsed = 1; + +#define LAST_OPERAND_LSL_12 LAST_OPERAND_SHIFT(ShiftType_LSL, 12) + +#define ADD_OPERAND_OPTIONAL_PATTERN_MUL \ + { \ + bool print_mul = ctx->imm != 1; \ + bool print_pattern = print_mul || ctx->pattern != 0x1f; \ + if (print_pattern) \ + { \ + ADD_OPERAND_PATTERN; \ + } \ + if (print_mul) \ + { \ + ADD_OPERAND_STR_IMM("mul", ctx->imm); \ + } \ + } + +#define ADD_OPERAND_OPTIONAL_PATTERN \ + if (ctx->pattern != 0x1f) \ + { \ + ADD_OPERAND_PATTERN; \ + } + +/* convert the result of pcode execution to a human-friendly list of operands */ +int decode_scratchpad(context* ctx, Instruction* instr) +{ + ArrangementSpec arr_spec = _1B; + + /* index of operand array, as it's built */ + int i = 0; + + /* populate operation */ + instr->operation = enc_to_oper(instr->encoding); + + /* default to 0 operands */ + InstructionOperand zero = {0}; + for (uint32_t ii = 0; ii < MAX_OPERANDS; ++ii) + instr->operands[ii] = zero; + + switch (instr->encoding) + { + /* instrucitons with no operands */ + case ENC_AUTIA1716_HI_HINTS: + case ENC_AUTIASP_HI_HINTS: + case ENC_AUTIAZ_HI_HINTS: + case ENC_AUTIB1716_HI_HINTS: + case ENC_AUTIBSP_HI_HINTS: + case ENC_AUTIBZ_HI_HINTS: + case ENC_AXFLAG_M_PSTATE: + case ENC_CFINV_M_PSTATE: + case ENC_CSDB_HI_HINTS: + case ENC_DGH_HI_HINTS: + case ENC_DRPS_64E_BRANCH_REG: + case ENC_ERETAA_64E_BRANCH_REG: + case ENC_ERETAB_64E_BRANCH_REG: + case ENC_ERET_64E_BRANCH_REG: + case ENC_ESB_HI_HINTS: + case ENC_NOP_HI_HINTS: + case ENC_PACIA1716_HI_HINTS: + case ENC_PACIASP_HI_HINTS: + case ENC_PACIAZ_HI_HINTS: + case ENC_PACIB1716_HI_HINTS: + case ENC_PACIBSP_HI_HINTS: + case ENC_PACIBZ_HI_HINTS: + case ENC_RETAA_64E_BRANCH_REG: + case ENC_RETAB_64E_BRANCH_REG: + case ENC_SEVL_HI_HINTS: + case ENC_SEV_HI_HINTS: + case ENC_WFE_HI_HINTS: + case ENC_WFI_HI_HINTS: + case ENC_XAFLAG_M_PSTATE: + case ENC_XPACLRI_HI_HINTS: + case ENC_YIELD_HI_HINTS: + case ENC_SETFFR_F_: + // case ENC_SSBB_ONLY_BARRIERS: + // case ENC_PSSBB_ONLY_BARRIERS: + case ENC_SB_ONLY_BARRIERS: + case ENC_TCOMMIT_ONLY_BARRIERS: + case ENC_PSSBB_DSB_BO_BARRIERS: + case ENC_SSBB_DSB_BO_BARRIERS: + break; + case ENC_WFET_ONLY_SYSTEMINSTRSWITHREG: + case ENC_WFIT_ONLY_SYSTEMINSTRSWITHREG: + { + // + ADD_OPERAND_XD; + break; + } + case ENC_PSB_HC_HINTS: + case ENC_TSB_HC_HINTS: + { + ADD_OPERAND_NAME("csync"); + break; + } + case ENC_LDR_B_LDST_IMMPRE: + case ENC_STR_B_LDST_IMMPRE: + { + // , [, #]! + ADD_OPERAND_BT; + ADD_OPERAND_MEM_PRE_INDEX(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDR_B_LDST_REGOFF: + case ENC_STR_B_LDST_REGOFF: + { + int reg_base = table_wbase_xbase[ctx->option & 1]; + // , [, (|),{}] + ADD_OPERAND_BT; + ADD_OPERAND_MEM_EXTENDED(reg_base, ctx->n, ctx->m); + if (ctx->option & 1) + { + OPTIONAL_EXTEND_AMOUNT_32(3); + } + else + { + OPTIONAL_EXTEND_AMOUNT_64_BEHAVIOR1; + } + if (ctx->S) + { + OPTIONAL_EXTEND_AMOUNT_0 + } + break; + } + case ENC_LDR_BL_LDST_REGOFF: + case ENC_STR_BL_LDST_REGOFF: + { + // , [,{, LSL #0}] + ADD_OPERAND_BT; + ADD_OPERAND_MEM_EXTENDED(REG_X_BASE, ctx->n, ctx->m); + OPTIONAL_EXTEND_LSL0; + break; + } + case ENC_LDR_B_LDST_IMMPOST: + case ENC_STR_B_LDST_IMMPOST: + { + // , [], # + ADD_OPERAND_BT; + ADD_OPERAND_MEM_POST_INDEX(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDR_B_LDST_POS: + case ENC_STR_B_LDST_POS: + { + // , [{, #}] + ADD_OPERAND_BT; + ADD_OPERAND_MEM_REG_OFFSET(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDUR_B_LDST_UNSCALED: + case ENC_STUR_B_LDST_UNSCALED: + { + // , [{, #}] + ADD_OPERAND_BT; + ADD_OPERAND_MEM_REG_OFFSET(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_MOVI_ASIMDIMM_D_DS: // display as hex + { + uint64_t imm = ctx->imm; + //
, # + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->rd); + ADD_OPERAND_IMM64(imm, 0); + break; + } + case ENC_FMOV_D_FLOATIMM: // display as float + { + float fimm = table_imm8_to_float[ctx->imm8]; + //
, # + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_FIMM; + break; + } + case ENC_FABS_D_FLOATDP1: + case ENC_FMOV_D_FLOATDP1: + case ENC_FNEG_D_FLOATDP1: + case ENC_FRINT32X_D_FLOATDP1: + case ENC_FRINT32Z_D_FLOATDP1: + case ENC_FRINT64X_D_FLOATDP1: + case ENC_FRINT64Z_D_FLOATDP1: + case ENC_FRINTA_D_FLOATDP1: + case ENC_FRINTI_D_FLOATDP1: + case ENC_FRINTM_D_FLOATDP1: + case ENC_FRINTN_D_FLOATDP1: + case ENC_FRINTP_D_FLOATDP1: + case ENC_FRINTX_D_FLOATDP1: + case ENC_FRINTZ_D_FLOATDP1: + case ENC_FSQRT_D_FLOATDP1: + { + //
, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_DN; + break; + } + case ENC_FADD_D_FLOATDP2: + case ENC_FDIV_D_FLOATDP2: + case ENC_FMAXNM_D_FLOATDP2: + case ENC_FMAX_D_FLOATDP2: + case ENC_FMINNM_D_FLOATDP2: + case ENC_FMIN_D_FLOATDP2: + case ENC_FMUL_D_FLOATDP2: + case ENC_FNMUL_D_FLOATDP2: + case ENC_FSUB_D_FLOATDP2: + { + //
,, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_DN; + ADD_OPERAND_DM; + break; + } + case ENC_FMADD_D_FLOATDP3: + case ENC_FMSUB_D_FLOATDP3: + case ENC_FNMADD_D_FLOATDP3: + case ENC_FNMSUB_D_FLOATDP3: + { + //
,,, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_DN; + ADD_OPERAND_DM; + ADD_OPERAND_DA; + break; + } + case ENC_FCSEL_D_FLOATSEL: + { + //
,,, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_DN; + ADD_OPERAND_DM; + ADD_OPERAND_COND; + break; + } + case ENC_FCVT_DH_FLOATDP1: + { + //
, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_HN; + break; + } + case ENC_SADDV_R_P_Z_: + case ENC_UADDV_R_P_Z_: + { + ArrangementSpec arr_spec = table_b_h_s_d[ctx->size]; + //
,,. + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_PRED_REG(ctx->g); + ADD_OPERAND_ZREG_T(ctx->n, arr_spec) + break; + } + case ENC_FCVT_DS_FLOATDP1: + { + //
, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_SN; + break; + } + case ENC_SCVTF_D32_FLOAT2INT: + case ENC_UCVTF_D32_FLOAT2INT: + { + //
, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_WN; + break; + } + case ENC_SCVTF_D32_FLOAT2FIX: + case ENC_UCVTF_D32_FLOAT2FIX: + { + uint64_t fbits = ctx->fracbits; + //
,, # + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_WN; + ADD_OPERAND_FBITS; + break; + } + case ENC_FMOV_D64_FLOAT2INT: + case ENC_SCVTF_D64_FLOAT2INT: + case ENC_UCVTF_D64_FLOAT2INT: + { + //
, + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_XN; + break; + } + case ENC_SCVTF_D64_FLOAT2FIX: + case ENC_UCVTF_D64_FLOAT2FIX: + { + uint64_t fbits = ctx->fracbits; + //
,, # + ADD_OPERAND_REG(REGSET_ZR, REG_D_BASE, ctx->d); + ADD_OPERAND_XN; + ADD_OPERAND_FBITS; + break; + } + case ENC_FCMPE_DZ_FLOATCMP: + case ENC_FCMP_DZ_FLOATCMP: + { + // , #0.0 + ADD_OPERAND_DN; + ADD_OPERAND_FLOAT32(0); + break; + } + case ENC_FCMPE_D_FLOATCMP: + case ENC_FCMP_D_FLOATCMP: + { + // , + ADD_OPERAND_DN; + ADD_OPERAND_DM; + break; + } + case ENC_FCCMPE_D_FLOATCCMP: + case ENC_FCCMP_D_FLOATCCMP: + { + // ,, #, + ADD_OPERAND_DN; + ADD_OPERAND_DM; + ADD_OPERAND_NZCV; + ADD_OPERAND_COND; + break; + } + case ENC_LDP_D_LDSTPAIR_PRE: + case ENC_STP_D_LDSTPAIR_PRE: + { + // ,, [, #]! + ADD_OPERAND_DT1; + ADD_OPERAND_DT2; + ADD_OPERAND_MEM_PRE_INDEX(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDP_D_LDSTPAIR_POST: + case ENC_STP_D_LDSTPAIR_POST: + { + uint64_t imm = ctx->offset; + // ,, [], # + ADD_OPERAND_DT1; + ADD_OPERAND_DT2; + ADD_OPERAND_MEM_POST_INDEX(REGSET_SP, REG_X_BASE, ctx->n, imm); + break; + } + case ENC_LDNP_D_LDSTNAPAIR_OFFS: + case ENC_LDP_D_LDSTPAIR_OFF: + case ENC_STNP_D_LDSTNAPAIR_OFFS: + case ENC_STP_D_LDSTPAIR_OFF: + { + uint64_t imm = ctx->offset; + // ,, [{, #}] + ADD_OPERAND_DT1; + ADD_OPERAND_DT2; + ADD_OPERAND_MEM_REG_OFFSET(REGSET_SP, REG_X_BASE, ctx->n, imm); + break; + } + case ENC_LDR_D_LDST_IMMPRE: + case ENC_STR_D_LDST_IMMPRE: + { + //
, [, #]! + ADD_OPERAND_DT; + ADD_OPERAND_MEM_PRE_INDEX(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDR_D_LDST_REGOFF: + case ENC_STR_D_LDST_REGOFF: + { + int reg_base = table_wbase_xbase[ctx->option & 1]; + //
, [, (|){,{}}] + ADD_OPERAND_DT; + ADD_OPERAND_MEM_EXTENDED(reg_base, ctx->n, ctx->m); + OPTIONAL_EXTEND_AMOUNT(3); + break; + } + case ENC_LDR_D_LDST_IMMPOST: + case ENC_STR_D_LDST_IMMPOST: + { + //
, [], # + ADD_OPERAND_DT; + ADD_OPERAND_MEM_POST_INDEX(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDR_D_LDST_POS: + case ENC_STR_D_LDST_POS: + { + //
, [{, #}] + ADD_OPERAND_DT; + ADD_OPERAND_MEM_REG_OFFSET(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDUR_D_LDST_UNSCALED: + case ENC_STUR_D_LDST_UNSCALED: + { + //
, [{, #}] + ADD_OPERAND_DT; + ADD_OPERAND_MEM_REG_OFFSET(REGSET_SP, REG_X_BASE, ctx->n, ctx->offset); + break; + } + case ENC_LDR_D_LOADLIT: + { + uint64_t eaddr = ctx->address + ctx->offset; + //
,