summaryrefslogtreecommitdiff
path: root/arch/armv7/armv7_disasm
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2024-03-05 19:50:13 -0500
committerRusty Wagner <rusty.wagner@gmail.com>2024-03-05 20:34:34 -0500
commite093c21ed880ac3eb72119be15093ee04f8ce299 (patch)
tree9f720ebdc0ae415734b1199ed341668c69710a94 /arch/armv7/armv7_disasm
parent0609276712622908254065546102381466033141 (diff)
Move architecture modules into the API repo
Diffstat (limited to 'arch/armv7/armv7_disasm')
-rw-r--r--arch/armv7/armv7_disasm/armv7.c8478
-rw-r--r--arch/armv7/armv7_disasm/armv7.h959
-rw-r--r--arch/armv7/armv7_disasm/test.c38
-rwxr-xr-xarch/armv7/armv7_disasm/test.py1635
4 files changed, 11110 insertions, 0 deletions
diff --git a/arch/armv7/armv7_disasm/armv7.c b/arch/armv7/armv7_disasm/armv7.c
new file mode 100644
index 00000000..69ce44fb
--- /dev/null
+++ b/arch/armv7/armv7_disasm/armv7.c
@@ -0,0 +1,8478 @@
+#define _CRT_SECURE_NO_WARNINGS
+#include "armv7.h"
+
+#ifdef __cplusplus
+using namespace armv7;
+#endif
+
+uint32_t armv7_64_bit_transfers(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_branch_and_block_data_transfer(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_coprocessor_instruction_and_supervisor_call(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_data_processing_and_misc(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_data_processing_imm(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_data_processing_reg_shifted_reg(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_data_processing_reg(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_decompose(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address, uint32_t bigEndian);
+uint32_t armv7_extension_register_load_store(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_extra_load_store(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_extra_load_store_unprivilaged(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_floating_point_data_processing(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_halfword_multiply_and_accumulate(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_load_store_word_and_unsigned_byte(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_media_instructions(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_memory_hints_simd_and_misc(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_miscellaneous(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_msr_imm_and_hints(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_multiply_and_accumulate(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_one_register_and_modified_imm(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_parallel_add_sub_reversal(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_parallel_add_sub_signed(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_parallel_add_sub_udiv(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_parallel_add_sub_unsigned(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_saturating_add_sub(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_simd_data_processing(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_simd_load_store(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_synchronization_primitives(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_three_register_different(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_three_register_same(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_transfers(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_two_register_and_shift(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_two_register_misc(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_two_register_scalar(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+uint32_t armv7_unconditional(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+typedef uint32_t (*armv7_decompose_instruction)(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address);
+
+static Register regMap[2] = {REG_D0, REG_Q0};
+
+
+#define SET_REGISTER(x) (1<<((x)))
+#define DECODE_DT(s,u) (enum DataType)(1+((((u&1))<<2) | ((s)&3)))
+
+static const char* operationString[] = {
+ "UNDEFINED",
+ "UNPREDICTABLE",
+ "adc",
+ "adcs",
+ "add",
+ "adds",
+ "addw",
+ "adr",
+ "and",
+ "ands",
+ "asr",
+ "asrs",
+ "b",
+ "bfc",
+ "bfi",
+ "bic",
+ "bics",
+ "bkpt",
+ "bl",
+ "blx",
+ "bx",
+ "bxj",
+ "cbnz",
+ "cbz",
+ "cdp",
+ "cdp2",
+ "clrex",
+ "clz",
+ "cmn",
+ "cmp",
+ "cps",
+ "cpsid",
+ "cpsie",
+ "dbg",
+ "dmb",
+ "dsb",
+ "enterx",
+ "eor",
+ "eors",
+ "eret",
+ "fldmdbx",
+ "fldmiax",
+ "fstmdbx",
+ "fstmiax",
+ "fstmx",
+ "hint",
+ "hvc",
+ "isb",
+ "it",
+ "lda",
+ "ldab",
+ "ldah",
+ "ldaex", // A32
+ "ldaexb", // A32
+ "ldaexh", // A32
+ "ldaexd", // A32
+ "ldc",
+ "ldc2",
+ "ldc2l",
+ "ldcl",
+ "ldm",
+ "ldmda",
+ "ldmdb",
+ "ldmia",
+ "ldmib",
+ "ldr",
+ "ldrb",
+ "ldrbt",
+ "ldrd",
+ "ldrex",
+ "ldrexb",
+ "ldrexd",
+ "ldrexh",
+ "ldrh",
+ "ldrht",
+ "ldrsb",
+ "ldrsbt",
+ "ldrsh",
+ "ldrsht",
+ "ldrt",
+ "leavex",
+ "lsl",
+ "lsls",
+ "lsr",
+ "lsrs",
+ "mcr",
+ "mcr2",
+ "mcrr",
+ "mcrr2",
+ "mla",
+ "mls",
+ "mov",
+ "movs",
+ "movt",
+ "movw",
+ "mrc",
+ "mrc2",
+ "mrrc",
+ "mrrc2",
+ "mrs",
+ "msr",
+ "mul",
+ "muls",
+ "mvn",
+ "mvns",
+ "nop",
+ "orn",
+ "orr",
+ "orrs",
+ "pkhbt",
+ "pkhtb",
+ "pld",
+ "pldw",
+ "pli",
+ "pop",
+ "push",
+ "qadd",
+ "qadd16",
+ "qadd8",
+ "qasx",
+ "qdadd",
+ "qdsub",
+ "qsax",
+ "qsub",
+ "qsub16",
+ "qsub8",
+ "rbit",
+ "rev",
+ "rev16",
+ "revsh",
+ "rfe",
+ "rfeda",
+ "rfedb",
+ "rfeia",
+ "rfeib",
+ "ror",
+ "rors",
+ "rrx",
+ "rsb",
+ "rsbs",
+ "rsc",
+ "sadd16",
+ "sadd8",
+ "sasx",
+ "sbc",
+ "sbcs",
+ "sbfx",
+ "sdiv",
+ "sel",
+ "setend",
+ "sev",
+ "shadd16",
+ "shadd8",
+ "shasx",
+ "shsax",
+ "shsub16",
+ "shsub8",
+ "smc",
+ "smlabb",
+ "smlabt",
+ "smlad",
+ "smladx",
+ "smlal",
+ "smlalbb",
+ "smlalbt",
+ "smlald",
+ "smlaldx",
+ "smlaltb",
+ "smlaltt",
+ "smlatb",
+ "smlatt",
+ "smlawb",
+ "smlawt",
+ "smlsd",
+ "smlsdx",
+ "smlsld",
+ "smlsldx",
+ "smmla",
+ "smmlar",
+ "smmls",
+ "smmlsr",
+ "smmul",
+ "smmulr",
+ "smuad",
+ "smuadx",
+ "smulbb",
+ "smulbt",
+ "smull",
+ "smultb",
+ "smultt",
+ "smulwb",
+ "smulwt",
+ "smusd",
+ "smusdt",
+ "smusdx",
+ "srs",
+ "srsda",
+ "srsdb",
+ "srsia",
+ "srsib",
+ "ssat",
+ "ssat16",
+ "ssax",
+ "ssub16",
+ "ssub8",
+ "stc",
+ "stc2",
+ "stc2l",
+ "stcl",
+ "stl", // A32
+ "stlb",
+ "stlh",
+ "stlex", // A32
+ "stlexb", // A32
+ "stlexh", // A32
+ "stlexd", // A32
+ "stm",
+ "stmbd",
+ "stmda",
+ "stmdb",
+ "stmia",
+ "stmib",
+ "str",
+ "strb",
+ "strbt",
+ "strd",
+ "strex",
+ "strexb",
+ "strexd",
+ "strexh",
+ "strh",
+ "strht",
+ "strt",
+ "sub",
+ "subs",
+ "subw",
+ "svc",
+ "swp",
+ "swpb",
+ "sxtab",
+ "sxtab16",
+ "sxtah",
+ "sxtb",
+ "sxtb16",
+ "sxth",
+ "tbb",
+ "tbh",
+ "teq",
+ "trap",
+ "trt",
+ "tst",
+ "uadd16",
+ "uadd8",
+ "uasx",
+ "ubfx",
+ "udf",
+ "udiv",
+ "uhadd16",
+ "uhadd8",
+ "uhasx",
+ "uhsax",
+ "uhsub16",
+ "uhsub8",
+ "umaal",
+ "umlal",
+ "umull",
+ "uqadd16",
+ "uqadd8",
+ "uqasx",
+ "uqsax",
+ "uqsub16",
+ "uqsub8",
+ "usad8",
+ "usada8",
+ "usat",
+ "usat16",
+ "usax",
+ "usub16",
+ "usub8",
+ "uxtab",
+ "uxtab16",
+ "uxtah",
+ "uxtb",
+ "uxtb16",
+ "uxth",
+ "vaba",
+ "vabal",
+ "vabd",
+ "vabdl",
+ "vabs",
+ "vacge",
+ "vacgt",
+ "vadd",
+ "vaddhn",
+ "vaddl",
+ "vaddw",
+ "vand",
+ "vbic",
+ "vbif",
+ "vbit",
+ "vbsl",
+ "vceq",
+ "vcge",
+ "vcgt",
+ "vcle",
+ "vcls",
+ "vclt",
+ "vclz",
+ "vcmp",
+ "vcmpe",
+ "vcnt",
+ "vcvt",
+ "vcvta",
+ "vcvtb",
+ "vcvtm",
+ "vcvtn",
+ "vcvtp",
+ "vcvtr",
+ "vcvtt",
+ "vdiv",
+ "vdup",
+ "veor",
+ "vext",
+ "vfma",
+ "vfms",
+ "vfnma",
+ "vfnms",
+ "vhadd",
+ "vhsub",
+ "vld1",
+ "vld2",
+ "vld3",
+ "vld4",
+ "vldm",
+ "vldmdb",
+ "vldmia",
+ "vldr",
+ "vmax",
+ "vmaxnm",
+ "vmin",
+ "vminm",
+ "vmla",
+ "vmlal",
+ "vmls",
+ "vmlsl",
+ "vmov",
+ "vmovl",
+ "vmovn",
+ "vmrs",
+ "vmsr",
+ "vmul",
+ "vmull",
+ "vmvn",
+ "vneg",
+ "vnmla",
+ "vnmls",
+ "vnmul",
+ "vorn",
+ "vorr",
+ "vpadal",
+ "vpadd",
+ "vpaddl",
+ "vpmax",
+ "vpmin",
+ "vpop",
+ "vpush",
+ "vqabs",
+ "vqadd",
+ "vqdmlal",
+ "vqdmlsl",
+ "vqdmulh",
+ "vqdmull",
+ "vqmovn",
+ "vqmovun",
+ "vqneg",
+ "vqrdmulh",
+ "vqrshl",
+ "vqrshrn",
+ "vqrshrun",
+ "vqshl",
+ "vqshlu",
+ "vqshrn",
+ "vqshrun",
+ "vqsub",
+ "vraddhn",
+ "vrecpe",
+ "vrecps",
+ "vrev16",
+ "vrev32",
+ "vrev64",
+ "vrhadd",
+ "vrhsub",
+ "vrinta",
+ "vrintm",
+ "vrintn",
+ "vrintp",
+ "vrintr",
+ "vrintx",
+ "vrintz",
+ "vrshl",
+ "vrshr",
+ "vrshrn",
+ "vrsqrte",
+ "vrsqrts",
+ "vrsra",
+ "vrsubhn",
+ "vsel",
+ "vshl",
+ "vshll",
+ "vshr",
+ "vshrn",
+ "vsli",
+ "vsqrt",
+ "vsra",
+ "vsri",
+ "vst1",
+ "vst2",
+ "vst3",
+ "vst4",
+ "vstm",
+ "vstmdb",
+ "vstmia",
+ "vstr",
+ "vsub",
+ "vsubhn",
+ "vsubl",
+ "vsubw",
+ "vswp",
+ "vtbl",
+ "vtbx",
+ "vtrn",
+ "vtst",
+ "vuzp",
+ "vzip",
+ "wfe",
+ "wfi",
+ "yield"
+};
+
+static const char* registerString[] = {
+ "r0",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ "r6",
+ "r7",
+ "r8",
+ "r9",
+ "r10",
+ "r11",
+ "r12",
+ // "sb",
+ // "sl",
+ // "fp",
+ // "ip",
+ "sp",
+ "lr",
+ "pc",
+ "s0",
+ "s1",
+ "s2",
+ "s3",
+ "s4",
+ "s5",
+ "s6",
+ "s7",
+ "s8",
+ "s9",
+ "s10",
+ "s11",
+ "s12",
+ "s13",
+ "s14",
+ "s15",
+ "s16",
+ "s17",
+ "s18",
+ "s19",
+ "s20",
+ "s21",
+ "s22",
+ "s23",
+ "s24",
+ "s25",
+ "s26",
+ "s27",
+ "s28",
+ "s29",
+ "s30",
+ "s31",
+ "d0",
+ "d1",
+ "d2",
+ "d3",
+ "d4",
+ "d5",
+ "d6",
+ "d7",
+ "d8",
+ "d9",
+ "d10",
+ "d11",
+ "d12",
+ "d13",
+ "d14",
+ "d15",
+ "d16",
+ "d17",
+ "d18",
+ "d19",
+ "d20",
+ "d21",
+ "d22",
+ "d23",
+ "d24",
+ "d25",
+ "d26",
+ "d27",
+ "d28",
+ "d29",
+ "d30",
+ "d31",
+ "q0",
+ "q1",
+ "q2",
+ "q3",
+ "q4",
+ "q5",
+ "q6",
+ "q7",
+ "q8",
+ "q9",
+ "q10",
+ "q11",
+ "q12",
+ "q13",
+ "q14",
+ "q15",
+
+ /* banked regs */
+ "elr_hyp",
+ "lr_abt",
+ "lr_fiq",
+ "lr_irq",
+ "lr_mon",
+ "lr_svc",
+ "lr_und",
+ "lr_usr",
+ "r10_fiq",
+ "r10_usr",
+ "r11_fiq",
+ "r11_usr",
+ "r12_fiq",
+ "r12_usr",
+ "r8_fiq",
+ "r8_usr",
+ "r9_fiq",
+ "r9_usr",
+ "spsr_abt",
+ "spsr_fiq",
+ "spsr_hyp",
+ "spsr_irq",
+ "spsr_mon",
+ "spsr_svc",
+ "spsr_und",
+ "sp_abt",
+ "sp_fiq",
+ "sp_hyp",
+ "sp_irq",
+ "sp_mon",
+ "sp_svc",
+ "sp_und",
+ "sp_usr",
+
+ /* special regs */
+ "apsr",
+ "apsr_g",
+ "apsr_nzcvq",
+ "apsr_nzcvqg",
+ "cpsr",
+ "cpsr_c",
+ "cpsr_x",
+ "cpsr_xc",
+ "cpsr_s",
+ "cpsr_sc",
+ "cpsr_sx",
+ "cpsr_sxc",
+ "cpsr_f",
+ "cpsr_fc",
+ "cpsr_fx",
+ "cpsr_fxc",
+ "cpsr_fs",
+ "cpsr_fsc",
+ "cpsr_fsx",
+ "cpsr_fsxc",
+ "spsr",
+ "spsr_c",
+ "spsr_x",
+ "spsr_xc",
+ "spsr_s",
+ "spsr_sc",
+ "spsr_sx",
+ "spsr_sxc",
+ "spsr_f",
+ "spsr_fc",
+ "spsr_fx",
+ "spsr_fxc",
+ "spsr_fs",
+ "spsr_fsc",
+ "spsr_fsx",
+ "spsr_fsxc",
+ "apsr_nzcv",
+ "fpsid", // 0
+ "fpscr", // 1
+ "mvfr2", // 5
+ "mvfr1", // 6
+ "mvfr0", // 7
+ "fpexc", // 8
+ "fpinst", // 9
+ "fpinst2", //10
+ "msp",
+ "psp",
+ "primask",
+ "basepri",
+ "faultmask",
+ "control",
+
+ /* invalid */
+ ""
+};
+
+static const char* coprocRegisterCString[] = {
+ "c0",
+ "c1",
+ "c2",
+ "c3",
+ "c4",
+ "c5",
+ "c6",
+ "c7",
+ "c8",
+ "c9",
+ "c10",
+ "c11",
+ "c12",
+ "c13",
+ "c14",
+ "c15",
+};
+
+static const char* coprocRegisterString[] = {
+ "p0",
+ "p1",
+ "p2",
+ "p3",
+ "p4",
+ "p5",
+ "p6",
+ "p7",
+ "p8",
+ "p9",
+ "p10",
+ "p11",
+ "p12",
+ "p13",
+ "p14",
+ "p15",
+};
+
+static const char* condString[] = {
+ "eq",
+ "ne",
+ "hs",
+ "lo",
+ "mi",
+ "pl",
+ "vs",
+ "vc",
+ "hi",
+ "ls",
+ "ge",
+ "lt",
+ "gt",
+ "le",
+ "", //COND_NONE
+ "", //COND_NONE2
+};
+
+static const char* iflagStrings[] = {
+ "none",
+ "f",
+ "i",
+ "if",
+ "a",
+ "af",
+ "ai",
+ "aif"
+};
+
+static const char* endianSpecStrings[] = {
+ "le", "be"
+};
+
+static const char* dsbOptionStrings[] = {
+ "",
+ "oshld", // 1
+ "oshst", // 2
+ "osh", // 3
+ "",
+ "nshld", // 5
+ "nshst", // 6
+ "nsh", // 7
+ "",
+ "ishld", // 9
+ "ishst", // 10
+ "ish", // 11
+ "",
+ "ld", // 13
+ "st", // 14
+ "sy", // 15
+};
+
+static const char* shiftString[] = {
+ "", //SHIFT_NONE
+ "lsl",
+ "lsr",
+ "asr",
+ "ror",
+ "rrx"
+};
+
+static const char* dataTypeString[] = {
+ "",
+ ".s8",
+ ".s16",
+ ".s32",
+ ".s64",
+ ".u8",
+ ".u16",
+ ".u32",
+ ".u64",
+ ".i8",
+ ".i16",
+ ".i32",
+ ".i64",
+ ".f16",
+ ".f32",
+ ".f64",
+ ".p8",
+ ".p16",
+ ".p32",
+ ".p64",
+ ".8",
+ ".16",
+ ".32",
+ ".64"
+};
+
+uint32_t simdExpandImm(uint32_t op, uint32_t cmode, uint64_t imm8, uint64_t* result, DataType* dt, OperandClass* cls)
+{
+ uint32_t testImm = 0;
+ imm8 &= 0xff;
+ static uint8_t repBit[2] = {0x00,0xff};
+ *cls = IMM;
+ switch ((cmode >> 1) & 7)
+ {
+ case 0:
+ testImm = 0;
+ *result = (imm8 << 32) | imm8;
+ *dt = DT_I32;
+ break;
+ case 1:
+ testImm = 1;
+ *result = (imm8 << 40) | (imm8 << 8);
+ *dt = DT_I32;
+ break;
+ case 2:
+ testImm = 1;
+ *result = (imm8 << 48) | (imm8 << 16);
+ *dt = DT_I32;
+ break;
+ case 3:
+ testImm = 1;
+ *result = (imm8 << 56) | (imm8 << 24);
+ *dt = DT_I32;
+ break;
+ case 4:
+ testImm = 0;
+ *result = (imm8 << 48) | (imm8 << 32) | (imm8 << 16) | imm8;
+ *dt = DT_I16;
+ break;
+ case 5:
+ testImm = 1;
+ *result = (imm8 << 56) | (imm8 << 40) | (imm8 << 24) | (imm8 << 8);
+ *dt = DT_I16;
+ break;
+ case 6:
+ testImm = 1;
+ *dt = DT_I32;
+ if ((cmode & 1) == 0)
+ *result = (((imm8 << 8) | 0xff) << 32) | ((imm8 << 8) | 0xff);
+ else
+ *result = (((imm8 << 16) | 0xffff) << 32) | ((imm8 << 16) | 0xffff);
+ break;
+ case 7:
+ testImm = 0;
+ if ((cmode & 1) == 0)
+ {
+ if (op == 0)
+ {
+ *dt = DT_I8;
+ *result = (imm8 << 56) | (imm8 << 48) | (imm8 << 40) | (imm8 << 32) |
+ (imm8 << 24) | (imm8 << 16) | (imm8 << 8) | imm8;
+ }
+ else
+ {
+ *dt = DT_I64;
+ *cls = IMM64;
+ *result = ((uint64_t) repBit[imm8 & 1]) |
+ (((uint64_t)repBit[(imm8 >> 1) & 1]) << 8) |
+ (((uint64_t)repBit[(imm8 >> 2) & 1]) << 16) |
+ (((uint64_t)repBit[(imm8 >> 3) & 1]) << 24) |
+ (((uint64_t)repBit[(imm8 >> 4) & 1]) << 32) |
+ (((uint64_t)repBit[(imm8 >> 5) & 1]) << 40) |
+ (((uint64_t)repBit[(imm8 >> 6) & 1]) << 48) |
+ (((uint64_t)repBit[(imm8 >> 7) & 1]) << 56);
+ }
+ }
+ else
+ {
+ if (op == 0)
+ {
+ *dt = DT_F32;
+ //imm32 = imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,5):imm8<5:0>:Zeros(19);
+ //imm64 = Replicate(imm32, 2);
+ *result = ((imm8 & 0x3f) << 19) | //19 + 6 bits
+ ((repBit[(imm8 >> 6) & 1] & 0x1f) << 25)| //5 bits
+ (~((imm8 >> 6) & 1) << 30) | //1 bit
+ (((imm8 >> 7) & 1) << 31); //1 bit
+ *result = (*result << 32) | *result;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ if (testImm == 1 && imm8 == 0)
+ return 0;
+ return 1;
+}
+
+uint64_t VFPExpandImm64(uint64_t imm8)
+{
+ ieee754_double t;
+ uint64_t bit6 = (imm8>>6) & 1;
+ uint64_t bit54 = (imm8>>4) & 3;
+ uint64_t x = bit6?0xff:0;
+
+ t.sign = imm8>>7;
+ t.exponent = (~bit6) << 10 | x << 2 | bit54;
+ t.fraction = (imm8 & 0xf) << 48;
+ return t.value;
+}
+
+uint32_t VFPExpandImm32(uint32_t imm8)
+{
+ ieee754 t;
+ uint32_t bit6 = (imm8>>6) & 1;
+ uint32_t bit54 = (imm8>>4) & 3;
+ uint32_t x = bit6?0x1f:0;
+
+ t.sign = imm8>>7;
+ t.exponent = (~bit6) << 7 | x << 2 | bit54;
+ t.fraction = (imm8 & 0xf) << 19;
+ return t.value;
+}
+
+Shift DecodeRegisterShift(uint32_t type)
+{
+ return (Shift)((type&3)+1);
+}
+uint32_t DecodeImmShift(uint32_t type, uint32_t imm, Shift* shift)
+{
+ /*
+ * (SRType, integer) DecodeImmShift(bits(2) type, bits(5) imm5)
+ * case type of
+ * when ‘00’
+ * shift_t = SRType_LSL;
+ * shift_n = UInt(imm5);
+ * when ‘01’
+ * shift_t = SRType_LSR;
+ * shift_n = if imm5 == ‘00000’ then 32 else UInt(imm5);
+ * when ‘10’
+ * shift_t = SRType_ASR;
+ * shift_n = if imm5 == ‘00000’ then 32 else UInt(imm5);
+ * when ‘11’
+ * if imm5 == ‘00000’ then
+ * shift_t = SRType_RRX; shift_n = 1;
+ * else
+ * shift_t = SRType_ROR; shift_n = UInt(imm5);
+ * return (shift_t, shift_n);
+ *
+ */
+
+ switch (type & 3)
+ {
+ case 0:
+ *shift = imm==0?SHIFT_NONE:SHIFT_LSL;
+ return imm;
+ case 1:
+ *shift = SHIFT_LSR;
+ return imm == 0 ? 32 : imm;
+ case 2:
+ *shift = SHIFT_ASR;
+ return imm == 0 ? 32 : imm;
+ case 3:
+ if (imm == 0)
+ {
+ *shift = SHIFT_RRX;
+ return 1;
+ }
+ else
+ {
+ *shift = SHIFT_ROR;
+ return imm;
+ }
+ }
+ return 0;
+}
+
+
+uint32_t ExpandImm(uint32_t imm)
+{
+ uint32_t base = imm & 0xff;
+ uint32_t rot = 2 * (imm >> 8);
+ return (base >> rot) | (base << (32-rot));
+}
+
+
+uint32_t bswap32(uint32_t x)
+{
+ return ((x << 24) & 0xff000000 ) |
+ ((x << 8) & 0x00ff0000 ) |
+ ((x >> 8) & 0x0000ff00 ) |
+ ((x >> 24) & 0x000000ff );
+}
+
+
+uint32_t armv7_decompose(uint32_t instructionValue,
+ Instruction* restrict instruction,
+ uint32_t address,
+ uint32_t bigEndian)
+{
+ /* A5.1 ARM instruction set encoding */
+ union {
+ struct {
+ uint32_t group2:4;
+ uint32_t op:1;
+ uint32_t group1:20;
+ uint32_t op1:3;
+ uint32_t cond:4;
+ };
+ uint32_t value;
+ } decode;
+
+ if (bigEndian)
+ decode.value = bswap32(instructionValue);
+ else
+ decode.value = instructionValue;
+
+ //Decompose the instructionValue into its various groups
+ static armv7_decompose_instruction group[2][8][2] = {
+ {
+ {armv7_data_processing_and_misc, armv7_data_processing_and_misc},
+ {armv7_data_processing_and_misc, armv7_data_processing_and_misc},
+ {armv7_load_store_word_and_unsigned_byte, armv7_load_store_word_and_unsigned_byte},
+ {armv7_load_store_word_and_unsigned_byte, armv7_media_instructions},
+ {armv7_branch_and_block_data_transfer, armv7_branch_and_block_data_transfer},
+ {armv7_branch_and_block_data_transfer, armv7_branch_and_block_data_transfer},
+ {armv7_coprocessor_instruction_and_supervisor_call, armv7_coprocessor_instruction_and_supervisor_call},
+ {armv7_coprocessor_instruction_and_supervisor_call, armv7_coprocessor_instruction_and_supervisor_call}
+ },{
+ {armv7_unconditional, armv7_unconditional},
+ {armv7_unconditional, armv7_unconditional},
+ {armv7_unconditional, armv7_unconditional},
+ {armv7_unconditional, armv7_unconditional},
+ {armv7_unconditional, armv7_unconditional},
+ {armv7_unconditional, armv7_unconditional},
+ {armv7_unconditional, armv7_unconditional},
+ {armv7_unconditional, armv7_unconditional},
+ }
+ };
+ return group[decode.cond == 15][decode.op1][decode.op](decode.value, instruction, address);
+}
+
+uint32_t armv7_data_processing_and_misc(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2 Data-processing and miscellaneous instructions */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t op2:4;
+ uint32_t group2:12;
+ uint32_t op1:5;
+ uint32_t op:1;
+ uint32_t id:2;
+ uint32_t cond:4;
+ };
+ } decode;
+
+ decode.value = instructionValue;
+ if (decode.op == 0)
+ {
+ if ((decode.op1 & 0x19) == 0x10) //10xx0
+ {
+ if ((decode.op2 & 8) == 0)
+ return armv7_miscellaneous(instructionValue, instruction, address);
+ else if ((decode.op2 & 9) == 8)
+ return armv7_halfword_multiply_and_accumulate(instructionValue, instruction, address);
+ }
+ else // !10xx0
+ {
+ if ((decode.op2 & 1) == 0)
+ {
+ return armv7_data_processing_reg(instructionValue, instruction, address);
+ }
+ else if ((decode.op2 & 9) == 1)
+ {
+ return armv7_data_processing_reg_shifted_reg(instructionValue, instruction, address);
+ }
+ }
+
+ if ((decode.op1 & 0x10) == 0 && decode.op2 == 9) //0xxxx
+ return armv7_multiply_and_accumulate(instructionValue, instruction, address);
+ else if ((decode.op1 & 0x10) == 0x10 && decode.op2 == 9) //1xxxx
+ return armv7_synchronization_primitives(instructionValue, instruction, address);
+
+ if ((decode.op1 & 0x12) == 2) //0xx1x
+ {
+ if (decode.op2 == 11)
+ return armv7_extra_load_store_unprivilaged(instructionValue, instruction, address);
+ }
+ else //!0xx1x
+ {
+ if (decode.op2 == 11 || (decode.op2 & 13) == 13)
+ return armv7_extra_load_store(instructionValue, instruction, address);
+ }
+
+ if ((decode.op1 & 0x13) == 2 && (decode.op2 & 13) == 13) //0xx10
+ {
+ return armv7_extra_load_store(instructionValue, instruction, address);
+ }
+
+ if ((decode.op1 & 0x13) == 3 && (decode.op2 & 13) == 13) //0xx11
+ {
+ return armv7_extra_load_store_unprivilaged(instructionValue, instruction, address);
+ }
+ return 1;
+ }
+ else if (decode.op == 1)
+ {
+ if ((decode.op1 & 0x19) != 0x10)
+ {
+ return armv7_data_processing_imm(instructionValue, instruction, address);
+ }
+ else
+ {
+ switch (decode.op1)
+ {
+ case 0x10:
+ {
+ //MOV instruction
+ union {
+ uint32_t value;
+ struct {
+ uint32_t imm12:12;
+ uint32_t rd:4;
+ uint32_t imm4:4;
+ uint32_t s:1;
+ uint32_t group2:7;
+ uint32_t cond:4;
+ };
+ } decode2;
+ decode2.value = instructionValue;
+ instruction->operation = ARMV7_MOVW;
+ instruction->cond = (enum Condition)decode2.cond;
+ instruction->setsFlags = 0; //decode2.s;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode2.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode2.imm4 << 12 | decode2.imm12;
+ return 0;
+ }
+ case 0x14:
+ {
+ //MOVT instruction
+ union {
+ uint32_t value;
+ struct {
+ uint32_t imm12:12;
+ uint32_t rd:4;
+ uint32_t imm4:4;
+ uint32_t group2:8;
+ uint32_t cond:4;
+ };
+ } decode2;
+ decode2.value = instructionValue;
+ instruction->operation = ARMV7_MOVT;
+ instruction->cond = (enum Condition)decode2.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode2.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = (decode2.imm4 << 12) | decode2.imm12;
+ return 0;
+ }
+ case 0x12:
+ case 0x16:
+ return armv7_msr_imm_and_hints(instructionValue, instruction, address);
+ default:
+ return armv7_data_processing_imm(instructionValue, instruction, address);
+ }
+ }
+ }
+ return 1;
+}
+
+uint32_t armv7_data_processing_reg(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.1 Data-processing (register) */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rm:4;
+ uint32_t zero:1;
+ uint32_t type:2;
+ uint32_t imm5:5;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t s:1;
+ uint32_t op:4;
+ uint32_t group3:3;
+ uint32_t cond:4;
+ };
+ } decode;
+
+ struct opInfo {
+ Operation op;
+ uint32_t type;
+ };
+ static struct opInfo operation[] = {
+ {ARMV7_AND, 0},
+ {ARMV7_EOR, 0},
+ {ARMV7_SUB, 0},
+ {ARMV7_RSB, 0},
+ {ARMV7_ADD, 0},
+ {ARMV7_ADC, 0},
+ {ARMV7_SBC, 0},
+ {ARMV7_RSC, 0},
+ {ARMV7_TST, 1},
+ {ARMV7_TEQ, 1},
+ {ARMV7_CMP, 1},
+ {ARMV7_CMN, 1},
+ {ARMV7_ORR, 0},
+ {ARMV7_MOV, 2},
+ {ARMV7_BIC, 0},
+ {ARMV7_MVN, 3}
+ };
+
+ /* AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * RSC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
+ * TST<c> <Rn>, <Rm>{, <shift>}
+ * TEQ<c> <Rn>, <Rm>{, <shift>}
+ * CMP<c> <Rn>, <Rm>{, <shift>}
+ * CMN<c> <Rn>, <Rm>{, <shift>}
+ * LSL{S}<c> <Rd>, <Rm>, #<imm5>
+ * LSR{S}<c> <Rd>, <Rm>, #<imm>
+ * ASR{S}<c> <Rd>, <Rm>, #<imm>
+ * ROR{S}<c> <Rd>, <Rm>, #<imm>
+ * RRX{S}<c> <Rd>, <Rm>
+ * MOV{S}<c> <Rd>, <Rm>
+ * MVN{S}<c> <Rd>, <Rm>{, <shift>}
+ */
+ decode.value = instructionValue;
+ struct opInfo* info = &operation[decode.op];
+ enum Shift dummy;
+ instruction->operation = info->op;
+ instruction->cond = (enum Condition)decode.cond;
+ instruction->setsFlags = decode.s;
+
+ if (instruction->operation == ARMV7_MOV)
+ {
+ /*COMPILER-BUG!!!!!
+ The following table if not declared static will be allocated and assigned on the stack
+ in the current stack frame. Gcc sometimes depending on surrounding code will
+ fail to initialize the opInfo.type field. Thus giving us an uninitialized value for
+ info->type, and causing all kinds of bad behavior.
+
+ The fix for now is to just declare the lookup table static causing gcc to allocate
+ it in the data segment rather than the stack.
+ */
+ static struct opInfo operation2[4][2] = {
+ {{ARMV7_MOV, 2}, {ARMV7_LSL, 4}},
+ {{ARMV7_LSR, 4}, {ARMV7_LSR, 4}},
+ {{ARMV7_ASR, 4}, {ARMV7_ASR, 4}},
+ {{ARMV7_RRX, 2}, {ARMV7_ROR, 4}}
+ };
+ info = &operation2[decode.type][decode.imm5 != 0];
+ instruction->operation = info->op;
+ }
+
+ switch (info->type)
+ {
+ case 0:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (enum Register)decode.rm;
+ instruction->operands[2].imm = DecodeImmShift(decode.type, decode.imm5,
+ &instruction->operands[2].shift);
+ break;
+ case 1:
+ instruction->setsFlags = 0;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.rn;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.rm;
+ instruction->operands[1].imm = DecodeImmShift(decode.type, decode.imm5,
+ &instruction->operands[1].shift);
+ break;
+ case 2:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.rm;
+ break;
+ case 3:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.rm;
+ instruction->operands[1].imm = DecodeImmShift(decode.type, decode.imm5,
+ &instruction->operands[1].shift);
+ break;
+ case 4:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.rm;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = DecodeImmShift(decode.type, decode.imm5, &dummy);
+ break;
+ }
+ return 0;
+}
+
+uint32_t armv7_data_processing_reg_shifted_reg(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.2 Data-processing (register-shifted register)*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:1;
+ uint32_t type:2;
+ uint32_t group2:1;
+ uint32_t rs:4;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t s:1;
+ uint32_t op:4;
+ uint32_t group3:3;
+ uint32_t cond:4;
+ } com;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:4;
+ uint32_t rm:4;
+ uint32_t rd:4;
+ uint32_t group2:4;
+ uint32_t s:1;
+ uint32_t group3:7;
+ uint32_t cond:4;
+ }ror;
+ } decode;
+
+
+ struct opInfo {
+ Operation op;
+ uint32_t type;
+ };
+ static struct opInfo operation[] = {
+ {ARMV7_AND, 0},
+ {ARMV7_EOR, 0},
+ {ARMV7_SUB, 0},
+ {ARMV7_RSB, 0},
+ {ARMV7_ADD, 0},
+ {ARMV7_ADC, 0},
+ {ARMV7_SBC, 0},
+ {ARMV7_RSC, 0},
+ {ARMV7_TST, 1},
+ {ARMV7_TEQ, 1},
+ {ARMV7_CMP, 1},
+ {ARMV7_CMN, 1},
+ {ARMV7_ORR, 0},
+ {ARMV7_LSL, 2},
+ {ARMV7_BIC, 0},
+ {ARMV7_MVN, 3}
+ };
+
+ /* 0 AND{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 0 EOR{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 0 SUB{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 0 RSB{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 0 ADD{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 0 SBC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 0 RSC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 1 TST<c> <Rn>, <Rm>, <type> <Rs>
+ * 1 TEQ<c> <Rn>, <Rm>, <type> <Rs>
+ * 1 CMP<c> <Rn>, <Rm>, <type> <Rs>
+ * 1 CMN<c> <Rn>, <Rm>, <type> <Rs>
+ * 0 ORR{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 2 LSL{S}<c> <Rd>, <Rn>, <Rm>
+ * 2 LSR{S}<c> <Rd>, <Rn>, <Rm>
+ * 2 ASR{S}<c> <Rd>, <Rn>, <Rm>
+ * 2 ROR{S}<c> <Rd>, <Rn>, <Rm>
+ * 0 BIC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
+ * 3 MVN{S}<c> <Rd>, <Rm>, <type> <Rs>
+ */
+
+ decode.value = instructionValue;
+ struct opInfo* op = &operation[decode.com.op];
+ instruction->operation = op->op;
+ instruction->cond = (enum Condition)decode.com.cond;
+ instruction->setsFlags = decode.com.s;
+
+ if (instruction->operation == ARMV7_LSL)
+ {
+ static struct opInfo operation2[4] = {
+ {ARMV7_LSL, 2},
+ {ARMV7_LSR, 2},
+ {ARMV7_ASR, 2},
+ {ARMV7_ROR, 2}
+ };
+ op = &operation2[decode.com.type];
+ instruction->operation = op->op;
+ if (decode.ror.rd == 15 || decode.ror.rn == 15 ||
+ decode.ror.rm == 15 || decode.ror.group2 != 0)
+ instruction->unpredictable = 1;
+ }
+
+ switch (op->type)
+ {
+ case 0:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.com.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.com.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (enum Register)decode.com.rm;
+ instruction->operands[2].shift = DecodeRegisterShift(decode.com.type);
+ instruction->operands[2].offset = (enum Register)decode.com.rs;
+ instruction->operands[2].flags.offsetRegUsed = 1;
+ break;
+ case 1:
+ instruction->setsFlags = 0;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.com.rn;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.com.rm;
+ instruction->operands[1].shift = DecodeRegisterShift(decode.com.type);
+ instruction->operands[1].offset = (enum Register)decode.com.rs;
+ instruction->operands[1].flags.offsetRegUsed = 1;
+ break;
+ case 2:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.ror.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.ror.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (enum Register)decode.ror.rm;
+ break;
+ case 3:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (enum Register)decode.com.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (enum Register)decode.com.rm;
+ instruction->operands[1].shift = DecodeRegisterShift(decode.com.type);
+ instruction->operands[1].offset = (enum Register)decode.com.rs;
+ instruction->operands[1].flags.offsetRegUsed = 1;
+ break;
+ }
+ return 0;
+}
+
+uint32_t armv7_data_processing_imm(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.3 Data-processing (immediate) */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t imm:12;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t s:1;
+ uint32_t op:4;
+ uint32_t group1:3;
+ uint32_t cond:4;
+ };
+ } decode;
+
+ static Operation operation[] = {
+ ARMV7_AND,
+ ARMV7_EOR,
+ ARMV7_SUB,
+ ARMV7_RSB,
+ ARMV7_ADD,
+ ARMV7_ADC,
+ ARMV7_SBC,
+ ARMV7_RSC,
+ ARMV7_TST,
+ ARMV7_TEQ,
+ ARMV7_CMP,
+ ARMV7_CMN,
+ ARMV7_ORR,
+ ARMV7_MOV,
+ ARMV7_BIC,
+ ARMV7_MVN,
+ };
+
+ decode.value = instructionValue;
+ instruction->operation = operation[decode.op];
+ instruction->cond = (enum Condition)decode.cond;
+ instruction->setsFlags = decode.s;
+ if ((instruction->operation == ARMV7_SUB ||
+ instruction->operation == ARMV7_ADD) &&
+ decode.rn == REG_PC)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.rd;
+ instruction->operands[1].cls = LABEL;
+ instruction->operands[1].imm = address + 8;
+ if (instruction->operation == ARMV7_ADD) {
+ instruction->operands[1].imm += ExpandImm(decode.imm);
+ }
+ else {
+ instruction->operands[1].imm -= ExpandImm(decode.imm);
+ }
+ instruction->operation = ARMV7_ADR;
+ return 0;
+ }
+ uint32_t i = 0;
+ if (instruction->operation == ARMV7_CMP ||
+ instruction->operation == ARMV7_CMN ||
+ instruction->operation == ARMV7_TST ||
+ instruction->operation == ARMV7_TEQ)
+ {
+ //instruction->cond = (Condition)COND_NONE;
+ instruction->setsFlags = 0;
+ }
+ else
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.rd;
+ }
+ if (instruction->operation != ARMV7_MOV &&
+ instruction->operation != ARMV7_MVN )
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.rn;
+ }
+ instruction->operands[i].cls = IMM;
+ instruction->operands[i].imm = ExpandImm(decode.imm);
+ return 0;
+}
+
+uint32_t armv7_multiply_and_accumulate(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.5 Multiply and multiply accumulate */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:4;
+ uint32_t rm:4;
+ uint32_t group2:4;
+ uint32_t rd:4;
+ uint32_t op:4;
+ uint32_t group3:4;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:4;
+ uint32_t rm:4;
+ uint32_t rdlo:4;
+ uint32_t rdhi:4;
+ uint32_t group2:8;
+ uint32_t cond:4;
+ } maal;
+ } decode;
+
+ static Operation operation[] = {
+ ARMV7_MUL,
+ ARMV7_MUL,
+ ARMV7_MLA,
+ ARMV7_MLA,
+ ARMV7_UMAAL,
+ ARMV7_UNDEFINED,
+ ARMV7_MLS,
+ ARMV7_UNDEFINED,
+ ARMV7_UMULL,
+ ARMV7_UMULL,
+ ARMV7_UMLAL,
+ ARMV7_UMLAL,
+ ARMV7_SMULL,
+ ARMV7_SMULL,
+ ARMV7_SMLAL,
+ ARMV7_SMLAL
+ };
+ decode.value = instructionValue;
+ instruction->operation = operation[decode.op];
+ instruction->setsFlags = decode.op & 1;
+ instruction->cond = (Condition)decode.cond;
+ instruction->unpredictable = decode.rd == 15 || decode.rn == 15 || decode.rm == 15;
+
+ uint32_t i = 0;
+ if (instruction->operation == ARMV7_MLS ||
+ instruction->operation == ARMV7_MLA)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)(Register)decode.maal.rdhi;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.rn;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.rm;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].reg = (Register)(Register)decode.maal.rdlo;
+ }
+ else
+ {
+ if (instruction->operation != ARMV7_MUL)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)(Register)decode.maal.rdlo;
+ }
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)(Register)decode.maal.rdhi;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.rn;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].reg = (Register)decode.rm;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_saturating_add_sub(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.6 Saturating addition and subtraction */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:8;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t op:4;
+ uint32_t group3:4;
+ uint32_t cond:4;
+ };
+ } decode;
+
+ static Operation operation[] = {
+ ARMV7_QADD,
+ ARMV7_QSUB,
+ ARMV7_QDADD,
+ ARMV7_QDSUB
+ };
+
+ decode.value = instructionValue;
+ instruction->operation = operation[(decode.op >> 1) & 3];
+ instruction->setsFlags = decode.op & 1;
+ instruction->cond = (Condition)decode.cond;
+ instruction->unpredictable = decode.rd == 15 || decode.rn == 15 || decode.rm == 15;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.rm;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.rn;
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_halfword_multiply_and_accumulate(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.7 Halfword multiply and multiply accumulate */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:5;
+ uint32_t op:1;
+ uint32_t group2:15;
+ uint32_t op1:2;
+ uint32_t group3:5;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t n:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t rm:4;
+ uint32_t ra:4;
+ uint32_t rd:4;
+ uint32_t group3:8;
+ uint32_t cond:4;
+ } smla;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:2;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t rm:4;
+ uint32_t ra:4;
+ uint32_t rd:4;
+ uint32_t group3:8;
+ uint32_t cond:4;
+ } smlaw;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:2;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t rm:4;
+ uint32_t group3:4;
+ uint32_t rd:4;
+ uint32_t group4:8;
+ uint32_t cond:4;
+ } smulw;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t n:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t rm:4;
+ uint32_t rdlo:4;
+ uint32_t rdhi:4;
+ uint32_t group3:8;
+ uint32_t cond:4;
+ } smlal;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t n:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t rm:4;
+ uint32_t group3:4;
+ uint32_t rd:4;
+ uint32_t group4:8;
+ uint32_t cond:4;
+ } smul;
+ } decode;
+
+ static Operation operation[4][4] = {
+ {ARMV7_SMLABB, ARMV7_SMLATB, ARMV7_SMLABT, ARMV7_SMLATT},
+ {ARMV7_SMLAWT, ARMV7_SMLAWB, ARMV7_SMULWT, ARMV7_SMULWB},
+ {ARMV7_SMLALBB, ARMV7_SMLALTB, ARMV7_SMLALBT, ARMV7_SMLALTT},
+ {ARMV7_SMULBB, ARMV7_SMULTB, ARMV7_SMULBT, ARMV7_SMULTT},
+ };
+ decode.value = instructionValue;
+ instruction->operation = operation[decode.op1][decode.op];
+ instruction->cond = (Condition)decode.cond;
+
+ switch (decode.op1)
+ {
+ case 0:
+ {
+ static Operation operation2[] = {ARMV7_SMLABB, ARMV7_SMLATB, ARMV7_SMLABT, ARMV7_SMLATT};
+ instruction->operation = operation2[(decode.smla.m << 1) | decode.smla.n];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smla.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smla.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smla.rm;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.smla.ra;
+ }
+ break;
+ case 1:
+ {
+ if (decode.op == 0)
+ {
+ if (decode.smlaw.m == 1)
+ instruction->operation = ARMV7_SMLAWT;
+ else
+ instruction->operation = ARMV7_SMLAWB;
+
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlaw.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlaw.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlaw.rm;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.smlaw.ra;
+ }
+ else
+ {
+ if (decode.smulw.m == 1)
+ instruction->operation = ARMV7_SMULWT;
+ else
+ instruction->operation = ARMV7_SMULWB;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smulw.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smulw.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smulw.rm;
+ }
+ }
+ break;
+ case 2:
+ {
+ static Operation operation2[] = {ARMV7_SMLALBB, ARMV7_SMLALTB, ARMV7_SMLALBT, ARMV7_SMLALTT};
+ instruction->operation = operation2[(decode.smlal.m << 1) | decode.smlal.n];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlal.rdlo;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlal.rdhi;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlal.rn;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.smlal.rm;
+ }
+ break;
+ case 3:
+ {
+ static Operation operation2[] = {ARMV7_SMULBB, ARMV7_SMULTB, ARMV7_SMULBT, ARMV7_SMULTT};
+ instruction->operation = operation2[(decode.smul.m << 1) | decode.smul.n];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smul.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smul.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smul.rm;
+ }
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_extra_load_store(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.8 Extra load/store instructions */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:5;
+ uint32_t op2:2;
+ uint32_t group2:13;
+ uint32_t op1:5;
+ uint32_t group3:3;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t rm:4;
+ uint32_t group4:4;
+ uint32_t immH:4;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t group5:1;
+ uint32_t w:1;
+ uint32_t group6:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t op:3;
+ uint32_t group7:7;
+ };
+ } decode;
+
+ struct opInfo {
+ Operation op;
+ uint32_t type;
+ };
+
+ //1 => register, 2 => immediate, 3 => literal
+ static struct opInfo operation[4][4] = {
+ {{ARMV7_UNDEFINED, 0}, {ARMV7_UNDEFINED, 0}, {ARMV7_UNDEFINED, 0}, {ARMV7_UNDEFINED, 0}},
+ {{ARMV7_STRH , 1}, {ARMV7_LDRH , 1}, {ARMV7_STRH , 2}, {ARMV7_LDRH , 2}},
+ {{ARMV7_LDRD , 1}, {ARMV7_LDRSB , 1}, {ARMV7_LDRD , 2}, {ARMV7_LDRSB , 2}},
+ {{ARMV7_STRD , 1}, {ARMV7_LDRSH , 1}, {ARMV7_STRD , 2}, {ARMV7_LDRSH , 2}},
+ };
+
+
+ decode.value = instructionValue;
+ struct opInfo *opinfo = &operation[decode.op2][((decode.op1 >> 1) & 2)|(decode.op1 & 1)];
+
+ instruction->operation = opinfo->op;
+ instruction->cond = (Condition)decode.cond;
+ uint32_t type = opinfo->type;
+ uint32_t i = 0;
+ uint32_t wback = decode.p == 0 || decode.w == 1;
+ uint32_t index = decode.p;
+
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.rt;
+ if (instruction->operation == ARMV7_STRD || instruction->operation == ARMV7_LDRD)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)(Register)((decode.rt + 1) % 16);
+ }
+
+ //type += (decode.rn == 15 && (
+ // instruction->operation == ARMV7_LDRH ||
+ // instruction->operation == ARMV7_LDRD ||
+ // instruction->operation == ARMV7_LDRSB ||
+ // instruction->operation == ARMV7_LDRSH
+ // ));
+
+ switch (type)
+ {
+ case 1://Register
+ {
+ static OperandClass memDecode[2][2] = {
+ {NONE, MEM_POST_IDX},
+ {MEM_IMM, MEM_PRE_IDX}
+ };
+ instruction->operands[i].cls = memDecode[index][wback];
+ instruction->operands[i].reg = (Register)decode.rn;
+ instruction->operands[i].flags.add = decode.u;
+ instruction->operands[i].offset = (Register)decode.rm;
+ instruction->operands[i].flags.offsetRegUsed = 1;
+ break;
+ }
+ case 2://Immediate
+ {
+ static OperandClass memDecode[2][2] = {
+ {NONE, MEM_POST_IDX},
+ {MEM_IMM, MEM_PRE_IDX}
+ };
+ instruction->operands[i].cls = memDecode[index][wback];
+ instruction->operands[i].reg = (Register)decode.rn;
+ instruction->operands[i].flags.add = decode.u;
+ instruction->operands[i].imm = decode.immH << 4 | decode.rm;
+ break;
+ }
+ case 3://Literal
+ instruction->operands[i].cls = LABEL;
+ if (decode.u == 1)
+ instruction->operands[i].imm = address + (decode.immH << 4 | decode.rm);
+ else
+ instruction->operands[i].imm = address - (decode.immH << 4 | decode.rm);
+ break;
+ default:
+ return 1;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_extra_load_store_unprivilaged(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.9 Extra load/store instructions, unprivileged */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:5;
+ uint32_t op2:2;
+ uint32_t group2:13;
+ uint32_t op:1;
+ uint32_t group3:1;
+ uint32_t i:1;
+ uint32_t group4:5;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t rm:4;
+ uint32_t group4:8;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t group5:2;
+ uint32_t i:1;
+ uint32_t u:1;
+ uint32_t group6:8;
+ }reg;
+ struct {
+ uint32_t immL:4;
+ uint32_t group1:4;
+ uint32_t immH:4;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t group2:2;
+ uint32_t i:1;
+ uint32_t u:1;
+ uint32_t group3:4;
+ uint32_t cond:4;
+ }imm;
+ } decode;
+
+ static Operation operation[4][2] = {
+ {ARMV7_UNDEFINED, ARMV7_UNDEFINED},
+ {ARMV7_STRHT, ARMV7_LDRHT},
+ {ARMV7_UNDEFINED, ARMV7_LDRSBT},
+ {ARMV7_UNDEFINED, ARMV7_LDRSHT}
+ };
+
+ static OperandClass memType[2] = {MEM_POST_IDX, MEM_POST_IDX};
+ decode.value = instructionValue;
+ instruction->operation = operation[decode.op2][decode.op];
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.reg.rt;
+ instruction->operands[1].cls = memType[decode.i];
+ instruction->operands[1].reg = (Register)decode.reg.rn;
+ instruction->operands[1].flags.add = decode.reg.u;
+
+ if (decode.i == 0)
+ {
+ instruction->operands[1].offset = (Register)decode.reg.rm;
+ instruction->operands[1].flags.offsetRegUsed = 1;
+ }
+ else
+ {
+ instruction->operands[1].imm = decode.imm.immH << 4 | decode.imm.immL;
+ }
+
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_synchronization_primitives(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.10 Synchronization primitives */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:8;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t op:4;
+ uint32_t group4:4;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t rt2:4;
+ uint32_t group1:4;
+ uint32_t group2:4;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t group3:2;
+ uint32_t b:1;
+ uint32_t group4:5;
+ uint32_t cond:4;
+ } swp;
+ struct {
+ uint32_t group1:4;
+ uint32_t group2:4;
+ uint32_t group3:4;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t group5:4;
+ uint32_t cond:4;
+ } ldrex;
+ struct {
+ uint32_t rt:4;
+ uint32_t group1:4;
+ uint32_t group2:4;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t group3:4;
+ uint32_t cond:4;
+ } strexd;
+ } decode;
+
+ struct opInfo {
+ Operation op;
+ uint32_t type;
+ };
+ static struct opInfo operation[] = {
+ {ARMV7_SWP, 0},
+ {ARMV7_UNDEFINED,0},
+ {ARMV7_UNDEFINED,0},
+ {ARMV7_UNDEFINED,0},
+ {ARMV7_SWPB, 0},
+ {ARMV7_UNDEFINED,0},
+ {ARMV7_UNDEFINED,0},
+ {ARMV7_UNDEFINED,0},
+ {ARMV7_STREX, 0},
+ {ARMV7_LDREX, 1},
+ {ARMV7_STREXD, 2},
+ {ARMV7_LDREXD, 3},
+ {ARMV7_STREXB, 4},
+ {ARMV7_LDREXB, 1},
+ {ARMV7_STREXH, 4},
+ {ARMV7_LDREXH, 1}
+ };
+
+ decode.value = instructionValue;
+ struct opInfo *op = &operation[decode.op];
+ instruction->operation = op->op;
+ instruction->cond = (Condition)decode.cond;
+
+ switch (op->type)
+ {
+ case 0:
+ //instruction->cond = (Condition)COND_NONE;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.swp.rt;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.swp.rt2;
+ instruction->operands[2].cls = MEM_IMM;
+ instruction->operands[2].flags.add = 1;
+ instruction->operands[2].reg = (Register)decode.swp.rn;
+ break;
+ case 1:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ldrex.rt;
+ instruction->operands[1].cls = MEM_IMM;
+ instruction->operands[1].flags.add = 1;
+ instruction->operands[1].reg = (Register)decode.ldrex.rn;
+ break;
+ case 2:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.strexd.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.strexd.rt;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(Register)((decode.strexd.rt + 1) % 16);
+ instruction->operands[3].cls = MEM_IMM;
+ instruction->operands[3].flags.add = 1;
+ instruction->operands[3].reg = (Register)decode.strexd.rn;
+ break;
+ case 3:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ldrex.rt;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(Register)((decode.ldrex.rt + 1) % 16);
+ instruction->operands[2].cls = MEM_IMM;
+ instruction->operands[2].flags.add = 1;
+ instruction->operands[2].reg = (Register)decode.ldrex.rn;
+ break;
+ case 4:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.swp.rt;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.swp.rt2;
+ instruction->operands[2].cls = MEM_IMM;
+ instruction->operands[2].flags.add = 1;
+ instruction->operands[2].reg = (Register)decode.swp.rn;
+ break;
+ }
+
+ // A32 extends the ARMv7 encodings by specializing on the b11..b8 == (1)(1)(1)(1) field
+ uint32_t b11_b8 = (instructionValue & 0xF00) >> 8;
+ if(b11_b8 == 0xE) {
+ switch(instruction->operation) {
+ case ARMV7_LDREX: instruction->operation = ARMV7_LDAEX; break; // A32
+ case ARMV7_LDREXB: instruction->operation = ARMV7_LDAEXB; break; // A32
+ case ARMV7_LDREXH: instruction->operation = ARMV7_LDAEXH; break; // A32
+ case ARMV7_LDREXD: instruction->operation = ARMV7_LDAEXD; break; // A32
+ case ARMV7_STREX: instruction->operation = ARMV7_STLEX; break; // A32
+ case ARMV7_STREXB: instruction->operation = ARMV7_STLEXB; break; // A32
+ case ARMV7_STREXH: instruction->operation = ARMV7_STLEXH; break; // A32
+ case ARMV7_STREXD: instruction->operation = ARMV7_STLEXD; break; // A32
+ default: break;
+ }
+ }
+ else
+ if(b11_b8 == 0xC) {
+ switch(instruction->operation) {
+ case ARMV7_STREX:
+ instruction->operation = ARMV7_STL; // A32
+ instruction->operands[0] = instruction->operands[1];
+ instruction->operands[1] = instruction->operands[2];
+ instruction->operands[2].cls = NONE;
+ break;
+ default: break;
+ }
+ }
+
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_msr_imm_and_hints(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.11 MSR (immediate), and hints */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t op2:8;
+ uint32_t rt:4;
+ uint32_t rm:4;
+ uint32_t op1:4;
+ uint32_t group1:2;
+ uint32_t op:1;
+ uint32_t group3:5;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t imm12:12;
+ uint32_t group1:6;
+ uint32_t mask:2;
+ uint32_t group2:8;
+ uint32_t cond:4;
+ }msr;
+ struct {
+ uint32_t imm12:12;
+ uint32_t group1:4;
+ uint32_t mask:4;
+ uint32_t group2:2;
+ uint32_t r:1;
+ uint32_t group3:5;
+ uint32_t cond:4;
+ }msr2;
+ } decode;
+
+ decode.value = instructionValue;
+ instruction->cond = (Condition)decode.cond;
+ if (decode.op == 0 && decode.op1 == 0)
+ {
+ if (decode.op2 < 5)
+ {
+ static Operation operation[] = {
+ ARMV7_NOP,
+ ARMV7_YIELD,
+ ARMV7_WFE,
+ ARMV7_WFI,
+ ARMV7_SEV
+ };
+ instruction->operation = operation[decode.op2];
+ instruction->cond = (Condition)decode.cond;
+ }
+ else if (decode.op2 >= 240)
+ {
+ instruction->operation = ARMV7_DBG;
+ instruction->operands[0].cls = IMM;
+ instruction->operands[0].imm = decode.op2 & 15;
+ }
+ else
+ {
+ instruction->operation = ARMV7_HINT;
+ instruction->operands[0].cls = IMM;
+ instruction->operands[0].imm = decode.op2;
+ }
+ }
+ else if (decode.op == 0 && (decode.op1 == 4 || (decode.op1 & 11) == 8))
+ {
+ instruction->operation = ARMV7_MSR;
+ instruction->operands[0].cls = REG_SPEC;
+ instruction->operands[0].reg = (Register)(Register)(REGS_APSR + decode.msr.mask);
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = ExpandImm(decode.msr.imm12);
+ }
+ else if (decode.op == 1 ||
+ (decode.op == 0 && ((decode.op1 & 3) == 1 || (decode.op1 & 2) == 2)))
+ {
+ instruction->operation = ARMV7_MSR;
+ instruction->operands[0].cls = REG_SPEC;
+ if (decode.msr2.r == 1)
+ instruction->operands[0].reg = (Register)(Register)(REGS_SPSR + decode.msr2.mask);
+ else
+ instruction->operands[0].reg = (Register)(Register)(REGS_CPSR + decode.msr2.mask);
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = ExpandImm(decode.msr.imm12);
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_miscellaneous(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.2.12 Miscellaneous instructions */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t op2:3;
+ uint32_t group2:2;
+ uint32_t b:1;
+ uint32_t group3:6;
+ uint32_t op1:4;
+ uint32_t group4:1;
+ uint32_t op:2;
+ uint32_t group5:5;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t imm4:4;
+ uint32_t group1:4;
+ uint32_t imm12:12;
+ uint32_t group2:12;
+ } set1;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:8;
+ uint32_t rd:4;
+ uint32_t group2:12;
+ uint32_t cond:4;
+ } clz;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:4;
+ uint32_t m:1;
+ uint32_t group2:3;
+ uint32_t rd:4;
+ uint32_t m1:4;
+ uint32_t group3:2;
+ uint32_t r:1;
+ uint32_t group4:5;
+ uint32_t cond:4;
+ } msr;
+ } decode;
+
+ decode.value = instructionValue;
+ switch (decode.op2)
+ {
+ case 0:
+ if (decode.b)
+ {
+ uint32_t sysm = decode.msr.m << 4 | decode.msr.m1;
+ static Register banked[2][32] = {
+ {
+ REGB_R8_USR, REGB_R9_USR, REGB_R10_USR, REGB_R11_USR,
+ REGB_R12_USR, REGB_SP_USR, REGB_LR_USR, REG_INVALID,
+ REGB_R8_FIQ, REGB_R9_FIQ, REGB_R10_FIQ, REGB_R11_FIQ,
+ REGB_R12_FIQ, REGB_SP_FIQ, REGB_LR_FIQ, REG_INVALID,
+ REGB_LR_IRQ, REGB_SP_IRQ, REGB_LR_SVC, REGB_SP_SVC,
+ REGB_LR_ABT, REGB_SP_ABT, REGB_LR_UND, REGB_SP_UND,
+ REG_INVALID, REG_INVALID, REG_INVALID, REG_INVALID,
+ REGB_LR_MON, REGB_SP_MON, REGB_ELR_HYP, REGB_SP_HYP
+ },{
+ REG_INVALID, REG_INVALID, REG_INVALID, REG_INVALID,
+ REG_INVALID, REG_INVALID, REG_INVALID, REG_INVALID,
+ REG_INVALID, REG_INVALID, REG_INVALID, REG_INVALID,
+ REG_INVALID, REG_INVALID, REGB_SPSR_FIQ, REG_INVALID,
+ REGB_SPSR_IRQ, REG_INVALID, REGB_SPSR_SVC, REG_INVALID,
+ REGB_SPSR_ABT, REG_INVALID, REGB_SPSR_UND, REG_INVALID,
+ REG_INVALID, REG_INVALID, REG_INVALID, REG_INVALID,
+ REGB_SPSR_MON, REG_INVALID, REGB_SPSR_HYP, REG_INVALID
+ }
+ };
+ if ((decode.op & 1) == 0)
+ {
+ instruction->operation = ARMV7_MRS;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.msr.rd;
+ instruction->operands[1].cls = REG_BANKED;
+ instruction->operands[1].regb = banked[decode.msr.r][sysm];
+ return instruction->operands[1].regb == REG_INVALID;
+ }
+ else
+ {
+ instruction->operation = ARMV7_MSR;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG_BANKED;
+ instruction->operands[0].regb = banked[decode.msr.r][sysm];
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.msr.rn;
+ return instruction->operands[0].regb == REG_INVALID;
+ }
+ }
+ else
+ {
+ switch (decode.op)
+ {
+ case 0:
+ case 2:
+ instruction->operation = ARMV7_MRS;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.msr.rd;
+ instruction->operands[1].cls = REG_SPEC;
+ if (decode.msr.r == 1)
+ instruction->operands[1].regs = REGS_SPSR;
+ else
+ instruction->operands[1].regs = REGS_APSR;
+ break;
+ case 1:
+ instruction->operation = ARMV7_MSR;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG_SPEC;
+ if ((decode.op1 & 3) == 0)
+ instruction->operands[0].regs = (Register)(REGS_APSR + (decode.msr.m1 >> 2));
+ else
+ {
+ if (decode.msr.r == 1)
+ instruction->operands[0].regs = (Register)(REGS_SPSR + decode.msr.m1);
+ else
+ instruction->operands[0].regs = (Register)(REGS_CPSR + decode.msr.m1);
+ }
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.msr.rn;
+ break;
+ case 3:
+ instruction->operation = ARMV7_MSR;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG_SPEC;
+ if (decode.msr.m1 == 8 || decode.msr.m1 == 4 || decode.msr.m1 == 12)
+ instruction->operands[0].regs = (Register)(REGS_APSR + (decode.msr.m1 & 3));
+ else
+ {
+ if (decode.msr.r == 1)
+ instruction->operands[0].regs = (Register)(REGS_SPSR + decode.msr.m1);
+ else
+ instruction->operands[0].regs = (Register)(REGS_CPSR + decode.msr.m1);
+ }
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.msr.rn;
+ break;
+ }
+ }
+ break;
+ case 1:
+ if (decode.op == 1)
+ {
+ instruction->operation = ARMV7_BX;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.clz.rm;
+ }
+ else if (decode.op == 3)
+ {
+ instruction->operation = ARMV7_CLZ;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.clz.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.clz.rm;
+ }
+ break;
+ case 2:
+ instruction->operation = ARMV7_BXJ;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.clz.rm;
+ break;
+ case 3:
+ instruction->operation = ARMV7_BLX;
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.clz.rm;
+ break;
+ case 5:
+ return armv7_saturating_add_sub(instructionValue, instruction, address);
+ case 6:
+ {
+ instruction->operation = ARMV7_ERET;
+ instruction->cond = (Condition)decode.cond;
+ break;
+ }
+ case 7:
+ {
+ static Operation operation[] = {ARMV7_UNDEFINED, ARMV7_BKPT, ARMV7_HVC, ARMV7_SMC};
+ instruction->operation = operation[decode.op];
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = IMM;
+ if (instruction->operation == ARMV7_SMC)
+ instruction->operands[0].imm = decode.set1.imm4;
+ else
+ instruction->operands[0].imm = decode.set1.imm12 << 4 | decode.set1.imm4;
+ break;
+ }
+ default:
+ return 1;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_load_store_word_and_unsigned_byte(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.3 Load/store word and unsigned byte */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t b:1;
+ uint32_t group2:11;
+ uint32_t rn:4;
+ uint32_t op1:5;
+ uint32_t a:1;
+ uint32_t group3:2;
+ uint32_t cond:4;
+ };
+ struct {
+ uint32_t imm12:12;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t w:1;
+ uint32_t group2:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group3:3;
+ uint32_t cond:4;
+ }stri;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:1;
+ uint32_t type:2;
+ uint32_t imm5:5;
+ uint32_t rt:4;
+ uint32_t rn:4;
+ uint32_t group2:1;
+ uint32_t w:1;
+ uint32_t group3:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group4:3;
+ uint32_t cond:4;
+ }strr;
+ } decode;
+
+ static Operation operation[32] =
+ {
+ /* 0*/ARMV7_STR, ARMV7_LDR, ARMV7_STRT, ARMV7_LDRT,
+ /* 4*/ARMV7_STRB, ARMV7_LDRB, ARMV7_STRBT, ARMV7_LDRBT,
+ /* 8*/ARMV7_STR, ARMV7_LDR, ARMV7_STRT, ARMV7_LDRT,
+ /*12*/ARMV7_STRB, ARMV7_LDRB, ARMV7_STRBT, ARMV7_LDRBT,
+ /*16*/ARMV7_STR, ARMV7_LDR, ARMV7_STR, ARMV7_LDR,
+ /*20*/ARMV7_STRB, ARMV7_LDRB, ARMV7_STRB, ARMV7_LDRB,
+ /*24*/ARMV7_STR, ARMV7_LDR, ARMV7_STR, ARMV7_LDR,
+ /*28*/ARMV7_STRB, ARMV7_LDRB, ARMV7_STRB, ARMV7_LDRB
+ };
+ decode.value = instructionValue;
+ instruction->operation = operation[decode.op1];
+ instruction->cond = (Condition)decode.cond;
+
+ static OperandClass memDecode[4] = { MEM_IMM, MEM_POST_IDX, MEM_IMM, MEM_PRE_IDX};
+ uint32_t memtype = decode.stri.p << 1 | (decode.stri.p == 0 || decode.stri.w == 1);
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.stri.rt;
+ instruction->operands[1].reg = (Register)decode.stri.rn;
+ instruction->operands[1].flags.add = decode.stri.u;
+
+ if (decode.a == 0)
+ {
+ if (decode.stri.rn == REG_PC)
+ {
+ instruction->operands[1].cls = LABEL;
+ if (decode.stri.u == 1)
+ instruction->operands[1].imm = ((address + 3) & ~3) + decode.stri.imm12 + 8;
+ else
+ instruction->operands[1].imm = ((address + 3) & ~3) - decode.stri.imm12 + 8;
+ }
+ else
+ {
+ instruction->operands[1].cls = memDecode[memtype];
+ instruction->operands[1].imm = decode.stri.imm12;
+ }
+ }
+ else
+ {
+ instruction->operands[1].cls = memDecode[memtype];
+ instruction->operands[1].offset = (Register)decode.strr.rm;
+ instruction->operands[1].flags.offsetRegUsed = 1;
+ instruction->operands[1].imm = DecodeImmShift(decode.strr.type, decode.strr.imm5,
+ &instruction->operands[1].shift);
+ }
+ return 0;
+}
+
+uint32_t armv7_parallel_add_sub_signed(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ //A5.4.1 Parallel addition and subtraction, signed
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:1;
+ uint32_t op2:3;
+ uint32_t group2:4;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t op1:2;
+ uint32_t group3:6;
+ uint32_t cond:4;
+ };
+ }decode;
+ decode.value = instructionValue;
+
+ /* SADD16<c> <Rd>, <Rn>, <Rm>
+ * SASX<c> <Rd>, <Rn>, <Rm>
+ * SSAX<c> <Rd>, <Rn>, <Rm>
+ * SSUB16<c> <Rd>, <Rn>, <Rm>
+ * SADD8<c> <Rd>, <Rn>, <Rm>
+ * SSUB8<c> <Rd>, <Rn>, <Rm>
+ *
+ * QADD16<c> <Rd>, <Rn>, <Rm>
+ * QASX<c> <Rd>, <Rn>, <Rm>
+ * QSAX<c> <Rd>, <Rn>, <Rm>
+ * QSUB16<c> <Rd>, <Rn>, <Rm>
+ * QADD8<c> <Rd>, <Rn>, <Rm>
+ * QSUB8<c> <Rd>, <Rn>, <Rm>
+ *
+ * SHADD16<c> <Rd>, <Rn>, <Rm>
+ * SHASX<c> <Rd>, <Rn>, <Rm>
+ * SHSAX<c> <Rd>, <Rn>, <Rm>
+ * SHSUB16<c> <Rd>, <Rn>, <Rm>
+ * SHADD8<c> <Rd>, <Rn>, <Rm>
+ * SHSUB8<c> <Rd>, <Rn>, <Rm>
+ */
+
+ static Operation operation[4][8] = {
+ {
+ ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED,
+ ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED
+ },{
+ ARMV7_SADD16, ARMV7_SASX, ARMV7_SSAX, ARMV7_SSUB16,
+ ARMV7_SADD8, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_SSUB8
+ },{
+ ARMV7_QADD16, ARMV7_QASX, ARMV7_QSAX, ARMV7_QSUB16,
+ ARMV7_QADD8, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_QSUB8
+ },{
+ ARMV7_SHADD16, ARMV7_SHASX, ARMV7_SHSAX, ARMV7_SHSUB16,
+ ARMV7_SHADD8, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_SHSUB8
+ }
+ };
+
+ instruction->operation = operation[decode.op1][decode.op2];
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.rm;
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_parallel_add_sub_unsigned(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ //A5.4.2 Parallel addition and subtraction, unsigned
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:1;
+ uint32_t op2:3;
+ uint32_t group2:4;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t op1:2;
+ uint32_t group3:6;
+ uint32_t cond:4;
+ };
+ }decode;
+ decode.value = instructionValue;
+
+ /* UADD16<c> <Rd>, <Rn>, <Rm>
+ * UASX<c> <Rd>, <Rn>, <Rm>
+ * USAX<c> <Rd>, <Rn>, <Rm>
+ * USUB16<c> <Rd>, <Rn>, <Rm>
+ * UADD8<c> <Rd>, <Rn>, <Rm>
+ * USUB8<c> <Rd>, <Rn>, <Rm>
+ *
+ * UQADD16<c> <Rd>, <Rn>, <Rm>
+ * UQASX<c> <Rd>, <Rn>, <Rm>
+ * UQSAX<c> <Rd>, <Rn>, <Rm>
+ * UQSUB16<c> <Rd>, <Rn>, <Rm>
+ * UQADD8<c> <Rd>, <Rn>, <Rm>
+ * UQSUB8<c> <Rd>, <Rn>, <Rm>
+ *
+ * UHADD16<c> <Rd>, <Rn>, <Rm>
+ * UHASX<c> <Rd>, <Rn>, <Rm>
+ * UHSAX<c> <Rd>, <Rn>, <Rm>
+ * UHSUB16<c> <Rd>, <Rn>, <Rm>
+ * UHADD8<c> <Rd>, <Rn>, <Rm>
+ * UHSUB8<c> <Rd>, <Rn>, <Rm>
+ */
+
+ static Operation operation[4][8] = {
+ {
+ ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED,
+ ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UNDEFINED
+ },{
+ ARMV7_UADD16, ARMV7_UASX, ARMV7_USAX, ARMV7_USUB16,
+ ARMV7_UADD8, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_USUB8
+ },{
+ ARMV7_UQADD16, ARMV7_UQASX, ARMV7_UQSAX, ARMV7_UQSUB16,
+ ARMV7_UQADD8, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UQSUB8
+ },{
+ ARMV7_UHADD16, ARMV7_UHASX, ARMV7_UHSAX, ARMV7_UHSUB16,
+ ARMV7_UHADD8, ARMV7_UNDEFINED, ARMV7_UNDEFINED, ARMV7_UHSUB8
+ }
+ };
+
+ instruction->operation = operation[decode.op1][decode.op2];
+ instruction->cond = (Condition)decode.cond;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.rm;
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_parallel_add_sub_reversal(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ //A5.4.3 Packing, unpacking, saturation, and reversal
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:5;
+ uint32_t op2:3;
+ uint32_t group2:8;
+ uint32_t a:4;
+ uint32_t op1:3;
+ uint32_t group3:5;
+ uint32_t cond:4;
+ }com;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:2;
+ uint32_t tb:1;
+ uint32_t imm5:5;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t group2:8;
+ uint32_t cond:4;
+ }pkh;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:6;
+ uint32_t rot:2;
+ uint32_t rd:4;
+ uint32_t rn:4;
+ uint32_t group2:8;
+ uint32_t cond:4;
+ } sxtab;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:2;
+ uint32_t sh:1;
+ uint32_t imm5:5;
+ uint32_t rd:4;
+ uint32_t sat_imm:5;
+ uint32_t group2:7;
+ uint32_t cond:4;
+ }ssat;
+ } decode;
+ decode.value = instructionValue;
+
+ /*
+ * PKHBT<c> <Rd>, <Rn>, <Rm>{, LSL #<imm>}
+ * PKHTB<c> <Rd>, <Rn>, <Rm>{, ASR #<imm>}
+ * SXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
+ * SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
+ * SXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
+ * UXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
+ * UXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
+ * UXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
+ * UXTH<c> <Rd>, <Rm>{, <rotation>}
+ * UXTB<c> <Rd>, <Rm>{, <rotation>}
+ * UXTB16<c> <Rd>, <Rm>{, <rotation>}
+ * SXTH<c> <Rd>, <Rm>{, <rotation>}
+ * SXTB16<c> <Rd>, <Rm>{, <rotation>}
+ * SXTB<c> <Rd>, <Rm>{, <rotation>}
+ * SEL<c> <Rd>, <Rn>, <Rm>
+ * SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
+ * USAT<c> <Rd>, #<imm5>, <Rn>{, <shift>}
+ * SSAT16<c> <Rd>, #<imm>, <Rn>
+ * USAT16<c> <Rd>, #<imm4>, <Rn>
+ * REV<c> <Rd>, <Rm>
+ * REV16<c> <Rd>, <Rm>
+ * RBIT<c> <Rd>, <Rm>
+ * REVSH<c> <Rd>, <Rm>
+ */
+
+ instruction->cond = (Condition)decode.com.cond;
+ switch (decode.com.op1)
+ {
+ case 0:
+ switch (decode.com.op2)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.pkh.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.pkh.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.pkh.rm;
+ instruction->operands[2].imm = DecodeImmShift(
+ decode.pkh.tb << 1,
+ decode.pkh.imm5,
+ &instruction->operands[2].shift);
+ if (decode.pkh.tb == 0)
+ instruction->operation = ARMV7_PKHBT;
+ else
+ instruction->operation = ARMV7_PKHTB;
+ break;
+ case 3:
+ {
+ static Operation operation2[] = {ARMV7_SXTAB16, ARMV7_SXTB16};
+ uint32_t i = 0;
+ instruction->operation = operation2[decode.com.a == 15];
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.sxtab.rd;
+ if (decode.com.a != 15)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.sxtab.rn;
+ }
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].reg = (Register)decode.sxtab.rm;
+ instruction->operands[i].shift = SHIFT_ROR;
+ instruction->operands[i].imm = decode.sxtab.rot << 3;
+ break;
+ }
+ case 5:
+ instruction->operation = ARMV7_SEL;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.pkh.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.pkh.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.pkh.rm;
+ break;
+ default:
+ return 1;
+ }
+ break;
+ case 2:
+ switch (decode.com.op2)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ instruction->operation = ARMV7_SSAT;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ssat.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.ssat.sat_imm+1;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.ssat.rn;
+ instruction->operands[2].imm = DecodeImmShift(
+ decode.ssat.sh << 1,
+ decode.ssat.imm5,
+ &instruction->operands[2].shift);
+ break;
+ case 1:
+ instruction->operation = ARMV7_SSAT16;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ssat.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.ssat.sat_imm+1;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.ssat.rn;
+ break;
+ case 3:
+ {
+ static Operation operation2[] = {ARMV7_SXTAB, ARMV7_SXTB};
+ instruction->operation = operation2[decode.com.a == 15];
+ uint32_t i = 0;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.pkh.rd;
+ if (decode.com.a != 15)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.pkh.rn;
+ }
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].shift = SHIFT_ROR;
+ instruction->operands[i].reg = (Register)decode.pkh.rm;
+ instruction->operands[i].imm = decode.sxtab.rot << 3;
+ break;
+ }
+ default:
+ return 1;
+ }
+ break;
+ case 3:
+ switch (decode.com.op2)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ instruction->operation = ARMV7_SSAT;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ssat.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.ssat.sat_imm+1;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.ssat.rn;
+ instruction->operands[2].imm = DecodeImmShift(
+ decode.ssat.sh << 1,
+ decode.ssat.imm5,
+ &instruction->operands[2].shift);
+ break;
+ case 1:
+ instruction->operation = ARMV7_REV;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.pkh.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.pkh.rm;
+ break;
+ case 3:
+ {
+ static Operation operation2[2] = {ARMV7_SXTAH, ARMV7_SXTH};
+ instruction->operation = operation2[decode.com.a == 15];
+ uint32_t i = 0;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.sxtab.rd;
+ if (decode.com.a != 15)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.sxtab.rn;
+ }
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].shift = SHIFT_ROR;
+ instruction->operands[i].reg = (Register)decode.sxtab.rm;
+ instruction->operands[i].imm = decode.sxtab.rot << 3;
+ }
+ break;
+ case 5:
+ instruction->operation = ARMV7_REV16;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.pkh.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.pkh.rm;
+ break;
+ default:
+ return 1;
+ }
+ break;
+ case 4:
+ if (decode.com.op2 == 3)
+ {
+ static Operation operation2[] = {ARMV7_UXTAB16, ARMV7_UXTB16};
+ instruction->operation = operation2[decode.com.a == 15];
+ uint32_t i = 0;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.pkh.rd;
+ if (decode.com.a != 15)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.pkh.rn;
+ }
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].shift = SHIFT_ROR;
+ instruction->operands[i].reg = (Register)decode.pkh.rm;
+ instruction->operands[i].imm = decode.sxtab.rot << 3;
+ }
+ break;
+ case 6:
+ case 7:
+ switch (decode.com.op2)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ instruction->operation = ARMV7_USAT;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ssat.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.ssat.sat_imm;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.ssat.rn;
+ instruction->operands[2].imm = DecodeImmShift(
+ decode.ssat.sh << 1,
+ decode.ssat.imm5,
+ &instruction->operands[2].shift);
+ break;
+ case 1:
+ if (decode.com.op1 == 6)
+ {
+ instruction->operation = ARMV7_USAT16;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ssat.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.ssat.sat_imm;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.ssat.rn;
+ }
+ else //decode.com.op1 == 7
+ {
+ instruction->operation = ARMV7_RBIT;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.pkh.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.pkh.rm;
+ }
+ break;
+ case 3:
+ {
+ if (decode.com.op1 == 6)
+ {
+ static Operation operation2[] = {ARMV7_UXTAB, ARMV7_UXTB};
+ instruction->operation = operation2[decode.com.a == 15];
+ }
+ else //decode.com.op1 == 7
+ {
+ static Operation operation2[] = {ARMV7_UXTAH, ARMV7_UXTH};
+ instruction->operation = operation2[decode.com.a == 15];
+ }
+ uint32_t i = 0;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.pkh.rd;
+ if (decode.com.a != 15)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)decode.pkh.rn;
+ }
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].shift = SHIFT_ROR;
+ instruction->operands[i].reg = (Register)decode.pkh.rm;
+ instruction->operands[i].imm = decode.sxtab.rot << 3;
+ }
+ break;
+ case 5:
+ instruction->operation = ARMV7_REVSH;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.pkh.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.pkh.rm;
+ break;
+ default:
+ return 1;
+ }
+ break;
+ default:
+ return 1;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_parallel_add_sub_udiv(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A5.4.4 Signed multiply, signed and unsigned divide*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t group2:1;
+ uint32_t op2:3;
+ uint32_t group3:4;
+ uint32_t a:4;
+ uint32_t group4:4;
+ uint32_t op1:3;
+ uint32_t group5:5;
+ uint32_t cond:4;
+ }com;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:2;
+ uint32_t rm:4;
+ uint32_t ra:4;
+ uint32_t rd:4;
+ uint32_t group3:8;
+ uint32_t cond:4;
+ } smlad;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)decode.com.cond;
+ /*
+ * SMLAD{X}<c> <Rd>, <Rn>, <Rm>, <Ra>
+ * SMUAD{X}<c> <Rd>, <Rn>, <Rm>
+ * SMLSD{X}<c> <Rd>, <Rn>, <Rm>, <Ra>
+ * SMUSD{X}<c> <Rd>, <Rn>, <Rm>
+ * SDIV<c> <Rd>, <Rn>, <Rm>
+ * UDIV<c> <Rd>, <Rn>, <Rm>
+ * SMLALD{X}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
+ * SMLSLD{X}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
+ * SMMLA{R}<c> <Rd>, <Rn>, <Rm>, <Ra>
+ * SMMUL{R}<c> <Rd>, <Rn>, <Rm>
+ * SMMLS{R}<c> <Rd>, <Rn>, <Rm>, <Ra>
+ */
+ switch (decode.com.op1)
+ {
+ case 0:
+ {
+ static Operation operation[2][2][2] = {
+ {
+ {ARMV7_SMLAD, ARMV7_SMUAD},
+ {ARMV7_SMLSD, ARMV7_SMUSD}
+ },{
+ {ARMV7_SMLADX, ARMV7_SMUADX},
+ {ARMV7_SMLSDX, ARMV7_SMUSDX}
+ }
+ };
+ if (decode.com.op2 > 3)
+ break;
+ instruction->operation = operation[decode.smlad.m][decode.com.op2 >> 1][decode.com.a == 15];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlad.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlad.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlad.rm;
+ if (decode.com.a != 15)
+ {
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.smlad.ra;
+ }
+ }
+ break;
+ case 1:
+ if (decode.com.op2 == 0)
+ {
+ instruction->operation = ARMV7_SDIV;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlad.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlad.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlad.rm;
+ }
+ break;
+ case 3:
+ if (decode.com.op2 == 0)
+ {
+ instruction->operation = ARMV7_UDIV;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlad.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlad.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlad.rm;
+ }
+ break;
+ case 4:
+ {
+ if (decode.com.op2 > 3)
+ break;
+
+ static Operation operation[2][2] = {
+ {ARMV7_SMLALD, ARMV7_SMLSLD},
+ {ARMV7_SMLALDX, ARMV7_SMLSLDX}
+ };
+ instruction->operation = operation[decode.smlad.m][decode.com.op2 >> 1];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlad.ra;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlad.rd;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlad.rn;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.smlad.rm;
+ }
+ break;
+ case 5:
+ {
+ if (decode.com.op2 < 2)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_SMMLA, ARMV7_SMMUL},
+ {ARMV7_SMMLAR, ARMV7_SMMULR}
+ };
+ instruction->operation = operation[decode.smlad.m][decode.com.a == 15];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlad.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlad.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlad.rm;
+ if (decode.com.a != 15)
+ {
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.smlad.ra;
+ }
+ }
+ else if (decode.com.op2 > 5)
+ {
+ static Operation operation[2] = {ARMV7_SMMLS, ARMV7_SMMLSR};
+ instruction->operation = operation[decode.smlad.m];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.smlad.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.smlad.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.smlad.rm;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.smlad.ra;
+ }
+ }
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_media_instructions(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.4 Media instructions */
+ union {
+ uint32_t value;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t op2:3;
+ uint32_t rm:4;
+ uint32_t rd:4;
+ uint32_t rx:4;
+ uint32_t op1l:3;
+ uint32_t op1h:2;
+ uint32_t group4:3;
+ uint32_t cond:4;
+ }com;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:3;
+ uint32_t lsb:5;
+ uint32_t rd:4;
+ uint32_t widthm1:5;
+ uint32_t group2:7;
+ uint32_t cond:4;
+ }sbfx;
+ struct {
+ uint32_t rn:4;
+ uint32_t group1:3;
+ uint32_t lsb:5;
+ uint32_t rd:4;
+ uint32_t msb:5;
+ uint32_t group2:7;
+ uint32_t cond:4;
+ }bfc;
+ struct {
+ uint32_t imm4:4;
+ uint32_t group1:4;
+ uint32_t imm12:12;
+ uint32_t group2:12;
+ }udf;
+ }decode;
+ decode.value = instructionValue;
+
+ switch (decode.com.op1h)
+ {
+ case 0:
+ if (decode.com.op1l < 4)
+ return armv7_parallel_add_sub_signed(instructionValue, instruction, address);
+ return armv7_parallel_add_sub_unsigned(instructionValue, instruction, address);
+ case 1:
+ return armv7_parallel_add_sub_reversal(instructionValue, instruction, address);
+ case 2:
+ return armv7_parallel_add_sub_udiv(instructionValue, instruction, address);
+ }
+ /* USAD8<c> <Rd>, <Rn>, <Rm>
+ * USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
+ * SBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
+ * BFC<c> <Rd>, #<lsb>, #<width>
+ * BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
+ * UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
+ * UDF<c> #<imm16>
+ */
+ instruction->operation = ARMV7_UNDEFINED;
+ instruction->cond = (Condition)decode.com.cond;
+ switch (decode.com.op1l)
+ {
+ case 0:
+ if (decode.com.op2 == 0)
+ {
+ if (decode.com.rd == 15)
+ {
+ instruction->operation = ARMV7_USAD8;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.com.rx;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.com.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.com.rm;
+ }
+ else
+ {
+ instruction->operation = ARMV7_USADA8;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.com.rx;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.com.rn;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.com.rm;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.com.rd;
+ }
+ }
+ break;
+ case 2:
+ case 3:
+ if ((decode.com.op2 & 3) == 2)
+ {
+ instruction->operation = ARMV7_SBFX;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.sbfx.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.sbfx.rn;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = decode.sbfx.lsb;
+ instruction->operands[3].cls = IMM;
+ instruction->operands[3].imm = decode.sbfx.widthm1+1;
+ }
+ break;
+ case 4:
+ case 5:
+ if ((decode.com.op2 & 3) == 0)
+ {
+ if (decode.com.rn == 15)
+ {
+ instruction->operation = ARMV7_BFC;
+ if (decode.bfc.lsb > decode.bfc.msb)
+ decode.bfc.lsb = decode.bfc.msb;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.bfc.rd;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.bfc.lsb;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = decode.bfc.msb + 1 - decode.bfc.lsb;
+ }
+ else
+ {
+ instruction->operation = ARMV7_BFI;
+ instruction->unpredictable = decode.bfc.lsb > decode.bfc.msb;
+ if (decode.bfc.lsb > decode.bfc.msb)
+ decode.bfc.lsb = decode.bfc.msb;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.bfc.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.bfc.rn;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = decode.bfc.lsb;
+ instruction->operands[3].cls = IMM;
+ instruction->operands[3].imm = decode.bfc.msb + 1 - decode.bfc.lsb;
+ }
+ }
+ break;
+ case 6:
+ case 7:
+ if ((decode.com.op2 & 3) == 2)
+ {
+ instruction->operation = ARMV7_UBFX;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.bfc.rd;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.bfc.rn;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = decode.bfc.lsb;
+ instruction->operands[3].cls = IMM;
+ instruction->operands[3].imm = decode.bfc.msb + 1;
+ }
+ else if ((decode.com.op2 & 3) == 3)
+ {
+ instruction->cond = (Condition)COND_NONE;
+ instruction->operation = ARMV7_UDF;
+ instruction->operands[0].cls = IMM;
+ instruction->operands[0].imm = (decode.udf.imm12 << 4) | decode.udf.imm4;
+ }
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_branch_and_block_data_transfer(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.5 Branch, branch with link, and block data transfer */
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:15;
+ uint32_t r:1;
+ uint32_t rn:4;
+ uint32_t op:6;
+ uint32_t group2:2;
+ uint32_t cond:4;
+ }com;
+ struct {
+ uint32_t registerList:16;
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t w:1;
+ uint32_t group2:6;
+ uint32_t cond:4;
+ }stmda;
+ struct {
+ uint32_t registerList:16;
+ uint32_t rn:4;
+ uint32_t group2:1;
+ uint32_t w:1;
+ uint32_t group3:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group4:7;
+ }ldm;
+ struct {
+ int32_t imm:24;
+ uint32_t group1:4;
+ uint32_t cond:4;
+ }b;
+ struct {
+ int32_t imm:24;
+ uint32_t h:1;
+ uint32_t group1:3;
+ uint32_t cond:4;
+ }blx;
+ } decode;
+ decode.value = instructionValue;
+
+ /* STMDA<c> <Rn>{!}, <registers>
+ * LDMDA<c> <Rn>{!}, <registers>
+ * STM<c> <Rn>{!}, <registers>
+ * LDM<c> <Rn>{!}, <registers>
+ * POP<c> <registers>; <registers> contains one register, <Rt>
+ * STMDB<c> <Rn>{!}, <registers>
+ * STMDB<c> <Rn>{!}, <registers>
+ * PUSH<c> <registers>; <registers> contains more than one register
+ * PUSH<c> <registers>; <registers> contains one register, <Rt>
+ * LDMDB<c> <Rn>{!}, <registers>
+ * STMIB<c> <Rn>{!}, <registers>
+ * LDMIB<c> <Rn>{!}, <registers>
+ * STM{<amode>}<c> <Rn>, <registers>
+ * LDM{<amode>}<c> <Rn>, <registers_without_pc>
+ * LDM{<amode>}<c> <Rn>{!}, <registers_with_pc>
+ * B<c> <label>
+ * BL<c> <label>
+ * BLX <label>
+ */
+ instruction->cond = (Condition)decode.com.cond;
+ uint32_t type = 0;
+ switch (decode.com.op)
+ {
+ case 0:
+ case 2:
+ instruction->operation = ARMV7_STMDA;
+ break;
+ case 1:
+ case 3:
+ instruction->operation = ARMV7_LDMDA;
+ break;
+ case 8:
+ case 10:
+ instruction->operation = ARMV7_STM;
+ break;
+ case 9:
+ instruction->operation = ARMV7_LDM;
+ break;
+ case 11:
+ if (decode.com.rn == REG_SP)
+ {
+ instruction->operation = ARMV7_POP;
+ type = 1;
+ }
+ else
+ {
+ instruction->operation = ARMV7_LDM;
+ }
+ break;
+ case 16:
+ instruction->operation = ARMV7_STMDB;
+ break;
+ case 18:
+ if (decode.com.rn == REG_SP)
+ {
+ instruction->operation = ARMV7_PUSH;
+ type = 1;
+ }
+ else
+ {
+ instruction->operation = ARMV7_STMDB;
+ }
+ break;
+ case 17:
+ case 19:
+ instruction->operation = ARMV7_LDMDB;
+ break;
+ case 24:
+ case 26:
+ instruction->operation = ARMV7_STMIB;
+ break;
+ case 25:
+ case 27:
+ instruction->operation = ARMV7_LDMIB;
+ break;
+ case 4: case 6: case 12: case 14: case 20: case 22: case 28: case 30:
+ {
+ uint32_t value = decode.ldm.p << 1 | decode.ldm.u;
+ switch (value)
+ {
+ case 0: instruction->operation = ARMV7_STMDA; break;
+ case 1: instruction->operation = ARMV7_STM; break;
+ case 2: instruction->operation = ARMV7_STMDB; break;
+ case 3: instruction->operation = ARMV7_STMIB; break;
+ }
+ type = 5;
+ break;
+ }
+ case 5: case 7: case 13: case 15: case 21: case 23: case 29: case 31:
+ {
+ uint32_t value = decode.ldm.p << 1 | decode.ldm.u;
+ switch (value)
+ {
+ case 0: instruction->operation = ARMV7_LDMDA; break;
+ case 1: instruction->operation = ARMV7_LDM; break;
+ case 2: instruction->operation = ARMV7_LDMDB; break;
+ case 3: instruction->operation = ARMV7_LDMIB; break;
+ }
+ type = 5;
+ break;
+ }
+ case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39:
+ case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47:
+ instruction->operation = ARMV7_B;
+ type = 3;
+ break;
+ case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55:
+ case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63:
+ if (decode.com.cond == 15)
+ {
+ instruction->operation = ARMV7_BLX;
+ type = 4;
+ }
+ else
+ {
+ instruction->operation = ARMV7_BL;
+ type = 3;
+ }
+ break;
+ default:
+ return 1;
+ }
+ switch (type)
+ {
+ case 0:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.stmda.rn;
+ instruction->operands[0].flags.wb = decode.stmda.w;
+ instruction->operands[1].cls = REG_LIST;
+ instruction->operands[1].flags.hasElements = 0;
+ instruction->operands[1].reg = (Register)(Register)decode.stmda.registerList;
+ break;
+ case 1:
+ instruction->operands[0].cls = REG_LIST;
+ instruction->operands[0].flags.hasElements = 0;
+ instruction->operands[0].reg = (Register)(Register)decode.stmda.registerList;
+ break;
+ case 2: //w/o PC
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.stmda.rn;
+ instruction->operands[0].flags.wb = decode.stmda.w;
+ instruction->operands[1].cls = REG_LIST;
+ instruction->operands[1].flags.hasElements = 0;
+ instruction->operands[1].reg = (Register)(Register)(decode.stmda.registerList & 0x7fff);
+ break;
+ case 3:
+ instruction->operands[0].cls = LABEL;
+ instruction->operands[0].imm = 8 + (decode.b.imm << 2)+ address;
+ break;
+ case 4:
+ instruction->operands[0].cls = LABEL;
+ //sign extend if the high bit of blx.imm is 1
+ instruction->operands[0].imm = address + 8 +
+ ((int32_t)((decode.blx.imm << 2 | decode.blx.h << 1) << 6) >> 6);
+ break;
+ case 5:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.ldm.rn;
+ instruction->operands[0].flags.wb = decode.ldm.w;
+ instruction->operands[1].cls = REG_LIST;
+ instruction->operands[1].reg = (Register)(Register)decode.ldm.registerList;
+ instruction->operands[1].flags.hasElements = 0;
+ instruction->operands[1].flags.wb = 1;
+ break;
+ case 6:
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.stmda.rn;
+ instruction->operands[0].flags.wb = decode.stmda.w;
+ instruction->operands[1].cls = REG_LIST;
+ instruction->operands[1].reg = (Register)(Register)decode.stmda.registerList;
+ instruction->operands[1].flags.hasElements = 0;
+ instruction->operands[1].flags.wb = (decode.stmda.registerList >> 15) & 1;
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_coprocessor_instruction_and_supervisor_call(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.6 Coprocessor instructions, and Supervisor Call */
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t op:1;
+ uint32_t group2:3;
+ uint32_t coproc:4;
+ uint32_t group3:4;
+ uint32_t rn:4;
+ uint32_t op1:6;
+ uint32_t group4:2;
+ uint32_t cond:4;
+ }com;
+ struct {
+ uint32_t imm:24;
+ uint32_t group1:4;
+ uint32_t cond:4;
+ }svc;
+ struct {
+ uint32_t imm8:8;
+ uint32_t coproc:4;
+ uint32_t crd:4;
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t w:1;
+ uint32_t d:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group2:3;
+ uint32_t cond:4;
+ }stc;
+ struct {
+ uint32_t crm:4;
+ uint32_t opc1:4;
+ uint32_t coproc:4;
+ uint32_t rt:4;
+ uint32_t rt2:4;
+ uint32_t group1:8;
+ uint32_t cond:4;
+ } mrrc;
+ struct {
+ uint32_t crm:4;
+ uint32_t group1:1;
+ uint32_t opc2:3;
+ uint32_t coproc:4;
+ uint32_t crd:4;
+ uint32_t crn:4;
+ uint32_t group2:1;
+ uint32_t opc1:3;
+ uint32_t group3:4;
+ uint32_t cond:4;
+ } mcr;
+ struct {
+ uint32_t crm:4;
+ uint32_t group1:1;
+ uint32_t opc2:3;
+ uint32_t coproc:4;
+ uint32_t crd:4;
+ uint32_t crn:4;
+ uint32_t opc1:4;
+ uint32_t group2:4;
+ uint32_t cond:4;
+ } cdp;
+ }decode;
+
+ /* 0 SVC<c> #<imm24>
+ * 1 STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>{, #+/-<imm>}]
+ * 1 STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>, #+/-<imm>]!
+ * 1 STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], #+/-<imm>
+ * 1 STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], <option>
+ * 1 LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>{, #+/-<imm>}]
+ * 1 LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>, #+/-<imm>]!
+ * 1 LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], #+/-<imm>
+ * 1 LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], <option>
+ * 2 MCRR{2}<c> <coproc>, <opc1>, <Rt>, <Rt2>, <CRm>
+ * 3 CDP{2}<c> <coproc>, <opc1>, <CRd>, <CRn>, <CRm>, <opc2>
+ * 4 MCR{2}<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}
+ */
+ (void)address;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)decode.com.cond;
+ uint32_t type = 0;
+ if (decode.com.op1 >> 1 == 0)
+ {
+ instruction->operation = ARMV7_UNDEFINED;
+ }
+ else if (decode.com.op1 >> 4 == 3)
+ {
+ instruction->operation = ARMV7_SVC;
+ }
+ else if (decode.com.coproc >> 1 != 5)
+ {
+ switch (decode.com.op1)
+ {
+ case 2: case 6: case 8: case 10: case 12: case 14: case 16: case 18:
+ case 20: case 22: case 24: case 26: case 28: case 30:
+ {
+ static Operation operation2[2][2] = {
+ {ARMV7_STC, ARMV7_STCL},
+ {ARMV7_STC2, ARMV7_STC2L}
+ };
+ instruction->operation = operation2[decode.stc.cond == 15][decode.stc.d];
+ type = 1;
+ break;
+ }
+ case 3: case 7: case 9: case 11: case 13: case 15: case 17: case 19:
+ case 21: case 23: case 25: case 27: case 29: case 31:
+ {
+ static Operation operation2[2][2] = {
+ {ARMV7_LDC, ARMV7_LDCL},
+ {ARMV7_LDC2, ARMV7_LDC2L}
+ };
+ instruction->operation = operation2[decode.stc.cond == 15][decode.stc.d];
+ type = 1;
+ break;
+ }
+ case 4:
+ {
+ static Operation operation[2] = {ARMV7_MCRR, ARMV7_MCRR2};
+ instruction->operation = operation[decode.com.cond == 15];
+ type = 2;
+ }
+ break;
+ case 5:
+ {
+ static Operation operation[2] = {ARMV7_MRRC, ARMV7_MRRC2};
+ instruction->operation = operation[decode.com.cond == 15];
+ type = 2;
+ }
+ break;
+ case 32: case 34: case 36: case 38: case 40: case 42: case 44: case 46:
+ if (decode.com.op == 0)
+ {
+ instruction->operation = ARMV7_CDP;
+ type = 3;
+ }
+ else
+ {
+ static Operation operation[2] = {ARMV7_MCR, ARMV7_MCR2};
+ instruction->operation = operation[decode.com.cond == 15];
+ type = 4;
+ }
+ break;
+ case 33: case 35: case 37: case 39: case 41: case 43: case 45: case 47:
+ if (decode.com.op == 0)
+ {
+ instruction->operation = ARMV7_CDP;
+ type = 3;
+ }
+ else
+ {
+ static Operation operation[2] = {ARMV7_MRC, ARMV7_MRC2};
+ instruction->operation = operation[decode.com.cond == 15];
+ type = 5;
+ }
+ break;
+ default:
+ return 1;
+ }
+ }
+ else
+ {
+ switch (decode.com.op1)
+ {
+ case 2: case 6: case 8: case 10: case 12: case 14: case 16:
+ case 3: case 7: case 9: case 11: case 13: case 15: case 17:
+ case 18: case 20: case 22: case 24: case 26: case 28: case 30:
+ case 19: case 21: case 23: case 25: case 27: case 29: case 31:
+ return armv7_extension_register_load_store(
+ instructionValue, instruction, address);
+ case 4: case 5:
+ return armv7_64_bit_transfers(
+ instructionValue, instruction, address);
+ case 32: case 34: case 36: case 38: case 40: case 42: case 44: case 46:
+ case 33: case 35: case 37: case 39: case 41: case 43: case 45: case 47:
+ if (decode.com.op == 0)
+ return armv7_floating_point_data_processing(
+ instructionValue, instruction, address);
+ else
+ return armv7_transfers(
+ instructionValue, instruction, address);
+ default:
+ return 1;
+ }
+ }
+
+ static OperandClass memDecode[2][2] = {
+ {MEM_OPTION, MEM_POST_IDX},
+ {MEM_IMM, MEM_PRE_IDX}
+ };
+ instruction->operands[2].flags.add = 0;
+ switch (type)
+ {
+ case 0:
+ instruction->operands[0].cls = IMM;
+ instruction->operands[0].imm = decode.svc.imm;
+ break;
+ case 1:
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.stc.coproc;
+ instruction->operands[1].cls = REG_COPROCC;
+ instruction->operands[1].reg = (Register)decode.stc.crd;
+ instruction->operands[2].cls = memDecode[decode.stc.p][decode.stc.w];
+ instruction->operands[2].reg = (Register)decode.stc.rn;
+ instruction->operands[2].flags.add = decode.stc.u;
+ if (instruction->operands[2].cls == MEM_OPTION)
+ instruction->operands[2].imm = decode.stc.imm8;
+ else
+ instruction->operands[2].imm = decode.stc.imm8 << 2;
+
+ break;
+ case 2:
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.mrrc.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.mrrc.opc1;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.mrrc.rt;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.mrrc.rt2;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.mrrc.crm;
+ break;
+ case 3:
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.cdp.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.cdp.opc1;
+ instruction->operands[2].cls = REG_COPROCC;
+ instruction->operands[2].reg = (Register)decode.cdp.crd;
+ instruction->operands[3].cls = REG_COPROCC;
+ instruction->operands[3].reg = (Register)decode.cdp.crn;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.cdp.crm;
+ instruction->operands[5].cls = IMM;
+ instruction->operands[5].imm = decode.cdp.opc2;
+ break;
+ case 4:
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.mcr.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.mcr.opc1;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.mcr.crd;
+ instruction->operands[3].cls = REG_COPROCC;
+ instruction->operands[3].reg = (Register)decode.mcr.crn;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.mcr.crm;
+ if (decode.mcr.opc2 != 0)
+ {
+ instruction->operands[5].cls = IMM;
+ instruction->operands[5].imm = decode.mcr.opc2;
+ }
+ break;
+ case 5:
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.mcr.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.mcr.opc1;
+ if (decode.mcr.crd == 15)
+ {
+ instruction->operands[2].cls = REG_SPEC;
+ instruction->operands[2].regs = REGS_APSR_NZCV;
+ }
+ else
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.mcr.crd;
+ }
+ instruction->operands[3].cls = REG_COPROCC;
+ instruction->operands[3].reg = (Register)decode.mcr.crn;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.mcr.crm;
+ if (decode.mcr.opc2 != 0)
+ {
+ instruction->operands[5].cls = IMM;
+ instruction->operands[5].imm = decode.mcr.opc2;
+ }
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_unconditional(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /* A5.7 Unconditional instructions */
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t op:1;
+ uint32_t group2:11;
+ uint32_t rn:4;
+ uint32_t op1:8;
+ uint32_t cond:4;
+ } com;
+ struct {
+ uint32_t mode:5;
+ uint32_t group1:16;
+ uint32_t w:1;
+ uint32_t group2:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group3:7;
+ } srs;
+ struct {
+ uint32_t group1:16;
+ uint32_t rn:4;
+ uint32_t group2:1;
+ uint32_t w:1;
+ uint32_t group3:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group4:7;
+ } rfe;
+ struct {
+ uint32_t imm24:24;
+ uint32_t h:1;
+ uint32_t group1:7;
+ } blx;
+ struct {
+ uint32_t imm:8;
+ uint32_t coproc:4;
+ uint32_t crd:4;
+ uint32_t rn:4;
+ uint32_t group1:1;
+ uint32_t w:1;
+ uint32_t d:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group2:3;
+ uint32_t cond:4;
+ } stc;
+ struct {
+ uint32_t crm:4;
+ uint32_t group1:1;
+ uint32_t opc2:3;
+ uint32_t coproc:4;
+ uint32_t crd:4;
+ uint32_t crn:4;
+ uint32_t opc1:4;
+ uint32_t group2:4;
+ uint32_t cond:4;
+ } cdp;
+ struct {
+ uint32_t crm:4;
+ uint32_t opc1:4;
+ uint32_t coproc:4;
+ uint32_t rt:4;
+ uint32_t rt2:4;
+ uint32_t group2:12;
+ } mcrr;
+ struct {
+ uint32_t crm:4;
+ uint32_t group1:1;
+ uint32_t opc2:3;
+ uint32_t coproc:4;
+ uint32_t rt:4;
+ uint32_t crn:4;
+ uint32_t group2:1;
+ uint32_t opc1:3;
+ uint32_t group3:4;
+ uint32_t cond:4;
+ } mrc;
+ } decode;
+
+ /* SRS{<amode>} SP{!}, #<mode>
+ * RFE{<amode>}{<c>}{<q>} <Rn>{!}
+ * BL<c> <label>
+ * BLX <label>
+ * STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>{, #+/-<imm>}]
+ * STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>, #+/-<imm>]!
+ * STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], #+/-<imm>
+ * STC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], <option>
+ * LDC{2}{L}<c> <coproc>, <CRd>, [<Rn>, #+/-<imm>]{!}
+ * LDC{2}{L}<c> <coproc>, <CRd>, [<Rn>], #+/-<imm>
+ * LDC{2}{L}<c> <coproc>, <CRd>, [<Rn>], <option>
+ * LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, <label>
+ * LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [PC, #+/-<imm>]
+ * LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [PC], <option>
+ * CDP{2}{<c>}{<q>} <coproc>, {#}<opc1>, <CRd>, <CRn>, <CRm> {, {#}<opc2>}
+ * M{CRR|RRC}{2}{<c>}{<q>} <coproc>, {#}<opc1>, <Rt>, <Rt2>, <CRm>
+ * M{CR|RC}{2}{<c>}{<q>} <coproc>, {#}<opc1>, <Rt>, <CRn>, <CRm>{, {#}<opc2>}
+ */
+ decode.value = instructionValue;
+ if (decode.com.op1 >> 7 == 0)
+ return armv7_memory_hints_simd_and_misc(instructionValue, instruction, address);
+ else
+ {
+ instruction->cond = (Condition)decode.com.cond;
+ uint32_t tmp = ((decode.com.op1 >> 3) & ~3) |
+ ((decode.com.op1 >> 1) & 2) | (decode.com.op1 & 1);
+ if (tmp == 18)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_SRSDA, ARMV7_SRSIA},
+ {ARMV7_SRSDB, ARMV7_SRSIB}
+ };
+ instruction->operation = operation[decode.srs.p][decode.srs.u];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)REG_SP;
+ instruction->operands[0].flags.wb = decode.srs.w;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.srs.mode;
+ }
+ else if (tmp == 17)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_RFEDA, ARMV7_RFEIA},
+ {ARMV7_RFEDB, ARMV7_RFEIB}
+ };
+ instruction->operation = operation[decode.rfe.p][decode.rfe.u];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.rfe.rn;
+ instruction->operands[0].flags.wb = decode.srs.w;
+ }
+ else if (decode.com.op1 >> 5 == 5)
+ {
+ instruction->operation = ARMV7_BLX;
+ instruction->operands[0].cls = LABEL;
+ //sign extend if the high bit of blx.imm is 1
+ instruction->operands[0].imm = address + 8 +
+ ((int32_t)((decode.blx.imm24 << 2 | decode.blx.h << 1) << 6) >> 6);
+ }
+ else if (decode.com.op1 >> 4 == 14)
+ {
+ if (decode.com.op == 0)
+ {
+ static Operation operation[2] = {ARMV7_CDP, ARMV7_CDP2};
+ instruction->operation = operation[decode.cdp.cond == 15];
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.cdp.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.cdp.opc1;
+ instruction->operands[2].cls = REG_COPROCC;
+ instruction->operands[2].reg = (Register)decode.cdp.crd;
+ instruction->operands[3].cls = REG_COPROCC;
+ instruction->operands[3].reg = (Register)decode.cdp.crn;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.cdp.crm;
+ if (decode.cdp.opc2 != 0)
+ {
+ instruction->operands[5].cls = IMM;
+ instruction->operands[5].imm = decode.cdp.opc2;
+ }
+ }
+ else
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_MCR, ARMV7_MCR2},
+ {ARMV7_MRC, ARMV7_MRC2}
+ };
+ instruction->operation = operation[decode.com.op1 & 1][decode.com.cond == 15];
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.mrc.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.mrc.opc1;
+ if ((decode.com.op1 & 1) == 1 && decode.mrc.rt == 15)
+ {
+ instruction->operands[2].cls = REG_SPEC;
+ instruction->operands[2].regs = REGS_APSR_NZCV;
+ }
+ else
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.mrc.rt;
+ }
+ instruction->operands[3].cls = REG_COPROCC;
+ instruction->operands[3].reg = (Register)decode.mrc.crn;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.mrc.crm;
+ if (decode.mrc.opc2 != 0)
+ {
+ instruction->operands[5].cls = IMM;
+ instruction->operands[5].imm = decode.mrc.opc2;
+ }
+ }
+ }
+ else if (decode.com.op1 == 196)
+ {
+ static Operation operation[2] = {ARMV7_MCRR, ARMV7_MCRR2};
+ instruction->operation = operation[decode.com.cond == 15];
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.mcrr.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.mcrr.opc1;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.mcrr.rt;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.mcrr.rt2;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.mcrr.crm;
+ }
+ else if (decode.com.op1 == 197)
+ {
+ static Operation operation[2] = {ARMV7_MRRC, ARMV7_MRRC2};
+ instruction->operation = operation[decode.com.cond == 15];
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.mcrr.coproc;
+ instruction->operands[1].cls = IMM;
+ instruction->operands[1].imm = decode.mcrr.opc1;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.mcrr.rt;
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)decode.mcrr.rt2;
+ instruction->operands[4].cls = REG_COPROCC;
+ instruction->operands[4].reg = (Register)decode.mcrr.crm;
+ }
+ else if ((decode.com.op1 & 1) == 0)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_STC, ARMV7_STC2},
+ {ARMV7_STCL, ARMV7_STC2L}
+ };
+ static OperandClass memDecode[2][2] = {
+ {MEM_OPTION, MEM_POST_IDX},
+ {MEM_IMM, MEM_PRE_IDX}
+ };
+ instruction->operation = operation[decode.stc.d][decode.stc.cond == 15];
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.stc.coproc;
+ instruction->operands[1].cls = REG_COPROCC;
+ instruction->operands[1].reg = (Register)decode.stc.crd;
+ instruction->operands[2].cls = memDecode[decode.stc.p][decode.stc.w];
+ instruction->operands[2].reg = (Register)decode.stc.rn;
+ if (instruction->operands[2].cls == MEM_OPTION)
+ instruction->operands[2].imm = decode.stc.imm;
+ else
+ instruction->operands[2].imm = decode.stc.imm << 2;
+ instruction->operands[2].flags.add = decode.stc.u;
+ }
+ else if ((((decode.com.op1 >> 4) & 14) | (decode.com.op1 & 1)) == 13)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_LDC, ARMV7_LDC2},
+ {ARMV7_LDCL, ARMV7_LDC2L}
+ };
+ static OperandClass memDecode[2][2] = {
+ {MEM_OPTION, MEM_POST_IDX},
+ {MEM_IMM, MEM_PRE_IDX}
+ };
+ instruction->operation = operation[decode.stc.d][decode.stc.cond == 15];
+ instruction->operands[0].cls = REG_COPROCP;
+ instruction->operands[0].reg = (Register)decode.stc.coproc;
+ instruction->operands[1].cls = REG_COPROCC;
+ instruction->operands[1].reg = (Register)decode.stc.crd;
+ instruction->operands[2].cls = memDecode[decode.stc.p][decode.stc.w];
+ if (instruction->operands[2].cls != MEM_OPTION && decode.com.rn == REG_PC)
+ {
+ //immediate
+ instruction->operands[2].cls = LABEL;
+ if (decode.stc.u == 1)
+ instruction->operands[2].imm = 8 + (address & ~3) + (decode.stc.imm << 2);
+ else
+ instruction->operands[2].imm = 8 + (address & ~3) - (decode.stc.imm << 2);
+ }
+ else
+ {
+ //literal
+ instruction->operands[2].reg = (Register)decode.stc.rn;
+ if (instruction->operands[2].cls == MEM_OPTION)
+ instruction->operands[2].imm = decode.stc.imm;
+ else
+ instruction->operands[2].imm = decode.stc.imm << 2;
+ instruction->operands[2].flags.add = decode.stc.u;
+ }
+ }
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_memory_hints_simd_and_misc(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A5.7.1 Memory hints, Advanced SIMD instructions, and miscellaneous instructions*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t op2:4;
+ uint32_t group2:8;
+ uint32_t rn:4;
+ uint32_t op1:7;
+ uint32_t group3:5;
+ } com;
+ struct {
+ uint32_t mode:5;
+ uint32_t group1:1;
+ uint32_t aif:3;
+ uint32_t group3:8;
+ uint32_t m:1;
+ uint32_t imod:2;
+ uint32_t group4:12;
+ } cps;
+ struct {
+ uint32_t imm12:12;
+ uint32_t group1:4;
+ uint32_t rn:4;
+ uint32_t group2:2;
+ uint32_t r:1;
+ uint32_t u:1;
+ uint32_t group3:8;
+ } pli;
+ struct {
+ uint32_t rm:4;
+ uint32_t group1:1;
+ uint32_t type:2;
+ uint32_t imm5:5;
+ uint32_t group2:4;
+ uint32_t rn:4;
+ uint32_t group3:1;
+ uint32_t w:1;
+ uint32_t group4:1;
+ uint32_t u:1;
+ uint32_t group5:8;
+ } plir;
+ }decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+ if ((decode.com.op1 >> 5) == 1)
+ {
+ return armv7_simd_data_processing(instructionValue, instruction, address);
+ }
+ else if ((decode.com.op1 & 0x71) == 64)
+ {
+ return armv7_simd_load_store(instructionValue, instruction, address);
+ }
+ else
+ {
+ switch (decode.com.op1)
+ {
+ case 16:
+ if ((decode.com.rn & 1) == 0)
+ {
+ static Operation operation[4] = {ARMV7_CPS, ARMV7_CPS, ARMV7_CPSIE, ARMV7_CPSID};
+ instruction->operation = operation[decode.cps.imod];
+ uint32_t i = 0;
+ if ((decode.cps.m == 1 && decode.cps.aif != 0) || decode.cps.m == 0)
+ {
+ instruction->operands[i].cls = IFLAGS;
+ instruction->operands[i++].iflag = (Iflags)decode.cps.aif;
+ }
+ if ((decode.cps.m == 0 &&decode.cps.mode != 0) || decode.cps.m == 1)
+ {
+ instruction->operands[i].cls = IMM;
+ instruction->operands[i].imm = decode.cps.mode;
+ }
+ }
+ else
+ {
+ instruction->operation = ARMV7_SETEND;
+ instruction->operands[0].cls = ENDIAN_SPEC;
+ instruction->operands[0].endian = (EndianSpec)((instructionValue >> 9) & 1);
+ }
+ break;
+ case 65:
+ case 73:
+ instruction->operation = ARMV7_NOP;
+ break;
+ case 69:
+ case 77:
+ instruction->operation = ARMV7_PLI;
+ instruction->operands[0].cls = MEM_IMM;
+ instruction->operands[0].reg = (Register)decode.pli.rn;
+ instruction->operands[0].imm = decode.pli.imm12;
+ instruction->operands[0].flags.add = decode.pli.u;
+ break;
+ case 81:
+ case 89:
+ {
+ static Operation operation[2] = {ARMV7_PLDW, ARMV7_PLD};
+ instruction->operation = operation[decode.pli.r];
+ instruction->operands[0].cls = MEM_IMM;
+ instruction->operands[0].reg = (Register)decode.pli.rn;
+ instruction->operands[0].imm = decode.pli.imm12;
+ instruction->operands[0].flags.add = decode.pli.u;
+ }
+ break;
+ case 85:
+ case 93:
+ //if (decode.pli.rn == 15)
+ {
+ static Operation operation[2] = {ARMV7_PLDW, ARMV7_PLD};
+ instruction->operation = operation[decode.pli.r];
+ instruction->operands[0].cls = MEM_IMM;
+ instruction->operands[0].reg = (Register)decode.pli.rn;
+ instruction->operands[0].imm = decode.pli.imm12;
+ instruction->operands[0].flags.add = decode.pli.u;
+ }
+ //else
+ //{
+ // instruction->operation = ARMV7_PLD;
+ // instruction->operands[0].cls = LABEL;
+ // if (decode.pli.u == 1)
+ // instruction->operands[0].imm = decode.pli.imm12 + address;
+ // else
+ // instruction->operands[0].imm = address - decode.pli.imm12;
+ //}
+ break;
+ case 87:
+ switch (decode.com.op2)
+ {
+ case 1:
+ instruction->operation = ARMV7_CLREX;
+ break;
+ case 4:
+ instruction->operation = ARMV7_DSB;
+ instruction->operands[0].cls = DSB_OPTION;
+ instruction->operands[0].dsbOpt = (DsbOption)(instructionValue & 15);
+ break;
+ case 5:
+ instruction->operation = ARMV7_DMB;
+ instruction->operands[0].cls = DSB_OPTION;
+ instruction->operands[0].dsbOpt = (DsbOption)(instructionValue & 15);
+ break;
+ case 6:
+ instruction->operation = ARMV7_ISB;
+ instruction->operands[0].cls = DSB_OPTION;
+ instruction->operands[0].dsbOpt = (DsbOption)(instructionValue & 15);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 97:
+ case 105:
+ instruction->operation = ARMV7_NOP;
+ break;
+ case 101:
+ case 109:
+ {
+ instruction->operation = ARMV7_PLI;
+ instruction->operands[0].cls = MEM_IMM;
+ instruction->operands[0].reg = (Register)decode.plir.rn;
+ instruction->operands[0].flags.add = decode.plir.u;
+ instruction->operands[0].offset = (Register)decode.plir.rm;
+ instruction->operands[0].flags.offsetRegUsed = 1;
+ instruction->operands[0].imm = DecodeImmShift(
+ decode.plir.type,
+ decode.plir.imm5,
+ &instruction->operands[0].shift);
+ }
+ break;
+ case 113:
+ case 121:
+ {
+ static Operation operation[2] = {ARMV7_PLDW, ARMV7_PLD};
+ instruction->operation = operation[decode.pli.r];
+ instruction->operands[0].cls = MEM_IMM;
+ instruction->operands[0].reg = (Register)decode.plir.rn;
+ instruction->operands[0].flags.add = decode.plir.u;
+ instruction->operands[0].offset = (Register)decode.plir.rm;
+ instruction->operands[0].flags.offsetRegUsed = 1;
+ instruction->operands[0].imm = DecodeImmShift(
+ decode.plir.type,
+ decode.plir.imm5,
+ &instruction->operands[0].shift);
+ }
+ break;
+ case 117:
+ case 125:
+ {
+ static Operation operation[2] = {ARMV7_PLDW, ARMV7_PLD};
+ instruction->operation = operation[decode.pli.r];
+ instruction->operands[0].cls = MEM_IMM;
+ instruction->operands[0].reg = (Register)decode.plir.rn;
+ instruction->operands[0].flags.add = decode.plir.u;
+ instruction->operands[0].offset = (Register)decode.plir.rm;
+ instruction->operands[0].flags.offsetRegUsed = 1;
+ instruction->operands[0].imm = DecodeImmShift(
+ decode.plir.type,
+ decode.plir.imm5,
+ &instruction->operands[0].shift);
+ }
+ break;
+ }
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+
+uint32_t armv7_simd_data_processing(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.4 Advanced SIMD data-processing instructions*/
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t c:4;
+ uint32_t b:4;
+ uint32_t group2:7;
+ uint32_t a:5;
+ uint32_t u:1;
+ uint32_t group3:7;
+ } com;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t op:1;
+ uint32_t n:1;
+ uint32_t len:2;
+ uint32_t group2:2;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t group3:2;
+ uint32_t d:1;
+ uint32_t group4:9;
+ } vtbl;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t n:1;
+ uint32_t imm4:4;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t group3:2;
+ uint32_t d:1;
+ uint32_t group4:9;
+ } vext;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t group2:5;
+ uint32_t vd:4;
+ uint32_t imm4:4;
+ uint32_t group3:2;
+ uint32_t d:1;
+ uint32_t group4:9;
+ } vdup;
+ } decode;
+ decode.value = instructionValue;
+ if (decode.com.a >> 4 == 0)
+ return armv7_three_register_same(instructionValue, instruction, address);
+
+ uint32_t a = decode.com.a & 7;
+ if ((decode.com.c & 9) == 1 && a == 0)
+ return armv7_one_register_and_modified_imm(instructionValue, instruction, address);
+
+ if ((decode.com.c & 9) == 9 || (a > 0 && (decode.com.c & 1) == 1))
+ return armv7_two_register_and_shift(instructionValue, instruction, address);
+
+ if (a <= 5)
+ {
+ if ((decode.com.c & 5) == 0)
+ return armv7_three_register_different(instructionValue, instruction, address);
+ if ((decode.com.c & 5) == 4)
+ return armv7_two_register_scalar(instructionValue, instruction, address);
+ }
+
+ if (decode.com.u == 0)
+ {
+ if ((decode.com.c & 1) != 0)
+ return 1;
+ instruction->operation = ARMV7_VEXT;
+ instruction->dataType = DT_8;
+ instruction->cond = (Condition)COND_NONE;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vext.q] + ((decode.vext.d << 4 | decode.vext.vd) >> decode.vext.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vext.q] + ((decode.vext.n << 4 | decode.vext.vn) >> decode.vext.q));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(regMap[decode.vext.q] + ((decode.vext.m << 4 | decode.vext.vm) >> decode.vext.q));
+ instruction->operands[3].cls = IMM;
+ instruction->operands[3].imm = decode.vext.imm4 * 8;
+ if (decode.vext.q)
+ instruction->operands[3].imm <<= 1;
+ }
+ else if (decode.com.b <= 7)
+ {
+ if ((decode.com.c & 1) != 0)
+ return 1;
+ return armv7_two_register_misc(instructionValue, instruction, address);
+ }
+ else if (decode.com.b <= 11)
+ {
+ if ((decode.com.c & 1) != 0)
+ return 1;
+ //VTBL, VTBX
+ static Operation operation[2] = {ARMV7_VTBL, ARMV7_VTBX};
+ instruction->operation = operation[decode.vtbl.op];
+ instruction->dataType = DT_8;
+ instruction->cond = (Condition)COND_NONE;
+ static uint8_t sizeMap[4] = {1,3,7,15};
+ uint32_t n = (decode.vtbl.n << 4) | decode.vtbl.vn;
+ instruction->unpredictable = (n + decode.vtbl.len + 1) > 32;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vtbl.d << 4) | decode.vtbl.vd));
+ instruction->operands[1].cls = REG_LIST_DOUBLE;
+ instruction->operands[1].flags.hasElements = 0;
+ instruction->operands[1].reg = (Register)(sizeMap[decode.vtbl.len] << (n));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vtbl.m << 4) | decode.vtbl.vm));
+ }
+ else if (decode.com.b == 12)
+ {
+ if ((decode.com.c & 9) != 0)
+ return 1;
+ instruction->operation = ARMV7_VDUP;
+ instruction->cond = (Condition)COND_NONE;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vdup.q] + ((decode.vdup.d << 4 | decode.vdup.vd) >> decode.vdup.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + (decode.vdup.m << 4 | decode.vdup.vm));
+ instruction->operands[1].flags.hasElements = 1;
+
+ if ((decode.vdup.imm4 & 1) == 1)
+ {
+ instruction->dataType = DT_8;
+ instruction->operands[1].imm = (decode.vdup.imm4 >> 1) & 7;
+ }
+ else if ((decode.vdup.imm4 & 3) == 2)
+ {
+ instruction->dataType = DT_16;
+ instruction->operands[1].imm = (decode.vdup.imm4 >> 2) & 3;
+ }
+ else if ((decode.vdup.imm4 & 7) == 4)
+ {
+ instruction->dataType = DT_32;
+ instruction->operands[1].imm = (decode.vdup.imm4 >> 3) & 1;
+ }
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_three_register_same(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.4.1 Three registers of the same length*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t b:1;
+ uint32_t group2:3;
+ uint32_t a:4;
+ uint32_t group3:8;
+ uint32_t c:2;
+ uint32_t group4:2;
+ uint32_t u:1;
+ uint32_t group5:7;
+ } com;
+ struct {
+ uint32_t vm:4;
+ uint32_t b:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t n:1;
+ uint32_t sz:1;
+ uint32_t op:1;
+ uint32_t group1:2;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t size:2;
+ uint32_t d:1;
+ uint32_t group2:1;
+ uint32_t u:1;
+ uint32_t group3:7;
+ } vh;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+ instruction->operation = ARMV7_UNDEFINED;
+ instruction->dataType = DECODE_DT(decode.vh.size, decode.vh.u);
+ int /* checkV0 = 0, */ src1 = 1, src2 = 2;
+ switch (decode.com.a)
+ {
+ case 0:
+ {
+ if (decode.com.b == 1)
+ instruction->operation = ARMV7_VQADD;
+ else
+ {
+ static Operation operation[2] = {ARMV7_VHADD, ARMV7_VHSUB};
+ instruction->operation = operation[decode.vh.op];
+ }
+ break;
+ }
+ case 1:
+ {
+ if (decode.com.b == 0)
+ {
+ instruction->operation = ARMV7_VRHADD;
+ }
+ else
+ {
+ if (decode.com.u == 0)
+ {
+ static Operation operation[4] = {ARMV7_VAND, ARMV7_VBIC, ARMV7_VORR, ARMV7_VORN};
+ instruction->operation = operation[decode.com.c];
+ if (decode.com.c == 2 && decode.vh.vn == decode.vh.vm)
+ instruction->operation = ARMV7_VORR;
+ }
+ else
+ {
+ static Operation operation[4] = {ARMV7_VEOR, ARMV7_VBSL, ARMV7_VBIT, ARMV7_VBIF};
+ instruction->operation = operation[decode.com.c];
+ }
+ instruction->dataType = DT_NONE;
+ }
+ break;
+ }
+ case 2:
+ {
+ if (decode.com.b == 0)
+ {
+ static Operation operation[2]= {ARMV7_VHADD, ARMV7_VHSUB};
+ instruction->operation = operation[decode.vh.op];
+ }
+ else
+ {
+ instruction->operation = ARMV7_VQSUB;
+ }
+ break;
+ }
+ case 3:
+ {
+ static Operation operation[2] = {ARMV7_VCGT, ARMV7_VCGE};
+ instruction->operation = operation[decode.com.b];
+ break;
+ }
+ case 4:
+ {
+ static Operation operation[2] = {ARMV7_VSHL, ARMV7_VQSHL};
+ instruction->operation = operation[decode.com.b];
+ src1 = 2;
+ src2 = 1;
+ break;
+ }
+ case 5:
+ {
+ static Operation operation[2] = {ARMV7_VRSHL, ARMV7_VQRSHL};
+ instruction->operation = operation[decode.com.b];
+ src1 = 2;
+ src2 = 1;
+ break;
+ }
+ case 6:
+ {
+ static Operation operation[2] = {ARMV7_VMAX, ARMV7_VMIN};
+ instruction->operation = operation[decode.vh.b];
+ break;
+ }
+ case 7:
+ {
+ static Operation operation[2] = {ARMV7_VABD, ARMV7_VABA};
+ instruction->operation = operation[decode.com.b];
+ break;
+ }
+ case 8:
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VADD, ARMV7_VSUB},
+ {ARMV7_VTST, ARMV7_VCEQ}
+ };
+ instruction->operation = operation[decode.com.b][decode.com.u];
+ if (instruction->operation == ARMV7_VTST)
+ {
+ instruction->dataType = (DataType)(DT_8 + decode.vh.size);
+ // checkV0 = decode.vh.q;
+ }
+ else
+ {
+ instruction->dataType = (DataType)(DT_I8 + decode.vh.size);
+ // checkV0 = decode.vh.q;
+ }
+ break;
+ }
+ case 9:
+ {
+ if (decode.vh.b == 0)
+ {
+ static Operation operation[2] = {ARMV7_VMLA, ARMV7_VMLS};
+ instruction->operation = operation[decode.com.u];
+ instruction->dataType = (DataType)(DT_I8 + decode.vh.size);
+ }
+ else
+ {
+ instruction->operation = ARMV7_VMUL;
+ if (decode.com.u == 1)
+ instruction->dataType = (DataType)(DT_P8);
+ else
+ {
+ instruction->dataType = (DataType)(DT_I8 + decode.vh.size);
+ }
+ }
+ break;
+ }
+ case 10:
+ {
+ static Operation operation[2] = {ARMV7_VPMAX, ARMV7_VPMIN};
+ instruction->operation = operation[decode.vh.b];
+ break;
+ }
+ case 11:
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VQDMULH, ARMV7_VQRDMULH},
+ {ARMV7_VPADD, ARMV7_UNDEFINED}
+ };
+ instruction->operation = operation[decode.com.b][decode.com.u];
+ if (instruction->operation == ARMV7_VPADD)
+ instruction->dataType = (DataType)(DT_I8 + decode.vh.size);
+ else
+ instruction->dataType = (DataType)(DT_S8 + decode.vh.size);
+ break;
+ }
+ case 12:
+ {
+ if (decode.com.b == 1 && decode.com.u == 0)
+ {
+ Operation operation[2] = {ARMV7_VFMA, ARMV7_VFMS};
+ instruction->operation = operation[decode.vh.size >> 1];
+ instruction->dataType = DT_F32;
+ }
+ break;
+ }
+ case 13:
+ {
+ if (decode.com.b == 0)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VADD, ARMV7_VSUB},
+ {ARMV7_VPADD, ARMV7_VABD}
+ };
+ instruction->operation = operation[decode.com.u][decode.com.c >> 1];
+ instruction->operation = (Operation)((instruction->operation == ARMV7_VMLA && decode.vh.op) + instruction->operation);
+ }
+ else
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VMLA, ARMV7_VMLS},
+ {ARMV7_VMUL, ARMV7_VMUL}
+ };
+ instruction->operation = operation[decode.com.u][decode.com.c >> 1];
+ }
+ instruction->dataType = DT_F32;
+ break;
+ }
+ case 14:
+ {
+ if (decode.com.b == 0)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VCEQ, ARMV7_VCEQ},
+ {ARMV7_VCGE, ARMV7_VCGT}
+ };
+ instruction->operation = operation[decode.com.u][decode.com.c >> 1];
+ }
+ else
+ {
+ static Operation operation[2] = {ARMV7_VACGE, ARMV7_VACGT};
+ instruction->operation = operation[decode.com.c >> 1];
+ }
+ instruction->dataType = DT_F32;
+ break;
+ }
+ case 15:
+ {
+ if (decode.com.b == 0)
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VMAX, ARMV7_VMIN},
+ {ARMV7_VPMAX, ARMV7_VPMIN}
+ };
+ instruction->operation = operation[decode.com.u][decode.com.c >> 1];
+ }
+ else
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VRECPS, ARMV7_VRSQRTS},
+ {ARMV7_UNDEFINED, ARMV7_UNDEFINED}
+ };
+ instruction->operation = operation[decode.com.u][decode.com.c >> 1];
+ }
+ instruction->dataType = DT_F32;
+ break;
+ }
+ }
+
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vh.q] + ((decode.vh.d << 4 | decode.vh.vd) >> decode.vh.q));
+ instruction->operands[src1].cls = REG;
+ instruction->operands[src1].reg = (Register)(regMap[decode.vh.q] + ((decode.vh.n << 4 | decode.vh.vn) >> decode.vh.q));
+ instruction->operands[src2].cls = REG;
+ instruction->operands[src2].reg = (Register)(regMap[decode.vh.q] + ((decode.vh.m << 4 | decode.vh.vm) >> decode.vh.q));
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_three_register_different(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.4.2 Three registers of different lengths*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:8;
+ uint32_t a:4;
+ uint32_t group2:8;
+ uint32_t b:2;
+ uint32_t group3:2;
+ uint32_t u:1;
+ uint32_t group4:7;
+ } com;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t n:1;
+ uint32_t op:1;
+ uint32_t op2:1;
+ uint32_t group3:2;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t size:2;
+ uint32_t d:1;
+ uint32_t diff:1;
+ uint32_t u:1;
+ uint32_t group5:7;
+ } vcom;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+
+ /* VADDL<c>.<dt> <Qd>, <Dn>, <Dm>
+ * VADDW<c>.<dt> <Qd>, <Qn>, <Dm>
+ * UBL<c>.<dt> <Qd>, <Dn>, <Dm>
+ * VSUBW<c>.<dt> <Qd>, <Qn>, <Dm>
+ * VADDHN<c>.<dt> <Dd>, <Qn>, <Qm>
+ * VRADDHN<c>.<dt> <Dd>, <Qn>, <Qm>
+ * VABAL<c>.<dt> <Qd>, <Dn>, <Dm> //A2
+ * VSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
+ * VRSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
+ * VABD<c>.<dt> <Qd>, <Qn>, <Qm>
+ * VABD<c>.<dt> <Dd>, <Dn>, <Dm>
+ * VABDL<c>.<dt> <Qd>, <Dn>, <Dm>
+ * V<op>L<c>.<dt> <Qd>, <Dn>, <Dm>
+ * VQD<op><c>.<dt> <Qd>, <Dn>, <Dm> //A1
+ * VMULL<c>.<dt> <Qd>, <Dn>, <Dm> //A2
+ * VQDMULL<c>.<dt> <Qd>, <Dn>, <Dm> //A1
+ * VMULL<c>.<dt> <Qd>, <Dn>, <Dm> //A2 op=1
+ */
+ switch (decode.com.a)
+ {
+ case 0:
+ case 1:
+ {
+ static Operation operation[2] = {ARMV7_VADDL, ARMV7_VADDW};
+ static DataType dataType[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_NONE},
+ {DT_U8, DT_U16, DT_U32, DT_NONE}
+ };
+ instruction->operation = operation[decode.vcom.op];
+ instruction->dataType = dataType[decode.vcom.u][decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcom.op] + (((decode.vcom.n << 4) | decode.vcom.vn) >> decode.vcom.op));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ if ((decode.vcom.vd & 1) == 1 ||
+ (decode.vcom.op == 1 && (decode.vcom.vn & 1) == 1))
+ return 1;
+ }
+ break;
+ case 2:
+ case 3:
+ {
+ static Operation operation[2] = {ARMV7_VSUBL, ARMV7_VSUBW};
+ static DataType dataType[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_NONE},
+ {DT_U8, DT_U16, DT_U32, DT_NONE}
+ };
+ instruction->operation = operation[decode.vcom.op];
+ instruction->dataType = dataType[decode.vcom.u][decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcom.op] + (((decode.vcom.n << 4) | decode.vcom.vn) >> decode.vcom.op));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ if ((decode.vcom.vd & 1) == 1 ||
+ (decode.vcom.op == 1 && (decode.vcom.vn & 1) == 1))
+ return 1;
+ }
+
+ break;
+ case 4:
+ {
+ static DataType dataType[4] = {DT_I16, DT_I32, DT_I64, DT_NONE};
+ static Operation operation[2] = {ARMV7_VADDHN, ARMV7_VRADDHN};
+ instruction->operation = operation[decode.com.u];
+ instruction->dataType = dataType[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vcom.d << 4) | decode.vcom.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_Q0 + (((decode.vcom.n << 4) | decode.vcom.vn) >> 1));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_Q0 + (((decode.vcom.m << 4) | decode.vcom.vm) >> 1));
+ }
+ break;
+ case 5:
+ {
+ static DataType dataType[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_NONE},
+ {DT_U8, DT_U16, DT_U32, DT_NONE}
+ };
+ instruction->operation = ARMV7_VABAL;
+ instruction->dataType = dataType[decode.vcom.u][decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ break;
+ case 6:
+ {
+ static DataType dataType[4] = {DT_I16, DT_I32, DT_I64, DT_NONE};
+ static Operation operation[2] = {ARMV7_VSUBHN, ARMV7_VRSUBHN};
+ instruction->operation = operation[decode.com.u];
+ instruction->dataType = dataType[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vcom.d << 4) | decode.vcom.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_Q0 + (((decode.vcom.n << 4) | decode.vcom.vn) >> 1));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_Q0 + (((decode.vcom.m << 4) | decode.vcom.vm) >> 1));
+ }
+ break;
+ case 7:
+ {
+ static Operation operation[2] = {ARMV7_VABD, ARMV7_VABDL};
+ static DataType dataType[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_NONE},
+ {DT_U8, DT_U16, DT_U32, DT_NONE}
+ };
+ instruction->operation = operation[decode.vcom.diff];
+ instruction->dataType = dataType[decode.vcom.u][decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ break;
+ case 8:
+ case 10:
+ {
+ static Operation operation[2] = {ARMV7_VMLAL, ARMV7_VMLSL};
+ static DataType dataType[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_NONE},
+ {DT_U8, DT_U16, DT_U32, DT_NONE}
+ };
+ instruction->operation = operation[decode.vcom.op2];
+ instruction->dataType = dataType[decode.vcom.u][decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ break;
+ case 9:
+ case 11:
+ if (decode.com.u == 0)
+ {
+ static Operation operation[2] = {ARMV7_VQDMLAL, ARMV7_VQDMLSL};
+ static DataType dataType[4] = {DT_S8, DT_S16, DT_S32, DT_NONE};
+ instruction->operation = operation[decode.vcom.op2];
+ instruction->dataType = dataType[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ break;
+ case 12: //op = 0
+ {
+ static DataType dataType[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_NONE},
+ {DT_U8, DT_U16, DT_U32, DT_NONE}
+ };
+ instruction->operation = ARMV7_VMULL;
+ instruction->dataType = dataType[decode.vcom.u][decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ break;
+ case 13:
+ if (decode.com.u == 0)
+ {
+ static DataType dataType[4] = {DT_S8, DT_S16, DT_S32, DT_NONE};
+ instruction->operation = ARMV7_VQDMULL;
+ instruction->dataType = dataType[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ break;
+ case 14: //op = 1
+ {
+ static DataType dataType[4] = {DT_P8, DT_P16, DT_P32, DT_NONE};
+ instruction->operation = ARMV7_VMULL;
+ instruction->dataType = dataType[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ break;
+ }
+
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_two_register_scalar(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.4.3 Two registers and a scalar*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:8;
+ uint32_t a:4;
+ uint32_t group2:8;
+ uint32_t b:2;
+ uint32_t group3:2;
+ uint32_t u:1;
+ uint32_t group4:7;
+ }com;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t n:1;
+ uint32_t f:1;
+ uint32_t l:1;
+ uint32_t op:1;
+ uint32_t diff:1;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t size:2;
+ uint32_t d:1;
+ uint32_t group5:1;
+ uint32_t q:1;
+ uint32_t group6:7;
+ }vcom;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+ switch (decode.com.a)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ case 6:
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_VMLA, ARMV7_VMLS},
+ {ARMV7_VMLAL, ARMV7_VMLSL}
+ };
+ static DataType dtMap[2][4][2] = {
+ {{DT_NONE, DT_NONE}, {DT_I16, DT_F16}, {DT_I32, DT_F32}, {DT_NONE, DT_NONE}},
+ {{DT_NONE, DT_NONE}, {DT_S16, DT_U16}, {DT_S32, DT_U32}, {DT_NONE, DT_NONE}}
+ };
+ instruction->operation = operation[decode.vcom.l][decode.vcom.op];
+ if (decode.vcom.l == 0)
+ instruction->dataType = dtMap[0][decode.vcom.size][decode.vcom.f];
+ else
+ instruction->dataType = dtMap[1][decode.vcom.size][decode.vcom.q];
+
+ instruction->operands[0].cls = REG;
+ if (decode.vcom.l == 0)
+ instruction->operands[0].reg = (Register)(regMap[decode.vcom.q] + (((decode.vcom.d << 4) | decode.vcom.vd) >> decode.vcom.q));
+ else
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcom.q] + (((decode.vcom.n << 4) | decode.vcom.vn) >> decode.vcom.q));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].flags.hasElements = 1;
+ if (decode.vcom.size == 0 || (decode.vcom.f == 1 && decode.vcom.size == 1))
+ {
+ return 1;
+ }
+ else if (decode.vcom.size == 1)
+ {
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm & 7));
+ instruction->operands[2].imm = (decode.vcom.m << 1) |(decode.vcom.vm >> 3);
+ }
+ else if (decode.vcom.size == 2)
+ {
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm));
+ instruction->operands[2].imm = decode.vcom.m;
+ }
+ else
+ return 1;
+ }
+ break;
+ case 3:
+ case 7:
+ if (decode.com.u == 0)
+ {
+
+ static Operation operation[2] = {ARMV7_VQDMLAL, ARMV7_VQDMLSL};
+ static DataType dtMap[4] = {DT_NONE, DT_S16, DT_S32, DT_NONE};
+ instruction->dataType = dtMap[decode.vcom.size];
+ if ((decode.vcom.vd & 1) == 1)
+ return 1;
+ if (decode.vcom.diff == 1)
+ {
+ //Encoding T1/A1
+ instruction->operation = operation[decode.vcom.l];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + ((decode.vcom.m << 4) | decode.vcom.vm));
+ }
+ else
+ {
+ //Encoding T2/A2
+ instruction->operation = operation[decode.vcom.op];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm & 7));
+ if (decode.vcom.size == 1)
+ instruction->operands[2].imm = (decode.vcom.m << 1) | (decode.vcom.vm >> 3);
+ else
+ instruction->operands[2].imm = decode.vcom.m;
+
+ instruction->operands[2].flags.hasElements = 1;
+ }
+ }
+ break;
+ case 8:
+ case 9:
+ {
+ static DataType dtMap[2][4] = {
+ {DT_NONE, DT_I16, DT_I32, DT_NONE},
+ {DT_NONE, DT_NONE, DT_F32, DT_NONE}
+ };
+ instruction->operation = ARMV7_VMUL;
+ instruction->dataType = dtMap[decode.vcom.f][decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vcom.q] + (((decode.vcom.d << 4) | decode.vcom.vd) >> decode.vcom.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcom.q] + (((decode.vcom.n << 4) | decode.vcom.vn) >> decode.vcom.q));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].flags.hasElements = 1;
+ if (decode.vcom.size == 1)
+ {
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm & 7));
+ instruction->operands[2].imm = (decode.vcom.m << 1) | (decode.vcom.vm >> 3);
+ }
+ else if (decode.vcom.size == 2)
+ {
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm));
+ instruction->operands[2].imm = decode.vcom.m;
+ }
+ else
+ return 1;
+ }
+ break;
+ case 10:
+ {
+ static DataType dtMap[4] = {DT_NONE, DT_S16, DT_S32, DT_NONE};
+ instruction->operation = ARMV7_VMULL;
+ instruction->dataType = dtMap[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + (((decode.vcom.n << 4) | decode.vcom.vn) >> decode.vcom.q));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].flags.hasElements = 1;
+ if (decode.vcom.size == 1)
+ {
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm & 7));
+ instruction->operands[2].imm = (decode.vcom.m << 1) | (decode.vcom.vm >> 3);
+ }
+ else if (decode.vcom.size == 2)
+ {
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm));
+ instruction->operands[2].imm = decode.vcom.m;
+ }
+ else
+ return 1;
+ }
+ break;
+ case 11:
+ if (decode.com.u == 0)
+ {
+ static DataType dtMap[4] = {DT_NONE, DT_S16, DT_S32, DT_NONE};
+ instruction->operation = ARMV7_VQDMULL;
+ instruction->dataType = dtMap[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vcom.d << 4) | decode.vcom.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcom.n << 4) | decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm & 7));
+ instruction->operands[2].imm = (decode.vcom.m << 1) | (decode.vcom.vm >> 3);
+ instruction->operands[2].flags.hasElements = 1;
+
+ }
+ break;
+ case 12:
+ {
+ //Encoding T2/A2
+ static DataType dtMap[4] = {DT_NONE, DT_S16, DT_S32, DT_NONE};
+ instruction->operation = ARMV7_VQDMULH;
+ instruction->dataType = dtMap[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vcom.q] + (decode.vcom.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcom.q] + (decode.vcom.vn));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm & 7));
+ instruction->operands[2].imm = (decode.vcom.m << 1) | (decode.vcom.vm >> 3);
+ instruction->operands[2].flags.hasElements = 1;
+ }
+ break;
+ case 13:
+ {
+ //Encoding T2/A2
+ static DataType dtMap[4] = {DT_NONE, DT_S16, DT_S32, DT_NONE};
+ instruction->operation = ARMV7_VQRDMULH;
+ instruction->dataType = dtMap[decode.vcom.size];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(((regMap[decode.vcom.q] + (((decode.vcom.d << 4) | decode.vcom.vd))) >> decode.vcom.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(((regMap[decode.vcom.q] + (((decode.vcom.n << 4) | decode.vcom.vn))) >> decode.vcom.q));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(REG_D0 + (decode.vcom.vm & 7));
+ instruction->operands[2].imm = (decode.vcom.m << 1) | (decode.vcom.vm >> 3);
+ instruction->operands[2].flags.hasElements = 1;
+ }
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_two_register_and_shift(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.4.4 Two registers and a shift amount*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:6;
+ uint32_t b:1;
+ uint32_t l:1;
+ uint32_t a:4;
+ uint32_t group2:7;
+ uint32_t imm3:3;
+ uint32_t group3:2;
+ uint32_t u:1;
+ uint32_t group4:7;
+ } com;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t l:1;
+ uint32_t op:1;
+ uint32_t group2:3;
+ uint32_t vd:4;
+ uint32_t imm6:6;
+ uint32_t d:1;
+ uint32_t group3:1;
+ uint32_t u:1;
+ uint32_t group4:7;
+ } vshr;
+ } decode;
+ /*
+ * VSHR<c>.<type><size> <Qd>, <Qm>, #<imm>
+ * VSHR<c>.<type><size> <Dd>, <Dm>, #<imm>
+ * VSRA<c>.<type><size> <Qd>, <Qm>, #<imm>
+ * VSRA<c>.<type><size> <Dd>, <Dm>, #<imm>
+ * VRSHR<c>.<type><size> <Qd>, <Qm>, #<imm>
+ * VRSHR<c>.<type><size> <Dd>, <Dm>, #<imm>
+ * VRSRA<c>.<type><size> <Qd>, <Qm>, #<imm>
+ * VRSRA<c>.<type><size> <Dd>, <Dm>, #<imm>
+ * VSRI<c>.<size> <Qd>, <Qm>, #<imm>
+ * VSRI<c>.<size> <Dd>, <Dm>, #<imm>
+ * VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
+ * VSHL<c>.I<size> <Dd>, <Dm>, #<imm>
+ * VSLI<c>.<size> <Qd>, <Qm>, #<imm>
+ * VSLI<c>.<size> <Dd>, <Dm>, #<imm>
+ * VQSHL{U}<c>.<type><size> <Qd>, <Qm>, #<imm>
+ * VQSHL{U}<c>.<type><size> <Dd>, <Dm>, #<imm>
+ * VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
+ * VQSHR{U}N<c>.<type><size> <Dd>, <Qm>, #<imm>
+ * VQRSHR{U}N<c>.<type><size> <Dd>, <Qm>, #<imm>
+ * VQSHR{U}N<c>.<type><size> <Dd>, <Qm>, #<imm>
+ * VQRSHR{U}N<c>.<type><size> <Dd>, <Qm>, #<imm>
+ * VSHLL<c>.<type><size> <Qd>, <Dm>, #<imm> //A1
+ * VMOVL<c>.<dt> <Qd>, <Dm>
+ * VCVT<c>.<Td>.<Tm> <Qd>, <Qm>, #<fbits>
+ * VCVT<c>.<Td>.<Tm> <Dd>, <Dm>, #<fbits>
+ */
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+ switch (decode.com.a)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ {
+ static Operation operation[4] = {
+ ARMV7_VSHR, ARMV7_VSRA, ARMV7_VRSHR, ARMV7_VRSRA};
+ instruction->operation = operation[decode.com.a];
+
+ static DataType dtMap[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_S64},
+ {DT_U8, DT_U16, DT_U32, DT_U64}
+ };
+ uint32_t imm = (decode.vshr.l << 6) | decode.vshr.imm6;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.d << 4) | decode.vshr.vd) >> decode.vshr.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.m << 4) | decode.vshr.vm) >> decode.vshr.q));
+ instruction->operands[2].cls = IMM;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = 16 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][0];
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = 32 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][1];
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][2];
+ }
+ else if (imm < 128)
+ {
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][3];
+ }
+ }
+ break;
+ case 4:
+ if (decode.com.u == 1)
+ {
+ instruction->operation = ARMV7_VSRI;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.d << 4) | decode.vshr.vd) >> decode.vshr.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.m << 4) | decode.vshr.vm) >> decode.vshr.q));
+ instruction->operands[2].cls = IMM;
+ uint32_t imm = (decode.vshr.l << 6) | decode.vshr.imm6;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = 16 - decode.vshr.imm6;
+ instruction->dataType = DT_8;
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = 32 - decode.vshr.imm6;
+ instruction->dataType = DT_16;
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ instruction->dataType = DT_32;
+ }
+ else if (imm < 128)
+ {
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ instruction->dataType = DT_64;
+ }
+ }
+ break;
+ case 5:
+ if (decode.com.u == 0)
+ {
+ instruction->operation = ARMV7_VSHL;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.d << 4) | decode.vshr.vd) >> decode.vshr.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.m << 4) | decode.vshr.vm) >> decode.vshr.q));
+ instruction->operands[2].cls = IMM;
+ uint32_t imm = (decode.vshr.l << 6) | decode.vshr.imm6;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 8;
+ instruction->dataType = DT_I8;
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 16;
+ instruction->dataType = DT_I16;
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 32;
+ instruction->dataType = DT_I32;
+ }
+ else if (imm < 128)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6;
+ instruction->dataType = DT_I64;
+ }
+ }
+ else
+ {
+ instruction->operation = ARMV7_VSLI;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vshr.q] + (((decode.vshr.d << 4) | decode.vshr.vd) >> decode.vshr.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vshr.q] + (((decode.vshr.m << 4) | decode.vshr.vm) >> decode.vshr.q));
+ instruction->operands[2].cls = IMM;
+ uint32_t imm = (decode.vshr.l << 6) | decode.vshr.imm6;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 8;
+ instruction->dataType = DT_8;
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 16;
+ instruction->dataType = DT_16;
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 32;
+ instruction->dataType = DT_32;
+ }
+ else if (imm < 128)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6;
+ instruction->dataType = DT_64;
+ }
+ }
+ break;
+ case 6:
+ case 7:
+ {
+ if (decode.vshr.op == 0)
+ {
+ if (decode.vshr.u == 0)
+ return 1;
+ instruction->operation = ARMV7_VQSHLU;
+ }
+ else
+ {
+ instruction->operation = ARMV7_VQSHL;
+ decode.com.u = !decode.com.u;
+ }
+ static DataType dtMap[2][4] = {
+ {DT_U8, DT_U16, DT_U32, DT_U64},
+ {DT_S8, DT_S16, DT_S32, DT_S64}
+ };
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vshr.q] + (((decode.vshr.d << 4) | decode.vshr.vd) >> decode.vshr.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vshr.q] + (((decode.vshr.m << 4) | decode.vshr.vm) >> decode.vshr.q));
+ instruction->operands[2].cls = IMM;
+ uint32_t imm = (decode.vshr.l << 6) | decode.vshr.imm6;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 8;
+ instruction->dataType = dtMap[decode.vshr.u][0];
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 16;
+ instruction->dataType = dtMap[decode.vshr.u][1];
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 32;
+ instruction->dataType = dtMap[decode.vshr.u][2];
+ }
+ else if (imm < 128)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][3];
+ }
+ }
+ break;
+ case 8:
+ if (decode.com.l == 0)
+ {
+ if (decode.com.u == 0)
+ {
+ static Operation operation[2] = {ARMV7_VSHRN, ARMV7_VRSHRN};
+ instruction->operation = operation[decode.com.b];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vshr.d << 4) | decode.vshr.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_Q0 + (((decode.vshr.m << 4) | decode.vshr.vm) >> 1));
+ instruction->operands[2].cls = IMM;
+ uint32_t imm = decode.vshr.imm6;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = 16 - decode.vshr.imm6;
+ instruction->dataType = DT_I16;
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = 32 - decode.vshr.imm6;
+ instruction->dataType = DT_I32;
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ instruction->dataType = DT_I64;
+ }
+ }
+ else
+ {
+ static Operation operation[2] = {ARMV7_VQSHRUN, ARMV7_VQRSHRUN};
+ instruction->operation = operation[decode.com.b];
+ DataType dtMap[2][4] = {
+ {DT_U8, DT_U16, DT_U32, DT_U64},
+ {DT_S8, DT_S16, DT_S32, DT_S64}
+ };
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vshr.d << 4) | decode.vshr.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_Q0 + (((decode.vshr.m << 4) | decode.vshr.vm) >> 1));
+ instruction->operands[2].cls = IMM;
+ uint32_t imm = decode.vshr.imm6;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = 16 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][1];
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = 32 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][2];
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][3];
+ }
+ }
+ }
+ break;
+ case 9:
+ if (decode.com.l == 0)
+ {
+ static Operation operation[2] = {ARMV7_VQSHRN, ARMV7_VQRSHRN};
+ instruction->operation = operation[decode.com.b];
+ static DataType dtMap[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_S64},
+ {DT_U8, DT_U16, DT_U32, DT_U64}
+ };
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vshr.d << 4) | decode.vshr.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_Q0 + (((decode.vshr.m << 4) | decode.vshr.vm) >> 1));
+ instruction->operands[2].cls = IMM;
+ uint32_t imm = decode.vshr.imm6;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = 16 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][1];
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = 32 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][2];
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ instruction->dataType = dtMap[decode.vshr.u][3];
+ }
+ }
+ break;
+ case 10:
+ if (decode.com.b == 0 && decode.com.l == 0)
+ {
+ instruction->operation = ARMV7_VSHLL;
+ static DataType dtMap[2][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_S64},
+ {DT_U8, DT_U16, DT_U32, DT_U64}
+ };
+ uint32_t imm = decode.vshr.imm6;
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vshr.d << 4) | decode.vshr.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vshr.m << 4) | decode.vshr.vm));
+ instruction->operands[2].cls = IMM;
+ if (imm < 16)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 8;
+ instruction->dataType = dtMap[decode.vshr.u][0];
+ }
+ else if (imm < 32)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 16;
+ instruction->dataType = dtMap[decode.vshr.u][1];
+ }
+ else if (imm < 64)
+ {
+ instruction->operands[2].imm = decode.vshr.imm6 - 32;
+ instruction->dataType = dtMap[decode.vshr.u][2];
+ }
+ if (instruction->operands[2].imm == 0)
+ {
+ instruction->operation = ARMV7_VMOVL;
+ instruction->operands[2].cls = NONE;
+ }
+ }
+ break;
+ case 14:
+ case 15:
+ instruction->operation = ARMV7_VCVT;
+ static DataType dtMap[2] = {DT_S32, DT_U32};
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.d << 4) | decode.vshr.vd) >> decode.vshr.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)
+ (regMap[decode.vshr.q] + (((decode.vshr.m << 4) | decode.vshr.vm) >> decode.vshr.q));
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = 64 - decode.vshr.imm6;
+ if (decode.vshr.op == 1)
+ {
+ instruction->dataType = dtMap[decode.vshr.u];
+ instruction->dataType2 = DT_F32;
+ }
+ else
+ {
+ instruction->dataType = DT_F32;
+ instruction->dataType2 = dtMap[decode.vshr.u];
+ }
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_two_register_misc(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.4.5 Two registers, miscellaneous*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:6;
+ uint32_t b:5;
+ uint32_t group2:5;
+ uint32_t a:2;
+ uint32_t group3:14;
+ } com;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t op:2;
+ uint32_t group2:3;
+ uint32_t vd:4;
+ uint32_t group3:2;
+ uint32_t size:2;
+ uint32_t group4:2;
+ uint32_t d:1;
+ uint32_t group5:9;
+ } vrev;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t group2:3;
+ uint32_t f:1;
+ uint32_t group3:1;
+ uint32_t vd:4;
+ uint32_t group4:2;
+ uint32_t size:2;
+ uint32_t group5:2;
+ uint32_t d:1;
+ uint32_t group6:9;
+ } vcgt;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t op:2;
+ uint32_t group2:4;
+ uint32_t vd:4;
+ uint32_t group4:2;
+ uint32_t size:2;
+ uint32_t group5:2;
+ uint32_t d:1;
+ uint32_t group6:9;
+ } vqmov;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t group2:1;
+ uint32_t f:1;
+ uint32_t vd:4;
+ uint32_t group4:2;
+ uint32_t size:2;
+ uint32_t group5:2;
+ uint32_t d:1;
+ uint32_t group6:9;
+ } vrsqrte;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:2;
+ uint32_t op:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t group4:2;
+ uint32_t size:2;
+ uint32_t group5:2;
+ uint32_t d:1;
+ uint32_t group6:9;
+ } vcvt;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t q:1;
+ uint32_t op:2;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t group4:2;
+ uint32_t size:2;
+ uint32_t group5:2;
+ uint32_t d:1;
+ uint32_t group6:9;
+ } vcvt2;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+
+ switch (decode.com.a)
+ {
+ case 0:
+ {
+ static DataType dtMap[5][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_S64},
+ {DT_U8, DT_U16, DT_U32, DT_U64},
+ {DT_I8, DT_I16, DT_I32, DT_I64},
+ {DT_8, DT_16, DT_32, DT_64},
+ {DT_NONE, DT_NONE, DT_NONE, DT_NONE}
+ };
+ switch (decode.com.b)
+ {
+ case 0:
+ case 1:
+ if (decode.vrev.op + decode.vrev.size >= 3)
+ return 1;
+ instruction->operation = ARMV7_VREV64;
+ instruction->dataType = dtMap[3][decode.vrev.size];
+ break;
+ case 2:
+ case 3:
+ if (decode.vrev.op + decode.vrev.size >= 3)
+ return 1;
+ instruction->operation = ARMV7_VREV32;
+ instruction->dataType = dtMap[3][decode.vrev.size];
+ break;
+ case 4:
+ case 5:
+ if (decode.vrev.op + decode.vrev.size >= 3)
+ return 1;
+ instruction->operation = ARMV7_VREV16;
+ instruction->dataType = dtMap[3][decode.vrev.size];
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ if (decode.vrev.size == 3)
+ return 1;
+ //op is guaranteed to be < 2
+ instruction->operation = ARMV7_VPADDL;
+ instruction->dataType = dtMap[decode.vrev.op][decode.vrev.size];
+ break;
+ case 16:
+ case 17:
+ if (decode.vrev.size == 3)
+ return 1;
+ instruction->operation = ARMV7_VCLS;
+ instruction->dataType = dtMap[0][decode.vrev.size];
+ break;
+ case 18:
+ case 19:
+ if (decode.vrev.size == 3)
+ return 1;
+ instruction->operation = ARMV7_VCLZ;
+ instruction->dataType = dtMap[2][decode.vrev.size];
+ break;
+ case 20:
+ case 21:
+ if (decode.vrev.size != 0)
+ return 1;
+ instruction->operation = ARMV7_VCNT;
+ instruction->dataType = DT_8;
+ break;
+ case 22:
+ case 23:
+ if (decode.vrev.size != 0)
+ return 1;
+ instruction->operation = ARMV7_VMVN;
+ instruction->dataType = dtMap[4][decode.vrev.size];
+ break;
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ if (decode.vrev.size == 3)
+ return 1;
+ instruction->operation = ARMV7_VPADAL;
+ instruction->dataType = dtMap[decode.vrev.op][decode.vrev.size];
+ break;
+ case 28:
+ case 29:
+ if (decode.vrev.size == 3)
+ return 1;
+ instruction->operation = ARMV7_VQABS;
+ instruction->dataType = dtMap[0][decode.vrev.size];
+ break;
+ case 30:
+ case 31:
+ if (decode.vrev.size == 3)
+ return 1;
+ instruction->operation = ARMV7_VQNEG;
+ instruction->dataType = dtMap[0][decode.vrev.size];
+ break;
+ }
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vrev.q] + (((decode.vrev.d << 4) | decode.vrev.vd) >> decode.vrev.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vrev.q] + (((decode.vrev.m << 4) | decode.vrev.vm) >> decode.vrev.q));
+ }
+ break;
+ case 1:
+ {
+ static DataType dtMap[4][4] = {
+ {DT_S8, DT_S16, DT_S32, DT_NONE},
+ {DT_NONE, DT_NONE, DT_F32, DT_NONE},
+ {DT_I8, DT_I16, DT_I32, DT_NONE},
+ {DT_NONE, DT_NONE, DT_F32, DT_NONE}
+ };
+ uint32_t type = 0;
+ switch (decode.com.b)
+ {
+ case 0:
+ case 1:
+ case 16:
+ case 17:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.f == 1 && decode.vcgt.size != 2))
+ return 1;
+ instruction->operation = ARMV7_VCGT;
+ instruction->dataType = dtMap[decode.vcgt.f][decode.vcgt.size];
+ break;
+ case 2:
+ case 3:
+ case 18:
+ case 19:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.f == 1 && decode.vcgt.size != 2))
+ return 1;
+ instruction->operation = ARMV7_VCGE;
+ instruction->dataType = dtMap[decode.vcgt.f][decode.vcgt.size];
+ break;
+ case 4:
+ case 5:
+ case 20:
+ case 21:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.f == 1 && decode.vcgt.size != 2))
+ return 1;
+ instruction->operation = ARMV7_VCEQ;
+ instruction->dataType = dtMap[2 + decode.vcgt.f][decode.vcgt.size];
+ break;
+ case 6:
+ case 7:
+ case 22:
+ case 23:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.f == 1 && decode.vcgt.size != 2))
+ return 1;
+ instruction->operation = ARMV7_VCLE;
+ instruction->dataType = dtMap[decode.vcgt.f][decode.vcgt.size];
+ break;
+ case 8:
+ case 9:
+ case 24:
+ case 25:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.f == 1 && decode.vcgt.size != 2))
+ return 1;
+ instruction->operation = ARMV7_VCLT;
+ instruction->dataType = dtMap[decode.vcgt.f][decode.vcgt.size];
+ break;
+ case 12:
+ case 13:
+ case 28:
+ case 29:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.f == 1 && decode.vcgt.size != 2))
+ return 1;
+ instruction->operation = ARMV7_VABS;
+ instruction->dataType = dtMap[decode.vcgt.f][decode.vcgt.size];
+ type = 1;
+ break;
+ case 14:
+ case 15:
+ case 30:
+ case 31:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.f == 1 && decode.vcgt.size != 2))
+ return 1;
+ instruction->operation = ARMV7_VNEG;
+ instruction->dataType = dtMap[decode.vcgt.f][decode.vcgt.size];
+ type = 1;
+ break;
+ }
+
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vcgt.q] + (((decode.vrev.d << 4) | decode.vcgt.vd) >> decode.vcgt.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcgt.q] + (((decode.vcgt.m << 4) | decode.vcgt.vm) >> decode.vcgt.q));
+ if (type == 0)
+ {
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = 0;
+ }
+ }
+ break;
+ case 2:
+ {
+ static DataType dtMap[4][4] = {
+ {DT_8, DT_16, DT_32, DT_64},
+ {DT_I8, DT_I16, DT_I32, DT_I64},
+ {DT_S8, DT_S16, DT_S32, DT_S64},
+ {DT_U8, DT_U16, DT_U32, DT_U64}
+ };
+ uint32_t type = 0;
+ switch (decode.com.b)
+ {
+ case 0:
+ case 1:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.q == 0 && decode.vcgt.size == 2))
+ return 1;
+ instruction->operation = ARMV7_VSWP;
+ break;
+ case 2:
+ case 3:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.q == 1 &&
+ ((decode.vcgt.vd & 1) == 1 || (decode.vcgt.vm & 1) == 1)))
+ return 1;
+ instruction->operation = ARMV7_VTRN;
+ instruction->dataType = dtMap[0][decode.vcgt.size];
+ break;
+ case 4:
+ case 5:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.q == 1 &&
+ ((decode.vcgt.vd & 1) == 1 || (decode.vcgt.vm & 1) == 1)))
+ return 1;
+ instruction->operation = ARMV7_VUZP;
+ instruction->dataType = dtMap[0][decode.vcgt.size];
+ break;
+ case 6:
+ case 7:
+ if (decode.vcgt.size == 3 ||
+ (decode.vcgt.q == 1 &&
+ ((decode.vcgt.vd & 1) == 1 || (decode.vcgt.vm & 1) == 1)))
+ return 1;
+ instruction->operation = ARMV7_VZIP;
+ instruction->dataType = dtMap[0][decode.vcgt.size];
+ break;
+ case 8:
+ if (decode.vcgt.size == 3 || (decode.vcgt.vm & 1) == 1)
+ return 1;
+ type = 2;
+ instruction->operation = ARMV7_VMOVN;
+ instruction->dataType = dtMap[1][decode.vcgt.size+1];
+ break;
+ case 9:
+ case 10:
+ case 11:
+ {
+ if (decode.vcgt.size == 3 || (decode.vcgt.vm & 1) == 1)
+ return 1;
+ Operation operation[4] = {
+ ARMV7_UNDEFINED, ARMV7_VQMOVUN, ARMV7_VQMOVN, ARMV7_VQMOVN};
+ type = 2;
+ instruction->operation = operation[decode.vqmov.op];
+ if (instruction->operation == ARMV7_VQMOVUN)
+ instruction->dataType = dtMap[2][decode.vcgt.size+1];
+ else
+ {
+ if (decode.vqmov.op == 2)
+ instruction->dataType = dtMap[2][decode.vcgt.size+1];
+ else if (decode.vqmov.op == 3)
+ instruction->dataType = dtMap[3][decode.vcgt.size+1];
+ }
+ }
+ break;
+ case 12:
+ instruction->operation = ARMV7_VSHLL;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = 8 << decode.vqmov.size;
+ instruction->dataType = dtMap[1][decode.vqmov.size];
+ type = 1;
+ break;
+ case 24:
+ case 28:
+ {
+ DataType dtMap2[2] = {DT_F16, DT_F32};
+ instruction->operation = ARMV7_VCVT;
+ instruction->dataType = dtMap2[decode.vcvt.op];
+ instruction->dataType2 = dtMap2[!decode.vcvt.op];
+ type = 3;
+ }
+ break;
+ }
+
+ if (type == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vcgt.q] + (((decode.vrev.d << 4) | decode.vcgt.vd) >> decode.vcgt.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcgt.q] + (((decode.vcgt.m << 4) | decode.vcgt.vm) >> decode.vcgt.q));
+ }
+ else if (type == 1)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vrev.d << 4) | decode.vcgt.vd) >> 1));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcgt.m << 4) | decode.vcgt.vm));
+ }
+ else if (type == 2)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vrev.d << 4) | decode.vcgt.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_Q0 + (((decode.vcgt.m << 4) | decode.vcgt.vm) >> 1));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vcvt.op] + (((decode.vrev.d << 4) | decode.vcgt.vd) >> decode.vcvt.op));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[!decode.vcvt.op] + (((decode.vcgt.m << 4) | decode.vcgt.vm) >> !decode.vcvt.op));
+ }
+
+ }
+ break;
+ case 3:
+ {
+ static DataType dtMap[2][4] = {
+ {DT_U8, DT_U16, DT_U32, DT_U64},
+ {DT_NONE, DT_F16, DT_F32, DT_F64}
+ };
+ switch (decode.com.b)
+ {
+ case 16:
+ case 17:
+ case 20:
+ case 21:
+ instruction->operation = ARMV7_VRECPE;
+ instruction->dataType = dtMap[decode.vrsqrte.f][decode.vcgt.size];
+ break;
+ case 18:
+ case 19:
+ case 22:
+ case 23:
+ instruction->operation = ARMV7_VRSQRTE;
+ instruction->dataType = dtMap[decode.vrsqrte.f][decode.vcgt.size];
+ break;
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ instruction->operation = ARMV7_VCVT;
+ if (decode.vcvt2.op < 2)
+ {
+ instruction->dataType = DT_F32;
+ if ((decode.vcvt2.op & 1) == 1)
+ instruction->dataType2 = DT_U32;
+ else
+ instruction->dataType2 = DT_S32;
+ }
+ else
+ {
+ instruction->dataType2 = DT_F32;
+ if ((decode.vcvt2.op & 1) == 1)
+ instruction->dataType = DT_U32;
+ else
+ instruction->dataType = DT_S32;
+ }
+ break;
+ }
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vcgt.q] + (((decode.vcgt.d << 4) | decode.vcgt.vd) >> decode.vcgt.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(regMap[decode.vcgt.q] + (((decode.vcgt.m << 4) | decode.vcgt.vm) >> decode.vcgt.q));
+ }
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_one_register_and_modified_imm(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.4.6 One register and a modified immediate value*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:5;
+ uint32_t op:1;
+ uint32_t group2:2;
+ uint32_t cmode:4;
+ uint32_t group3:20;
+ } com;
+ struct {
+ uint32_t imm4:4;
+ uint32_t group1:1;
+ uint32_t op:1;
+ uint32_t q:1;
+ uint32_t group2:1;
+ uint32_t cmode:4;
+ uint32_t vd:4;
+ uint32_t imm3:3;
+ uint32_t group3:3;
+ uint32_t d:1;
+ uint32_t group4:1;
+ uint32_t i:1;
+ uint32_t group5:7;
+ } vmov;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+ if (decode.com.op == 0)
+ {
+ switch (decode.com.cmode)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ instruction->operation = ARMV7_VMOV;
+ break;
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ instruction->operation = ARMV7_VORR;
+ break;
+ case 8:
+ case 10:
+ instruction->operation = ARMV7_VMOV;
+ break;
+ case 9:
+ case 11:
+ instruction->operation = ARMV7_VORR;
+ break;
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ instruction->operation = ARMV7_VMOV;
+ break;
+ }
+
+ }
+ else
+ {
+ switch (decode.com.cmode)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ instruction->operation = ARMV7_VMVN;
+ break;
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ instruction->operation = ARMV7_VBIC;
+ break;
+ case 8:
+ case 10:
+ instruction->operation = ARMV7_VMVN;
+ break;
+ case 9:
+ case 11:
+ instruction->operation = ARMV7_VBIC;
+ break;
+ case 12:
+ case 13:
+ instruction->operation = ARMV7_VMVN;
+ break;
+ case 14:
+ instruction->operation = ARMV7_VMOV;
+ break;
+ }
+ }
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vmov.q] + (((decode.vmov.d << 4) | decode.vmov.vd) >> decode.vmov.q));
+ instruction->operands[1].cls = IMM;
+ if (simdExpandImm(
+ decode.vmov.op,
+ decode.vmov.cmode,
+ (decode.vmov.i << 7) | (decode.vmov.imm3 << 4) | decode.vmov.imm4,
+ &instruction->operands[1].imm64,
+ &instruction->dataType,
+ &instruction->operands[1].cls) == 0)
+ return 1;
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+uint32_t armv7_floating_point_data_processing(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.5 Floating-point data-processing instructions*/
+ (void)address;
+ union{
+ uint32_t value;
+ struct{
+ uint32_t opc4:4;
+ uint32_t group1:2;
+ uint32_t opc3:2;
+ uint32_t sz:1;
+ uint32_t group2:7;
+ uint32_t opc2:4;
+ uint32_t opc1:4;
+ uint32_t group3:4;
+ uint32_t cond:4;
+ }com;
+ struct{
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t op:1;
+ uint32_t n:1;
+ uint32_t sz:1;
+ uint32_t group2:3;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t group3:2;
+ uint32_t d:1;
+ uint32_t group4:4;
+ uint32_t t:1;
+ uint32_t group5:4;
+ }vmla;
+ struct{
+ uint32_t imm4l:4;
+ uint32_t group1:4;
+ uint32_t sz:1;
+ uint32_t group2:3;
+ uint32_t vd:4;
+ uint32_t imm4h:4;
+ uint32_t group3:2;
+ uint32_t d:1;
+ uint32_t group4:9;
+ }vmov;
+ struct{
+ uint32_t imm4:4;
+ uint32_t group1:1;
+ uint32_t i:1;
+ uint32_t group2:1;
+ uint32_t sx:1;
+ uint32_t sf:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t u:1;
+ uint32_t group4:1;
+ uint32_t op:1;
+ uint32_t group5:3;
+ uint32_t d:1;
+ uint32_t group6:9;
+ }vcvt;
+ struct{
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t op:1;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t rm:2;
+ uint32_t group4:4;
+ uint32_t d:1;
+ uint32_t group5:9;
+ }vcvt2;
+ struct{
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t t:1;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t op:1;
+ uint32_t group4:5;
+ uint32_t d:1;
+ uint32_t group5:9;
+ }vcvtt;
+ struct{
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t op:1;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t group4:6;
+ uint32_t d:1;
+ uint32_t group5:9;
+ }vrint;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t op:1;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t rm:2;
+ uint32_t group4:4;
+ uint32_t d:1;
+ uint32_t group5:9;
+ }vcvta;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t op:1;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t rm:2;
+ uint32_t group4:4;
+ uint32_t d:1;
+ uint32_t group5:9;
+ } vcvtr;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:1;
+ uint32_t n:1;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t cc:2;
+ uint32_t d:1;
+ uint32_t group4:9;
+ } vsel;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t op:1;
+ uint32_t n:1;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t vn:4;
+ uint32_t group4:2;
+ uint32_t d:1;
+ uint32_t group5:9;
+ } vmax;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:2;
+ uint32_t sz:1;
+ uint32_t group3:3;
+ uint32_t vd:4;
+ uint32_t rm:2;
+ uint32_t group4:4;
+ uint32_t d:1;
+ uint32_t group5:9;
+ } vrint2;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)decode.com.cond;
+ instruction->dataType = (DataType)(DT_F32 + decode.vmla.sz);
+ uint32_t type = 0;
+ /*
+ * VNMLA<c>.F64 <Dd>, <Dn>, <Dm>
+ * VNMLA<c>.F32 <Sd>, <Sn>, <Sm>
+ * VNMLS<c>.F64 <Dd>, <Dn>, <Dm>
+ * VNMLS<c>.F32 <Sd>, <Sn>, <Sm>
+ * VNMUL<c>.F64 <Dd>, <Dn>, <Dm>
+ * VNMUL<c>.F32 <Sd>, <Sn>, <Sm>
+ */
+ switch (decode.com.opc1)
+ {
+ case 0:
+ case 4:
+ {
+ static Operation operation[2] = {ARMV7_VMLA, ARMV7_VMLS};
+ instruction->operation = operation[decode.vmla.op];
+ type = 1;
+ }
+ break;
+ case 1:
+ case 5:
+ {
+ static Operation operation[2] = {ARMV7_VNMLS, ARMV7_VNMLA};
+ instruction->operation = operation[decode.vmla.op];
+ type = 1;
+ }
+ break;
+ case 2:
+ case 6:
+ {
+ static Operation operation[2] = {ARMV7_VMUL, ARMV7_VNMUL};
+ instruction->operation = operation[decode.com.opc3 & 1];
+ type = 1;
+ }
+ break;
+ case 3:
+ case 7:
+ {
+ static Operation operation[2] = {ARMV7_VADD, ARMV7_VSUB};
+ instruction->operation = operation[decode.com.opc3 & 1];
+ type = 1;
+ }
+ break;
+ case 8:
+ case 12:
+ {
+ static Operation operation[4] = {ARMV7_VDIV, ARMV7_UNDEFINED, ARMV7_VDIV, ARMV7_UNDEFINED};
+ instruction->operation = operation[decode.com.opc3];
+ type = 1;
+ }
+ break;
+ case 9:
+ case 13:
+ {
+ static Operation operation[2] = {ARMV7_VFNMS, ARMV7_VFNMA};
+ instruction->operation = operation[decode.vmla.op];
+ type = 1;
+ }
+ break;
+ case 10:
+ case 14:
+ {
+ static Operation operation[2] = {ARMV7_VFMA, ARMV7_VFMS};
+ instruction->operation = operation[decode.vmla.op];
+ type = 1;
+ }
+ break;
+ case 11:
+ case 15:
+ /*
+ * VMOV<c>.F64 <Dd>, #<imm>
+ * VMOV<c>.F32 <Sd>, #<imm>
+ * VMOV<c>.F64 <Dd>, <Dm>
+ * VMOV<c>.F32 <Sd>, <Sm>
+ * VABS<c>.F64 <Dd>, <Dm>
+ * VABS<c>.F32 <Sd>, <Sm>
+ * VNEG<c>.F64 <Dd>, <Dm>
+ * VNEG<c>.F32 <Sd>, <Sm>
+ * VSQRT<c>.F64 <Dd>, <Dm>
+ * VSQRT<c>.F32 <Sd>, <Sm>
+ * VCVT<y><c>.F32.F16 <Sd>, <Sm>
+ * VCVT<y><c>.F16.F32 <Sd>, <Sm>
+ * VCMP{E}<c>.F64 <Dd>, <Dm>
+ * VCMP{E}<c>.F32 <Sd>, <Sm>
+ * VCMP{E}<c>.F64 <Dd>, #0.0
+ * VCMP{E}<c>.F32 <Sd>, #0.0
+ * VCVT<c>.F64.F32 <Dd>, <Sm>
+ * VCVT<c>.F32.F64 <Sd>, <Dm>
+ * VCVT{R}<c>.S32.F64 <Sd>, <Dm>
+ * VCVT{R}<c>.S32.F32 <Sd>, <Sm>
+ * VCVT{R}<c>.U32.F64 <Sd>, <Dm>
+ * VCVT{R}<c>.U32.F32 <Sd>, <Sm>
+ * VCVT<c>.F64.<Tm> <Dd>, <Sm>
+ * VCVT<c>.F32.<Tm> <Sd>, <Sm>
+ * VCVT<c>.<Td>.F64 <Dd>, <Dd>, #<fbits>
+ * VCVT<c>.<Td>.F32 <Sd>, <Sd>, #<fbits>
+ * VCVT<c>.F64.<Td> <Dd>, <Dd>, #<fbits>
+ * VCVT<c>.F32.<Td> <Sd>, <Sd>, #<fbits>
+ */
+ type = 1;
+ static uint32_t fregMap[2] = {REG_S0, REG_D0};
+ if ((decode.com.opc3 & 1) == 0)
+ {
+ instruction->operation = ARMV7_VMOV;
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmov.vd << 1) | decode.vmov.d));
+ instruction->operands[1].cls = FIMM32;
+ instruction->operands[1].imm =
+ VFPExpandImm32(decode.vmov.imm4h << 4 | decode.vmov.imm4l);
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmov.d << 4) | decode.vmov.vd));
+ instruction->operands[1].cls = FIMM64;
+ instruction->operands[1].imm64 =
+ VFPExpandImm64(decode.vmov.imm4h << 4 | decode.vmov.imm4l);
+ }
+ }
+ else
+ {
+ switch (decode.com.opc2)
+ {
+ case 0:
+ {
+ static OperandClass immMap[2] = {FIMM32, FIMM64};
+ instruction->operands[0].cls = REG;
+ if (decode.com.opc3 == 1)
+ {
+ instruction->operation = ARMV7_VMOV;
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[1].cls = immMap[decode.vmla.sz];
+ instruction->operands[1].imm =
+ VFPExpandImm32(decode.vmla.vn << 4 | decode.vmla.vm);
+ }
+ else
+ {
+ instruction->operands[0].reg = (Register)(REG_Q0 + (((decode.vmla.d << 4) | decode.vmla.vd) >> 1));
+ instruction->operands[1].cls = immMap[decode.vmla.sz];
+ instruction->operands[1].imm64 =
+ VFPExpandImm64(decode.vmla.vn << 4 | decode.vmla.vm);
+ }
+ }
+ else
+ {
+ instruction->operation = ARMV7_VABS;
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vmla.m << 4) | decode.vmla.vm));
+ }
+ }
+ }
+ break;
+ case 1:
+ {
+ static Operation operation[4] = {
+ ARMV7_UNDEFINED, ARMV7_VNEG,
+ ARMV7_UNDEFINED, ARMV7_VSQRT,
+ };
+ instruction->operation = operation[decode.com.opc3];
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vmla.m << 4) | decode.vmla.vm));
+ }
+ }
+ break;
+ case 2:
+ case 3:
+ {
+ static Operation operation[2] = {ARMV7_VCVTB, ARMV7_VCVTT};
+ instruction->operation = operation[decode.vcvtt.t];
+ static DataType dtMap[2][2] = {
+ {DT_F16, DT_F32},
+ {DT_F16, DT_F64}
+ };
+ instruction->dataType = dtMap[decode.vcvtt.sz][!decode.vcvtt.op];
+ instruction->dataType2 = dtMap[decode.vcvtt.sz][decode.vcvtt.op];
+ if (decode.vcvtt.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vcvtt.vd << 1) | decode.vcvtt.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vcvtt.vm << 1) | decode.vcvtt.m));
+
+ }
+ else
+ {
+ if (decode.vcvtt.op == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vcvtt.d << 4) | decode.vcvtt.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vcvtt.vm << 1) | decode.vcvtt.m));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vcvtt.vd << 1) | decode.vcvtt.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vcvtt.m << 4) | decode.vcvtt.vm));
+ }
+ }
+ }
+ break;
+ case 4:
+ {
+ static Operation operation[2] = {ARMV7_VCMP, ARMV7_VCMPE};
+ instruction->operation = operation[decode.vmla.n];
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vmla.m << 4) | decode.vmla.vm));
+ }
+ }
+ break;
+ case 5:
+ {
+ static Operation operation[2] = {ARMV7_VCMP, ARMV7_VCMPE};
+ instruction->operation = operation[decode.vmla.n];
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ }
+ instruction->operands[1].cls = FIMM32;
+ }
+ break;
+ case 6:
+ {
+ static Operation operation[2] = {ARMV7_VRINTR, ARMV7_VRINTZ};
+ instruction->operation = operation[decode.vrint.op];
+ if (decode.vrint.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vrint.vd << 1) | decode.vrint.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vrint.vm << 1) | decode.vrint.m));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vrint.d << 4) | decode.vrint.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vrint.m << 4) | decode.vrint.vm));
+ }
+ }
+ break;
+ case 7:
+ {
+ static DataType dtMap[2] = {DT_F32, DT_F64};
+ if (decode.com.opc3 == 3)
+ {
+ instruction->operation = ARMV7_VCVT;
+ instruction->dataType = dtMap[!decode.vmla.sz];
+ instruction->dataType2 = dtMap[decode.vmla.sz];
+ if (decode.vmla.sz == 1)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vmla.m << 4) | decode.vmla.vm));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ }
+
+ }
+ else
+ {
+ instruction->operation = ARMV7_VRINTX;
+ instruction->dataType = dtMap[decode.vmla.sz];
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vmla.m << 4) | decode.vmla.vm));
+ }
+ }
+ }
+ break;
+ case 8:
+ {
+ instruction->operation = ARMV7_VCVT;
+ static DataType dtMap1[2] = {DT_F32, DT_F64};
+ static DataType dtMap2[2] = {DT_U32, DT_S32};
+ instruction->dataType = dtMap1[decode.vcvtr.sz];
+ instruction->dataType2 = dtMap2[decode.vcvtr.op];
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ }
+
+ }
+ break;
+ case 12:
+ {
+ /*
+ * VCVT{R}<c>.S32.F64 <Sd>, <Dm>
+ * VCVT{R}<c>.S32.F32 <Sd>, <Sm>
+ * VCVT{R}<c>.U32.F64 <Sd>, <Dm>
+ * VCVT{R}<c>.U32.F32 <Sd>, <Sm>
+ * VCVT<c>.F64.<Tm> <Dd>, <Sm>
+ * VCVT<c>.F32.<Tm> <Sd>, <Sm>
+ */
+ if (decode.vmla.t == 0)
+ {
+ static Operation operation[2] = {ARMV7_VCVT, ARMV7_VCVTR};
+ instruction->operation = operation[decode.vmla.op];
+ static DataType dtMap[2] = {DT_F32, DT_F64};
+ instruction->dataType = dtMap[!decode.vcvt.u];
+ instruction->dataType2 = dtMap[decode.vcvt.u];
+ if (decode.vmla.sz == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vmla.d << 4) | decode.vmla.vd));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(REG_D0 + ((decode.vmla.m << 4) | decode.vmla.vm));
+ }
+ }
+ else
+ {
+ Operation operation[2] = {ARMV7_VCVT, ARMV7_VCVTR};
+ instruction->operation = operation[!decode.vcvtr.op];
+ DataType dtMap2[2] = {DT_F32, DT_F64};
+ instruction->dataType = DT_U32;
+ instruction->dataType2 = dtMap2[decode.vcvta.sz];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vcvta.vd << 1) | decode.vcvta.d));
+ instruction->operands[1].cls = REG;
+ if (decode.vcvta.sz == 1)
+ instruction->operands[1].reg = (Register)(fregMap[decode.vcvta.sz] +
+ ((decode.vcvta.m << 4) | decode.vcvta.vm));
+ else
+ instruction->operands[1].reg = (Register)(fregMap[decode.vcvta.sz] +
+ ((decode.vcvta.vm << 1) | decode.vcvta.m));
+ }
+ }
+ break;
+ case 13:
+ {
+ static Operation operation[2] = {ARMV7_VCVTR, ARMV7_VCVT};
+ instruction->operation = operation[decode.vcvt.sx];
+ static DataType dtMap2[2] = {DT_F32, DT_F64};
+ instruction->dataType = DT_S32;
+ instruction->dataType2 = dtMap2[decode.vcvta.sz];
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vcvta.vd << 1) | decode.vcvta.d));
+ instruction->operands[1].cls = REG;
+ if (decode.vcvta.sz == 1)
+ instruction->operands[1].reg = (Register)(fregMap[decode.vcvta.sz] +
+ ((decode.vcvta.m << 4) | decode.vcvta.vm));
+ else
+ instruction->operands[1].reg = (Register)(fregMap[decode.vcvta.sz] +
+ ((decode.vcvta.vm << 1) | decode.vcvta.m));
+ }
+ break;
+ case 10:
+ case 11:
+ {
+ static DataType dt[2][2] = {
+ {DT_S16, DT_U16},
+ {DT_S32, DT_U32}
+ };
+ static DataType fdt[2] = {DT_F32, DT_F64};
+ instruction->operation = ARMV7_VCVT;
+ if (decode.vmla.op == 0)
+ {
+ instruction->dataType = dt[decode.vcvt.sx][decode.vcvt.u];
+ instruction->dataType2 = fdt[decode.vcvt.sf];
+ }
+ else
+ {
+ instruction->dataType = fdt[decode.vcvt.sf];
+ instruction->dataType2 = dt[decode.vcvt.sx][decode.vcvt.u];
+ }
+ uint32_t reg;
+ if (decode.vcvt.sf == 1)
+ {
+ reg = fregMap[decode.vcvt.sf] + ((decode.vcvt.d << 4) | decode.vcvt.vd);
+ }
+ else
+ {
+ reg = fregMap[decode.vcvt.sf] + ((decode.vcvt.vd << 1) | decode.vcvt.d);
+ }
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)reg;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)reg;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = (16 << decode.vcvt.sx) - ((decode.vcvt.imm4 << 1) | decode.vcvt.i);
+
+ }
+ break;
+ case 14:
+ case 15:
+ {
+ /*
+ * VCVT<c>.<Td>.F64 <Dd>, <Dd>, #<fbits>
+ * VCVT<c>.<Td>.F32 <Sd>, <Sd>, #<fbits>
+ * VCVT<c>.F64.<Td> <Dd>, <Dd>, #<fbits>
+ * VCVT<c>.F32.<Td> <Sd>, <Sd>, #<fbits>
+ */
+ static DataType dt[2][2] = {
+ {DT_S16, DT_U16},
+ {DT_S32, DT_U32}
+ };
+ static DataType fdt[2] = {DT_F32, DT_F64};
+ instruction->operation = ARMV7_VCVT;
+ if (decode.vmla.op == 1)
+ {
+ instruction->dataType = dt[decode.vcvt.sx][decode.vcvt.u];
+ instruction->dataType2 = fdt[decode.vcvt.sf];
+ }
+ else
+ {
+ instruction->dataType = fdt[decode.vcvt.sf];
+ instruction->dataType2 = dt[decode.vcvt.sx][decode.vcvt.u];
+ }
+ uint32_t reg;
+ if (decode.vcvt.sf == 1)
+ {
+ reg = fregMap[decode.vcvt.sf] + ((decode.vcvt.d << 4) | decode.vcvt.vd);
+ }
+ else
+ {
+ reg = fregMap[decode.vcvt.sf] + ((decode.vcvt.vd << 1) | decode.vcvt.d);
+ }
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)reg;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)reg;
+ instruction->operands[2].cls = IMM;
+ instruction->operands[2].imm = (16 << decode.vcvt.sx) - ((decode.vcvt.imm4 << 1) | decode.vcvt.i);
+ }
+ break;
+ }
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+ }
+// }
+// else
+// {
+// uint32_t fregMap[2] = {REG_SINGLE, REG_DOUBLE};
+// DataType dtMap[2] = {DT_F32, DT_F64};
+// printf("opc1: %d\n", decode.com.opc1);
+// switch (decode.com.opc1)
+// {
+// case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+// instruction->operation = ARMV7_VSEL;
+// instruction->cond = (Condition)decode.com.cond;
+// instruction->dataType = dtMap[decode.vsel.sz];
+// instruction->operands[0].cls = fregMap[decode.vsel.sz];
+// instruction->operands[0].reg = (Register)decode.vsel.vd;
+// instruction->operands[1].cls = fregMap[decode.vsel.sz];
+// instruction->operands[1].reg = (Register)decode.vsel.vn;
+// instruction->operands[2].cls = fregMap[decode.vsel.sz];
+// instruction->operands[2].reg = (Register)decode.vsel.vm;
+// break;
+// case 8: case 12:
+// {
+// Operation operation[2] = {ARMV7_VMAXNM, ARMV7_VMINM};
+// instruction->operation = operation[decode.vmax.op];
+// instruction->dataType = dtMap[decode.vmax.sz];
+// instruction->operands[0].cls = fregMap[decode.vmax.sz];
+// instruction->operands[0].reg = (Register)decode.vmax.vd;
+// instruction->operands[1].cls = fregMap[decode.vmax.sz];
+// instruction->operands[1].reg = (Register)decode.vmax.vn;
+// instruction->operands[2].cls = fregMap[decode.vmax.sz];
+// instruction->operands[2].reg = (Register)decode.vmax.vm;
+// }
+// break;
+// case 11: case 15:
+// if ((decode.com.opc2 >> 2) == 2 )
+// {
+// if (decode.com.opc3 == 1)
+// {
+// Operation operation[4] = {ARMV7_VRINTA, ARMV7_VRINTN, ARMV7_VRINTP, ARMV7_VRINTM};
+// instruction->operation = operation[decode.vrint2.rm];
+// instruction->dataType = dtMap[decode.vrint2.sz];
+// instruction->operands[0].cls = fregMap[decode.vrint2.sz];
+// instruction->operands[0].reg = (Register)decode.vrint2.vd;
+// instruction->operands[1].cls = fregMap[decode.vrint2.sz];
+// instruction->operands[1].reg = (Register)decode.vrint2.vm;
+// }
+// }
+// else if ((decode.com.opc2 >> 2) == 3)
+// {
+// if ((decode.com.opc3 & 2) == 1)
+// {
+// DataType dtMap2[2] = {DT_U32, DT_S32};
+// Operation operation[4] = {ARMV7_VCVTA, ARMV7_VCVTN, ARMV7_VCVTP, ARMV7_VCVTM};
+// instruction->operation = operation[decode.vcvt2.rm];
+// instruction->dataType = dtMap2[decode.vcvt2.op];
+// instruction->dataType2 = dtMap[decode.vcvt2.sz];
+// instruction->operands[0].cls = fregMap[decode.vcvt2.sz];
+// instruction->operands[0].reg = (Register)decode.vcvt2.vd;
+// instruction->operands[1].cls = fregMap[decode.vcvt2.sz];
+// instruction->operands[1].reg = (Register)decode.vcvt2.vm;
+// }
+// }
+// else
+// {
+// printf("opc2: %d opc3: %d\n", decode.com.opc2, decode.com.opc3);
+// }
+// break;
+// default:
+// printf("opc1: %d\n", decode.com.opc1);
+// break;
+// }
+// return instruction->operation == ARMV7_UNDEFINED;
+// }
+
+ uint32_t i = 0;
+ if (decode.vmla.sz == 1)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)(REG_D0 + (decode.vmla.vd | (decode.vmla.d << 4)));
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].reg = (Register)(REG_D0 + (decode.vmla.vn | (decode.vmla.n << 4)));
+ i += type;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].reg = (Register)(REG_D0 + (decode.vmla.vm | (decode.vmla.m << 4)));
+ }
+ else
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i++].reg = (Register)(REG_S0 + ((decode.vmla.vd << 1) | decode.vmla.d));
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].reg = (Register)(REG_S0 + ((decode.vmla.vn << 1) | decode.vmla.n));
+ i += type;
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].reg = (Register)(REG_S0 + ((decode.vmla.vm << 1) | decode.vmla.m));
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+#define ROTL32(x, n) ((x << (n)) | (x >> (32-(n))))
+static uint32_t reg_start_and_size_to_list(uint32_t start, uint32_t size)
+{
+ if (size > 32)
+ size = 32 - start;
+ return ((1 << size) - 1) << start;
+ //return ROTL32((((uint32_t)-1) >> (32-size)), start);
+}
+
+uint32_t armv7_extension_register_load_store(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.6 Extension register load/store instructions*/
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:16;
+ uint32_t rn:4;
+ uint32_t opcode:5;
+ uint32_t group2:3;
+ uint32_t cond:4;
+ }com;
+ struct {
+ uint32_t vm:4;
+ uint32_t op:4;
+ uint32_t c:1;
+ uint32_t group2:19;
+ uint32_t cond:4;
+ }vmov;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:6;
+ uint32_t rt:4;
+ uint32_t rt2:2;
+ uint32_t op:1;
+ uint32_t group3:7;
+ uint32_t cond:4;
+ }vmov1;
+ struct {
+ uint32_t imm8:8;
+ uint32_t size:1;
+ uint32_t group1:3;
+ uint32_t vd:4;
+ uint32_t rn:4;
+ uint32_t group2:1;
+ uint32_t w:1;
+ uint32_t d:1;
+ uint32_t u:1;
+ uint32_t p:1;
+ uint32_t group3:3;
+ uint32_t cond:4;
+ }vstm;
+ }decode;
+ (void)address;
+
+ decode.value = instructionValue;
+ instruction->cond = (Condition)decode.com.cond;
+ switch (decode.com.opcode)
+ {
+ case 4:
+ case 5:
+ {
+ instruction->operation = ARMV7_VMOV;
+ uint32_t fregMap[2] = {REG_S0, REG_R0};
+ uint32_t m = (decode.vmov1.vm << 1) | decode.vmov1.m;
+
+ if (decode.vmov.c == 0)
+ {
+ if (decode.vmov1.op == 1)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(fregMap[decode.vmov.op] + (m));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(fregMap[decode.vmov.op] + (m+1));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(fregMap[!decode.vmov.op] + (decode.vmov.vm));
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)(fregMap[!decode.vmov.op] + (decode.vmov.vm + 1));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(fregMap[!decode.vmov.op] + (decode.vmov.vm));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)(fregMap[!decode.vmov.op] + (decode.vmov.vm + 1));
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)(fregMap[decode.vmov.op] + (m));
+ instruction->operands[3].cls = REG;
+ instruction->operands[3].reg = (Register)(fregMap[decode.vmov.op] + (m+1));
+ }
+ }
+ else
+ {
+ if (decode.vmov1.op == 1)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)m;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.vmov1.rt;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.vmov1.rt2;
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)decode.vmov1.rt;
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.vmov1.rt2;
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)m;
+ }
+ }
+ }
+ break;
+ case 18:
+ case 22:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ {
+ static OperandClass regListType[2] = {REG_LIST_SINGLE, REG_LIST_DOUBLE};
+ if ((decode.vstm.p == 0 && decode.vstm.u == 0 && decode.vstm.w == 0) ||
+ ((decode.vstm.imm8 & 1) == 1 && decode.vstm.size == 1))
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_UNDEFINED, ARMV7_FSTMIAX},
+ {ARMV7_FSTMDBX, ARMV7_UNDEFINED}
+ };
+ instruction->operation = operation[decode.vstm.p][decode.vstm.u];
+ }
+ else if (decode.vstm.p == 1 && decode.vstm.u == 0 &&
+ decode.vstm.w == 1 && decode.vstm.rn == 13)
+ {
+ instruction->operation = ARMV7_VPUSH;
+ }
+ else
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_UNDEFINED, ARMV7_VSTMIA},
+ {ARMV7_VSTMDB, ARMV7_UNDEFINED}
+ };
+ instruction->operation = operation[decode.vstm.p][decode.vstm.u];
+ }
+ uint32_t i = 0;
+ if (instruction->operation != ARMV7_VPUSH)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].flags.wb = decode.vstm.w;
+ instruction->operands[i++].reg = (Register)decode.vstm.rn;
+ }
+ instruction->operands[i].cls = regListType[decode.vstm.size];
+ instruction->operands[i].flags.hasElements = 0;
+ uint32_t d = 0;
+ if (decode.vstm.size == 0)
+ d = (decode.vstm.vd << 1) | decode.vstm.d;
+ else
+ d = (decode.vstm.d << 4) | decode.vstm.vd;
+
+ instruction->operands[i].reg = (Register)reg_start_and_size_to_list(d, decode.vstm.imm8 >> decode.vstm.size);
+ }
+ break;
+ case 16:
+ case 20:
+ case 24:
+ case 28:
+ instruction->operation = ARMV7_VSTR;
+ if (decode.vstm.size == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vstm.vd << 1) | decode.vstm.d));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vstm.d << 4) | decode.vstm.vd));
+ }
+ instruction->operands[1].cls = MEM_IMM;
+ instruction->operands[1].reg = (Register)decode.vstm.rn;
+ instruction->operands[1].imm = decode.vstm.imm8 << 2;
+ instruction->operands[1].flags.add = decode.vstm.u;
+ break;
+ case 9:
+ case 11:
+ case 13:
+ case 15:
+ case 19:
+ case 23:
+ {
+ static OperandClass regListType[2] = {REG_LIST_SINGLE, REG_LIST_DOUBLE};
+ if ((decode.vstm.p == 0 && decode.vstm.u == 0 && decode.vstm.w == 0) ||
+ ((decode.vstm.imm8 & 1) == 1 && decode.vstm.size == 1))
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_UNDEFINED, ARMV7_FLDMIAX},
+ {ARMV7_FLDMDBX, ARMV7_UNDEFINED}
+ };
+ instruction->operation = operation[decode.vstm.p][decode.vstm.u];
+ }
+ else if (decode.vstm.p == 0 && decode.vstm.u == 1 &&
+ decode.vstm.w == 1 && decode.vstm.rn == 13)
+ {
+ instruction->operation = ARMV7_VPOP;
+ }
+ else if (decode.vstm.p == 1 && decode.vstm.w == 0)
+ {
+ instruction->operation = ARMV7_VLDR;
+ }
+ else
+ {
+ static Operation operation[2][2] = {
+ {ARMV7_UNDEFINED, ARMV7_VLDMIA},
+ {ARMV7_VLDMDB, ARMV7_UNDEFINED}
+ };
+ instruction->operation = operation[decode.vstm.p][decode.vstm.u];
+ }
+ uint32_t i = 0;
+ if (instruction->operation != ARMV7_VPOP)
+ {
+ instruction->operands[i].cls = REG;
+ instruction->operands[i].flags.wb = decode.vstm.w;
+ instruction->operands[i++].reg = (Register)decode.vstm.rn;
+ }
+ instruction->operands[i].cls = regListType[decode.vstm.size];
+ instruction->operands[i].flags.hasElements = 0;
+ uint32_t d = 0;
+ if (decode.vstm.size == 0)
+ d = (decode.vstm.vd << 1) | decode.vstm.d;
+ else
+ d = (decode.vstm.d << 4) | decode.vstm.vd;
+
+ instruction->operands[i].reg = (Register)reg_start_and_size_to_list(d, decode.vstm.imm8 >> decode.vstm.size);
+ }
+ break;
+ case 17:
+ case 21:
+ case 25:
+ case 29:
+ instruction->operation = ARMV7_VLDR;
+ if (decode.vstm.size == 0)
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_S0 + ((decode.vstm.vd << 1) | decode.vstm.d));
+ }
+ else
+ {
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(REG_D0 + ((decode.vstm.d << 4) | decode.vstm.vd));
+ }
+ instruction->operands[1].cls = MEM_IMM;
+ instruction->operands[1].reg = (Register)decode.vstm.rn;
+ instruction->operands[1].imm = decode.vstm.imm8 << 2;
+ instruction->operands[1].flags.add = decode.vstm.u;
+ break;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_simd_load_store(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.7 Advanced SIMD element or structure load/store instructions*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:8;
+ uint32_t b:4;
+ uint32_t group2:9;
+ uint32_t l:1;
+ uint32_t group3:1;
+ uint32_t a:1;
+ uint32_t group4:8;
+ } com;
+ struct {
+ uint32_t rm:4;
+ uint32_t align:2;
+ uint32_t size:2;
+ uint32_t type:4;
+ uint32_t vd:4;
+ uint32_t rn:4;
+ uint32_t group1:2;
+ uint32_t d:1;
+ uint32_t group2:9;
+ } vst;
+ struct {
+ uint32_t rm:4;
+ uint32_t index_align:4;
+ uint32_t group1:2;
+ uint32_t size:2;
+ uint32_t vd:4;
+ uint32_t rn:4;
+ uint32_t group2:2;
+ uint32_t d:1;
+ uint32_t group3:9;
+ } v2;
+ struct {
+ uint32_t rm:4;
+ uint32_t a:1;
+ uint32_t t:1;
+ uint32_t size:2;
+ uint32_t group1:4;
+ uint32_t vd:4;
+ uint32_t rn:4;
+ uint32_t group2:2;
+ uint32_t d:1;
+ uint32_t group3:9;
+ } v3;
+ } decode;
+ decode.value = instructionValue;
+ instruction->cond = (Condition)COND_NONE;
+ static DataType dtMap[4] = {DT_8, DT_16, DT_32, DT_64};
+ uint32_t type = -1;
+ uint32_t regs = 1;
+ if (decode.com.l == 0)
+ {
+ if (decode.com.a == 0)
+ {
+ switch (decode.com.b)
+ {
+ case 2:
+ case 6:
+ case 7:
+ case 10:
+ instruction->operation = ARMV7_VST1;
+ type = 0;
+ break;
+ case 3:
+ case 8:
+ case 9:
+ instruction->operation = ARMV7_VST2;
+ type = 1;
+ break;
+ case 4:
+ case 5:
+ instruction->operation = ARMV7_VST3;
+ type = 2;
+ break;
+ case 0:
+ case 1:
+ instruction->operation = ARMV7_VST4;
+ type = 3;
+ break;
+ }
+ }
+ else
+ {
+ switch (decode.com.b)
+ {
+ case 0:
+ case 4:
+ case 8:
+ instruction->operation = ARMV7_VST1;
+ type = 4;
+ break;
+ case 1:
+ case 5:
+ case 9:
+ instruction->operation = ARMV7_VST2;
+ type = 5;
+ break;
+ case 2:
+ case 6:
+ case 10:
+ instruction->operation = ARMV7_VST3;
+ type = 6;
+ break;
+ case 3:
+ case 7:
+ case 11:
+ instruction->operation = ARMV7_VST4;
+ type = 7;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (decode.com.a == 0)
+ {
+ switch (decode.com.b)
+ {
+ case 2:
+ case 6:
+ case 7:
+ case 10:
+ instruction->operation = ARMV7_VLD1;
+ type = 0;
+ break;
+ case 3:
+ case 8:
+ case 9:
+ instruction->operation = ARMV7_VLD2;
+ type = 1;
+ break;
+ case 4:
+ case 5:
+ instruction->operation = ARMV7_VLD3;
+ type = 2;
+ break;
+ case 0:
+ case 1:
+ instruction->operation = ARMV7_VLD4;
+ type = 3;
+ break;
+ }
+ }
+ else
+ {
+ switch (decode.com.b)
+ {
+ case 0:
+ case 4:
+ case 8:
+ instruction->operation = ARMV7_VLD1;
+ type = 4;
+ break;
+ case 12:
+ instruction->operation = ARMV7_VLD1;
+ type = 8;
+ break;
+ case 1:
+ case 5:
+ case 9:
+ instruction->operation = ARMV7_VLD2;
+ type = 5;
+ break;
+ case 13:
+ instruction->operation = ARMV7_VLD2;
+ type = 9;
+ break;
+ case 2:
+ case 6:
+ case 10:
+ instruction->operation = ARMV7_VLD3;
+ type = 6;
+ break;
+ case 14:
+ instruction->operation = ARMV7_VLD3;
+ type = 10;
+ break;
+ case 3:
+ case 7:
+ case 11:
+ instruction->operation = ARMV7_VLD4;
+ type = 7;
+ break;
+ case 15:
+ instruction->operation = ARMV7_VLD4;
+ type = 11;
+ break;
+ }
+ }
+ }
+
+ switch (type)
+ {
+ case 0:
+ {
+ instruction->dataType = dtMap[decode.vst.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].flags.hasElements = 0;
+ uint32_t d = (decode.vst.d << 4) | decode.vst.vd;
+ if (decode.vst.type == 7)
+ {
+ instruction->operands[0].reg = (Register)(1 << d);
+ if (((decode.vst.align >> 1) & 1) == 1)
+ return 1;
+ }
+ else if (decode.vst.type == 10)
+ {
+ instruction->operands[0].reg = (Register)(3 << d);
+ if ((decode.vst.align & 3) == 3)
+ return 1;
+ }
+ else if (decode.vst.type == 6)
+ {
+ instruction->operands[0].reg = (Register)(7 << d);
+ }
+ else if (decode.vst.type == 2)
+ {
+ instruction->operands[0].reg = (Register)(15 << d);
+ }
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.vst.rn;
+ instruction->operands[1].flags.wb = decode.vst.rm == 13;
+ if (decode.vst.align == 0)
+ instruction->operands[1].imm = 0;
+ else
+ instruction->operands[1].imm = 32 << decode.vst.align;
+ if (decode.vst.rm != 15 && decode.vst.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.vst.rm;
+ }
+ }
+ break;
+ case 1:
+ {
+ switch (decode.vst.type)
+ {
+ case 8:
+ if (decode.vst.align == 3)
+ return 1;
+ regs = 3 << ((decode.vst.d << 4) | decode.vst.vd);
+ break;
+ case 9:
+ if (decode.vst.align == 3)
+ return 1;
+ regs = 5 << ((decode.vst.d << 4) | decode.vst.vd);
+ break;
+ case 3:
+ regs = 15 << ((decode.vst.d << 4) | decode.vst.vd);
+ break;
+ }
+
+ instruction->dataType = dtMap[decode.vst.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].flags.hasElements = 0;
+ instruction->operands[0].reg = (Register)regs;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.vst.rn;
+ instruction->operands[1].flags.wb = decode.vst.rm == 13;
+ if (decode.vst.align == 0)
+ instruction->operands[1].imm = 0;
+ else
+ instruction->operands[1].imm = 32 << decode.vst.align;
+ if (decode.vst.rm != 15 && decode.vst.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.vst.rm;
+ }
+ }
+ break;
+ case 2:
+ if (decode.vst.type == 4)
+ regs = 7 << ((decode.vst.d << 4) | decode.vst.vd);
+ else if (decode.vst.type == 5)
+ regs = 21 << ((decode.vst.d << 4) | decode.vst.vd);
+
+ instruction->dataType = dtMap[decode.vst.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].flags.hasElements = 0;
+ instruction->operands[0].reg = (Register)regs;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.vst.rn;
+ instruction->operands[1].flags.wb = decode.vst.rm == 13;
+ if (decode.vst.align == 0)
+ instruction->operands[1].imm = 0;
+ else
+ instruction->operands[1].imm = 32 << decode.vst.align;
+ if (decode.vst.rm != 15 && decode.vst.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.vst.rm;
+ }
+ break;
+ case 3:
+ if (decode.vst.type == 0)
+ regs = ROTL32(0xf, ((decode.vst.d << 4) | decode.vst.vd));
+ else if (decode.vst.type == 1)
+ regs = ROTL32(0x55, ((decode.vst.d << 4) | decode.vst.vd));
+
+ instruction->dataType = dtMap[decode.vst.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].flags.hasElements = 0;
+ instruction->operands[0].reg = (Register)regs;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.vst.rn;
+ instruction->operands[1].flags.wb = decode.vst.rm == 13;
+ if (decode.vst.align == 0)
+ instruction->operands[1].imm = 0;
+ else
+ instruction->operands[1].imm = 32 << decode.vst.align;
+ if (decode.vst.rm != 15 && decode.vst.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.vst.rm;
+ }
+ break;
+ case 4:
+ switch (decode.v2.size)
+ {
+ case 0:
+ if ((decode.v2.index_align & 1) != 0)
+ return 1;
+ regs = 1 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 1) & 7;
+ break;
+ case 1:
+ if ((decode.v2.index_align & 2) != 0)
+ return 1;
+ if ((decode.v2.index_align & 3) == 1)
+ instruction->operands[1].imm = 16;
+
+ regs = 1 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 2) & 3;
+ break;
+ case 2:
+ if ((decode.v2.index_align & 4) != 0)
+ return 1;
+ if ((decode.v2.index_align & 7) == 3)
+ instruction->operands[1].imm = 32;
+ regs = 1 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 3) & 1;
+ break;
+ case 3:
+ return 1;
+ }
+ instruction->dataType = dtMap[decode.v2.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)regs;
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v2.rn;
+ instruction->operands[1].flags.wb = decode.v2.rm == 13;
+ if (decode.v2.rm != 15 && decode.v2.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v2.rm;
+ }
+ break;
+ case 5:
+ switch (decode.v2.size)
+ {
+ case 0:
+ if ((decode.v2.index_align & 1) == 1)
+ instruction->operands[1].imm = 16;
+
+ regs = 3 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 1) & 7;
+ break;
+ case 1:
+ if ((decode.v2.index_align & 1) == 1)
+ instruction->operands[1].imm = 32;
+
+ if (((decode.v2.index_align >> 1) & 1) == 1)
+ regs = 5 << ((decode.v2.d << 4) | decode.v2.vd);
+ else
+ regs = 3 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 2) & 3;
+ break;
+ case 2:
+ if ((decode.v2.index_align & 3) == 1)
+ instruction->operands[1].imm = 64;
+
+ if (((decode.v2.index_align >> 2) & 1) == 1)
+ regs = 5 << ((decode.v2.d << 4) | decode.v2.vd);
+ else
+ regs = 3 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 3) & 1;
+ break;
+ case 3:
+ return 1;
+ }
+ instruction->dataType = dtMap[decode.v2.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)regs;
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v2.rn;
+ instruction->operands[1].flags.wb = decode.v2.rm == 13;
+ if (decode.v2.rm != 15 && decode.v2.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v2.rm;
+ }
+ break;
+ case 6:
+ switch (decode.v2.size)
+ {
+ case 0:
+ if ((decode.v2.index_align & 1) == 1)
+ instruction->operands[1].imm = 16;
+
+ regs = 7 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 1) & 7;
+ break;
+ case 1:
+ if ((decode.v2.index_align & 1) == 1)
+ instruction->operands[1].imm = 32;
+
+ if (((decode.v2.index_align >> 1) & 1) == 1)
+ regs = 21 << ((decode.v2.d << 4) | decode.v2.vd);
+ else
+ regs = 7 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 2) & 3;
+ break;
+ case 2:
+ if ((decode.v2.index_align & 3) == 1)
+ instruction->operands[1].imm = 64;
+
+ if (((decode.v2.index_align >> 2) & 1) == 1)
+ regs = 21 << ((decode.v2.d << 4) | decode.v2.vd);
+ else
+ regs = 7 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 3) & 1;
+ break;
+ case 3:
+ return 1;
+ }
+ instruction->dataType = dtMap[decode.v2.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)regs;
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v2.rn;
+ instruction->operands[1].flags.wb = decode.v2.rm == 13;
+ if (decode.v2.rm != 15 && decode.v2.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v2.rm;
+ }
+ break;
+ case 7:
+ switch (decode.v2.size)
+ {
+ case 0:
+ if ((decode.v2.index_align & 1) == 1)
+ instruction->operands[1].imm = 32;
+
+ regs = 15 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 1) & 7;
+ break;
+ case 1:
+ if ((decode.v2.index_align & 1) == 1)
+ instruction->operands[1].imm = 64;
+
+ if (((decode.v2.index_align >> 1) & 1) == 1)
+ regs = 85 << ((decode.v2.d << 4) | decode.v2.vd);
+ else
+ regs = 15 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 2) & 3;
+ break;
+ case 2:
+ if ((decode.v2.index_align & 3) == 1)
+ instruction->operands[1].imm = 64;
+ else if ((decode.v2.index_align & 3) == 2)
+ instruction->operands[1].imm = 128;
+
+ if (((decode.v2.index_align >> 2) & 1) == 1)
+ regs = 85 << ((decode.v2.d << 4) | decode.v2.vd);
+ else
+ regs = 15 << ((decode.v2.d << 4) | decode.v2.vd);
+ instruction->operands[0].imm = (decode.v2.index_align >> 3) & 1;
+ break;
+ case 3:
+ return 1;
+ }
+ instruction->dataType = dtMap[decode.v2.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)regs;
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v2.rn;
+ instruction->operands[1].flags.wb = decode.v2.rm == 13;
+ if (decode.v2.rm != 15 && decode.v2.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v2.rm;
+ }
+ break;
+ case 8:
+ {
+ static uint32_t regNumMap[2] = {1,3};
+ instruction->dataType = dtMap[decode.v3.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)(regNumMap[decode.v3.t] << ((decode.v3.d << 4) | decode.v3.vd));
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[0].flags.emptyElement = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v3.rn;
+ instruction->operands[1].flags.wb = decode.v3.rm == 13;
+ if (decode.v3.rm != 15 && decode.v3.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v3.rm;
+ }
+ }
+ break;
+ case 9:
+ {
+ static uint32_t regNumMap[2] = {3,5};
+ instruction->dataType = dtMap[decode.v3.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)(regNumMap[decode.v3.t] << ((decode.v3.d << 4) | decode.v3.vd));
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[0].flags.emptyElement = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v3.rn;
+ instruction->operands[1].flags.wb = decode.v3.rm == 13;
+ if (decode.v3.rm != 15 && decode.v3.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v3.rm;
+ }
+ if ((decode.vst.align & 1) == 1)
+ instruction->operands[1].imm = 16 << decode.vst.size;
+ }
+ break;
+ case 10:
+ {
+ static uint32_t regNumMap[2] = {7,21};
+ instruction->dataType = dtMap[decode.v3.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)(regNumMap[decode.v3.t] << ((decode.v3.d << 4) | decode.v3.vd));
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[0].flags.emptyElement = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v3.rn;
+ instruction->operands[1].flags.wb = decode.v3.rm == 13;
+ if (decode.v3.rm != 15 && decode.v3.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v3.rm;
+ }
+ }
+ break;
+ case 11:
+ {
+ static uint32_t regNumMap[2] = {15,85};
+ instruction->dataType = dtMap[decode.v3.size];
+ instruction->operands[0].cls = REG_LIST_DOUBLE;
+ instruction->operands[0].reg = (Register)(regNumMap[decode.v3.t] << ((decode.v3.d << 4) | decode.v3.vd));
+ instruction->operands[0].flags.hasElements = 1;
+ instruction->operands[0].flags.emptyElement = 1;
+ instruction->operands[1].cls = MEM_ALIGNED;
+ instruction->operands[1].reg = (Register)decode.v3.rn;
+ instruction->operands[1].flags.wb = decode.v3.rm == 13;
+ if (decode.v3.rm != 15 && decode.v3.rm != 13)
+ {
+ instruction->operands[2].cls = REG;
+ instruction->operands[2].reg = (Register)decode.v3.rm;
+ }
+ if ((decode.vst.align & 1) == 1)
+ {
+ if (decode.vst.size == 0)
+ instruction->operands[1].imm = 32;
+ else if (decode.vst.size < 3)
+ instruction->operands[1].imm = 64;
+ else
+ instruction->operands[0].imm = 128;
+ }
+ }
+ break;
+ default:
+ return 1;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_transfers(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.8 - 8, 16, and 32-bit transfer between ARM core and extension registers*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:5;
+ uint32_t b:2;
+ uint32_t group2:1;
+ uint32_t c:1;
+ uint32_t group3:11;
+ uint32_t l:1;
+ uint32_t a:3;
+ uint32_t group4:4;
+ uint32_t cond:4;
+ } com;
+ struct {
+ uint32_t group1:12;
+ uint32_t rt:4;
+ uint32_t reg:4;
+ uint32_t group2:12;
+ } vmsr;
+ struct {
+ uint32_t group1:7;
+ uint32_t n:1;
+ uint32_t group2:4;
+ uint32_t rt:4;
+ uint32_t vn:4;
+ uint32_t op:1;
+ uint32_t group3:11;
+ } vmov;
+ struct {
+ uint32_t group1:5;
+ uint32_t opc2:2;
+ uint32_t d:1;
+ uint32_t group2:4;
+ uint32_t rt:4;
+ uint32_t vd:4;
+ uint32_t group3:1;
+ uint32_t opc1:2;
+ uint32_t u:1;
+ uint32_t group4:8;
+ } vmov2;
+ struct {
+ uint32_t group1:5;
+ uint32_t e:1;
+ uint32_t group2:1;
+ uint32_t d:1;
+ uint32_t group3:4;
+ uint32_t rt:4;
+ uint32_t vd:4;
+ uint32_t group4:1;
+ uint32_t q:1;
+ uint32_t b:1;
+ uint32_t group5:9;
+ } vdup;
+ } decode;
+
+ decode.value = instructionValue;
+ instruction->cond = (Condition)decode.com.cond;
+ if (decode.com.c == 0)
+ {
+ if (decode.com.a == 0)
+ {
+ instruction->operation = ARMV7_VMOV;
+ instruction->operands[decode.vmov.op].cls = REG;
+ instruction->operands[decode.vmov.op].reg = (Register)(REG_S0 + (((decode.vmov.vn << 1) | decode.vmov.n)));
+ instruction->operands[!decode.vmov.op].cls = REG;
+ instruction->operands[!decode.vmov.op].reg = (Register)decode.vmov.rt;
+ }
+ else if (decode.com.a == 7)
+ {
+ static Register regs[16] = {
+ REGS_FPSID, // 0
+ REGS_FPSCR, // 1
+ REG_INVALID,
+ REG_INVALID,
+ REG_INVALID,
+ REGS_MVFR2,
+ REGS_MVFR1, // 6
+ REGS_MVFR0, // 7
+ REGS_FPEXC, // 8
+ REGS_FPINST, // 9
+ REGS_FPINST2, //10
+ REG_INVALID,
+ REG_INVALID,
+ REG_INVALID,
+ REG_INVALID,
+ REG_INVALID,
+ };
+ static Operation operation[2] = {ARMV7_VMSR, ARMV7_VMRS};
+ instruction->operation = operation[decode.com.l];
+ instruction->operands[decode.com.l].cls = REG_SPEC;
+ instruction->operands[decode.com.l].regs = regs[decode.vmsr.reg];
+ if (instruction->operands[decode.com.l].regs == REG_INVALID)
+
+ return 1;
+ if (instruction->operands[decode.com.l].regs == REGS_FPSCR && decode.vmsr.rt == 15)
+ {
+ instruction->operands[!decode.com.l].cls = REG_SPEC;
+ instruction->operands[!decode.com.l].regs = REGS_APSR_NZCV;
+ }
+ else
+ {
+ instruction->operands[!decode.com.l].cls = REG;
+ instruction->operands[!decode.com.l].reg = (Register)decode.vmsr.rt;
+ }
+ }
+ }
+ else
+ {
+ if (decode.com.a < 4 || decode.com.l == 1)
+ {
+ instruction->operation = ARMV7_VMOV;
+ instruction->operands[decode.com.l].cls = REG;
+ instruction->operands[decode.com.l].reg = (Register)(REG_D0 + (((decode.vmov2.d << 4) | decode.vmov2.vd)));
+ instruction->operands[decode.com.l].flags.hasElements = 1;
+ if (decode.com.l == 0)
+ {
+ switch ((decode.vmov2.opc1 << 2) | decode.vmov2.opc2)
+ {
+ case 8: case 9: case 10: case 11:
+ case 12: case 13: case 14: case 15:
+ instruction->operands[decode.com.l].imm = ((decode.vmov2.opc1 & 1) << 2) | decode.vmov2.opc2;
+ instruction->dataType = DT_8;
+ break;
+ case 1: case 3: case 5: case 7:
+ instruction->operands[decode.com.l].imm =
+ ((decode.vmov2.opc1 & 1) << 1) | ((decode.vmov2.opc2 >> 1) & 1);
+ instruction->dataType = DT_16;
+ break;
+ case 0: case 4:
+ instruction->operands[decode.com.l].imm = decode.vmov2.opc1 & 1;
+ instruction->dataType = DT_32;
+ break;
+ case 2: case 6:
+ return 1;
+ }
+ }
+ else
+ {
+ uint32_t opc1_1 = (decode.vmov2.opc1 >> 1) & 1;
+ uint32_t opc2_0 = decode.vmov2.opc2 & 1;
+ uint32_t u = decode.vmov2.u;
+ if (u == 0)
+ {
+ if (u == 0 && opc1_1 == 1)
+ {
+ instruction->dataType = DT_S8;
+ instruction->operands[decode.com.l].imm =
+ ((decode.vmov2.opc1 & 1) << 2) | decode.vmov2.opc2;
+ }
+ else if (u == 0 && opc1_1 == 0 && opc2_0 == 1)
+ {
+ instruction->dataType = DT_S16;
+ instruction->operands[decode.com.l].imm =
+ ((decode.vmov2.opc1 & 1) << 1) | ((decode.vmov2.opc2 >> 1) & 1);
+ }
+ else if (u == 0 && opc1_1 == 0 && decode.vmov2.opc2 == 0)
+ {
+ instruction->dataType = DT_32;
+ instruction->operands[decode.com.l].imm = decode.vmov2.opc1 & 1;
+ }
+ }
+ else
+ {
+ if (opc1_1 == 1)
+ {
+ instruction->dataType = DT_U8;
+ instruction->operands[decode.com.l].imm =
+ ((decode.vmov2.opc1 & 1) << 2) | decode.vmov2.opc2;
+ }
+ else if (opc1_1 == 0 && opc2_0 == 1)
+ {
+ instruction->dataType = DT_U16;
+ instruction->operands[decode.com.l].imm =
+ ((decode.vmov2.opc1 & 1) << 1) | ((decode.vmov2.opc2 >> 1) & 1);
+ }
+ }
+ }
+ instruction->operands[!decode.com.l].cls = REG;
+ instruction->operands[!decode.com.l].reg = (Register)decode.vmov2.rt;
+ }
+ else
+ {
+ if (decode.com.b < 2)
+ {
+ instruction->operation = ARMV7_VDUP;
+ instruction->dataType = (DataType)(DT_32 - ((decode.vdup.b << 1) | decode.vdup.e));
+ instruction->operands[0].cls = REG;
+ instruction->operands[0].reg = (Register)(regMap[decode.vdup.q] + (((decode.vdup.d << 4) | decode.vdup.vd) >> decode.vdup.q));
+ instruction->operands[1].cls = REG;
+ instruction->operands[1].reg = (Register)decode.vdup.rt;
+ }
+ }
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+uint32_t armv7_64_bit_transfers(uint32_t instructionValue, Instruction* restrict instruction, uint32_t address)
+{
+ /*A7.9 64-bit transfers between ARM core and extension registers*/
+ (void)address;
+ union {
+ uint32_t value;
+ struct {
+ uint32_t group1:4;
+ uint32_t one:1;
+ uint32_t op:1;
+ uint32_t zero:2;
+ uint32_t c:1;
+ uint32_t group2:17;
+ uint32_t cond:4;
+ } com;
+ struct {
+ uint32_t vm:4;
+ uint32_t group1:1;
+ uint32_t m:1;
+ uint32_t group2:6;
+ uint32_t rt:4;
+ uint32_t rt2:4;
+ uint32_t op:1;
+ uint32_t group3:7;
+ uint32_t cond:4;
+ } vmov1;
+ } decode;
+ decode.value = instructionValue;
+ if (decode.com.zero != 0 || decode.com.one != 1)
+ return 1;
+
+ instruction->operation = ARMV7_VMOV;
+ if (decode.com.c == 0)
+ {
+ // VMOV<c> <Sm>, <Sm1>, <Rt>, <Rt2>
+ // VMOV<c> <Rt>, <Rt2>, <Sm>, <Sm1>
+ static uint8_t entries[2][4] = {{0,1,2,3}, {2,3,0,1}};
+ instruction->operands[entries[decode.vmov1.op][0]].cls = REG;
+ instruction->operands[entries[decode.vmov1.op][0]].reg = (Register)(REG_S0 + ((decode.vmov1.vm << 1) | decode.vmov1.m));
+ instruction->operands[entries[decode.vmov1.op][1]].cls = REG;
+ instruction->operands[entries[decode.vmov1.op][1]].reg = (Register)(REG_S0 + (((decode.vmov1.vm << 1) | decode.vmov1.m) + 1));
+ instruction->operands[entries[decode.vmov1.op][2]].cls = REG;
+ instruction->operands[entries[decode.vmov1.op][2]].reg = (Register)decode.vmov1.rt;
+ instruction->operands[entries[decode.vmov1.op][3]].cls = REG;
+ instruction->operands[entries[decode.vmov1.op][3]].reg = (Register)decode.vmov1.rt2;
+ }
+ else
+ {
+ // VMOV<c> <Dm>, <Rt>, <Rt2>
+ // VMOV<c> <Rt>, <Rt2>, <Dm>
+ static uint8_t entries[2][3] = {{0,1,2}, {2,0,1}};
+ instruction->operands[entries[decode.vmov1.op][0]].cls = REG;
+ instruction->operands[entries[decode.vmov1.op][0]].reg = (Register)(REG_D0 + ((decode.vmov1.m << 4) | decode.vmov1.vm));
+ instruction->operands[entries[decode.vmov1.op][1]].cls = REG;
+ instruction->operands[entries[decode.vmov1.op][1]].reg = (Register)decode.vmov1.rt;
+ instruction->operands[entries[decode.vmov1.op][2]].cls = REG;
+ instruction->operands[entries[decode.vmov1.op][2]].reg = (Register)decode.vmov1.rt2;
+ }
+ return instruction->operation == ARMV7_UNDEFINED;
+}
+
+const char* get_operation(Operation operation)
+{
+ if (operation > ARMV7_UNDEFINED && operation < ARMV7_END_INSTRUCTION)
+ return operationString[operation];
+ return "";
+}
+
+const char* get_vector_data_type(DataType dataType)
+{
+ if (dataType >= DT_NONE && dataType < DT_END)
+ return dataTypeString[dataType];
+ return "";
+}
+
+const char* get_register_name(Register reg)
+{
+ if (reg >= REG_R0 && reg < REG_INVALID)
+ return registerString[reg];
+ return NULL;
+}
+
+const char* get_banked_register_name(Register regb)
+{
+ if (regb >= REGB_ELR_HYP && regb <= REGB_SP_USR)
+ return registerString[regb];
+ return NULL;
+}
+
+const char* get_spec_register_name(Register regs)
+{
+ if (regs >= REGS_APSR && regs <= REGS_CONTROL)
+ return registerString[regs];
+ return NULL;
+}
+
+const char* get_coproc_register_c_name(CoprocRegisterC regc)
+{
+ if (regc >= REG_C0 && regc < REG_CEND)
+ return coprocRegisterCString[regc - REG_C0];
+ return NULL;
+}
+
+const char* get_coproc_register_p_name(CoprocRegisterP regp)
+{
+ if (regp >= REG_P0 && regp < REG_PEND)
+ return coprocRegisterString[regp - REG_P0];
+ return NULL;
+}
+
+const char* get_iflag(Iflags iflag)
+{
+ if (iflag >= IFL_NONE && iflag < IFL_END)
+ return iflagStrings[iflag];
+ return NULL;
+}
+
+const char* get_endian(EndianSpec spec)
+{
+ return endianSpecStrings[spec == 1];
+}
+
+const char* get_dsb_option(DsbOption opt)
+{
+ if (opt >= DSB_NONE0 && opt < DSB_END)
+ return dsbOptionStrings[opt];
+ return NULL;
+}
+
+const char* get_shift(Shift shift)
+{
+ if (shift >= SHIFT_NONE && shift < SHIFT_END)
+ return shiftString[shift];
+ return NULL;
+}
+
+const char* get_condition(Condition cond)
+{
+ if (cond >= COND_EQ && cond < COND_END)
+ return condString[cond];
+ return "";
+}
+
+uint32_t get_register_names(Register reg, const char** regNames, OperandClass cls)
+{
+ uint32_t base = REG_R0;
+ if (cls == REG_LIST_SINGLE)
+ base = REG_S0;
+ else if (cls == REG_LIST_DOUBLE)
+ base = REG_D0;
+ for (int32_t i = 31; i >= 0; i--)
+ {
+ if (((reg>>i)&1) == 1)
+ regNames[i] = get_register_name((Register)(i + base));
+ else
+ regNames[i] = 0;
+ }
+ return 0;
+}
+
+uint32_t get_register_list(InstructionOperand* op, char* out, size_t outLength, OperandClass cls)
+{
+ const char* regbuf[32] = {0};
+ get_register_names(op->reg, regbuf, cls);
+ uint32_t first = 1;
+ if (out == NULL)
+ return 1;
+
+ char* end = out + outLength;
+ out[0] = '\0';
+ for (uint32_t i = 0; i < 32 && out < end; i++)
+ {
+ if (regbuf[i] != 0)
+ {
+ if (first == 0)
+ out += snprintf(out, end - out, ", ");
+
+ first = 0;
+ out += snprintf(out, end - out, "%s", regbuf[i]);
+ if (op->flags.hasElements == 1)
+ {
+ if (op->flags.emptyElement == 1)
+ out += snprintf(out, end - out, "[]");
+ else
+ out += snprintf(out, end - out, "[%d]", op->imm);
+ }
+ }
+ }
+ return 0;
+}
+
+uint32_t get_register_size(Register reg)
+{
+ if (reg <= REG_S31)
+ return 4;
+ else if (reg <= REG_D31)
+ return 8;
+ else if (reg <= REG_Q15)
+ return 16;
+ return 0;
+}
+
+char* get_full_operation(char* outBuffer, size_t outBufferSize, Instruction* restrict instruction)
+{
+ static const char* setsFlags[2] = {"", ".s"};
+
+ snprintf(outBuffer, outBufferSize, "%s%s%s%s%s",
+ get_operation(instruction->operation),
+ setsFlags[instruction->setsFlags],
+ get_condition(instruction->cond),
+ get_vector_data_type(instruction->dataType),
+ get_vector_data_type(instruction->dataType2));
+
+ return outBuffer;
+}
+
+uint32_t armv7_disassemble(
+ Instruction* restrict instruction,
+ char* outBuffer,
+ uint32_t outBufferSize)
+{
+ char operands[512];
+ char tmpOperand[1024];
+ static const char* neg[2] = {"-", ""};
+ static const char* wb[2] = {"", "!"};
+ static const char* crt[2] = {"", " ^"};
+ memset(operands, 0, sizeof(operands));
+
+ char* start = (char*)&operands;
+ char* end = start + sizeof(operands);
+
+ for (uint32_t i = 0; i < MAX_OPERANDS && instruction->operands[i].cls != NONE && start < end; i++)
+ {
+ InstructionOperand* op = &instruction->operands[i];
+ if (i != 0)
+ start += snprintf(start, end - start, ", ");
+ switch (op->cls)
+ {
+ case REG:
+ //reg
+ //reg[imm]
+ //reg <shift> imm
+ //reg <shfit> offset
+ if (op->flags.hasElements == 1)
+ {
+ if (op->flags.emptyElement == 1)
+ start += snprintf(start, end - start, "%s[]", get_register_name(op->reg));
+ else
+ start += snprintf(start, end - start, "%s[%d]", get_register_name(op->reg), op->imm);
+ }
+ else if (op->shift == SHIFT_NONE)
+ {
+ start += snprintf(start, end - start, "%s%s", get_register_name(op->reg), wb[op->flags.wb]);
+ }
+ else if (op->flags.offsetRegUsed == 1)
+ { //shifted by register
+ start += snprintf(start, end - start, "%s, %s %s",
+ get_register_name(op->reg),
+ get_shift(op->shift),
+ get_register_name(op->offset));
+ }
+ else
+ { //shifted by immediate
+ if (op->shift == SHIFT_RRX)
+ start += snprintf(start, end - start, "%s, %s",
+ get_register_name(op->reg),
+ get_shift(op->shift));
+ else if (op->imm != 0)
+ start += snprintf(start, end - start, "%s, %s #%#x",
+ get_register_name(op->reg),
+ get_shift(op->shift),
+ op->imm);
+ else
+ start += snprintf(start, end - start, "%s", get_register_name(op->reg));
+ }
+ break;
+ case REG_LIST:
+ case REG_LIST_SINGLE:
+ case REG_LIST_DOUBLE:
+ get_register_list(op, tmpOperand, sizeof(tmpOperand), op->cls);
+ start += snprintf(start, end - start, "{%s}%s", tmpOperand, crt[op->flags.wb]);
+ break;
+ case REG_SPEC:
+ start += snprintf(start, end - start, "%s", get_spec_register_name(op->regs));
+ break;
+ case REG_BANKED:
+ start += snprintf(start, end - start, "%s", get_banked_register_name(op->regb));
+ break;
+ case REG_COPROCP:
+ start += snprintf(start, end - start, "%s", get_coproc_register_p_name(op->regp));
+ break;
+ case REG_COPROCC:
+ start += snprintf(start, end - start, "%s", get_coproc_register_c_name(op->regc));
+ break;
+ case IFLAGS:
+ start += snprintf(start, end - start, "%s", get_iflag(op->iflag));
+ break;
+ case ENDIAN_SPEC:
+ start += snprintf(start, end - start, "%s", get_endian(op->endian));
+ break;
+ case DSB_OPTION:
+ start += snprintf(start, end - start, "%s", get_dsb_option(op->dsbOpt));
+ break;
+ case IMM:
+ start += snprintf(start, end - start, "#%#x", op->imm);
+ break;
+ case LABEL:
+ start += snprintf(start, end - start, "%#x", op->imm);
+ break;
+ case IMM64:
+ start += snprintf(start, end - start, "#%#" PRIx64, op->imm64);
+ break;
+ case FIMM32:
+ start += snprintf(start, end - start, "#%f", op->immf);
+ break;
+ case FIMM64:
+ start += snprintf(start, end - start, "#%e", op->immd);
+ break;
+ case MEM_ALIGNED:
+ if (op->imm != 0)
+ snprintf(tmpOperand, sizeof(tmpOperand), ":%#x", op->imm);
+ else
+ tmpOperand[0] = 0;
+ start += snprintf(start, end - start, "[%s%s]%s",
+ get_register_name(op->reg),
+ tmpOperand,
+ wb[op->flags.wb]);
+ break;
+ case MEM_OPTION:
+ start += snprintf(start, end - start, "[%s], {%#x}",
+ get_register_name(op->reg),
+ op->imm);
+ break;
+ case MEM_PRE_IDX:
+ if (op->flags.offsetRegUsed == 1)
+ {
+ if (op->imm == 0)
+ snprintf(tmpOperand, sizeof(tmpOperand), "%s", get_register_name(op->offset));
+ else if (op->shift == SHIFT_RRX)
+ snprintf(tmpOperand, sizeof(tmpOperand), "%s, %s",
+ get_register_name(op->offset),
+ get_shift(op->shift));
+ else
+ snprintf(tmpOperand, sizeof(tmpOperand), "%s, %s #%#x",
+ get_register_name(op->offset),
+ get_shift(op->shift),
+ op->imm);
+
+ start += snprintf(start, end - start, "[%s, %s%s]!",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ tmpOperand);
+ }
+ else
+ {
+ start += snprintf(start, end - start, "[%s, #%s%#x]!",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ op->imm);
+ }
+ break;
+ case MEM_POST_IDX:
+ if (op->flags.offsetRegUsed == 1)
+ {
+ if (op->imm == 0)
+ snprintf(tmpOperand, sizeof(tmpOperand), "%s", get_register_name(op->offset));
+ else
+ if (op->shift == SHIFT_RRX)
+ snprintf(tmpOperand, sizeof(tmpOperand), "%s, %s", get_register_name(op->offset), get_shift(op->shift));
+ else
+ snprintf(tmpOperand, sizeof(tmpOperand), "%s, %s #%#x", get_register_name(op->offset), get_shift(op->shift), op->imm);
+
+ start += snprintf(start, end - start, "[%s], %s%s",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ tmpOperand);
+ }
+ else
+ {
+ start += snprintf(start, end - start, "[%s], #%s%#x",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ op->imm);
+ }
+ break;
+ case MEM_IMM:
+ if (op->shift == SHIFT_NONE)
+ {
+ if (op->flags.offsetRegUsed == 1)
+ {
+ start += snprintf(start, end - start, "[%s, %s%s]",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ get_register_name(op->offset));
+ }
+ else
+ {
+ if (op->imm != 0)
+ start += snprintf(start, end - start, "[%s, #%s%#x]",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ op->imm);
+ else
+ start += snprintf(start, end - start, "[%s]", get_register_name(op->reg));
+ }
+ }
+ else if (op->shift == SHIFT_RRX)
+ start += snprintf(start, end - start, "[%s, %s%s, %s]",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ get_register_name(op->offset),
+ get_shift(op->shift));
+ else
+ start += snprintf(start, end - start, "[%s, %s%s, %s #%#x]",
+ get_register_name(op->reg),
+ neg[op->flags.add == 1],
+ get_register_name(op->offset),
+ get_shift(op->shift),
+ op->imm);
+ break;
+ default:
+ return 4;
+ }
+ }
+ snprintf(outBuffer, outBufferSize, "%s\t%s",
+ get_full_operation(tmpOperand, sizeof(tmpOperand), instruction),
+ operands);
+ return 0;
+}
diff --git a/arch/armv7/armv7_disasm/armv7.h b/arch/armv7/armv7_disasm/armv7.h
new file mode 100644
index 00000000..dc26483f
--- /dev/null
+++ b/arch/armv7/armv7_disasm/armv7.h
@@ -0,0 +1,959 @@
+#pragma once
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+ #define snprintf _snprintf
+ #define restrict __restrict
+ #define inline __inline
+#else
+ #include <stdlib.h>
+ #ifdef __cplusplus
+ #define restrict __restrict
+ #endif
+#endif
+
+#define MAX_OPERANDS 6
+
+#define UNCONDITIONAL(c) (((c) == COND_NONE) || ((c) == COND_NONE2))
+#define CONDITIONAL(c) (((c) != COND_NONE) && ((c) != COND_NONE2))
+
+#ifdef __cplusplus
+#define restrict __restrict
+
+namespace armv7 {
+#endif
+
+enum Operation {
+ ARMV7_UNDEFINED,
+ ARMV7_UNPREDICTABLE,
+ ARMV7_ADC,
+ ARMV7_ADCS,
+ ARMV7_ADD,
+ ARMV7_ADDS,
+ ARMV7_ADDW,
+ ARMV7_ADR,
+ ARMV7_AND,
+ ARMV7_ANDS,
+ ARMV7_ASR,
+ ARMV7_ASRS,
+ ARMV7_B,
+ ARMV7_BFC,
+ ARMV7_BFI,
+ ARMV7_BIC,
+ ARMV7_BICS,
+ ARMV7_BKPT,
+ ARMV7_BL,
+ ARMV7_BLX,
+ ARMV7_BX,
+ ARMV7_BXJ,
+ ARMV7_CBNZ,
+ ARMV7_CBZ,
+ ARMV7_CDP,
+ ARMV7_CDP2,
+ ARMV7_CLREX,
+ ARMV7_CLZ,
+ ARMV7_CMN,
+ ARMV7_CMP,
+ ARMV7_CPS,
+ ARMV7_CPSID,
+ ARMV7_CPSIE,
+ ARMV7_DBG,
+ ARMV7_DMB,
+ ARMV7_DSB,
+ ARMV7_ENTERX,
+ ARMV7_EOR,
+ ARMV7_EORS,
+ ARMV7_ERET,
+ ARMV7_FLDMDBX,
+ ARMV7_FLDMIAX,
+ ARMV7_FSTMDBX,
+ ARMV7_FSTMIAX,
+ ARMV7_FSTMX,
+ ARMV7_HINT,
+ ARMV7_HVC,
+ ARMV7_ISB,
+ ARMV7_IT,
+ ARMV7_LDA,
+ ARMV7_LDAB,
+ ARMV7_LDAH,
+ ARMV7_LDAEX, // A32
+ ARMV7_LDAEXB, // A32
+ ARMV7_LDAEXH, // A32
+ ARMV7_LDAEXD, // A32
+ ARMV7_LDC,
+ ARMV7_LDC2,
+ ARMV7_LDC2L,
+ ARMV7_LDCL,
+ ARMV7_LDM,
+ ARMV7_LDMDA,
+ ARMV7_LDMDB,
+ ARMV7_LDMIA,
+ ARMV7_LDMIB,
+ ARMV7_LDR,
+ ARMV7_LDRB,
+ ARMV7_LDRBT,
+ ARMV7_LDRD,
+ ARMV7_LDREX,
+ ARMV7_LDREXB,
+ ARMV7_LDREXD,
+ ARMV7_LDREXH,
+ ARMV7_LDRH,
+ ARMV7_LDRHT,
+ ARMV7_LDRSB,
+ ARMV7_LDRSBT,
+ ARMV7_LDRSH,
+ ARMV7_LDRSHT,
+ ARMV7_LDRT,
+ ARMV7_LEAVEX,
+ ARMV7_LSL,
+ ARMV7_LSLS,
+ ARMV7_LSR,
+ ARMV7_LSRS,
+ ARMV7_MCR,
+ ARMV7_MCR2,
+ ARMV7_MCRR,
+ ARMV7_MCRR2,
+ ARMV7_MLA,
+ ARMV7_MLS,
+ ARMV7_MOV,
+ ARMV7_MOVS,
+ ARMV7_MOVT,
+ ARMV7_MOVW,
+ ARMV7_MRC,
+ ARMV7_MRC2,
+ ARMV7_MRRC,
+ ARMV7_MRRC2,
+ ARMV7_MRS,
+ ARMV7_MSR,
+ ARMV7_MUL,
+ ARMV7_MULS,
+ ARMV7_MVN,
+ ARMV7_MVNS,
+ ARMV7_NOP,
+ ARMV7_ORN,
+ ARMV7_ORR,
+ ARMV7_ORRS,
+ ARMV7_PKHBT,
+ ARMV7_PKHTB,
+ ARMV7_PLD,
+ ARMV7_PLDW,
+ ARMV7_PLI,
+ ARMV7_POP,
+ ARMV7_PUSH,
+ ARMV7_QADD,
+ ARMV7_QADD16,
+ ARMV7_QADD8,
+ ARMV7_QASX,
+ ARMV7_QDADD,
+ ARMV7_QDSUB,
+ ARMV7_QSAX,
+ ARMV7_QSUB,
+ ARMV7_QSUB16,
+ ARMV7_QSUB8,
+ ARMV7_RBIT,
+ ARMV7_REV,
+ ARMV7_REV16,
+ ARMV7_REVSH,
+ ARMV7_RFE,
+ ARMV7_RFEDA,
+ ARMV7_RFEDB,
+ ARMV7_RFEIA,
+ ARMV7_RFEIB,
+ ARMV7_ROR,
+ ARMV7_RORS,
+ ARMV7_RRX,
+ ARMV7_RSB,
+ ARMV7_RSBS,
+ ARMV7_RSC,
+ ARMV7_SADD16,
+ ARMV7_SADD8,
+ ARMV7_SASX,
+ ARMV7_SBC,
+ ARMV7_SBCS,
+ ARMV7_SBFX,
+ ARMV7_SDIV,
+ ARMV7_SEL,
+ ARMV7_SETEND,
+ ARMV7_SEV,
+ ARMV7_SHADD16,
+ ARMV7_SHADD8,
+ ARMV7_SHASX,
+ ARMV7_SHSAX,
+ ARMV7_SHSUB16,
+ ARMV7_SHSUB8,
+ ARMV7_SMC,
+ ARMV7_SMLABB,
+ ARMV7_SMLABT,
+ ARMV7_SMLAD,
+ ARMV7_SMLADX,
+ ARMV7_SMLAL,
+ ARMV7_SMLALBB,
+ ARMV7_SMLALBT,
+ ARMV7_SMLALD,
+ ARMV7_SMLALDX,
+ ARMV7_SMLALTB,
+ ARMV7_SMLALTT,
+ ARMV7_SMLATB,
+ ARMV7_SMLATT,
+ ARMV7_SMLAWB,
+ ARMV7_SMLAWT,
+ ARMV7_SMLSD,
+ ARMV7_SMLSDX,
+ ARMV7_SMLSLD,
+ ARMV7_SMLSLDX,
+ ARMV7_SMMLA,
+ ARMV7_SMMLAR,
+ ARMV7_SMMLS,
+ ARMV7_SMMLSR,
+ ARMV7_SMMUL,
+ ARMV7_SMMULR,
+ ARMV7_SMUAD,
+ ARMV7_SMUADX,
+ ARMV7_SMULBB,
+ ARMV7_SMULBT,
+ ARMV7_SMULL,
+ ARMV7_SMULTB,
+ ARMV7_SMULTT,
+ ARMV7_SMULWB,
+ ARMV7_SMULWT,
+ ARMV7_SMUSD,
+ ARMV7_SMUSDT,
+ ARMV7_SMUSDX,
+ ARMV7_SRS,
+ ARMV7_SRSDA,
+ ARMV7_SRSDB,
+ ARMV7_SRSIA,
+ ARMV7_SRSIB,
+ ARMV7_SSAT,
+ ARMV7_SSAT16,
+ ARMV7_SSAX,
+ ARMV7_SSUB16,
+ ARMV7_SSUB8,
+ ARMV7_STC,
+ ARMV7_STC2,
+ ARMV7_STC2L,
+ ARMV7_STCL,
+ ARMV7_STL, // A32
+ ARMV7_STLB,
+ ARMV7_STLH,
+ ARMV7_STLEX, // A32
+ ARMV7_STLEXB, // A32
+ ARMV7_STLEXH, // A32
+ ARMV7_STLEXD, // A32
+ ARMV7_STM,
+ ARMV7_STMBD,
+ ARMV7_STMDA,
+ ARMV7_STMDB,
+ ARMV7_STMIA,
+ ARMV7_STMIB,
+ ARMV7_STR,
+ ARMV7_STRB,
+ ARMV7_STRBT,
+ ARMV7_STRD,
+ ARMV7_STREX,
+ ARMV7_STREXB,
+ ARMV7_STREXD,
+ ARMV7_STREXH,
+ ARMV7_STRH,
+ ARMV7_STRHT,
+ ARMV7_STRT,
+ ARMV7_SUB,
+ ARMV7_SUBS,
+ ARMV7_SUBW,
+ ARMV7_SVC,
+ ARMV7_SWP,
+ ARMV7_SWPB,
+ ARMV7_SXTAB,
+ ARMV7_SXTAB16,
+ ARMV7_SXTAH,
+ ARMV7_SXTB,
+ ARMV7_SXTB16,
+ ARMV7_SXTH,
+ ARMV7_TBB,
+ ARMV7_TBH,
+ ARMV7_TEQ,
+ ARMV7_TRAP,
+ ARMV7_TRT,
+ ARMV7_TST,
+ ARMV7_UADD16,
+ ARMV7_UADD8,
+ ARMV7_UASX,
+ ARMV7_UBFX,
+ ARMV7_UDF,
+ ARMV7_UDIV,
+ ARMV7_UHADD16,
+ ARMV7_UHADD8,
+ ARMV7_UHASX,
+ ARMV7_UHSAX,
+ ARMV7_UHSUB16,
+ ARMV7_UHSUB8,
+ ARMV7_UMAAL,
+ ARMV7_UMLAL,
+ ARMV7_UMULL,
+ ARMV7_UQADD16,
+ ARMV7_UQADD8,
+ ARMV7_UQASX,
+ ARMV7_UQSAX,
+ ARMV7_UQSUB16,
+ ARMV7_UQSUB8,
+ ARMV7_USAD8,
+ ARMV7_USADA8,
+ ARMV7_USAT,
+ ARMV7_USAT16,
+ ARMV7_USAX,
+ ARMV7_USUB16,
+ ARMV7_USUB8,
+ ARMV7_UXTAB,
+ ARMV7_UXTAB16,
+ ARMV7_UXTAH,
+ ARMV7_UXTB,
+ ARMV7_UXTB16,
+ ARMV7_UXTH,
+ ARMV7_VABA,
+ ARMV7_VABAL,
+ ARMV7_VABD,
+ ARMV7_VABDL,
+ ARMV7_VABS,
+ ARMV7_VACGE,
+ ARMV7_VACGT,
+ ARMV7_VADD,
+ ARMV7_VADDHN,
+ ARMV7_VADDL,
+ ARMV7_VADDW,
+ ARMV7_VAND,
+ ARMV7_VBIC,
+ ARMV7_VBIF,
+ ARMV7_VBIT,
+ ARMV7_VBSL,
+ ARMV7_VCEQ,
+ ARMV7_VCGE,
+ ARMV7_VCGT,
+ ARMV7_VCLE,
+ ARMV7_VCLS,
+ ARMV7_VCLT,
+ ARMV7_VCLZ,
+ ARMV7_VCMP,
+ ARMV7_VCMPE,
+ ARMV7_VCNT,
+ ARMV7_VCVT,
+ ARMV7_VCVTA,
+ ARMV7_VCVTB,
+ ARMV7_VCVTM,
+ ARMV7_VCVTN,
+ ARMV7_VCVTP,
+ ARMV7_VCVTR,
+ ARMV7_VCVTT,
+ ARMV7_VDIV,
+ ARMV7_VDUP,
+ ARMV7_VEOR,
+ ARMV7_VEXT,
+ ARMV7_VFMA,
+ ARMV7_VFMS,
+ ARMV7_VFNMA,
+ ARMV7_VFNMS,
+ ARMV7_VHADD,
+ ARMV7_VHSUB,
+ ARMV7_VLD1,
+ ARMV7_VLD2,
+ ARMV7_VLD3,
+ ARMV7_VLD4,
+ ARMV7_VLDM,
+ ARMV7_VLDMDB,
+ ARMV7_VLDMIA,
+ ARMV7_VLDR,
+ ARMV7_VMAX,
+ ARMV7_VMAXNM,
+ ARMV7_VMIN,
+ ARMV7_VMINM,
+ ARMV7_VMLA,
+ ARMV7_VMLAL,
+ ARMV7_VMLS,
+ ARMV7_VMLSL,
+ ARMV7_VMOV,
+ ARMV7_VMOVL,
+ ARMV7_VMOVN,
+ ARMV7_VMRS,
+ ARMV7_VMSR,
+ ARMV7_VMUL,
+ ARMV7_VMULL,
+ ARMV7_VMVN,
+ ARMV7_VNEG,
+ ARMV7_VNMLA,
+ ARMV7_VNMLS,
+ ARMV7_VNMUL,
+ ARMV7_VORN,
+ ARMV7_VORR,
+ ARMV7_VPADAL,
+ ARMV7_VPADD,
+ ARMV7_VPADDL,
+ ARMV7_VPMAX,
+ ARMV7_VPMIN,
+ ARMV7_VPOP,
+ ARMV7_VPUSH,
+ ARMV7_VQABS,
+ ARMV7_VQADD,
+ ARMV7_VQDMLAL,
+ ARMV7_VQDMLSL,
+ ARMV7_VQDMULH,
+ ARMV7_VQDMULL,
+ ARMV7_VQMOVN,
+ ARMV7_VQMOVUN,
+ ARMV7_VQNEG,
+ ARMV7_VQRDMULH,
+ ARMV7_VQRSHL,
+ ARMV7_VQRSHRN,
+ ARMV7_VQRSHRUN,
+ ARMV7_VQSHL,
+ ARMV7_VQSHLU,
+ ARMV7_VQSHRN,
+ ARMV7_VQSHRUN,
+ ARMV7_VQSUB,
+ ARMV7_VRADDHN,
+ ARMV7_VRECPE,
+ ARMV7_VRECPS,
+ ARMV7_VREV16,
+ ARMV7_VREV32,
+ ARMV7_VREV64,
+ ARMV7_VRHADD,
+ ARMV7_VRHSUB,
+ ARMV7_VRINTA,
+ ARMV7_VRINTM,
+ ARMV7_VRINTN,
+ ARMV7_VRINTP,
+ ARMV7_VRINTR,
+ ARMV7_VRINTX,
+ ARMV7_VRINTZ,
+ ARMV7_VRSHL,
+ ARMV7_VRSHR,
+ ARMV7_VRSHRN,
+ ARMV7_VRSQRTE,
+ ARMV7_VRSQRTS,
+ ARMV7_VRSRA,
+ ARMV7_VRSUBHN,
+ ARMV7_VSEL,
+ ARMV7_VSHL,
+ ARMV7_VSHLL,
+ ARMV7_VSHR,
+ ARMV7_VSHRN,
+ ARMV7_VSLI,
+ ARMV7_VSQRT,
+ ARMV7_VSRA,
+ ARMV7_VSRI,
+ ARMV7_VST1,
+ ARMV7_VST2,
+ ARMV7_VST3,
+ ARMV7_VST4,
+ ARMV7_VSTM,
+ ARMV7_VSTMDB,
+ ARMV7_VSTMIA,
+ ARMV7_VSTR,
+ ARMV7_VSUB,
+ ARMV7_VSUBHN,
+ ARMV7_VSUBL,
+ ARMV7_VSUBW,
+ ARMV7_VSWP,
+ ARMV7_VTBL,
+ ARMV7_VTBX,
+ ARMV7_VTRN,
+ ARMV7_VTST,
+ ARMV7_VUZP,
+ ARMV7_VZIP,
+ ARMV7_WFE,
+ ARMV7_WFI,
+ ARMV7_YIELD,
+ ARMV7_END_INSTRUCTION
+};
+
+enum Shift {
+ SHIFT_NONE,
+ SHIFT_LSL,
+ SHIFT_LSR,
+ SHIFT_ASR,
+ SHIFT_ROR,
+ SHIFT_RRX,
+ SHIFT_END
+};
+
+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_NONE,
+ COND_NONE2,
+ COND_END
+};
+
+
+enum RegisterList {
+ REG_LIST_R0 = 0x0001,
+ REG_LIST_R1 = 0x0002,
+ REG_LIST_R2 = 0x0004,
+ REG_LIST_R3 = 0x0008,
+ REG_LIST_R4 = 0x0010,
+ REG_LIST_R5 = 0x0020,
+ REG_LIST_R6 = 0x0040,
+ REG_LIST_R7 = 0x0080,
+ REG_LIST_R8 = 0x0100,
+ REG_LIST_SB = 0x0200,
+ REG_LIST_SL = 0x0400,
+ REG_LIST_FP = 0x0800,
+ REG_LIST_IP = 0x1000,
+ REG_LIST_SP = 0x2000,
+ REG_LIST_LR = 0x4000,
+ REG_LIST_PC = 0x8000,
+};
+
+enum Register
+{
+ REG_R0 = 0,
+ REG_R1,
+ REG_R2,
+ REG_R3,
+ REG_R4,
+ REG_R5,
+ REG_R6,
+ REG_R7,
+ REG_R8,
+ REG_R9,
+ REG_R10,
+ REG_R11,
+ REG_R12,
+ REG_SP, REG_R13 = 13,
+ REG_LR, REG_R14 = 14,
+ REG_PC, REG_R15 = 15,
+ 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,
+
+ /* banked registers */
+ REGB_ELR_HYP,
+ REGB_LR_ABT,
+ REGB_LR_FIQ,
+ REGB_LR_IRQ,
+ REGB_LR_MON,
+ REGB_LR_SVC,
+ REGB_LR_UND,
+ REGB_LR_USR,
+ REGB_R10_FIQ,
+ REGB_R10_USR,
+ REGB_R11_FIQ,
+ REGB_R11_USR,
+ REGB_R12_FIQ,
+ REGB_R12_USR,
+ REGB_R8_FIQ,
+ REGB_R8_USR,
+ REGB_R9_FIQ,
+ REGB_R9_USR,
+ REGB_SPSR_ABT,
+ REGB_SPSR_FIQ,
+ REGB_SPSR_HYP,
+ REGB_SPSR_IRQ,
+ REGB_SPSR_MON,
+ REGB_SPSR_SVC,
+ REGB_SPSR_UND,
+ REGB_SP_ABT,
+ REGB_SP_FIQ,
+ REGB_SP_HYP,
+ REGB_SP_IRQ,
+ REGB_SP_MON,
+ REGB_SP_SVC,
+ REGB_SP_UND,
+ REGB_SP_USR,
+
+ /* special registers */
+ REGS_APSR,
+ REGS_APSR_G,
+ REGS_APSR_NZCVQ,
+ REGS_APSR_NZCVQG,
+ REGS_CPSR,
+ REGS_CPSR_C,
+ REGS_CPSR_X,
+ REGS_CPSR_XC,
+ REGS_CPSR_S,
+ REGS_CPSR_SC,
+ REGS_CPSR_SX,
+ REGS_CPSR_SXC,
+ REGS_CPSR_F,
+ REGS_CPSR_FC,
+ REGS_CPSR_FX,
+ REGS_CPSR_FXC,
+ REGS_CPSR_FS,
+ REGS_CPSR_FSC,
+ REGS_CPSR_FSX,
+ REGS_CPSR_FSXC,
+ REGS_SPSR,
+ REGS_SPSR_C,
+ REGS_SPSR_X,
+ REGS_SPSR_XC,
+ REGS_SPSR_S,
+ REGS_SPSR_SC,
+ REGS_SPSR_SX,
+ REGS_SPSR_SXC,
+ REGS_SPSR_F,
+ REGS_SPSR_FC,
+ REGS_SPSR_FX,
+ REGS_SPSR_FXC,
+ REGS_SPSR_FS,
+ REGS_SPSR_FSC,
+ REGS_SPSR_FSX,
+ REGS_SPSR_FSXC,
+ REGS_APSR_NZCV,
+ REGS_FPSID, // 0
+ REGS_FPSCR, // 1
+ REGS_MVFR2, // 5
+ REGS_MVFR1, // 6
+ REGS_MVFR0, // 7
+ REGS_FPEXC, // 8
+ REGS_FPINST, // 9
+ REGS_FPINST2, //10
+ REGS_MSP,
+ REGS_PSP,
+
+ // these are M-profile only (special)
+ // but are here in ARM common (general)
+ // TODO: implement "microarchitecture support"
+ REGS_PRIMASK,
+ REGS_BASEPRI,
+ REGS_FAULTMASK,
+ REGS_CONTROL,
+
+ REG_INVALID,
+};
+
+enum CoprocRegisterC {
+ REG_C0,
+ REG_C1,
+ REG_C2,
+ REG_C3,
+ REG_C4,
+ REG_C5,
+ REG_C6,
+ REG_C7,
+ REG_C8,
+ REG_C9,
+ REG_C10,
+ REG_C11,
+ REG_C12,
+ REG_C13,
+ REG_C14,
+ REG_C15,
+ REG_CEND
+};
+
+enum CoprocRegisterP {
+ 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_PEND
+};
+
+enum Iflags {
+ IFL_NONE, // 000
+ IFL_A, // 001
+ IFL_I, // 010
+ IFL_IA, // 011
+ IFL_F, // 100
+ IFL_FA, // 101
+ IFL_FI, // 110
+ IFL_FIA, // 111
+ IFL_END //
+};
+
+enum EndianSpec {
+ ES_LE,
+ ES_BE
+};
+
+enum DsbOption {
+ DSB_NONE0, // 0
+ DSB_NONE1, // 1
+ DSB_OSHST, // 2
+ DSB_OSH, // 3
+ DSB_NONE4, // 4
+ DSB_NONE5, // 5
+ DSB_NSHST, // 6
+ DSB_NSH, //7
+ DSB_NONE8, // 8
+ DSB_NONE9, // 9
+ DSB_ISHST, // 10
+ DSB_ISH, // 11
+ DSB_NONE12, // 12
+ DSB_NONE13, // 13
+ DSB_ST, // 14
+ DSB_SY, // 15
+ DSB_END
+};
+
+enum OperandClass {
+ NONE,
+ IMM,
+ IMM64,
+ LABEL,
+ REG,
+ REG_LIST,
+ REG_LIST_SINGLE,
+ REG_LIST_DOUBLE,
+ REG_SPEC,
+ REG_BANKED,
+ REG_COPROCC,
+ REG_COPROCP,
+ IFLAGS,
+ ENDIAN_SPEC,
+ DSB_OPTION,
+ MEM_ALIGNED,
+ MEM_PRE_IDX,
+ MEM_POST_IDX,
+ MEM_IMM,
+ MEM_OPTION,
+ FIMM16,
+ FIMM32,
+ FIMM64
+};
+
+enum DataType {
+ DT_NONE = 0,
+ DT_S8 = 1,
+ DT_S16,
+ DT_S32,
+ DT_S64,
+ DT_U8,
+ DT_U16,
+ DT_U32,
+ DT_U64,
+ DT_I8,
+ DT_I16,
+ DT_I32,
+ DT_I64,
+ DT_F16,
+ DT_F32,
+ DT_F64,
+ DT_P8,
+ DT_P16,
+ DT_P32,
+ DT_P64,
+ DT_8,
+ DT_16,
+ DT_32,
+ DT_64,
+ DT_END
+};
+
+struct InstructionOperand {
+ enum OperandClass cls;
+ struct {
+ uint32_t wb:1; //write back?
+ uint32_t add:1; //Tells whether offset should be added or subtracted
+ uint32_t hasElements:1; //does the register have an array index
+ uint32_t emptyElement:1;
+ uint32_t offsetRegUsed:1; //Is the offset register being used
+ } flags;
+ union {
+ enum Register reg;
+ enum Register regb; /* banked reg */
+ enum Register regs; /* special reg */
+ enum CoprocRegisterP regp;
+ enum CoprocRegisterC regc;
+ enum DsbOption dsbOpt;
+ enum Iflags iflag;
+ enum EndianSpec endian;
+ enum Condition cond;
+ };
+ enum Register offset;
+ enum Shift shift;
+ union {
+ uint32_t imm;
+ double immd;
+ float immf;
+ uint64_t imm64;
+ };
+};
+
+struct Instruction{
+ enum Operation operation;
+ enum Condition cond;
+ enum DataType dataType;
+ enum DataType dataType2;
+ uint32_t setsFlags;
+ uint32_t unpredictable;
+ struct InstructionOperand operands[MAX_OPERANDS];
+};
+
+typedef union _ieee754 {
+ uint32_t value;
+ struct {
+ uint32_t fraction:23;
+ uint32_t exponent:8;
+ uint32_t sign:1;
+ };
+ float fvalue;
+}ieee754;
+
+typedef union _ieee754_double {
+ uint64_t value;
+ struct {
+ uint64_t fraction:52;
+ uint64_t exponent:11;
+ uint64_t sign:1;
+ };
+ double fvalue;
+}ieee754_double;
+
+#ifndef __cplusplus
+ typedef enum OperandClass OperandClass;
+ typedef enum Operation Operation;
+ typedef enum Shift Shift;
+ typedef enum Condition Condition;
+ typedef enum Register Register;
+ typedef enum BankedRegister BankedRegister;
+ typedef enum SpecRegister SpecRegister;
+ typedef enum CoprocRegisterP CoprocRegisterP;
+ typedef enum CoprocRegisterC CoprocRegisterC;
+ typedef enum DataType DataType;
+ typedef enum Iflags Iflags;
+ typedef enum EndianSpec EndianSpec;
+ typedef enum DsbOption DsbOption;
+ typedef struct InstructionOperand InstructionOperand;
+ typedef struct Instruction Instruction;
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+ uint32_t armv7_decompose(
+ uint32_t instructionValue,
+ Instruction* restrict instruction,
+ uint32_t address,
+ uint32_t littleEndian);
+
+ uint32_t armv7_disassemble(
+ Instruction* restrict instruction,
+ char* outBuffer,
+ uint32_t outBufferSize);
+
+ //Helpers for disassembling the instruction operands to strings
+ const char* get_operation(Operation operation);
+ char* get_full_operation(char* outBuffer, size_t outBufferSize, Instruction* restrict instruction);
+ const char* get_vector_data_type(DataType dataType);
+ const char* get_register_name(Register reg);
+ const char* get_banked_register_name(Register regb);
+ const char* get_spec_register_name(Register regs);
+ const char* get_coproc_register_c_name(CoprocRegisterC regc);
+ const char* get_coproc_register_p_name(CoprocRegisterP regp);
+ const char* get_iflag(Iflags iflag);
+ const char* get_endian(EndianSpec spec);
+ const char* get_dsb_option(DsbOption opt);
+ const char* get_shift(Shift shift);
+ const char* get_condition(Condition cond);
+ uint32_t get_register_size(Register reg);
+ uint32_t get_register_names(Register reg, const char** regNames, OperandClass type);
+#ifdef __cplusplus
+ } //end extern "C"
+#endif
+
+#ifdef __cplusplus
+} //end namespace
+#endif
diff --git a/arch/armv7/armv7_disasm/test.c b/arch/armv7/armv7_disasm/test.c
new file mode 100644
index 00000000..162cb5ac
--- /dev/null
+++ b/arch/armv7/armv7_disasm/test.c
@@ -0,0 +1,38 @@
+// gcc -g test.c armv7.c -o test
+// lldb ./test -- e28f007b
+// b armv7_decompose
+// b armv7_disassemble
+//
+
+#include <stdio.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "armv7.h"
+
+int main(int ac, char **av)
+{
+ uint32_t insword = strtoul(av[1], NULL, 16);
+ uint32_t address = 0;
+ uint32_t endian = 0;
+ uint32_t rc;
+
+ Instruction instr;
+ memset(&instr, 0, sizeof(instr));
+
+ rc = armv7_decompose(insword, &instr, address, endian);
+ if(rc) {
+ printf("ERROR: armv7_decompose() returned %d\n", rc);
+ return rc;
+ }
+
+ char instxt[4096];
+ memset(instxt, 0, sizeof(instxt));
+ rc = armv7_disassemble(&instr, instxt, sizeof(instxt));
+ if(rc) {
+ printf("ERROR: armv7_disassemble() returned %d\n", rc);
+ return rc;
+ }
+
+ printf("%08X: %s\n", address, instxt);
+}
+
diff --git a/arch/armv7/armv7_disasm/test.py b/arch/armv7/armv7_disasm/test.py
new file mode 100755
index 00000000..5f2e117c
--- /dev/null
+++ b/arch/armv7/armv7_disasm/test.py
@@ -0,0 +1,1635 @@
+#!/usr/bin/env python
+
+# compile disassembler to ctypes-able shared object:
+# MAC: gcc armv7.c -shared -o disasm.dylib
+
+# (bytes, expected_disassembly, options)
+test_cases = (
+ # msr, mrs
+ (b'\x00\x80\x0f\xe1', 'mrs r8, apsr', {}),
+ (b'\x00\x80\x0f\xe1', 'mrs r8, apsr', {}),
+ (b'\x00\x80\x4f\xe1', 'mrs r8, spsr', {}),
+ (b'\x05\xf0\x28\xe3', 'msr apsr_nzcvq, #0x5', {}),
+ (b'\x05\xf0\x24\xe3', 'msr apsr_g, #0x5', {}),
+ (b'\x05\xf0\x28\xe3', 'msr apsr_nzcvq, #0x5', {}),
+ (b'\x05\xf0\x28\xe3', 'msr apsr_nzcvq, #0x5', {}),
+ (b'\x05\xf0\x2c\xe3', 'msr apsr_nzcvqg, #0x5', {}),
+ (b'\x05\xf0\x29\xe3', 'msr cpsr_fc, #0x5', {}),
+ (b'\x05\xf0\x21\xe3', 'msr cpsr_c, #0x5', {}),
+ (b'\x05\xf0\x22\xe3', 'msr cpsr_x, #0x5', {}),
+ (b'\x05\xf0\x29\xe3', 'msr cpsr_fc, #0x5', {}),
+ (b'\x05\xf0\x29\xe3', 'msr cpsr_fc, #0x5', {}),
+ (b'\x05\xf0\x2e\xe3', 'msr cpsr_fsx, #0x5', {}),
+ (b'\x05\xf0\x69\xe3', 'msr spsr_fc, #0x5', {}),
+ (b'\x05\xf0\x6f\xe3', 'msr spsr_fsxc, #0x5', {}),
+ (b'\x05\xf0\x2f\xe3', 'msr cpsr_fsxc, #0x5', {}),
+ (b'\x00\xf0\x28\xe1', 'msr apsr_nzcvq, r0', {}),
+ (b'\x00\xf0\x24\xe1', 'msr apsr_g, r0', {}),
+ (b'\x00\xf0\x28\xe1', 'msr apsr_nzcvq, r0', {}),
+ (b'\x00\xf0\x28\xe1', 'msr apsr_nzcvq, r0', {}),
+ (b'\x00\xf0\x2c\xe1', 'msr apsr_nzcvqg, r0', {}),
+ (b'\x00\xf0\x29\xe1', 'msr cpsr_fc, r0', {}),
+ (b'\x00\xf0\x21\xe1', 'msr cpsr_c, r0', {}),
+ (b'\x00\xf0\x22\xe1', 'msr cpsr_x, r0', {}),
+ (b'\x00\xf0\x29\xe1', 'msr cpsr_fc, r0', {}),
+ (b'\x00\xf0\x29\xe1', 'msr cpsr_fc, r0', {}),
+ (b'\x00\xf0\x2e\xe1', 'msr cpsr_fsx, r0', {}),
+ (b'\x00\xf0\x69\xe1', 'msr spsr_fc, r0', {}),
+ (b'\x00\xf0\x6f\xe1', 'msr spsr_fsxc, r0', {}),
+ (b'\x00\xf0\x2f\xe1', 'msr cpsr_fsxc, r0', {}),
+
+ # supervisor calls
+ (b'\x10\x00\x00\xef', 'svc #0x10', {}),
+ (b'\x00\x00\x00\xef', 'svc #0', {}),
+ (b'\xff\xff\xff\xef', 'svc #0xffffff', {}),
+ (b'\x01\x00\x00\xef', 'svc #0x1', {}),
+ (b'\x02\x00\x00\xef', 'svc #0x2', {}),
+ (b'\x56\x34\x12\xef', 'svc #0x123456', {}),
+ #
+ (b'\x93\xfc\x80\xe1', 'stl r3, [r0]', {}), # NOT 'strex pc, r3, [r0]'
+ (b'\x94\xfc\x81\xe1', 'stl r4, [r1]', {}),
+ (b'\x95\xfc\x82\xe1', 'stl r5, [r2]', {}),
+ (b'\x96\xfc\x83\xe1', 'stl r6, [r3]', {}),
+ # store register exclusive should be A32 stlex, stlexb, stlexh, stlexd when b11...b8 == 1110
+ (b'\x9f\x1e\x87\xe1', 'stlex r1, pc, [r7]', {}),
+ (b'\x9f\x2e\xe5\xe1', 'stlexh r2, pc, [r5]', {}),
+ (b'\x9f\x3e\xc4\xe1', 'stlexb r3, pc, [r4]', {}),
+ (b'\x9f\x5e\x86\xe1', 'stlex r5, pc, [r6]', {}),
+ (b'\x9f\x5e\xc6\xe1', 'stlexb r5, pc, [r6]', {}),
+ (b'\x94\x2e\xa6\xe1', 'stlexd r2, r4, r5, [r6]', {}),
+ (b'\x9f\xce\xe9\xe1', 'stlexh r12, pc, [r9]', {}),
+ # load register exclusive should be A32 ldaex, ldaexb, ldaexh, ldaexd when b11...b8 == 1110
+ (b'\x9f\x1e\x97\xe1', 'ldaex r1, [r7]', {}),
+ (b'\x9f\x2e\xf5\xe1', 'ldaexh r2, [r5]', {}),
+ (b'\x9f\x3e\xd4\xe1', 'ldaexb r3, [r4]', {}),
+ (b'\x9f\x5e\x96\xe1', 'ldaex r5, [r6]', {}),
+ (b'\x9f\x5e\xd6\xe1', 'ldaexb r5, [r6]', {}),
+ (b'\x9f\x6e\xb8\xe1', 'ldaexd r6, r7, [r8]', {}),
+ (b'\x9f\xce\xf9\xe1', 'ldaexh r12, [r9]', {}),
+ # load register exclusive should SUCCEED when b11...b8 == 1111
+ (b'\x9f\x1f\x97\xe1', 'ldrex r1, [r7]', {}),
+ (b'\x9f\x2f\xf5\xe1', 'ldrexh r2, [r5]', {}),
+ (b'\x9f\x3f\xd4\xe1', 'ldrexb r3, [r4]', {}),
+ (b'\x9f\x5f\x96\xe1', 'ldrex r5, [r6]', {}),
+ (b'\x9f\x5f\xd6\xe1', 'ldrexb r5, [r6]', {}),
+ (b'\x9f\x6f\xb8\xe1', 'ldrexd r6, r7, [r8]', {}),
+ (b'\x9f\xcf\xf9\xe1', 'ldrexh r12, [r9]', {}),
+ # load register exclusive should FAIL when b11...b8 != 1111 ...DEBATABLE!
+ #(b'\x9f\x1d\x97\xe1', 'decomposer failed', {}),
+ #(b'\x9f\x2c\xf5\xe1', 'decomposer failed', {}),
+ #(b'\x9f\x3b\xd4\xe1', 'decomposer failed', {}),
+ #(b'\x9f\x6a\xb8\xe1', 'decomposer failed', {}),
+ # adr
+ (b'\x7b\x00\x8f\xe2', 'adr r0, 0x83', {}),
+ # ENCODING A1: cond.4|00|1|0100|0|1111|Rd.4|imm12.12
+ # when ADR aliases "add pc, something"
+ (b'\x00\x00\x8f\xe2', 'adr r0, 0x8', {'addr':0}),
+ (b'\x00\x00\x8f\xe2', 'adr r0, 0xc', {'addr':4}),
+ (b'\x00\x00\x8f\xe2', 'adr r0, 0xa0000008', {'addr':0xa0000000}),
+ (b'\x00\x00\x8f\xe2', 'adr r0, 0xa000000c', {'addr':0xa0000004}),
+ (b'\x24\x00\x8f\xe2', 'adr r0, 0x2c', {'addr':0}), # 0 + 8 + 0x24 == 0x2C
+ (b'\x24\x00\x8f\xe2', 'adr r0, 0x30', {'addr':4}), # 4 + 8 + 0x24 == 0x30
+ (b'\x24\x00\x8f\xe2', 'adr r0, 0xa000002c', {'addr':0xa0000000}), # a0000020 + 8 + 0x24 = 0xa000002c
+ (b'\x24\x00\x8f\xe2', 'adr r0, 0xa0000030', {'addr':0xa0000004}), # a0000030 + 8 + 0x24 = 0xa0000030
+ # ENCODING A2: cond.4|00|1|0010|0|1111|Rd.4|imm12.12
+ # when ADR aliases "sub pc, something"
+ (b'\x00\x00\x4f\xe2', 'adr r0, 0x8', {'addr':0}),
+ (b'\x00\x00\x4f\xe2', 'adr r0, 0xc', {'addr':4}),
+ (b'\x00\x00\x4f\xe2', 'adr r0, 0xa0000008', {'addr':0xa0000000}),
+ (b'\x00\x00\x4f\xe2', 'adr r0, 0xa000000c', {'addr':0xa0000004}),
+ (b'\x24\x00\x4f\xe2', 'adr r0, 0xffffffe4', {'addr':0}), # 0 + 8 - 0x24 = 0xffffffe4
+ (b'\x24\x00\x4f\xe2', 'adr r0, 0xffffffe8', {'addr':4}), # 4 + 8 - 0x24 = 0xffffffe8
+ (b'\x24\x00\x4f\xe2', 'adr r0, 0x9fffffe4', {'addr':0xa0000000}), # 0xa00000000 + 8 - 0x24 = 0x9fffffe4
+ (b'\x24\x00\x4f\xe2', 'adr r0, 0x9fffffe8', {'addr':0xa0000004}), # 0xa00000004 + 8 - 0x24 = 0x9fffffe8
+ #
+ (b'\x03\x10\x02\xe0', 'and r1, r2, r3', {}),
+ (b'\x03\x10\x22\xe0', 'eor r1, r2, r3', {}),
+ (b'\x03\x10\x42\xe0', 'sub r1, r2, r3', {}),
+ (b'\x03\x10\x82\xe0', 'add r1, r2, r3', {}),
+ (b'\x03\x10\x82\xe1', 'orr r1, r2, r3', {}),
+ (b'\x03\x10\xc2\xe1', 'bic r1, r2, r3', {}),
+ (b'\x03\x20\x02\xe0', 'and r2, r2, r3', {}),
+ (b'\x03\x20\x12\x00', 'and.seq r2, r2, r3', {}),
+ (b'\x03\x20\x22\xe0', 'eor r2, r2, r3', {}),
+ (b'\x03\x20\x32\x00', 'eor.seq r2, r2, r3', {}),
+ (b'\x03\x20\x42\xe0', 'sub r2, r2, r3', {}),
+ (b'\x03\x20\x52\x00', 'sub.seq r2, r2, r3', {}),
+ (b'\x03\x20\x82\xe0', 'add r2, r2, r3', {}),
+ (b'\x03\x20\x82\xe1', 'orr r2, r2, r3', {}),
+ (b'\x03\x20\x92\x00', 'add.seq r2, r2, r3', {}),
+ (b'\x03\x20\x92\x01', 'orr.seq r2, r2, r3', {}),
+ (b'\x03\x20\xc2\xe1', 'bic r2, r2, r3', {}),
+ (b'\x03\x20\xd2\x01', 'bic.seq r2, r2, r3', {}),
+ (b'\x06\x20\x02\xe2', 'and r2, r2, #0x6', {}),
+ (b'\x06\x20\x12\x02', 'and.seq r2, r2, #0x6', {}),
+ (b'\x06\x20\x22\xe2', 'eor r2, r2, #0x6', {}),
+ (b'\x06\x20\x32\x02', 'eor.seq r2, r2, #0x6', {}),
+ (b'\x06\x20\x42\xe2', 'sub r2, r2, #0x6', {}),
+ (b'\x06\x20\x52\x02', 'sub.seq r2, r2, #0x6', {}),
+ (b'\x06\x20\x82\xe2', 'add r2, r2, #0x6', {}),
+ (b'\x06\x20\x82\xe3', 'orr r2, r2, #0x6', {}),
+ (b'\x06\x20\x92\x02', 'add.seq r2, r2, #0x6', {}),
+ (b'\x06\x20\x92\x03', 'orr.seq r2, r2, #0x6', {}),
+ (b'\x06\x20\xc2\xe3', 'bic r2, r2, #0x6', {}),
+ (b'\x06\x20\xd2\x03', 'bic.seq r2, r2, #0x6', {}),
+ (b'\x03\x20\xa0\x01', 'moveq r2, r3', {}),
+ (b'\x00\x50\x97\xe5', 'ldr r5, [r7]', {}),
+ (b'\x3f\x60\x93\xe5', 'ldr r6, [r3, #0x3f]', {}),
+ (b'\xff\x2f\xb4\xe5', 'ldr r2, [r4, #0xfff]!', {}),
+ (b'\x1e\x10\x92\xe4', 'ldr r1, [r2], #0x1e', {}),
+ (b'\x1e\x30\x11\xe4', 'ldr r3, [r1], #-0x1e', {}),
+ (b'\x00\x90\x12\xe4', 'ldr r9, [r2], #-0', {}),
+ (b'\x01\x30\x98\xe7', 'ldr r3, [r8, r1]', {}),
+ (b'\x03\x20\x15\xe7', 'ldr r2, [r5, -r3]', {}),
+ (b'\x09\x10\xb5\xe7', 'ldr r1, [r5, r9]!', {}),
+ (b'\x08\x60\x37\xe7', 'ldr r6, [r7, -r8]!', {}),
+ (b'\xa2\x11\xb0\xe7', 'ldr r1, [r0, r2, lsr #0x3]!', {}),
+ (b'\x02\x50\x99\xe6', 'ldr r5, [r9], r2', {}),
+ (b'\x06\x40\x13\xe6', 'ldr r4, [r3], -r6', {}),
+ (b'\x82\x37\x18\xe7', 'ldr r3, [r8, -r2, lsl #0xf]', {}),
+ (b'\xc3\x17\x95\xe6', 'ldr r1, [r5], r3, asr #0xf', {}),
+ (b'\x00\x30\xd8\xe5', 'ldrb r3, [r8]', {}),
+ (b'\x3f\x10\xdd\xe5', 'ldrb r1, [sp, #0x3f]', {}),
+ (b'\xff\x9f\xf3\xe5', 'ldrb r9, [r3, #0xfff]!', {}),
+ (b'\x16\x80\xd1\xe4', 'ldrb r8, [r1], #0x16', {}),
+ (b'\x13\x20\x57\xe4', 'ldrb r2, [r7], #-0x13', {}),
+ (b'\x05\x90\xd8\xe7', 'ldrb r9, [r8, r5]', {}),
+ (b'\x01\x10\x55\xe7', 'ldrb r1, [r5, -r1]', {}),
+ (b'\x02\x30\xf5\xe7', 'ldrb r3, [r5, r2]!', {}),
+ (b'\x03\x60\x79\xe7', 'ldrb r6, [r9, -r3]!', {}),
+ (b'\x04\x20\xd1\xe6', 'ldrb r2, [r1], r4', {}),
+ (b'\x05\x80\x54\xe6', 'ldrb r8, [r4], -r5', {}),
+ (b'\x81\x77\x5c\xe7', 'ldrb r7, [r12, -r1, lsl #0xf]', {}),
+ (b'\xc9\x57\xd2\xe6', 'ldrb r5, [r2], r9, asr #0xf', {}),
+ (b'\x04\x30\xf1\xe4', 'ldrbt r3, [r1], #0x4', {}),
+ (b'\x08\x20\x78\xe4', 'ldrbt r2, [r8], #-0x8', {}),
+ (b'\x06\x80\xf7\xe6', 'ldrbt r8, [r7], r6', {}),
+ (b'\x06\x16\x72\xe6', 'ldrbt r1, [r2], -r6, lsl #0xc', {}),
+ (b'\xd0\x20\xc5\xe1', 'ldrd r2, r3, [r5]', {}),
+ (b'\xdf\x60\xc2\xe1', 'ldrd r6, r7, [r2, #0xf]', {}),
+ (b'\xd0\x02\xe9\xe1', 'ldrd r0, r1, [r9, #0x20]!', {}),
+ (b'\xd8\x60\xc1\xe0', 'ldrd r6, r7, [r1], #0x8', {}),
+ (b'\xd0\x00\xc8\xe0', 'ldrd r0, r1, [r8], #0', {}),
+ (b'\xd0\x00\xc8\xe0', 'ldrd r0, r1, [r8], #0', {}),
+ (b'\xd0\x00\x48\xe0', 'ldrd r0, r1, [r8], #-0', {}),
+ (b'\xd3\x40\x81\xe1', 'ldrd r4, r5, [r1, r3]', {}),
+ (b'\xd2\x40\xa7\xe1', 'ldrd r4, r5, [r7, r2]!', {}),
+ (b'\xdc\x00\x88\xe0', 'ldrd r0, r1, [r8], r12', {}),
+ (b'\xdc\x00\x08\xe0', 'ldrd r0, r1, [r8], -r12', {}),
+ (b'\xb0\x30\xd4\xe1', 'ldrh r3, [r4]', {}),
+ (b'\xb4\x20\xd7\xe1', 'ldrh r2, [r7, #0x4]', {}),
+ (b'\xb0\x14\xf8\xe1', 'ldrh r1, [r8, #0x40]!', {}),
+ (b'\xb4\xc0\xdd\xe0', 'ldrh r12, [sp], #0x4', {}),
+ (b'\xb4\x60\x95\xe1', 'ldrh r6, [r5, r4]', {}),
+ (b'\xbb\x30\xb8\xe1', 'ldrh r3, [r8, r11]!', {}),
+ (b'\xb1\x10\x32\xe1', 'ldrh r1, [r2, -r1]!', {}),
+ (b'\xb2\x90\x97\xe0', 'ldrh r9, [r7], r2', {}),
+ (b'\xb2\x40\x13\xe0', 'ldrh r4, [r3], -r2', {}),
+ (b'\xb0\x98\xf7\xe0', 'ldrht r9, [r7], #0x80', {}),
+ (b'\xbb\x44\x73\xe0', 'ldrht r4, [r3], #-0x4b', {}),
+ (b'\xb2\x90\xb7\xe0', 'ldrht r9, [r7], r2', {}),
+ (b'\xb2\x40\x33\xe0', 'ldrht r4, [r3], -r2', {}),
+ (b'\xd0\x30\xd4\xe1', 'ldrsb r3, [r4]', {}),
+ (b'\xd1\x21\xd7\xe1', 'ldrsb r2, [r7, #0x11]', {}),
+ (b'\xdf\x1f\xf8\xe1', 'ldrsb r1, [r8, #0xff]!', {}),
+ (b'\xd9\xc0\xdd\xe0', 'ldrsb r12, [sp], #0x9', {}),
+ (b'\xd4\x60\x95\xe1', 'ldrsb r6, [r5, r4]', {}),
+ (b'\xdb\x30\xb8\xe1', 'ldrsb r3, [r8, r11]!', {}),
+ (b'\xd1\x10\x32\xe1', 'ldrsb r1, [r2, -r1]!', {}),
+ (b'\xd2\x90\x97\xe0', 'ldrsb r9, [r7], r2', {}),
+ (b'\xd2\x40\x13\xe0', 'ldrsb r4, [r3], -r2', {}),
+ (b'\xd1\x50\xf6\xe0', 'ldrsbt r5, [r6], #0x1', {}),
+ (b'\xdc\x30\x78\xe0', 'ldrsbt r3, [r8], #-0xc', {}),
+ (b'\xd5\x80\xb9\xe0', 'ldrsbt r8, [r9], r5', {}),
+ (b'\xd4\x20\x31\xe0', 'ldrsbt r2, [r1], -r4', {}),
+ (b'\xf0\x50\xd9\xe1', 'ldrsh r5, [r9]', {}),
+ (b'\xf7\x40\xd5\xe1', 'ldrsh r4, [r5, #0x7]', {}),
+ (b'\xf7\x33\xf6\xe1', 'ldrsh r3, [r6, #0x37]!', {}),
+ (b'\xf9\x20\x57\xe0', 'ldrsh r2, [r7], #-0x9', {}),
+ (b'\xf5\x30\x91\xe1', 'ldrsh r3, [r1, r5]', {}),
+ (b'\xf1\x40\xb6\xe1', 'ldrsh r4, [r6, r1]!', {}),
+ (b'\xf6\x50\x33\xe1', 'ldrsh r5, [r3, -r6]!', {}),
+ (b'\xf8\x60\x99\xe0', 'ldrsh r6, [r9], r8', {}),
+ (b'\xf3\x70\x18\xe0', 'ldrsh r7, [r8], -r3', {}),
+ (b'\xf1\x50\xf6\xe0', 'ldrsht r5, [r6], #0x1', {}),
+ (b'\xfc\x30\x78\xe0', 'ldrsht r3, [r8], #-0xc', {}),
+ (b'\xf5\x80\xb9\xe0', 'ldrsht r8, [r9], r5', {}),
+ (b'\xf4\x20\x31\xe0', 'ldrsht r2, [r1], -r4', {}),
+ (b'\x00\x80\x8c\xe5', 'str r8, [r12]', {}),
+ (b'\x0c\x70\x81\xe5', 'str r7, [r1, #0xc]', {}),
+ (b'\x28\x30\xa5\xe5', 'str r3, [r5, #0x28]!', {}),
+ (b'\xff\x9f\x8d\xe4', 'str r9, [sp], #0xfff', {}),
+ (b'\x80\x10\x07\xe4', 'str r1, [r7], #-0x80', {}),
+ (b'\x00\x10\x00\xe4', 'str r1, [r0], #-0', {}),
+ (b'\x03\x90\x86\xe7', 'str r9, [r6, r3]', {}),
+ (b'\x02\x80\x00\xe7', 'str r8, [r0, -r2]', {}),
+ (b'\x06\x70\xa1\xe7', 'str r7, [r1, r6]!', {}),
+ (b'\x01\x60\x2d\xe7', 'str r6, [sp, -r1]!', {}),
+ (b'\x09\x50\x83\xe6', 'str r5, [r3], r9', {}),
+ (b'\x05\x40\x02\xe6', 'str r4, [r2], -r5', {}),
+ (b'\x02\x31\x04\xe7', 'str r3, [r4, -r2, lsl #0x2]', {}),
+ (b'\x43\x2c\x87\xe6', 'str r2, [r7], r3, asr #0x18', {}),
+ (b'\x00\x90\xc2\xe5', 'strb r9, [r2]', {}),
+ (b'\x03\x70\xc1\xe5', 'strb r7, [r1, #0x3]', {}),
+ (b'\x95\x61\xe4\xe5', 'strb r6, [r4, #0x195]!', {}),
+ (b'\x48\x50\xc7\xe4', 'strb r5, [r7], #0x48', {}),
+ (b'\x01\x10\x4d\xe4', 'strb r1, [sp], #-0x1', {}),
+ (b'\x09\x10\xc2\xe7', 'strb r1, [r2, r9]', {}),
+ (b'\x08\x20\x43\xe7', 'strb r2, [r3, -r8]', {}),
+ (b'\x07\x30\xe4\xe7', 'strb r3, [r4, r7]!', {}),
+ (b'\x06\x40\x65\xe7', 'strb r4, [r5, -r6]!', {}),
+ (b'\x05\x50\xc6\xe6', 'strb r5, [r6], r5', {}),
+ (b'\x04\x60\x42\xe6', 'strb r6, [r2], -r4', {}),
+ (b'\x83\x72\x4c\xe7', 'strb r7, [r12, -r3, lsl #0x5]', {}),
+ (b'\x42\xd6\xc7\xe6', 'strb sp, [r7], r2, asr #0xc', {}),
+ (b'\x0c\x60\xe2\xe4', 'strbt r6, [r2], #0xc', {}),
+ (b'\x0d\x50\x66\xe4', 'strbt r5, [r6], #-0xd', {}),
+ (b'\x05\x40\xe9\xe6', 'strbt r4, [r9], r5', {}),
+ (b'\x82\x31\x68\xe6', 'strbt r3, [r8], -r2, lsl #0x3', {}),
+ (b'\xf0\x10\xc4\xe1', 'strd r1, r2, [r4]', {}),
+ (b'\xf1\x20\xc6\xe1', 'strd r2, r3, [r6, #0x1]', {}),
+ (b'\xf6\x31\xe7\xe1', 'strd r3, r4, [r7, #0x16]!', {}),
+ (b'\xf7\x40\xc8\xe0', 'strd r4, r5, [r8], #0x7', {}),
+ (b'\xf0\x50\xcd\xe0', 'strd r5, r6, [sp], #0', {}),
+ (b'\xf0\x60\xce\xe0', 'strd r6, r7, [lr], #0', {}),
+ (b'\xf0\x70\x49\xe0', 'strd r7, r8, [r9], #-0', {}),
+ (b'\xf1\x80\x84\xe1', 'strd r8, r9, [r4, r1]', {}),
+ (b'\xf9\x70\xa3\xe1', 'strd r7, r8, [r3, r9]!', {}),
+ (b'\xf8\x60\x85\xe0', 'strd r6, r7, [r5], r8', {}),
+ (b'\xfa\x50\x0c\xe0', 'strd r5, r6, [r12], -r10', {}),
+ (b'\xb0\x30\xc4\xe1', 'strh r3, [r4]', {}),
+ (b'\xb4\x20\xc7\xe1', 'strh r2, [r7, #0x4]', {}),
+ (b'\xb0\x14\xe8\xe1', 'strh r1, [r8, #0x40]!', {}),
+ (b'\xb4\xc0\xcd\xe0', 'strh r12, [sp], #0x4', {}),
+ (b'\xb4\x60\x85\xe1', 'strh r6, [r5, r4]', {}),
+ (b'\xbb\x30\xa8\xe1', 'strh r3, [r8, r11]!', {}),
+ (b'\xb1\x10\x22\xe1', 'strh r1, [r2, -r1]!', {}),
+ (b'\xb2\x90\x87\xe0', 'strh r9, [r7], r2', {}),
+ (b'\xb2\x40\x03\xe0', 'strh r4, [r3], -r2', {}),
+ (b'\xbc\x24\xe5\xe0', 'strht r2, [r5], #0x4c', {}),
+ (b'\xb9\x81\x61\xe0', 'strht r8, [r1], #-0x19', {}),
+ (b'\xb4\x50\xa3\xe0', 'strht r5, [r3], r4', {}),
+ (b'\xb0\x60\x28\xe0', 'strht r6, [r8], -r0', {}),
+ (b'\x00\x00\x90\xe7', 'ldr r0, [r0, r0]', {}),
+ (b'\x20\x00\x90\xe7', 'ldr r0, [r0, r0, lsr #0x20]', {}),
+ (b'\x20\x08\x90\xe7', 'ldr r0, [r0, r0, lsr #0x10]', {}),
+ (b'\x00\x00\x90\xe7', 'ldr r0, [r0, r0]', {}),
+ (b'\x00\x08\x90\xe7', 'ldr r0, [r0, r0, lsl #0x10]', {}),
+ (b'\x40\x00\x90\xe7', 'ldr r0, [r0, r0, asr #0x20]', {}),
+ (b'\x40\x08\x90\xe7', 'ldr r0, [r0, r0, asr #0x10]', {}),
+ (b'\x60\x00\x90\xe7', 'ldr r0, [r0, r0, rrx]', {}),
+ (b'\x60\x08\x90\xe7', 'ldr r0, [r0, r0, ror #0x10]', {}),
+ (b'\x00\xf0\xd0\xf7', 'pld [r0, r0]', {}),
+ (b'\x20\xf0\xd0\xf7', 'pld [r0, r0, lsr #0x20]', {}),
+ (b'\x20\xf8\xd0\xf7', 'pld [r0, r0, lsr #0x10]', {}),
+ (b'\x00\xf0\xd0\xf7', 'pld [r0, r0]', {}),
+ (b'\x00\xf8\xd0\xf7', 'pld [r0, r0, lsl #0x10]', {}),
+ (b'\x40\xf0\xd0\xf7', 'pld [r0, r0, asr #0x20]', {}),
+ (b'\x40\xf8\xd0\xf7', 'pld [r0, r0, asr #0x10]', {}),
+ (b'\x60\xf0\xd0\xf7', 'pld [r0, r0, rrx]', {}),
+ (b'\x60\xf8\xd0\xf7', 'pld [r0, r0, ror #0x10]', {}),
+ (b'\x00\x00\x80\xe7', 'str r0, [r0, r0]', {}),
+ (b'\x20\x00\x80\xe7', 'str r0, [r0, r0, lsr #0x20]', {}),
+ (b'\x20\x08\x80\xe7', 'str r0, [r0, r0, lsr #0x10]', {}),
+ (b'\x00\x00\x80\xe7', 'str r0, [r0, r0]', {}),
+ (b'\x00\x08\x80\xe7', 'str r0, [r0, r0, lsl #0x10]', {}),
+ (b'\x40\x00\x80\xe7', 'str r0, [r0, r0, asr #0x20]', {}),
+ (b'\x40\x08\x80\xe7', 'str r0, [r0, r0, asr #0x10]', {}),
+ (b'\x60\x00\x80\xe7', 'str r0, [r0, r0, rrx]', {}),
+ (b'\x60\x08\x80\xe7', 'str r0, [r0, r0, ror #0x10]', {}),
+ (b'\x62\x00\x91\xe6', 'ldr r0, [r1], r2, rrx', {}),
+ (b'\x05\x30\x94\xe6', 'ldr r3, [r4], r5', {}),
+ (b'\x08\x60\x87\xe6', 'str r6, [r7], r8', {}),
+ (b'\x0b\x90\x8a\xe6', 'str r9, [r10], r11', {}),
+ (b'\x0f\xd0\xae\xe0', 'adc sp, lr, pc', {}),
+ (b'\x29\x10\xa8\xe0', 'adc r1, r8, r9, lsr #0x20', {}),
+ (b'\x2f\x28\xa7\xe0', 'adc r2, r7, pc, lsr #0x10', {}),
+ (b'\x0a\x30\xa6\xe0', 'adc r3, r6, r10', {}),
+ (b'\x0e\x48\xa5\xe0', 'adc r4, r5, lr, lsl #0x10', {}),
+ (b'\x4b\x50\xa4\xe0', 'adc r5, r4, r11, asr #0x20', {}),
+ (b'\x4d\x68\xa3\xe0', 'adc r6, r3, sp, asr #0x10', {}),
+ (b'\x6c\x70\xa2\xe0', 'adc r7, r2, r12, rrx', {}),
+ (b'\x60\x88\xa1\xe0', 'adc r8, r1, r0, ror #0x10', {}),
+ (b'\x0e\x00\x5d\xe1', 'cmp sp, lr', {}),
+ (b'\x28\x00\x51\xe1', 'cmp r1, r8, lsr #0x20', {}),
+ (b'\x27\x08\x52\xe1', 'cmp r2, r7, lsr #0x10', {}),
+ (b'\x06\x00\x53\xe1', 'cmp r3, r6', {}),
+ (b'\x05\x08\x54\xe1', 'cmp r4, r5, lsl #0x10', {}),
+ (b'\x44\x00\x55\xe1', 'cmp r5, r4, asr #0x20', {}),
+ (b'\x43\x08\x56\xe1', 'cmp r6, r3, asr #0x10', {}),
+ (b'\x62\x00\x57\xe1', 'cmp r7, r2, rrx', {}),
+ (b'\x61\x08\x58\xe1', 'cmp r8, r1, ror #0x10', {}),
+ (b'\x7f\x00\x60\xe1', 'smc #0xf', {}),
+ (b'\x70\x00\x60\x01', 'smceq #0', {}),
+ (b'\x02\x10\xb0\xe6', 'ldrt r1, [r0], r2', {}),
+ (b'\xa2\x11\xb0\xe6', 'ldrt r1, [r0], r2, lsr #0x3', {}),
+ (b'\x04\x10\xb0\xe4', 'ldrt r1, [r0], #0x4', {}),
+ (b'\x02\x10\xf0\xe6', 'ldrbt r1, [r0], r2', {}),
+ (b'\xa2\x11\xf0\xe6', 'ldrbt r1, [r0], r2, lsr #0x3', {}),
+ (b'\x04\x10\xf0\xe4', 'ldrbt r1, [r0], #0x4', {}),
+ (b'\x02\x10\xa0\xe6', 'strt r1, [r0], r2', {}),
+ (b'\xa2\x11\xa0\xe6', 'strt r1, [r0], r2, lsr #0x3', {}),
+ (b'\x04\x10\xa0\xe4', 'strt r1, [r0], #0x4', {}),
+ (b'\x02\x10\xe0\xe6', 'strbt r1, [r0], r2', {}),
+ (b'\xa2\x11\xe0\xe6', 'strbt r1, [r0], r2, lsr #0x3', {}),
+ (b'\x04\x10\xe0\xe4', 'strbt r1, [r0], #0x4', {}),
+ (b'\xa2\x11\xb0\xe7', 'ldr r1, [r0, r2, lsr #0x3]!', {}),
+ (b'\xa2\x11\xf0\xe7', 'ldrb r1, [r0, r2, lsr #0x3]!', {}),
+ (b'\xd2\x10\xb0\xe0', 'ldrsbt r1, [r0], r2', {}),
+ (b'\xd4\x10\xf0\xe0', 'ldrsbt r1, [r0], #0x4', {}),
+ (b'\xf2\x10\xb0\xe0', 'ldrsht r1, [r0], r2', {}),
+ (b'\xf4\x10\xf0\xe0', 'ldrsht r1, [r0], #0x4', {}),
+ (b'\xb2\x10\xb0\xe0', 'ldrht r1, [r0], r2', {}),
+ (b'\xb4\x10\xf0\xe0', 'ldrht r1, [r0], #0x4', {}),
+ (b'\xb2\x10\xa0\xe0', 'strht r1, [r0], r2', {}),
+ (b'\xb4\x10\xe0\xe0', 'strht r1, [r0], #0x4', {}),
+ (b'\x1e\xff\x2f\xe1', 'bx lr', {}),
+ (b'\xa0\x0d\xe1\xf2', 'vqdmull.s32 q8, d17, d16', {}),
+ (b'\x03\x10\x02\xe0', 'and r1, r2, r3', {}),
+ (b'\x03\x10\x12\xe0', 'and.s r1, r2, r3', {}),
+ (b'\x03\x10\x22\xe0', 'eor r1, r2, r3', {}),
+ (b'\x03\x10\x32\xe0', 'eor.s r1, r2, r3', {}),
+ (b'\x03\x10\x42\xe0', 'sub r1, r2, r3', {}),
+ (b'\x03\x10\x52\xe0', 'sub.s r1, r2, r3', {}),
+ (b'\x03\x10\x82\xe0', 'add r1, r2, r3', {}),
+ (b'\x03\x10\x92\xe0', 'add.s r1, r2, r3', {}),
+ (b'\x03\x10\xa2\xe0', 'adc r1, r2, r3', {}),
+ (b'\x03\x10\xc2\xe1', 'bic r1, r2, r3', {}),
+ (b'\x03\x10\xd2\xe1', 'bic.s r1, r2, r3', {}),
+ (b'\x02\x10\xa0\xe1', 'mov r1, r2', {}),
+ (b'\x02\x10\xe0\xe1', 'mvn r1, r2', {}),
+ (b'\x02\x10\xf0\xe1', 'mvn.s r1, r2', {}),
+ (b'\x90\x02\xcb\xe7', 'bfi r0, r0, #0x5, #0x7', {}),
+ (b'\x7a\x00\x20\xe1', 'bkpt #0xa', {}),
+ (b'\x81\x17\x11\xee', 'cdp p7, #0x1, c1, c1, c1, #0x4', {}),
+ (b'\x81\x17\x11\xfe', 'cdp2 p7, #0x1, c1, c1, c1, #0x4', {}),
+ (b'\x13\x14\x82\xe0', 'add r1, r2, r3, lsl r4', {}),
+ (b'\x30\x0f\xa6\xe6', 'ssat16 r0, #0x7, r0', {}),
+ #(b'\x00\x00\x0a\xf1', 'cpsie none, #0', {}),
+ (b'\xb0\x30\x42\xe1', 'strh r3, [r2]', {}),
+ (b'\x59\xf0\x7f\xf5', 'dmb ishld', {}),
+ (b'\x51\xf0\x7f\xf5', 'dmb oshld', {}),
+ (b'\x55\xf0\x7f\xf5', 'dmb nshld', {}),
+ (b'\x5d\xf0\x7f\xf5', 'dmb ld', {}),
+ (b'\x49\xf0\x7f\xf5', 'dsb ishld', {}),
+ (b'\x41\xf0\x7f\xf5', 'dsb oshld', {}),
+ (b'\x45\xf0\x7f\xf5', 'dsb nshld', {}),
+ (b'\x4d\xf0\x7f\xf5', 'dsb ld', {}),
+ (b'\x05\xf0\x20\xe3', 'hint #0x5', {}),
+ (b'\x0f\x10\xa2\xe2', 'adc r1, r2, #0xf', {}),
+ (b'\xf0\x10\xa2\xe2', 'adc r1, r2, #0xf0', {}),
+ (b'\x0f\x1c\xa2\xe2', 'adc r1, r2, #0xf00', {}),
+ (b'\x0f\x1a\xa2\xe2', 'adc r1, r2, #0xf000', {}),
+ (b'\x0f\x18\xa2\xe2', 'adc r1, r2, #0xf0000', {}),
+ (b'\x0f\x16\xa2\xe2', 'adc r1, r2, #0xf00000', {}),
+ (b'\x0f\x14\xa2\xe2', 'adc r1, r2, #0xf000000', {}),
+ (b'\x0f\x12\xa2\xe2', 'adc r1, r2, #0xf0000000', {}),
+ (b'\xff\x12\xa2\xe2', 'adc r1, r2, #0xf000000f', {}),
+ (b'\x0f\x1c\xb2\xe2', 'adc.s r1, r2, #0xf00', {}),
+ (b'\x0f\x1c\xb2\x02', 'adc.seq r1, r2, #0xf00', {}),
+ (b'\x0f\x1c\xa2\x02', 'adceq r1, r2, #0xf00', {}),
+ (b'\x06\x40\xa5\xe0', 'adc r4, r5, r6', {}),
+ (b'\x86\x40\xa5\xe0', 'adc r4, r5, r6, lsl #0x1', {}),
+ (b'\x86\x4f\xa5\xe0', 'adc r4, r5, r6, lsl #0x1f', {}),
+ (b'\xa6\x40\xa5\xe0', 'adc r4, r5, r6, lsr #0x1', {}),
+ (b'\xa6\x4f\xa5\xe0', 'adc r4, r5, r6, lsr #0x1f', {}),
+ (b'\x26\x40\xa5\xe0', 'adc r4, r5, r6, lsr #0x20', {}),
+ (b'\xc6\x40\xa5\xe0', 'adc r4, r5, r6, asr #0x1', {}),
+ (b'\xc6\x4f\xa5\xe0', 'adc r4, r5, r6, asr #0x1f', {}),
+ (b'\x46\x40\xa5\xe0', 'adc r4, r5, r6, asr #0x20', {}),
+ (b'\xe6\x40\xa5\xe0', 'adc r4, r5, r6, ror #0x1', {}),
+ (b'\xe6\x4f\xa5\xe0', 'adc r4, r5, r6, ror #0x1f', {}),
+ (b'\x18\x69\xa7\xe0', 'adc r6, r7, r8, lsl r9', {}),
+ (b'\x38\x69\xa7\xe0', 'adc r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\xa7\xe0', 'adc r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\xa7\xe0', 'adc r6, r7, r8, ror r9', {}),
+ (b'\x66\x40\xa5\xe0', 'adc r4, r5, r6, rrx', {}),
+ (b'\x06\x50\xa5\xe0', 'adc r5, r5, r6', {}),
+ (b'\x85\x40\xa4\xe0', 'adc r4, r4, r5, lsl #0x1', {}),
+ (b'\x85\x4f\xa4\xe0', 'adc r4, r4, r5, lsl #0x1f', {}),
+ (b'\xa5\x40\xa4\xe0', 'adc r4, r4, r5, lsr #0x1', {}),
+ (b'\xa5\x4f\xa4\xe0', 'adc r4, r4, r5, lsr #0x1f', {}),
+ (b'\x25\x40\xa4\xe0', 'adc r4, r4, r5, lsr #0x20', {}),
+ (b'\xc5\x40\xa4\xe0', 'adc r4, r4, r5, asr #0x1', {}),
+ (b'\xc5\x4f\xa4\xe0', 'adc r4, r4, r5, asr #0x1f', {}),
+ (b'\x45\x40\xa4\xe0', 'adc r4, r4, r5, asr #0x20', {}),
+ (b'\xe5\x40\xa4\xe0', 'adc r4, r4, r5, ror #0x1', {}),
+ (b'\xe5\x4f\xa4\xe0', 'adc r4, r4, r5, ror #0x1f', {}),
+ (b'\x65\x40\xa4\xe0', 'adc r4, r4, r5, rrx', {}),
+ (b'\x17\x69\xa6\xe0', 'adc r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\xa6\xe0', 'adc r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\xa6\xe0', 'adc r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\xa6\xe0', 'adc r6, r6, r7, ror r9', {}),
+ (b'\x65\x40\xa4\xe0', 'adc r4, r4, r5, rrx', {}),
+ (b'\x0f\x4a\x85\xe2', 'add r4, r5, #0xf000', {}),
+ (b'\x06\x40\x85\xe0', 'add r4, r5, r6', {}),
+ (b'\x86\x42\x85\xe0', 'add r4, r5, r6, lsl #0x5', {}),
+ (b'\xa6\x42\x85\xe0', 'add r4, r5, r6, lsr #0x5', {}),
+ (b'\xa6\x42\x85\xe0', 'add r4, r5, r6, lsr #0x5', {}),
+ (b'\xc6\x42\x85\xe0', 'add r4, r5, r6, asr #0x5', {}),
+ (b'\xe6\x42\x85\xe0', 'add r4, r5, r6, ror #0x5', {}),
+ (b'\x18\x69\x87\xe0', 'add r6, r7, r8, lsl r9', {}),
+ (b'\x13\x49\x84\xe0', 'add r4, r4, r3, lsl r9', {}),
+ (b'\x38\x69\x87\xe0', 'add r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\x87\xe0', 'add r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\x87\xe0', 'add r6, r7, r8, ror r9', {}),
+ (b'\x66\x40\x85\xe0', 'add r4, r5, r6, rrx', {}),
+ (b'\x0f\x5a\x85\xe2', 'add r5, r5, #0xf000', {}),
+ (b'\x05\x40\x84\xe0', 'add r4, r4, r5', {}),
+ (b'\x85\x42\x84\xe0', 'add r4, r4, r5, lsl #0x5', {}),
+ (b'\xa5\x42\x84\xe0', 'add r4, r4, r5, lsr #0x5', {}),
+ (b'\xa5\x42\x84\xe0', 'add r4, r4, r5, lsr #0x5', {}),
+ (b'\xc5\x42\x84\xe0', 'add r4, r4, r5, asr #0x5', {}),
+ (b'\xe5\x42\x84\xe0', 'add r4, r4, r5, ror #0x5', {}),
+ (b'\x17\x69\x86\xe0', 'add r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\x86\xe0', 'add r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\x86\xe0', 'add r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\x86\xe0', 'add r6, r6, r7, ror r9', {}),
+ (b'\x65\x40\x84\xe0', 'add r4, r4, r5, rrx', {}),
+ (b'\x04\x00\x40\xe2', 'sub r0, r0, #0x4', {}),
+ (b'\x15\x40\x45\xe2', 'sub r4, r5, #0x15', {}),
+ (b'\x22\x30\x81\xe0', 'add r3, r1, r2, lsr #0x20', {}),
+ (b'\x42\x30\x81\xe0', 'add r3, r1, r2, asr #0x20', {}),
+ (b'\x0f\xa0\x01\xe2', 'and r10, r1, #0xf', {}),
+ (b'\x06\xa0\x01\xe0', 'and r10, r1, r6', {}),
+ (b'\x06\xa5\x01\xe0', 'and r10, r1, r6, lsl #0xa', {}),
+ (b'\x26\xa5\x01\xe0', 'and r10, r1, r6, lsr #0xa', {}),
+ (b'\x26\xa5\x01\xe0', 'and r10, r1, r6, lsr #0xa', {}),
+ (b'\x46\xa5\x01\xe0', 'and r10, r1, r6, asr #0xa', {}),
+ (b'\x66\xa5\x01\xe0', 'and r10, r1, r6, ror #0xa', {}),
+ (b'\x18\x62\x07\xe0', 'and r6, r7, r8, lsl r2', {}),
+ (b'\x38\x62\x07\xe0', 'and r6, r7, r8, lsr r2', {}),
+ (b'\x58\x62\x07\xe0', 'and r6, r7, r8, asr r2', {}),
+ (b'\x78\x62\x07\xe0', 'and r6, r7, r8, ror r2', {}),
+ (b'\x66\xa0\x01\xe0', 'and r10, r1, r6, rrx', {}),
+ (b'\x02\x21\xc3\xe3', 'bic r2, r3, #0x80000000', {}),
+ (b'\x0f\x10\x01\xe2', 'and r1, r1, #0xf', {}),
+ (b'\x01\xa0\x0a\xe0', 'and r10, r10, r1', {}),
+ (b'\x01\xa5\x0a\xe0', 'and r10, r10, r1, lsl #0xa', {}),
+ (b'\x21\xa5\x0a\xe0', 'and r10, r10, r1, lsr #0xa', {}),
+ (b'\x21\xa5\x0a\xe0', 'and r10, r10, r1, lsr #0xa', {}),
+ (b'\x41\xa5\x0a\xe0', 'and r10, r10, r1, asr #0xa', {}),
+ (b'\x61\xa5\x0a\xe0', 'and r10, r10, r1, ror #0xa', {}),
+ (b'\x17\x62\x06\xe0', 'and r6, r6, r7, lsl r2', {}),
+ (b'\x37\x62\x06\xe0', 'and r6, r6, r7, lsr r2', {}),
+ (b'\x57\x62\x06\xe0', 'and r6, r6, r7, asr r2', {}),
+ (b'\x77\x62\x06\xe0', 'and r6, r6, r7, ror r2', {}),
+ (b'\x61\xa0\x0a\xe0', 'and r10, r10, r1, rrx', {}),
+ (b'\x22\x30\x01\xe0', 'and r3, r1, r2, lsr #0x20', {}),
+ (b'\x42\x30\x01\xe0', 'and r3, r1, r2, asr #0x20', {}),
+ (b'\x44\x20\xa0\xe1', 'asr r2, r4, #0x20', {}),
+ (b'\x44\x21\xa0\xe1', 'asr r2, r4, #0x2', {}),
+ (b'\x04\x20\xa0\xe1', 'mov r2, r4', {}),
+ (b'\x44\x41\xa0\xe1', 'asr r4, r4, #0x2', {}),
+ (b'\x9f\x51\xd3\xe7', 'bfc r5, #0x3, #0x11', {}),
+ (b'\x9f\x51\xd3\x37', 'bfclo r5, #0x3, #0x11', {}),
+ (b'\x92\x51\xd3\xe7', 'bfi r5, r2, #0x3, #0x11', {}),
+ (b'\x92\x51\xd3\x17', 'bfine r5, r2, #0x3, #0x11', {}),
+ (b'\x0f\xa0\xc1\xe3', 'bic r10, r1, #0xf', {}),
+ (b'\x06\xa0\xc1\xe1', 'bic r10, r1, r6', {}),
+ (b'\x06\xa5\xc1\xe1', 'bic r10, r1, r6, lsl #0xa', {}),
+ (b'\x26\xa5\xc1\xe1', 'bic r10, r1, r6, lsr #0xa', {}),
+ (b'\x26\xa5\xc1\xe1', 'bic r10, r1, r6, lsr #0xa', {}),
+ (b'\x46\xa5\xc1\xe1', 'bic r10, r1, r6, asr #0xa', {}),
+ (b'\x66\xa5\xc1\xe1', 'bic r10, r1, r6, ror #0xa', {}),
+ (b'\x18\x62\xc7\xe1', 'bic r6, r7, r8, lsl r2', {}),
+ (b'\x38\x62\xc7\xe1', 'bic r6, r7, r8, lsr r2', {}),
+ (b'\x58\x62\xc7\xe1', 'bic r6, r7, r8, asr r2', {}),
+ (b'\x78\x62\xc7\xe1', 'bic r6, r7, r8, ror r2', {}),
+ (b'\x66\xa0\xc1\xe1', 'bic r10, r1, r6, rrx', {}),
+ (b'\x0f\x10\xc1\xe3', 'bic r1, r1, #0xf', {}),
+ (b'\x01\xa0\xca\xe1', 'bic r10, r10, r1', {}),
+ (b'\x01\xa5\xca\xe1', 'bic r10, r10, r1, lsl #0xa', {}),
+ (b'\x21\xa5\xca\xe1', 'bic r10, r10, r1, lsr #0xa', {}),
+ (b'\x21\xa5\xca\xe1', 'bic r10, r10, r1, lsr #0xa', {}),
+ (b'\x41\xa5\xca\xe1', 'bic r10, r10, r1, asr #0xa', {}),
+ (b'\x61\xa5\xca\xe1', 'bic r10, r10, r1, ror #0xa', {}),
+ (b'\x17\x62\xc6\xe1', 'bic r6, r6, r7, lsl r2', {}),
+ (b'\x37\x62\xc6\xe1', 'bic r6, r6, r7, lsr r2', {}),
+ (b'\x57\x62\xc6\xe1', 'bic r6, r6, r7, asr r2', {}),
+ (b'\x77\x62\xc6\xe1', 'bic r6, r6, r7, ror r2', {}),
+ (b'\x61\xa0\xca\xe1', 'bic r10, r10, r1, rrx', {}),
+ (b'\x22\x30\xc1\xe1', 'bic r3, r1, r2, lsr #0x20', {}),
+ (b'\x42\x30\xc1\xe1', 'bic r3, r1, r2, asr #0x20', {}),
+ (b'\x7a\x00\x20\xe1', 'bkpt #0xa', {}),
+ (b'\x7f\xff\x2f\xe1', 'bkpt #0xffff', {}),
+ (b'\x27\x3b\x6d\x9b', 'blls #0x1b4ec9c', {}),
+ (b'\xa0\xb0\x7b\xfa', 'blx #0x1eec280', {}),
+ (b'\x50\xd8\x3d\xfa', 'blx #0xf76140', {}),
+ (b'\x32\xff\x2f\xe1', 'blx r2', {}),
+ (b'\x32\xff\x2f\x11', 'blxne r2', {}),
+ (b'\x12\xff\x2f\xe1', 'bx r2', {}),
+ (b'\x12\xff\x2f\x11', 'bxne r2', {}),
+ (b'\x22\xff\x2f\xe1', 'bxj r2', {}),
+ (b'\x22\xff\x2f\x11', 'bxjne r2', {}),
+ (b'\x81\x17\x11\xee', 'cdp p7, #0x1, c1, c1, c1, #0x4', {}),
+ (b'\x81\x17\x11\xfe', 'cdp2 p7, #0x1, c1, c1, c1, #0x4', {}),
+ (b'\xe0\x6c\x0c\xfe', 'cdp2 p12, #0, c6, c12, c0, #0x7', {}),
+ (b'\x81\x17\x11\x1e', 'cdpne p7, #0x1, c1, c1, c1, #0x4', {}),
+ (b'\x1f\xf0\x7f\xf5', 'clrex ', {}),
+ (b'\x12\x1f\x6f\xe1', 'clz r1, r2', {}),
+ (b'\x12\x1f\x6f\x01', 'clzeq r1, r2', {}),
+ (b'\x0f\x00\x71\xe3', 'cmn r1, #0xf', {}),
+ (b'\x06\x00\x71\xe1', 'cmn r1, r6', {}),
+ (b'\x06\x05\x71\xe1', 'cmn r1, r6, lsl #0xa', {}),
+ (b'\x26\x05\x71\xe1', 'cmn r1, r6, lsr #0xa', {}),
+ (b'\x26\x05\x7d\xe1', 'cmn sp, r6, lsr #0xa', {}),
+ (b'\x46\x05\x71\xe1', 'cmn r1, r6, asr #0xa', {}),
+ (b'\x66\x05\x71\xe1', 'cmn r1, r6, ror #0xa', {}),
+ (b'\x18\x02\x77\xe1', 'cmn r7, r8, lsl r2', {}),
+ (b'\x38\x02\x7d\xe1', 'cmn sp, r8, lsr r2', {}),
+ (b'\x58\x02\x77\xe1', 'cmn r7, r8, asr r2', {}),
+ (b'\x78\x02\x77\xe1', 'cmn r7, r8, ror r2', {}),
+ (b'\x66\x00\x71\xe1', 'cmn r1, r6, rrx', {}),
+ (b'\x0f\x00\x51\xe3', 'cmp r1, #0xf', {}),
+ (b'\x06\x00\x51\xe1', 'cmp r1, r6', {}),
+ (b'\x06\x05\x51\xe1', 'cmp r1, r6, lsl #0xa', {}),
+ (b'\x26\x05\x51\xe1', 'cmp r1, r6, lsr #0xa', {}),
+ (b'\x26\x05\x5d\xe1', 'cmp sp, r6, lsr #0xa', {}),
+ (b'\x46\x05\x51\xe1', 'cmp r1, r6, asr #0xa', {}),
+ (b'\x66\x05\x51\xe1', 'cmp r1, r6, ror #0xa', {}),
+ (b'\x18\x02\x57\xe1', 'cmp r7, r8, lsl r2', {}),
+ (b'\x38\x02\x5d\xe1', 'cmp sp, r8, lsr r2', {}),
+ (b'\x58\x02\x57\xe1', 'cmp r7, r8, asr r2', {}),
+ (b'\x78\x02\x57\xe1', 'cmp r7, r8, ror r2', {}),
+ (b'\x66\x00\x51\xe1', 'cmp r1, r6, rrx', {}),
+ (b'\x02\x00\x70\xe3', 'cmn r0, #0x2', {}),
+ (b'\x00\x00\x5e\xe3', 'cmp lr, #0', {}),
+ (b'\xc0\x01\x08\xf1', 'cpsie aif', {}),
+ (b'\x0f\x00\x02\xf1', 'cps #0xf', {}),
+ (b'\xca\x00\x0e\xf1', 'cpsid if, #0xa', {}),
+ (b'\xf0\xf0\x20\xe3', 'dbg #0', {}),
+ (b'\xf5\xf0\x20\xe3', 'dbg #0x5', {}),
+ (b'\xff\xf0\x20\xe3', 'dbg #0xf', {}),
+ (b'\x5f\xf0\x7f\xf5', 'dmb sy', {}),
+ (b'\x5e\xf0\x7f\xf5', 'dmb st', {}),
+ (b'\x5d\xf0\x7f\xf5', 'dmb #0xd', {}),
+ (b'\x5c\xf0\x7f\xf5', 'dmb #0xc', {}),
+ (b'\x5b\xf0\x7f\xf5', 'dmb ish', {}),
+ (b'\x5a\xf0\x7f\xf5', 'dmb ishst', {}),
+ (b'\x59\xf0\x7f\xf5', 'dmb #0x9', {}),
+ (b'\x58\xf0\x7f\xf5', 'dmb #0x8', {}),
+ (b'\x57\xf0\x7f\xf5', 'dmb nsh', {}),
+ (b'\x56\xf0\x7f\xf5', 'dmb nshst', {}),
+ (b'\x55\xf0\x7f\xf5', 'dmb #0x5', {}),
+ (b'\x54\xf0\x7f\xf5', 'dmb #0x4', {}),
+ (b'\x53\xf0\x7f\xf5', 'dmb osh', {}),
+ (b'\x52\xf0\x7f\xf5', 'dmb oshst', {}),
+ (b'\x51\xf0\x7f\xf5', 'dmb #0x1', {}),
+ (b'\x50\xf0\x7f\xf5', 'dmb #0', {}),
+ (b'\x5f\xf0\x7f\xf5', 'dmb sy', {}),
+ (b'\x5e\xf0\x7f\xf5', 'dmb st', {}),
+ (b'\x5b\xf0\x7f\xf5', 'dmb ish', {}),
+ (b'\x5b\xf0\x7f\xf5', 'dmb ish', {}),
+ (b'\x5a\xf0\x7f\xf5', 'dmb ishst', {}),
+ (b'\x5a\xf0\x7f\xf5', 'dmb ishst', {}),
+ (b'\x57\xf0\x7f\xf5', 'dmb nsh', {}),
+ (b'\x57\xf0\x7f\xf5', 'dmb nsh', {}),
+ (b'\x56\xf0\x7f\xf5', 'dmb nshst', {}),
+ (b'\x56\xf0\x7f\xf5', 'dmb nshst', {}),
+ (b'\x53\xf0\x7f\xf5', 'dmb osh', {}),
+ (b'\x52\xf0\x7f\xf5', 'dmb oshst', {}),
+ (b'\x5f\xf0\x7f\xf5', 'dmb sy', {}),
+ (b'\x4f\xf0\x7f\xf5', 'dsb sy', {}),
+ (b'\x4e\xf0\x7f\xf5', 'dsb st', {}),
+ (b'\x4d\xf0\x7f\xf5', 'dsb #0xd', {}),
+ (b'\x4c\xf0\x7f\xf5', 'dsb #0xc', {}),
+ (b'\x4b\xf0\x7f\xf5', 'dsb ish', {}),
+ (b'\x4a\xf0\x7f\xf5', 'dsb ishst', {}),
+ (b'\x49\xf0\x7f\xf5', 'dsb #0x9', {}),
+ (b'\x48\xf0\x7f\xf5', 'dsb #0x8', {}),
+ (b'\x47\xf0\x7f\xf5', 'dsb nsh', {}),
+ (b'\x46\xf0\x7f\xf5', 'dsb nshst', {}),
+ (b'\x45\xf0\x7f\xf5', 'dsb #0x5', {}),
+ (b'\x44\xf0\x7f\xf5', 'dsb #0x4', {}),
+ (b'\x43\xf0\x7f\xf5', 'dsb osh', {}),
+ (b'\x42\xf0\x7f\xf5', 'dsb oshst', {}),
+ (b'\x41\xf0\x7f\xf5', 'dsb #0x1', {}),
+ (b'\x40\xf0\x7f\xf5', 'dsb #0', {}),
+ (b'\x48\xf0\x7f\xf5', 'dsb #0x8', {}),
+ (b'\x47\xf0\x7f\xf5', 'dsb nsh', {}),
+ (b'\x4f\xf0\x7f\xf5', 'dsb sy', {}),
+ (b'\x4e\xf0\x7f\xf5', 'dsb st', {}),
+ (b'\x4b\xf0\x7f\xf5', 'dsb ish', {}),
+ (b'\x4b\xf0\x7f\xf5', 'dsb ish', {}),
+ (b'\x4a\xf0\x7f\xf5', 'dsb ishst', {}),
+ (b'\x4a\xf0\x7f\xf5', 'dsb ishst', {}),
+ (b'\x47\xf0\x7f\xf5', 'dsb nsh', {}),
+ (b'\x47\xf0\x7f\xf5', 'dsb nsh', {}),
+ (b'\x46\xf0\x7f\xf5', 'dsb nshst', {}),
+ (b'\x46\xf0\x7f\xf5', 'dsb nshst', {}),
+ (b'\x43\xf0\x7f\xf5', 'dsb osh', {}),
+ (b'\x42\xf0\x7f\xf5', 'dsb oshst', {}),
+ (b'\x4f\xf0\x7f\xf5', 'dsb sy', {}),
+ (b'\x4f\xf0\x7f\xf5', 'dsb sy', {}),
+ (b'\x42\xf0\x7f\xf5', 'dsb oshst', {}),
+ (b'\x0f\x4a\x25\xe2', 'eor r4, r5, #0xf000', {}),
+ (b'\x06\x40\x25\xe0', 'eor r4, r5, r6', {}),
+ (b'\x86\x42\x25\xe0', 'eor r4, r5, r6, lsl #0x5', {}),
+ (b'\xa6\x42\x25\xe0', 'eor r4, r5, r6, lsr #0x5', {}),
+ (b'\xa6\x42\x25\xe0', 'eor r4, r5, r6, lsr #0x5', {}),
+ (b'\xc6\x42\x25\xe0', 'eor r4, r5, r6, asr #0x5', {}),
+ (b'\xe6\x42\x25\xe0', 'eor r4, r5, r6, ror #0x5', {}),
+ (b'\x18\x69\x27\xe0', 'eor r6, r7, r8, lsl r9', {}),
+ (b'\x38\x69\x27\xe0', 'eor r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\x27\xe0', 'eor r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\x27\xe0', 'eor r6, r7, r8, ror r9', {}),
+ (b'\x66\x40\x25\xe0', 'eor r4, r5, r6, rrx', {}),
+ (b'\x0f\x5a\x25\xe2', 'eor r5, r5, #0xf000', {}),
+ (b'\x05\x40\x24\xe0', 'eor r4, r4, r5', {}),
+ (b'\x85\x42\x24\xe0', 'eor r4, r4, r5, lsl #0x5', {}),
+ (b'\xa5\x42\x24\xe0', 'eor r4, r4, r5, lsr #0x5', {}),
+ (b'\xa5\x42\x24\xe0', 'eor r4, r4, r5, lsr #0x5', {}),
+ (b'\xc5\x42\x24\xe0', 'eor r4, r4, r5, asr #0x5', {}),
+ (b'\xe5\x42\x24\xe0', 'eor r4, r4, r5, ror #0x5', {}),
+ (b'\x17\x69\x26\xe0', 'eor r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\x26\xe0', 'eor r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\x26\xe0', 'eor r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\x26\xe0', 'eor r6, r6, r7, ror r9', {}),
+ (b'\x65\x40\x24\xe0', 'eor r4, r4, r5, rrx', {}),
+ (b'\x22\x30\x21\xe0', 'eor r3, r1, r2, lsr #0x20', {}),
+ (b'\x42\x30\x21\xe0', 'eor r3, r1, r2, asr #0x20', {}),
+ (b'\x6f\xf0\x7f\xf5', 'isb sy', {}),
+ (b'\x6f\xf0\x7f\xf5', 'isb sy', {}),
+ (b'\x6f\xf0\x7f\xf5', 'isb sy', {}),
+ (b'\x61\xf0\x7f\xf5', 'isb #0x1', {}),
+ (b'\x01\x80\x91\xfd', 'ldc2 p0, c8, [r1, #0x4]', {}),
+ (b'\x00\x71\x92\xfd', 'ldc2 p1, c7, [r2]', {}),
+ (b'\x38\x62\x13\xfd', 'ldc2 p2, c6, [r3, ', {}),
+ (b'\x1e\x53\x34\xfd', 'ldc2 p3, c5, [r4, !', {}),
+ (b'\x04\x44\xb5\xfc', 'ldc2 p4, c4, [r5], #0x10', {}),
+ (b'\x12\x35\x36\xfc', 'ldc2 p5, c3, [r6], #-0x48', {}),
+ (b'\x01\x26\xd7\xfd', 'ldc2l p6, c2, [r7, #0x4]', {}),
+ (b'\x00\x17\xd8\xfd', 'ldc2l p7, c1, [r8]', {}),
+ (b'\x38\x08\x59\xfd', 'ldc2l p8, c0, [r9, ', {}),
+ (b'\x1e\x19\x7a\xfd', 'ldc2l p9, c1, [r10, !', {}),
+ (b'\x04\x20\xfb\xfc', 'ldc2l p0, c2, [r11], #0x10', {}),
+ (b'\x12\x31\x7c\xfc', 'ldc2l p1, c3, [r12], #-0x48', {}),
+ (b'\x01\x4c\x90\xed', 'ldc p12, c4, [r0, #0x4]', {}),
+ (b'\x00\x5d\x91\xed', 'ldc p13, c5, [r1]', {}),
+ (b'\x38\x6e\x12\xed', 'ldc p14, c6, [r2, ', {}),
+ (b'\x1e\x7f\x33\xed', 'ldc p15, c7, [r3, !', {}),
+ (b'\x04\x85\xb4\xec', 'ldc p5, c8, [r4], #0x10', {}),
+ (b'\x12\x94\x35\xec', 'ldc p4, c9, [r5], #-0x48', {}),
+ (b'\x01\xa3\xd6\xed', 'ldcl p3, c10, [r6, #0x4]', {}),
+ (b'\x00\xb2\xd7\xed', 'ldcl p2, c11, [r7]', {}),
+ (b'\x38\xc1\x58\xed', 'ldcl p1, c12, [r8, ', {}),
+ (b'\x1e\xd0\x79\xed', 'ldcl p0, c13, [r9, !', {}),
+ (b'\x04\xe6\xfa\xec', 'ldcl p6, c14, [r10], #0x10', {}),
+ (b'\x12\xf7\x7b\xec', 'ldcl p7, c15, [r11], #-0x48', {}),
+ (b'\x01\x4c\x90\x3d', 'ldclo p12, c4, [r0, #0x4]', {}),
+ (b'\x00\x5d\x91\x8d', 'ldchi p13, c5, [r1]', {}),
+ (b'\x38\x6e\x12\x2d', 'ldchs p14, c6, [r2, ', {}),
+ (b'\x1e\x7f\x33\x3d', 'ldclo p15, c7, [r3, !', {}),
+ (b'\x04\x85\xb4\x0c', 'ldceq p5, c8, [r4], #0x10', {}),
+ (b'\x12\x94\x35\xcc', 'ldcgt p4, c9, [r5], #-0x48', {}),
+ (b'\x01\xa3\xd6\xbd', 'ldcllt p3, c10, [r6, #0x4]', {}),
+ (b'\x00\xb2\xd7\xad', 'ldclge p2, c11, [r7]', {}),
+ (b'\x38\xc1\x58\xdd', 'ldclle p1, c12, [r8, ', {}),
+ (b'\x1e\xd0\x79\x1d', 'ldclne p0, c13, [r9, !', {}),
+ (b'\x04\xe6\xfa\x0c', 'ldcleq p6, c14, [r10], #0x10', {}),
+ (b'\x12\xf7\x7b\x8c', 'ldclhi p7, c15, [r11], #-0x48', {}),
+ (b'\x19\x82\x91\xfc', 'ldc2 p2, c8, [r1], {25}', {}),
+ (b'\x7a\x20\x92\xe8', 'ldm r2, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x92\xe8', 'ldm r2, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x92\xe9', 'ldmib r2, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x12\xe8', 'ldmda r2, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x12\xe9', 'ldmdb r2, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x92\xe8', 'ldm r2, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\xb2\xe8', 'ldm r2!, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\xb2\xe9', 'ldmib r2!, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x32\xe8', 'ldmda r2!, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x32\xe9', 'ldmdb r2!, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x05\x40\xd0\xe8', 'ldm r0, {r0, r2, lr} ^', {}),
+ (b'\x0f\x80\xfd\xe8', 'ldm sp!, {r0, r1, r2, r3, pc} ^', {}),
+ (b'\xb0\x80\x7b\x80', 'ldrhthi r8, [r11], #-0', {}),
+ (b'\xb0\x80\xfb\x80', 'ldrhthi r8, [r11], #0', {}),
+ (b'\x84\x2f\xa0\xe1', 'lsl r2, r4, #0x1f', {}),
+ (b'\x84\x20\xa0\xe1', 'lsl r2, r4, #0x1', {}),
+ (b'\x04\x20\xa0\xe1', 'mov r2, r4', {}),
+ (b'\x84\x40\xa0\xe1', 'lsl r4, r4, #0x1', {}),
+ (b'\x24\x20\xa0\xe1', 'lsr r2, r4, #0x20', {}),
+ (b'\x24\x21\xa0\xe1', 'lsr r2, r4, #0x2', {}),
+ (b'\x04\x20\xa0\xe1', 'mov r2, r4', {}),
+ (b'\x24\x41\xa0\xe1', 'lsr r4, r4, #0x2', {}),
+ (b'\x91\x57\x21\xee', 'mcr p7, #0x1, r5, c1, c1, #0x4', {}),
+ (b'\x91\x57\x21\xfe', 'mcr2 p7, #0x1, r5, c1, c1, #0x4', {}),
+ (b'\x91\x57\x21\x9e', 'mcrls p7, #0x1, r5, c1, c1, #0x4', {}),
+ (b'\xf1\x57\x44\xec', 'mcrr p7, #0x15, r5, r4, c1', {}),
+ (b'\xf1\x57\x44\xfc', 'mcrr2 p7, #0x15, r5, r4, c1', {}),
+ (b'\xf1\x57\x44\xcc', 'mcrrgt p7, #0x15, r5, r4, c1', {}),
+ (b'\x92\x43\x21\xe0', 'mla r1, r2, r3, r4', {}),
+ (b'\x92\x43\x31\xe0', 'mlas r1, r2, r3, r4', {}),
+ (b'\x92\x43\x21\x10', 'mlane r1, r2, r3, r4', {}),
+ (b'\x92\x43\x31\x10', 'mlasne r1, r2, r3, r4', {}),
+ (b'\x95\x36\x62\xe0', 'mls r2, r5, r6, r3', {}),
+ (b'\x95\x36\x62\x10', 'mlsne r2, r5, r6, r3', {}),
+ (b'\x07\x30\xa0\xe3', 'mov r3, #0x7', {}),
+ (b'\xff\x4e\xa0\xe3', 'mov r4, #0xff0', {}),
+ (b'\xff\x58\xa0\xe3', 'mov r5, #0xff0000', {}),
+ (b'\xff\x6f\x0f\xe3', 'movw r6, #0xffff', {}),
+ (b'\xff\x9f\x0f\xe3', 'movw r9, #0xffff', {}),
+ (b'\x07\x30\xb0\xe3', 'movs r3, #0x7', {}),
+ (b'\xff\x4e\xa0\x03', 'moveq r4, #0xff0', {}),
+ (b'\xff\x58\xb0\x03', 'mov.seq r5, #0xff0000', {}),
+ (b'\x03\x20\xa0\xe1', 'mov r2, r3', {}),
+ (b'\x03\x20\xb0\xe1', 'movs r2, r3', {}),
+ (b'\x03\x20\xa0\x01', 'moveq r2, r3', {}),
+ (b'\x03\x20\xb0\x01', 'mov.seq r2, r3', {}),
+ (b'\x08\xc0\xa0\xe1', 'mov r12, r8', {}),
+ (b'\x03\x20\xa0\xe1', 'mov r2, r3', {}),
+ (b'\x08\xc0\xa0\xe1', 'mov r12, r8', {}),
+ (b'\x03\x20\xa0\xe1', 'mov r2, r3', {}),
+ (b'\x08\xc0\xa0\xe1', 'mov r12, r8', {}),
+ (b'\x03\x20\xa0\xe1', 'mov r2, r3', {}),
+ (b'\x08\xc0\xa0\xe1', 'mov r12, r8', {}),
+ (b'\x03\x20\xa0\xe1', 'mov r2, r3', {}),
+ (b'\x07\x30\x40\xe3', 'movt r3, #0x7', {}),
+ (b'\xff\x6f\x4f\xe3', 'movt r6, #0xffff', {}),
+ (b'\xf0\x4f\x40\x03', 'movteq r4, #0xff0', {}),
+ (b'\x92\x1e\x11\xee', 'mrc p14, #0, r1, c1, c2, #0x4', {}),
+ (b'\xd6\xff\xff\xee', 'mrc p15, #0x7, apsr_nzcv, c15, c6, #0x6', {}),
+ (b'\x92\x1e\x11\xfe', 'mrc2 p14, #0, r1, c1, c2, #0x4', {}),
+ (b'\x30\xf9\xff\xfe', 'mrc2 p9, #0x7, apsr_nzcv, c15, c0, #0x1', {}),
+ (b'\xd6\xff\xff\x0e', 'mrceq p15, #0x7, apsr_nzcv, c15, c6, #0x6', {}),
+ (b'\x11\x57\x54\xec', 'mrrc p7, #0x1, r5, r4, c1', {}),
+ (b'\x11\x57\x54\xfc', 'mrrc2 p7, #0x1, r5, r4, c1', {}),
+ (b'\x11\x57\x54\x3c', 'mrrclo p7, #0x1, r5, r4, c1', {}),
+ (b'\x96\x07\x05\xe0', 'mul r5, r6, r7', {}),
+ (b'\x96\x07\x15\xe0', 'muls r5, r6, r7', {}),
+ (b'\x96\x07\x05\xc0', 'mulgt r5, r6, r7', {}),
+ (b'\x96\x07\x15\xd0', 'mulsle r5, r6, r7', {}),
+ (b'\x07\x30\xe0\xe3', 'mvn r3, #0x7', {}),
+ (b'\xff\x4e\xe0\xe3', 'mvn r4, #0xff0', {}),
+ (b'\xff\x58\xe0\xe3', 'mvn r5, #0xff0000', {}),
+ (b'\x07\x30\xf0\xe3', 'mvns r3, #0x7', {}),
+ (b'\xff\x4e\xe0\x03', 'mvneq r4, #0xff0', {}),
+ (b'\xff\x58\xf0\x03', 'mvn.seq r5, #0xff0000', {}),
+ (b'\x03\x20\xe0\xe1', 'mvn r2, r3', {}),
+ (b'\x03\x20\xf0\xe1', 'mvns r2, r3', {}),
+ (b'\x86\x59\xe0\xe1', 'mvn r5, r6, lsl #0x13', {}),
+ (b'\xa6\x54\xe0\xe1', 'mvn r5, r6, lsr #0x9', {}),
+ (b'\x46\x52\xe0\xe1', 'mvn r5, r6, asr #0x4', {}),
+ (b'\x66\x53\xe0\xe1', 'mvn r5, r6, ror #0x6', {}),
+ (b'\x66\x50\xe0\xe1', 'mvn r5, r6, rrx', {}),
+ (b'\x03\x20\xe0\x01', 'mvneq r2, r3', {}),
+ (b'\x03\x25\xf0\x01', 'mvn.seq r2, r3, lsl #0xa', {}),
+ (b'\x16\x57\xe0\xe1', 'mvn r5, r6, lsl r7', {}),
+ (b'\x36\x57\xf0\xe1', 'mvns r5, r6, lsr r7', {}),
+ (b'\x56\x57\xe0\xc1', 'mvngt r5, r6, asr r7', {}),
+ (b'\x76\x57\xf0\xb1', 'mvnslt r5, r6, ror r7', {}),
+ (b'\x00\x50\x68\xe2', 'rsb r5, r8, #0', {}),
+ (b'\x00\xf0\x20\xe3', 'nop ', {}),
+ (b'\x00\xf0\x20\xe3', 'nop ', {}),
+ (b'\x00\xf0\x20\xc3', 'nopgt ', {}),
+ (b'\x0f\x4a\x85\xe3', 'orr r4, r5, #0xf000', {}),
+ (b'\x06\x40\x85\xe1', 'orr r4, r5, r6', {}),
+ (b'\x86\x42\x85\xe1', 'orr r4, r5, r6, lsl #0x5', {}),
+ (b'\xa6\x42\x85\xe1', 'orr r4, r5, r6, lsr #0x5', {}),
+ (b'\xa6\x42\x85\xe1', 'orr r4, r5, r6, lsr #0x5', {}),
+ (b'\xc6\x42\x85\xe1', 'orr r4, r5, r6, asr #0x5', {}),
+ (b'\xe6\x42\x85\xe1', 'orr r4, r5, r6, ror #0x5', {}),
+ (b'\x18\x69\x87\xe1', 'orr r6, r7, r8, lsl r9', {}),
+ (b'\x38\x69\x87\xe1', 'orr r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\x87\xe1', 'orr r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\x87\xe1', 'orr r6, r7, r8, ror r9', {}),
+ (b'\x66\x40\x85\xe1', 'orr r4, r5, r6, rrx', {}),
+ (b'\x0f\x5a\x85\xe3', 'orr r5, r5, #0xf000', {}),
+ (b'\x05\x40\x84\xe1', 'orr r4, r4, r5', {}),
+ (b'\x85\x42\x84\xe1', 'orr r4, r4, r5, lsl #0x5', {}),
+ (b'\xa5\x42\x84\xe1', 'orr r4, r4, r5, lsr #0x5', {}),
+ (b'\xa5\x42\x84\xe1', 'orr r4, r4, r5, lsr #0x5', {}),
+ (b'\xc5\x42\x84\xe1', 'orr r4, r4, r5, asr #0x5', {}),
+ (b'\xe5\x42\x84\xe1', 'orr r4, r4, r5, ror #0x5', {}),
+ (b'\x17\x69\x86\xe1', 'orr r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\x86\xe1', 'orr r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\x86\xe1', 'orr r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\x86\xe1', 'orr r6, r6, r7, ror r9', {}),
+ (b'\x65\x40\x84\xe1', 'orr r4, r4, r5, rrx', {}),
+ (b'\x0f\x4a\x95\x03', 'orr.seq r4, r5, #0xf000', {}),
+ (b'\x06\x40\x85\x11', 'orrne r4, r5, r6', {}),
+ (b'\x86\x42\x95\x01', 'orr.seq r4, r5, r6, lsl #0x5', {}),
+ (b'\x78\x69\x87\x31', 'orrlo r6, r7, r8, ror r9', {}),
+ (b'\x66\x40\x95\x81', 'orrshi r4, r5, r6, rrx', {}),
+ (b'\x0f\x5a\x85\x23', 'orrhs r5, r5, #0xf000', {}),
+ (b'\x05\x40\x94\x01', 'orr.seq r4, r4, r5', {}),
+ (b'\x57\x69\x86\x11', 'orrne r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\x96\xb1', 'orrslt r6, r6, r7, ror r9', {}),
+ (b'\x65\x40\x94\xc1', 'orrsgt r4, r4, r5, rrx', {}),
+ (b'\x22\x30\x81\xe1', 'orr r3, r1, r2, lsr #0x20', {}),
+ (b'\x42\x30\x81\xe1', 'orr r3, r1, r2, asr #0x20', {}),
+ (b'\x13\x20\x82\xe6', 'pkhbt r2, r2, r3', {}),
+ (b'\x93\x2f\x82\xe6', 'pkhbt r2, r2, r3, lsl #0x1f', {}),
+ (b'\x13\x20\x82\xe6', 'pkhbt r2, r2, r3', {}),
+ (b'\x93\x27\x82\xe6', 'pkhbt r2, r2, r3, lsl #0xf', {}),
+ (b'\x13\x20\x82\xe6', 'pkhbt r2, r2, r3', {}),
+ (b'\xd3\x2f\x82\xe6', 'pkhtb r2, r2, r3, asr #0x1f', {}),
+ (b'\xd3\x27\x82\xe6', 'pkhtb r2, r2, r3, asr #0xf', {}),
+ (b'\x04\x70\x9d\xe4', 'pop {r7}', {}),
+ (b'\x80\x07\xbd\xe8', 'pop {r7, r8, r9, r10}', {}),
+ (b'\x04\x70\x2d\xe5', 'str r7, [sp, #-0x4]!', {}),
+ (b'\x80\x07\x2d\xe9', 'push {r7, r8, r9, r10}', {}),
+ (b'\x52\x10\x03\xe1', 'qadd r1, r2, r3', {}),
+ (b'\x52\x10\x03\x11', 'qaddne r1, r2, r3', {}),
+ (b'\x13\x1f\x22\xe6', 'qadd16 r1, r2, r3', {}),
+ (b'\x13\x1f\x22\xc6', 'qadd16gt r1, r2, r3', {}),
+ (b'\x93\x1f\x22\xe6', 'qadd8 r1, r2, r3', {}),
+ (b'\x93\x1f\x22\xd6', 'qadd8le r1, r2, r3', {}),
+ (b'\x57\x60\x48\xe1', 'qdadd r6, r7, r8', {}),
+ (b'\x57\x60\x48\x81', 'qdaddhi r6, r7, r8', {}),
+ (b'\x57\x60\x68\xe1', 'qdsub r6, r7, r8', {}),
+ (b'\x57\x60\x68\x81', 'qdsubhi r6, r7, r8', {}),
+ (b'\x50\x9f\x2c\xe6', 'qsax r9, r12, r0', {}),
+ (b'\x50\x9f\x2c\x06', 'qsaxeq r9, r12, r0', {}),
+ (b'\x52\x10\x23\xe1', 'qsub r1, r2, r3', {}),
+ (b'\x52\x10\x23\x11', 'qsubne r1, r2, r3', {}),
+ (b'\x73\x1f\x22\xe6', 'qsub16 r1, r2, r3', {}),
+ (b'\x73\x1f\x22\xc6', 'qsub16gt r1, r2, r3', {}),
+ (b'\xf3\x1f\x22\xe6', 'qsub8 r1, r2, r3', {}),
+ (b'\xf3\x1f\x22\xd6', 'qsub8le r1, r2, r3', {}),
+ (b'\x32\x1f\xff\xe6', 'rbit r1, r2', {}),
+ (b'\x32\x1f\xff\x16', 'rbitne r1, r2', {}),
+ (b'\x39\x1f\xbf\xe6', 'rev r1, r9', {}),
+ (b'\x35\x1f\xbf\x16', 'revne r1, r5', {}),
+ (b'\xb3\x8f\xbf\xe6', 'rev16 r8, r3', {}),
+ (b'\xb4\xcf\xbf\x16', 'rev16ne r12, r4', {}),
+ (b'\xb9\x4f\xff\xe6', 'revsh r4, r9', {}),
+ (b'\xb1\x9f\xff\x16', 'revshne r9, r1', {}),
+ (b'\x00\x0a\x12\xf8', 'rfeda r2', {}),
+ (b'\x00\x0a\x13\xf9', 'rfedb r3', {}),
+ (b'\x00\x0a\x95\xf8', 'rfeia r5', {}),
+ (b'\x00\x0a\x96\xf9', 'rfeib r6', {}),
+ (b'\x00\x0a\x34\xf8', 'rfeda r4!', {}),
+ (b'\x00\x0a\x37\xf9', 'rfedb r7!', {}),
+ (b'\x00\x0a\xb9\xf8', 'rfeia r9!', {}),
+ (b'\x00\x0a\xb8\xf9', 'rfeib r8!', {}),
+ (b'\x00\x0a\x12\xf8', 'rfeda r2', {}),
+ (b'\x00\x0a\x13\xf9', 'rfedb r3', {}),
+ (b'\x00\x0a\x95\xf8', 'rfeia r5', {}),
+ (b'\x00\x0a\x96\xf9', 'rfeib r6', {}),
+ (b'\x00\x0a\x34\xf8', 'rfeda r4!', {}),
+ (b'\x00\x0a\x37\xf9', 'rfedb r7!', {}),
+ (b'\x00\x0a\xb9\xf8', 'rfeia r9!', {}),
+ (b'\x00\x0a\xb8\xf9', 'rfeib r8!', {}),
+ (b'\x00\x0a\x91\xf8', 'rfeia r1', {}),
+ (b'\x00\x0a\xb1\xf8', 'rfeia r1!', {}),
+ (b'\xe4\x2f\xa0\xe1', 'ror r2, r4, #0x1f', {}),
+ (b'\xe4\x20\xa0\xe1', 'ror r2, r4, #0x1', {}),
+ (b'\x04\x20\xa0\xe1', 'mov r2, r4', {}),
+ (b'\xe4\x40\xa0\xe1', 'ror r4, r4, #0x1', {}),
+ (b'\x0f\x4a\x65\xe2', 'rsb r4, r5, #0xf000', {}),
+ (b'\x06\x40\x65\xe0', 'rsb r4, r5, r6', {}),
+ (b'\x86\x42\x65\xe0', 'rsb r4, r5, r6, lsl #0x5', {}),
+ (b'\xa6\x42\x65\x30', 'rsblo r4, r5, r6, lsr #0x5', {}),
+ (b'\xa6\x42\x65\xe0', 'rsb r4, r5, r6, lsr #0x5', {}),
+ (b'\xc6\x42\x65\xe0', 'rsb r4, r5, r6, asr #0x5', {}),
+ (b'\xe6\x42\x65\xe0', 'rsb r4, r5, r6, ror #0x5', {}),
+ (b'\x18\x69\x67\xe0', 'rsb r6, r7, r8, lsl r9', {}),
+ (b'\x38\x69\x67\xe0', 'rsb r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\x67\xe0', 'rsb r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\x67\xd0', 'rsble r6, r7, r8, ror r9', {}),
+ (b'\x66\x40\x65\xe0', 'rsb r4, r5, r6, rrx', {}),
+ (b'\x0f\x5a\x65\xe2', 'rsb r5, r5, #0xf000', {}),
+ (b'\x05\x40\x64\xe0', 'rsb r4, r4, r5', {}),
+ (b'\x85\x42\x64\xe0', 'rsb r4, r4, r5, lsl #0x5', {}),
+ (b'\xa5\x42\x64\xe0', 'rsb r4, r4, r5, lsr #0x5', {}),
+ (b'\xa5\x42\x64\x10', 'rsbne r4, r4, r5, lsr #0x5', {}),
+ (b'\xc5\x42\x64\xe0', 'rsb r4, r4, r5, asr #0x5', {}),
+ (b'\xe5\x42\x64\xe0', 'rsb r4, r4, r5, ror #0x5', {}),
+ (b'\x17\x69\x66\xc0', 'rsbgt r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\x66\xe0', 'rsb r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\x66\xe0', 'rsb r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\x66\xe0', 'rsb r6, r6, r7, ror r9', {}),
+ (b'\x65\x40\x64\xe0', 'rsb r4, r4, r5, rrx', {}),
+ (b'\x0f\x4a\xe5\xe2', 'rsc r4, r5, #0xf000', {}),
+ (b'\x06\x40\xe5\xe0', 'rsc r4, r5, r6', {}),
+ (b'\x86\x42\xe5\xe0', 'rsc r4, r5, r6, lsl #0x5', {}),
+ (b'\xa6\x42\xe5\x30', 'rsclo r4, r5, r6, lsr #0x5', {}),
+ (b'\xa6\x42\xe5\xe0', 'rsc r4, r5, r6, lsr #0x5', {}),
+ (b'\xc6\x42\xe5\xe0', 'rsc r4, r5, r6, asr #0x5', {}),
+ (b'\xe6\x42\xe5\xe0', 'rsc r4, r5, r6, ror #0x5', {}),
+ (b'\x18\x69\xe7\xe0', 'rsc r6, r7, r8, lsl r9', {}),
+ (b'\x38\x69\xe7\xe0', 'rsc r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\xe7\xe0', 'rsc r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\xe7\xd0', 'rscle r6, r7, r8, ror r9', {}),
+ (b'\xfe\x1e\xf8\xe2', 'rscs r1, r8, #0xfe0', {}),
+ (b'\x0f\x5a\xe5\xe2', 'rsc r5, r5, #0xf000', {}),
+ (b'\x05\x40\xe4\xe0', 'rsc r4, r4, r5', {}),
+ (b'\x85\x42\xe4\xe0', 'rsc r4, r4, r5, lsl #0x5', {}),
+ (b'\xa5\x42\xe4\xe0', 'rsc r4, r4, r5, lsr #0x5', {}),
+ (b'\xa5\x42\xe4\x10', 'rscne r4, r4, r5, lsr #0x5', {}),
+ (b'\xc5\x42\xe4\xe0', 'rsc r4, r4, r5, asr #0x5', {}),
+ (b'\xe5\x42\xe4\xe0', 'rsc r4, r4, r5, ror #0x5', {}),
+ (b'\x17\x69\xe6\xc0', 'rscgt r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\xe6\xe0', 'rsc r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\xe6\xe0', 'rsc r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\xe6\xe0', 'rsc r6, r6, r7, ror r9', {}),
+ (b'\x61\x00\xa0\xe1', 'rrx r0, r1', {}),
+ (b'\x6f\xd0\xa0\xe1', 'rrx sp, pc', {}),
+ (b'\x6e\xf0\xa0\xe1', 'rrx pc, lr', {}),
+ (b'\x6d\xe0\xa0\xe1', 'rrx lr, sp', {}),
+ (b'\x61\x00\xb0\xe1', 'rrxs r0, r1', {}),
+ (b'\x6f\xd0\xb0\xe1', 'rrxs sp, pc', {}),
+ (b'\x6e\xf0\xb0\xe1', 'rrxs pc, lr', {}),
+ (b'\x6d\xe0\xb0\xe1', 'rrxs lr, sp', {}),
+ (b'\x13\x1f\x12\xe6', 'sadd16 r1, r2, r3', {}),
+ (b'\x13\x1f\x12\xc6', 'sadd16gt r1, r2, r3', {}),
+ (b'\x93\x1f\x12\xe6', 'sadd8 r1, r2, r3', {}),
+ (b'\x93\x1f\x12\xd6', 'sadd8le r1, r2, r3', {}),
+ (b'\x30\x9f\x1c\xe6', 'sasx r9, r12, r0', {}),
+ (b'\x30\x9f\x1c\x06', 'sasxeq r9, r12, r0', {}),
+ (b'\x0f\x4a\xc5\xe2', 'sbc r4, r5, #0xf000', {}),
+ (b'\x06\x40\xc5\xe0', 'sbc r4, r5, r6', {}),
+ (b'\x86\x42\xc5\xe0', 'sbc r4, r5, r6, lsl #0x5', {}),
+ (b'\xa6\x42\xc5\xe0', 'sbc r4, r5, r6, lsr #0x5', {}),
+ (b'\xa6\x42\xc5\xe0', 'sbc r4, r5, r6, lsr #0x5', {}),
+ (b'\xc6\x42\xc5\xe0', 'sbc r4, r5, r6, asr #0x5', {}),
+ (b'\xe6\x42\xc5\xe0', 'sbc r4, r5, r6, ror #0x5', {}),
+ (b'\x18\x69\xc7\xe0', 'sbc r6, r7, r8, lsl r9', {}),
+ (b'\x38\x69\xc7\xe0', 'sbc r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\xc7\xe0', 'sbc r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\xc7\xe0', 'sbc r6, r7, r8, ror r9', {}),
+ (b'\x0f\x5a\xc5\xe2', 'sbc r5, r5, #0xf000', {}),
+ (b'\x05\x40\xc4\xe0', 'sbc r4, r4, r5', {}),
+ (b'\x85\x42\xc4\xe0', 'sbc r4, r4, r5, lsl #0x5', {}),
+ (b'\xa5\x42\xc4\xe0', 'sbc r4, r4, r5, lsr #0x5', {}),
+ (b'\xa5\x42\xc4\xe0', 'sbc r4, r4, r5, lsr #0x5', {}),
+ (b'\xc5\x42\xc4\xe0', 'sbc r4, r4, r5, asr #0x5', {}),
+ (b'\xe5\x42\xc4\xe0', 'sbc r4, r4, r5, ror #0x5', {}),
+ (b'\x17\x69\xc6\xe0', 'sbc r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\xc6\xe0', 'sbc r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\xc6\xe0', 'sbc r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\xc6\xe0', 'sbc r6, r6, r7, ror r9', {}),
+ (b'\x55\x48\xa0\xe7', 'sbfx r4, r5, #0x16, #0x1', {}),
+ (b'\x55\x48\xaf\xc7', 'sbfxgt r4, r5, #0x16, #0x10', {}),
+ (b'\xb1\x9f\x82\xe6', 'sel r9, r2, r1', {}),
+ (b'\xb1\x9f\x82\x16', 'selne r9, r2, r1', {}),
+ (b'\x00\x02\x01\xf1', 'setend be', {}),
+ (b'\x00\x02\x01\xf1', 'setend be', {}),
+ (b'\x00\x00\x01\xf1', 'setend le', {}),
+ (b'\x00\x00\x01\xf1', 'setend le', {}),
+ (b'\x04\xf0\x20\xe3', 'sev ', {}),
+ (b'\x04\xf0\x20\x03', 'seveq ', {}),
+ (b'\x12\x4f\x38\xe6', 'shadd16 r4, r8, r2', {}),
+ (b'\x12\x4f\x38\xc6', 'shadd16gt r4, r8, r2', {}),
+ (b'\x92\x4f\x38\xe6', 'shadd8 r4, r8, r2', {}),
+ (b'\x92\x4f\x38\xc6', 'shadd8gt r4, r8, r2', {}),
+ (b'\x32\x4f\x38\xe6', 'shasx r4, r8, r2', {}),
+ (b'\x32\x4f\x38\xc6', 'shasxgt r4, r8, r2', {}),
+ (b'\x72\x4f\x38\xe6', 'shsub16 r4, r8, r2', {}),
+ (b'\x72\x4f\x38\xc6', 'shsub16gt r4, r8, r2', {}),
+ (b'\xf2\x4f\x38\xe6', 'shsub8 r4, r8, r2', {}),
+ (b'\xf2\x4f\x38\xc6', 'shsub8gt r4, r8, r2', {}),
+ (b'\x81\x09\x03\xe1', 'smlabb r3, r1, r9, r0', {}),
+ (b'\xc6\x14\x05\xe1', 'smlabt r5, r6, r4, r1', {}),
+ (b'\xa2\x23\x04\xe1', 'smlatb r4, r2, r3, r2', {}),
+ (b'\xe3\x48\x08\xe1', 'smlatt r8, r3, r8, r4', {}),
+ (b'\x81\x09\x03\xa1', 'smlabbge r3, r1, r9, r0', {}),
+ (b'\xc6\x14\x05\xd1', 'smlabtle r5, r6, r4, r1', {}),
+ (b'\xa2\x23\x04\x11', 'smlatbne r4, r2, r3, r2', {}),
+ (b'\xe3\x48\x08\x01', 'smlatteq r8, r3, r8, r4', {}),
+ (b'\x13\x85\x02\xe7', 'smlad r2, r3, r5, r8', {}),
+ (b'\x33\x85\x02\xe7', 'smladx r2, r3, r5, r8', {}),
+ (b'\x13\x85\x02\x07', 'smladeq r2, r3, r5, r8', {}),
+ (b'\x33\x85\x02\x87', 'smladxhi r2, r3, r5, r8', {}),
+ (b'\x95\x28\xe3\xe0', 'smlal r2, r3, r5, r8', {}),
+ (b'\x95\x28\xf3\xe0', 'smlals r2, r3, r5, r8', {}),
+ (b'\x95\x28\xe3\x00', 'smlaleq r2, r3, r5, r8', {}),
+ (b'\x95\x28\xf3\x80', 'smlalshi r2, r3, r5, r8', {}),
+ (b'\x89\x30\x41\xe1', 'smlalbb r3, r1, r9, r0', {}),
+ (b'\xc4\x51\x46\xe1', 'smlalbt r5, r6, r4, r1', {}),
+ (b'\xa3\x42\x42\xe1', 'smlaltb r4, r2, r3, r2', {}),
+ (b'\xe8\x84\x43\xe1', 'smlaltt r8, r3, r8, r4', {}),
+ (b'\x89\x30\x41\xa1', 'smlalbbge r3, r1, r9, r0', {}),
+ (b'\xc4\x51\x46\xd1', 'smlalbtle r5, r6, r4, r1', {}),
+ (b'\xa3\x42\x42\x11', 'smlaltbne r4, r2, r3, r2', {}),
+ (b'\xe8\x84\x43\x01', 'smlaltteq r8, r3, r8, r4', {}),
+ (b'\x15\x28\x43\xe7', 'smlald r2, r3, r5, r8', {}),
+ (b'\x35\x28\x43\xe7', 'smlaldx r2, r3, r5, r8', {}),
+ (b'\x15\x28\x43\x07', 'smlaldeq r2, r3, r5, r8', {}),
+ (b'\x35\x28\x43\x87', 'smlaldxhi r2, r3, r5, r8', {}),
+ (b'\x83\x8a\x22\xe1', 'smlawb r2, r3, r10, r8', {}),
+ (b'\xc3\x95\x28\xe1', 'smlawt r8, r3, r5, r9', {}),
+ (b'\x87\x85\x22\x01', 'smlawbeq r2, r7, r5, r8', {}),
+ (b'\xc3\x80\x21\x81', 'smlawthi r1, r3, r0, r8', {}),
+ (b'\x53\x85\x02\xe7', 'smlsd r2, r3, r5, r8', {}),
+ (b'\x73\x85\x02\xe7', 'smlsdx r2, r3, r5, r8', {}),
+ (b'\x53\x85\x02\x07', 'smlsdeq r2, r3, r5, r8', {}),
+ (b'\x73\x85\x02\x87', 'smlsdxhi r2, r3, r5, r8', {}),
+ (b'\x55\x21\x49\xe7', 'smlsld r2, r9, r5, r1', {}),
+ (b'\x72\x48\x4b\xe7', 'smlsldx r4, r11, r2, r8', {}),
+ (b'\x55\x86\x42\x07', 'smlsldeq r8, r2, r5, r6', {}),
+ (b'\x73\x18\x40\x87', 'smlsldxhi r1, r0, r3, r8', {}),
+ (b'\x12\x43\x51\xe7', 'smmla r1, r2, r3, r4', {}),
+ (b'\x33\x12\x54\xe7', 'smmlar r4, r3, r2, r1', {}),
+ (b'\x12\x43\x51\x37', 'smmlalo r1, r2, r3, r4', {}),
+ (b'\x33\x12\x54\x27', 'smmlarhs r4, r3, r2, r1', {}),
+ (b'\xd2\x43\x51\xe7', 'smmls r1, r2, r3, r4', {}),
+ (b'\xf3\x12\x54\xe7', 'smmlsr r4, r3, r2, r1', {}),
+ (b'\xd2\x43\x51\x37', 'smmlslo r1, r2, r3, r4', {}),
+ (b'\xf3\x12\x54\x27', 'smmlsrhs r4, r3, r2, r1', {}),
+ (b'\x13\xf4\x52\xe7', 'smmul r2, r3, r4', {}),
+ (b'\x32\xf1\x53\xe7', 'smmulr r3, r2, r1', {}),
+ (b'\x13\xf4\x52\x37', 'smmullo r2, r3, r4', {}),
+ (b'\x32\xf1\x53\x27', 'smmulrhs r3, r2, r1', {}),
+ (b'\x13\xf4\x02\xe7', 'smuad r2, r3, r4', {}),
+ (b'\x32\xf1\x03\xe7', 'smuadx r3, r2, r1', {}),
+ (b'\x13\xf4\x02\xb7', 'smuadlt r2, r3, r4', {}),
+ (b'\x32\xf1\x03\xa7', 'smuadxge r3, r2, r1', {}),
+ (b'\x89\x00\x63\xe1', 'smulbb r3, r9, r0', {}),
+ (b'\xc4\x01\x65\xe1', 'smulbt r5, r4, r1', {}),
+ (b'\xa2\x02\x64\xe1', 'smultb r4, r2, r2', {}),
+ (b'\xe3\x04\x68\xe1', 'smultt r8, r3, r4', {}),
+ (b'\x89\x00\x61\xa1', 'smulbbge r1, r9, r0', {}),
+ (b'\xc6\x04\x65\xd1', 'smulbtle r5, r6, r4', {}),
+ (b'\xa3\x02\x62\x11', 'smultbne r2, r3, r2', {}),
+ (b'\xe3\x04\x68\x01', 'smultteq r8, r3, r4', {}),
+ (b'\x90\x31\xc9\xe0', 'smull r3, r9, r0, r1', {}),
+ (b'\x90\x32\xd9\xe0', 'smulls r3, r9, r0, r2', {}),
+ (b'\x94\x85\xc3\x00', 'smulleq r8, r3, r4, r5', {}),
+ (b'\x94\x83\xd3\x00', 'smull.seq r8, r3, r4, r3', {}),
+ (b'\xa9\x00\x23\xe1', 'smulwb r3, r9, r0', {}),
+ (b'\xe9\x02\x23\xe1', 'smulwt r3, r9, r2', {}),
+ (b'\x50\xf1\x03\xe7', 'smusd r3, r0, r1', {}),
+ (b'\x79\xf2\x03\xe7', 'smusdx r3, r9, r2', {}),
+ (b'\x53\xf2\x08\x07', 'smusdeq r8, r3, r2', {}),
+ (b'\x74\xf3\x07\x17', 'smusdxne r7, r4, r3', {}),
+ (b'\x05\x05\x4d\xf8', 'srsda sp, #0x5', {}),
+ (b'\x01\x05\x4d\xf9', 'srsdb sp, #0x1', {}),
+ (b'\x00\x05\xcd\xf8', 'srsia sp, #0', {}),
+ (b'\x0f\x05\xcd\xf9', 'srsib sp, #0xf', {}),
+ (b'\x1f\x05\x6d\xf8', 'srsda sp!, #0x1f', {}),
+ (b'\x13\x05\x6d\xf9', 'srsdb sp!, #0x13', {}),
+ (b'\x02\x05\xed\xf8', 'srsia sp!, #0x2', {}),
+ (b'\x0e\x05\xed\xf9', 'srsib sp!, #0xe', {}),
+ (b'\x0b\x05\xcd\xf9', 'srsib sp, #0xb', {}),
+ (b'\x0a\x05\xcd\xf8', 'srsia sp, #0xa', {}),
+ (b'\x09\x05\x4d\xf9', 'srsdb sp, #0x9', {}),
+ (b'\x05\x05\x4d\xf8', 'srsda sp, #0x5', {}),
+ (b'\x05\x05\xed\xf9', 'srsib sp!, #0x5', {}),
+ (b'\x05\x05\xed\xf8', 'srsia sp!, #0x5', {}),
+ (b'\x05\x05\x6d\xf9', 'srsdb sp!, #0x5', {}),
+ (b'\x05\x05\x6d\xf8', 'srsda sp!, #0x5', {}),
+ (b'\x05\x05\xcd\xf8', 'srsia sp, #0x5', {}),
+ (b'\x05\x05\xed\xf8', 'srsia sp!, #0x5', {}),
+ (b'\x05\x05\x4d\xf8', 'srsda sp, #0x5', {}),
+ (b'\x01\x05\x4d\xf9', 'srsdb sp, #0x1', {}),
+ (b'\x00\x05\xcd\xf8', 'srsia sp, #0', {}),
+ (b'\x0f\x05\xcd\xf9', 'srsib sp, #0xf', {}),
+ (b'\x1f\x05\x6d\xf8', 'srsda sp!, #0x1f', {}),
+ (b'\x13\x05\x6d\xf9', 'srsdb sp!, #0x13', {}),
+ (b'\x02\x05\xed\xf8', 'srsia sp!, #0x2', {}),
+ (b'\x0e\x05\xed\xf9', 'srsib sp!, #0xe', {}),
+ (b'\x0b\x05\xcd\xf9', 'srsib sp, #0xb', {}),
+ (b'\x0a\x05\xcd\xf8', 'srsia sp, #0xa', {}),
+ (b'\x09\x05\x4d\xf9', 'srsdb sp, #0x9', {}),
+ (b'\x05\x05\x4d\xf8', 'srsda sp, #0x5', {}),
+ (b'\x05\x05\xed\xf9', 'srsib sp!, #0x5', {}),
+ (b'\x05\x05\xed\xf8', 'srsia sp!, #0x5', {}),
+ (b'\x05\x05\x6d\xf9', 'srsdb sp!, #0x5', {}),
+ (b'\x05\x05\x6d\xf8', 'srsda sp!, #0x5', {}),
+ (b'\x05\x05\xcd\xf8', 'srsia sp, #0x5', {}),
+ (b'\x05\x05\xed\xf8', 'srsia sp!, #0x5', {}),
+ (b'\x1a\x80\xa0\xe6', 'ssat r8, #0x1, r10', {}),
+ (b'\x1a\x80\xa0\xe6', 'ssat r8, #0x1, r10', {}),
+ (b'\x9a\x8f\xa0\xe6', 'ssat r8, #0x1, r10, lsl #0x1f', {}),
+ (b'\x5a\x80\xa0\xe6', 'ssat r8, #0x1, r10, asr #0x20', {}),
+ (b'\xda\x80\xa0\xe6', 'ssat r8, #0x1, r10, asr #0x1', {}),
+ (b'\x37\x2f\xa0\xe6', 'ssat16 r2, #0x1, r7', {}),
+ (b'\x35\x3f\xaf\xe6', 'ssat16 r3, #0x16, r5', {}),
+ (b'\x54\x2f\x13\xe6', 'ssax r2, r3, r4', {}),
+ (b'\x54\x2f\x13\xb6', 'ssaxlt r2, r3, r4', {}),
+ (b'\x76\x1f\x10\xe6', 'ssub16 r1, r0, r6', {}),
+ (b'\x72\x5f\x13\x16', 'ssub16ne r5, r3, r2', {}),
+ (b'\xf4\x9f\x12\xe6', 'ssub8 r9, r2, r4', {}),
+ (b'\xf2\x5f\x11\x06', 'ssub8eq r5, r1, r2', {}),
+ (b'\x01\x80\x81\xfd', 'stc2 p0, c8, [r1, #0x4]', {}),
+ (b'\x00\x71\x82\xfd', 'stc2 p1, c7, [r2]', {}),
+ (b'\x38\x62\x03\xfd', 'stc2 p2, c6, [r3, ', {}),
+ (b'\x1e\x53\x24\xfd', 'stc2 p3, c5, [r4, !', {}),
+ (b'\x04\x44\xa5\xfc', 'stc2 p4, c4, [r5], #0x10', {}),
+ (b'\x12\x35\x26\xfc', 'stc2 p5, c3, [r6], #-0x48', {}),
+ (b'\x01\x26\xc7\xfd', 'stc2l p6, c2, [r7, #0x4]', {}),
+ (b'\x00\x17\xc8\xfd', 'stc2l p7, c1, [r8]', {}),
+ (b'\x38\x08\x49\xfd', 'stc2l p8, c0, [r9, ', {}),
+ (b'\x1e\x19\x6a\xfd', 'stc2l p9, c1, [r10, !', {}),
+ (b'\x04\x20\xeb\xfc', 'stc2l p0, c2, [r11], #0x10', {}),
+ (b'\x12\x31\x6c\xfc', 'stc2l p1, c3, [r12], #-0x48', {}),
+ (b'\x01\x4c\x80\xed', 'stc p12, c4, [r0, #0x4]', {}),
+ (b'\x00\x5d\x81\xed', 'stc p13, c5, [r1]', {}),
+ (b'\x38\x6e\x02\xed', 'stc p14, c6, [r2, ', {}),
+ (b'\x1e\x7f\x23\xed', 'stc p15, c7, [r3, !', {}),
+ (b'\x04\x85\xa4\xec', 'stc p5, c8, [r4], #0x10', {}),
+ (b'\x12\x94\x25\xec', 'stc p4, c9, [r5], #-0x48', {}),
+ (b'\x01\xa3\xc6\xed', 'stcl p3, c10, [r6, #0x4]', {}),
+ (b'\x00\xb2\xc7\xed', 'stcl p2, c11, [r7]', {}),
+ (b'\x38\xc1\x48\xed', 'stcl p1, c12, [r8, ', {}),
+ (b'\x1e\xd0\x69\xed', 'stcl p0, c13, [r9, !', {}),
+ (b'\x04\xe6\xea\xec', 'stcl p6, c14, [r10], #0x10', {}),
+ (b'\x12\xf7\x6b\xec', 'stcl p7, c15, [r11], #-0x48', {}),
+ (b'\x01\x4c\x80\x3d', 'stclo p12, c4, [r0, #0x4]', {}),
+ (b'\x00\x5d\x81\x8d', 'stchi p13, c5, [r1]', {}),
+ (b'\x38\x6e\x02\x2d', 'stchs p14, c6, [r2, ', {}),
+ (b'\x1e\x7f\x23\x3d', 'stclo p15, c7, [r3, !', {}),
+ (b'\x04\x85\xa4\x0c', 'stceq p5, c8, [r4], #0x10', {}),
+ (b'\x12\x94\x25\xcc', 'stcgt p4, c9, [r5], #-0x48', {}),
+ (b'\x01\xa3\xc6\xbd', 'stcllt p3, c10, [r6, #0x4]', {}),
+ (b'\x00\xb2\xc7\xad', 'stclge p2, c11, [r7]', {}),
+ (b'\x38\xc1\x48\xdd', 'stclle p1, c12, [r8, ', {}),
+ (b'\x1e\xd0\x69\x1d', 'stclne p0, c13, [r9, !', {}),
+ (b'\x04\xe6\xea\x0c', 'stcleq p6, c14, [r10], #0x10', {}),
+ (b'\x12\xf7\x6b\x8c', 'stclhi p7, c15, [r11], #-0x48', {}),
+ (b'\x19\x82\x81\xfc', 'stc2 p2, c8, [r1], {25}', {}),
+ (b'\x7a\x20\x82\xe8', 'stm r2, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x40\x83\xe8', 'stm r3, {r1, r3, r4, r5, r6, lr}', {}),
+ (b'\x7a\x20\x84\xe9', 'stmib r4, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\x05\xe8', 'stmda r5, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x01\x06\xe9', 'stmdb r6, {r1, r3, r4, r5, r6, r8}', {}),
+ (b'\x7a\x20\x0d\xe9', 'stmdb sp, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\xa8\xe8', 'stm r8!, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x20\xa9\xe9', 'stmib r9!, {r1, r3, r4, r5, r6, sp}', {}),
+ (b'\x7a\x00\x2d\xe8', 'stmda sp!, {r1, r3, r4, r5, r6}', {}),
+ (b'\xa2\x20\x20\xe9', 'stmdb r0!, {r1, r5, r7, sp}', {}),
+ (b'\x93\x1f\xc4\xe1', 'strexb r1, r3, [r4]', {}),
+ (b'\x92\x4f\xe5\xe1', 'strexh r4, r2, [r5]', {}),
+ (b'\x91\x2f\x87\xe1', 'strex r2, r1, [r7]', {}),
+ (b'\x92\x6f\xa8\xe1', 'strexd r6, r2, r3, [r8]', {}),
+ (b'\x00\x30\x2a\x55', 'strpl r3, [r10, #-0]!', {}),
+ (b'\x00\x30\xaa\x55', 'strpl r3, [r10, #0]!', {}),
+ (b'\x0f\x4a\x45\xe2', 'sub r4, r5, #0xf000', {}),
+ (b'\x06\x40\x45\xe0', 'sub r4, r5, r6', {}),
+ (b'\x86\x42\x45\xe0', 'sub r4, r5, r6, lsl #0x5', {}),
+ (b'\xa6\x42\x45\xe0', 'sub r4, r5, r6, lsr #0x5', {}),
+ (b'\xa6\x42\x45\xe0', 'sub r4, r5, r6, lsr #0x5', {}),
+ (b'\xc6\x42\x45\xe0', 'sub r4, r5, r6, asr #0x5', {}),
+ (b'\xe6\x42\x45\xe0', 'sub r4, r5, r6, ror #0x5', {}),
+ (b'\x18\x69\x47\xe0', 'sub r6, r7, r8, lsl r9', {}),
+ (b'\x38\x69\x47\xe0', 'sub r6, r7, r8, lsr r9', {}),
+ (b'\x58\x69\x47\xe0', 'sub r6, r7, r8, asr r9', {}),
+ (b'\x78\x69\x47\xe0', 'sub r6, r7, r8, ror r9', {}),
+ (b'\x0f\x5a\x45\xe2', 'sub r5, r5, #0xf000', {}),
+ (b'\x05\x40\x44\xe0', 'sub r4, r4, r5', {}),
+ (b'\x85\x42\x44\xe0', 'sub r4, r4, r5, lsl #0x5', {}),
+ (b'\xa5\x42\x44\xe0', 'sub r4, r4, r5, lsr #0x5', {}),
+ (b'\xa5\x42\x44\xe0', 'sub r4, r4, r5, lsr #0x5', {}),
+ (b'\xc5\x42\x44\xe0', 'sub r4, r4, r5, asr #0x5', {}),
+ (b'\xe5\x42\x44\xe0', 'sub r4, r4, r5, ror #0x5', {}),
+ (b'\x17\x69\x46\xe0', 'sub r6, r6, r7, lsl r9', {}),
+ (b'\x37\x69\x46\xe0', 'sub r6, r6, r7, lsr r9', {}),
+ (b'\x57\x69\x46\xe0', 'sub r6, r6, r7, asr r9', {}),
+ (b'\x77\x69\x46\xe0', 'sub r6, r6, r7, ror r9', {}),
+ (b'\x22\x30\x41\xe0', 'sub r3, r1, r2, lsr #0x20', {}),
+ (b'\x42\x30\x41\xe0', 'sub r3, r1, r2, asr #0x20', {}),
+ (b'\x92\x10\x03\xe1', 'swp r1, r2, [r3]', {}),
+ (b'\x94\x40\x06\xe1', 'swp r4, r4, [r6]', {}),
+ (b'\x91\x50\x49\xe1', 'swpb r5, r1, [r9]', {}),
+ (b'\x74\x20\xa3\xe6', 'sxtab r2, r3, r4', {}),
+ (b'\x76\x40\xa5\xe6', 'sxtab r4, r5, r6', {}),
+ (b'\x79\x64\xa2\xb6', 'sxtablt r6, r2, r9, ror #0x8', {}),
+ (b'\x74\x58\xa1\xe6', 'sxtab r5, r1, r4, ror #0x10', {}),
+ (b'\x73\x7c\xa8\xe6', 'sxtab r7, r8, r3, ror #0x18', {}),
+ (b'\x74\x00\x81\xa6', 'sxtab16ge r0, r1, r4', {}),
+ (b'\x77\x60\x82\xe6', 'sxtab16 r6, r2, r7', {}),
+ (b'\x78\x34\x85\xe6', 'sxtab16 r3, r5, r8, ror #0x8', {}),
+ (b'\x71\x38\x82\xe6', 'sxtab16 r3, r2, r1, ror #0x10', {}),
+ (b'\x73\x1c\x82\x06', 'sxtab16eq r1, r2, r3, ror #0x18', {}),
+ (b'\x79\x10\xb3\xe6', 'sxtah r1, r3, r9', {}),
+ (b'\x76\x60\xb1\x86', 'sxtahhi r6, r1, r6', {}),
+ (b'\x73\x34\xb8\xe6', 'sxtah r3, r8, r3, ror #0x8', {}),
+ (b'\x74\x28\xb2\x36', 'sxtahlo r2, r2, r4, ror #0x10', {}),
+ (b'\x73\x9c\xb3\xe6', 'sxtah r9, r3, r3, ror #0x18', {}),
+ (b'\x74\x20\xaf\xa6', 'sxtbge r2, r4', {}),
+ (b'\x76\x50\xaf\xe6', 'sxtb r5, r6', {}),
+ (b'\x79\x64\xaf\xe6', 'sxtb r6, r9, ror #0x8', {}),
+ (b'\x71\x58\xaf\x36', 'sxtblo r5, r1, ror #0x10', {}),
+ (b'\x73\x8c\xaf\xe6', 'sxtb r8, r3, ror #0x18', {}),
+ (b'\x74\x10\x8f\xe6', 'sxtb16 r1, r4', {}),
+ (b'\x77\x60\x8f\xe6', 'sxtb16 r6, r7', {}),
+ (b'\x75\x34\x8f\x26', 'sxtb16hs r3, r5, ror #0x8', {}),
+ (b'\x71\x38\x8f\xe6', 'sxtb16 r3, r1, ror #0x10', {}),
+ (b'\x73\x2c\x8f\xa6', 'sxtb16ge r2, r3, ror #0x18', {}),
+ (b'\x79\x30\xbf\x16', 'sxthne r3, r9', {}),
+ (b'\x76\x10\xbf\xe6', 'sxth r1, r6', {}),
+ (b'\x78\x34\xbf\xe6', 'sxth r3, r8, ror #0x8', {}),
+ (b'\x72\x28\xbf\xd6', 'sxthle r2, r2, ror #0x10', {}),
+ (b'\x73\x9c\xbf\xe6', 'sxth r9, r3, ror #0x18', {}),
+ (b'\x0f\x0a\x35\xe3', 'teq r5, #0xf000', {}),
+ (b'\x05\x00\x34\xe1', 'teq r4, r5', {}),
+ (b'\x85\x02\x34\xe1', 'teq r4, r5, lsl #0x5', {}),
+ (b'\xa5\x02\x34\xe1', 'teq r4, r5, lsr #0x5', {}),
+ (b'\xa5\x02\x34\xe1', 'teq r4, r5, lsr #0x5', {}),
+ (b'\xc5\x02\x34\xe1', 'teq r4, r5, asr #0x5', {}),
+ (b'\xe5\x02\x34\xe1', 'teq r4, r5, ror #0x5', {}),
+ (b'\x17\x09\x36\xe1', 'teq r6, r7, lsl r9', {}),
+ (b'\x37\x09\x36\xe1', 'teq r6, r7, lsr r9', {}),
+ (b'\x57\x09\x36\xe1', 'teq r6, r7, asr r9', {}),
+ (b'\x77\x09\x36\xe1', 'teq r6, r7, ror r9', {}),
+ (b'\x0f\x0a\x15\xe3', 'tst r5, #0xf000', {}),
+ (b'\x05\x00\x14\xe1', 'tst r4, r5', {}),
+ (b'\x85\x02\x14\xe1', 'tst r4, r5, lsl #0x5', {}),
+ (b'\xa5\x02\x14\xe1', 'tst r4, r5, lsr #0x5', {}),
+ (b'\xa5\x02\x14\xe1', 'tst r4, r5, lsr #0x5', {}),
+ (b'\xc5\x02\x14\xe1', 'tst r4, r5, asr #0x5', {}),
+ (b'\xe5\x02\x14\xe1', 'tst r4, r5, ror #0x5', {}),
+ (b'\x17\x09\x16\xe1', 'tst r6, r7, lsl r9', {}),
+ (b'\x37\x09\x16\xe1', 'tst r6, r7, lsr r9', {}),
+ (b'\x57\x09\x16\xe1', 'tst r6, r7, asr r9', {}),
+ (b'\x77\x09\x16\xe1', 'tst r6, r7, ror r9', {}),
+ (b'\x13\x1f\x52\xe6', 'uadd16 r1, r2, r3', {}),
+ (b'\x13\x1f\x52\xc6', 'uadd16gt r1, r2, r3', {}),
+ (b'\x93\x1f\x52\xe6', 'uadd8 r1, r2, r3', {}),
+ (b'\x93\x1f\x52\xd6', 'uadd8le r1, r2, r3', {}),
+ (b'\x30\x9f\x5c\xe6', 'uasx r9, r12, r0', {}),
+ (b'\x30\x9f\x5c\x06', 'uasxeq r9, r12, r0', {}),
+ (b'\x55\x48\xe0\xe7', 'ubfx r4, r5, #0x16, #0x1', {}),
+ (b'\x55\x48\xef\xc7', 'ubfxgt r4, r5, #0x16, #0x10', {}),
+ (b'\x12\x4f\x78\xe6', 'uhadd16 r4, r8, r2', {}),
+ (b'\x12\x4f\x78\xc6', 'uhadd16gt r4, r8, r2', {}),
+ (b'\x92\x4f\x78\xe6', 'uhadd8 r4, r8, r2', {}),
+ (b'\x92\x4f\x78\xc6', 'uhadd8gt r4, r8, r2', {}),
+ (b'\x32\x4f\x78\xe6', 'uhasx r4, r8, r2', {}),
+ (b'\x32\x4f\x78\xc6', 'uhasxgt r4, r8, r2', {}),
+ (b'\x72\x4f\x78\xe6', 'uhsub16 r4, r8, r2', {}),
+ (b'\x72\x4f\x78\xc6', 'uhsub16gt r4, r8, r2', {}),
+ (b'\xf2\x4f\x78\xe6', 'uhsub8 r4, r8, r2', {}),
+ (b'\xf2\x4f\x78\xc6', 'uhsub8gt r4, r8, r2', {}),
+ (b'\x95\x36\x44\xe0', 'umaal r3, r4, r5, r6', {}),
+ (b'\x95\x36\x44\xb0', 'umaallt r3, r4, r5, r6', {}),
+ (b'\x96\x28\xa4\xe0', 'umlal r2, r4, r6, r8', {}),
+ (b'\x92\x66\xa1\xc0', 'umlalgt r6, r1, r2, r6', {}),
+ (b'\x92\x23\xb9\xe0', 'umlals r2, r9, r2, r3', {}),
+ (b'\x91\x32\xb5\x00', 'umlal.seq r3, r5, r1, r2', {}),
+ (b'\x96\x28\x84\xe0', 'umull r2, r4, r6, r8', {}),
+ (b'\x92\x66\x81\xc0', 'umullgt r6, r1, r2, r6', {}),
+ (b'\x92\x23\x99\xe0', 'umulls r2, r9, r2, r3', {}),
+ (b'\x91\x32\x95\x00', 'umull.seq r3, r5, r1, r2', {}),
+ (b'\x13\x1f\x62\xe6', 'uqadd16 r1, r2, r3', {}),
+ (b'\x19\x4f\x67\xc6', 'uqadd16gt r4, r7, r9', {}),
+ (b'\x98\x3f\x64\xe6', 'uqadd8 r3, r4, r8', {}),
+ (b'\x92\x8f\x61\xd6', 'uqadd8le r8, r1, r2', {}),
+ (b'\x31\x2f\x64\xe6', 'uqasx r2, r4, r1', {}),
+ (b'\x39\x5f\x62\x86', 'uqasxhi r5, r2, r9', {}),
+ (b'\x57\x1f\x63\xe6', 'uqsax r1, r3, r7', {}),
+ (b'\x52\x3f\x66\xe6', 'uqsax r3, r6, r2', {}),
+ (b'\x73\x1f\x65\xe6', 'uqsub16 r1, r5, r3', {}),
+ (b'\x75\x3f\x62\xc6', 'uqsub16gt r3, r2, r5', {}),
+ (b'\xf4\x2f\x61\xe6', 'uqsub8 r2, r1, r4', {}),
+ (b'\xf9\x4f\x66\xd6', 'uqsub8le r4, r6, r9', {}),
+ (b'\x11\xf4\x82\xe7', 'usad8 r2, r1, r4', {}),
+ (b'\x16\xf9\x84\xd7', 'usad8le r4, r6, r9', {}),
+ (b'\x15\x73\x81\xe7', 'usada8 r1, r5, r3, r7', {}),
+ (b'\x12\x15\x83\xc7', 'usada8gt r3, r2, r5, r1', {}),
+ (b'\x1a\x80\xe1\xe6', 'usat r8, #0x1, r10', {}),
+ (b'\x1a\x80\xe4\xe6', 'usat r8, #0x4, r10', {}),
+ (b'\x9a\x8f\xe5\xe6', 'usat r8, #0x5, r10, lsl #0x1f', {}),
+ (b'\x5a\x80\xff\xe6', 'usat r8, #0x31, r10, asr #0x20', {}),
+ (b'\xda\x80\xf0\xe6', 'usat r8, #0x16, r10, asr #0x1', {}),
+ (b'\x37\x2f\xe2\xe6', 'usat16 r2, #0x2, r7', {}),
+ (b'\x35\x3f\xef\xe6', 'usat16 r3, #0x15, r5', {}),
+ (b'\x54\x2f\x53\xe6', 'usax r2, r3, r4', {}),
+ (b'\x54\x2f\x53\x16', 'usaxne r2, r3, r4', {}),
+ (b'\x77\x4f\x52\xe6', 'usub16 r4, r2, r7', {}),
+ (b'\x73\x1f\x51\x86', 'usub16hi r1, r1, r3', {}),
+ (b'\xf5\x1f\x58\xe6', 'usub8 r1, r8, r5', {}),
+ (b'\xf3\x9f\x52\xd6', 'usub8le r9, r2, r3', {}),
+ (b'\x74\x20\xe3\xe6', 'uxtab r2, r3, r4', {}),
+ (b'\x76\x40\xe5\xe6', 'uxtab r4, r5, r6', {}),
+ (b'\x79\x64\xe2\xb6', 'uxtablt r6, r2, r9, ror #0x8', {}),
+ (b'\x74\x58\xe1\xe6', 'uxtab r5, r1, r4, ror #0x10', {}),
+ (b'\x73\x7c\xe8\xe6', 'uxtab r7, r8, r3, ror #0x18', {}),
+ (b'\x74\x00\xc1\xa6', 'uxtab16ge r0, r1, r4', {}),
+ (b'\x77\x60\xc2\xe6', 'uxtab16 r6, r2, r7', {}),
+ (b'\x78\x34\xc5\xe6', 'uxtab16 r3, r5, r8, ror #0x8', {}),
+ (b'\x71\x38\xc2\xe6', 'uxtab16 r3, r2, r1, ror #0x10', {}),
+ (b'\x73\x1c\xc2\x06', 'uxtab16eq r1, r2, r3, ror #0x18', {}),
+ (b'\x79\x10\xf3\xe6', 'uxtah r1, r3, r9', {}),
+ (b'\x76\x60\xf1\x86', 'uxtahhi r6, r1, r6', {}),
+ (b'\x73\x34\xf8\xe6', 'uxtah r3, r8, r3, ror #0x8', {}),
+ (b'\x74\x28\xf2\x36', 'uxtahlo r2, r2, r4, ror #0x10', {}),
+ (b'\x73\x9c\xf3\xe6', 'uxtah r9, r3, r3, ror #0x18', {}),
+ (b'\x74\x20\xef\xa6', 'uxtbge r2, r4', {}),
+ (b'\x76\x50\xef\xe6', 'uxtb r5, r6', {}),
+ (b'\x79\x64\xef\xe6', 'uxtb r6, r9, ror #0x8', {}),
+ (b'\x71\x58\xef\x36', 'uxtblo r5, r1, ror #0x10', {}),
+ (b'\x73\x8c\xef\xe6', 'uxtb r8, r3, ror #0x18', {}),
+ (b'\x74\x10\xcf\xe6', 'uxtb16 r1, r4', {}),
+ (b'\x77\x60\xcf\xe6', 'uxtb16 r6, r7', {}),
+ (b'\x75\x34\xcf\x26', 'uxtb16hs r3, r5, ror #0x8', {}),
+ (b'\x71\x38\xcf\xe6', 'uxtb16 r3, r1, ror #0x10', {}),
+ (b'\x73\x2c\xcf\xa6', 'uxtb16ge r2, r3, ror #0x18', {}),
+ (b'\x79\x30\xff\x16', 'uxthne r3, r9', {}),
+ (b'\x76\x10\xff\xe6', 'uxth r1, r6', {}),
+ (b'\x78\x34\xff\xe6', 'uxth r3, r8, ror #0x8', {}),
+ (b'\x72\x28\xff\xd6', 'uxthle r2, r2, ror #0x10', {}),
+ (b'\x73\x9c\xff\xe6', 'uxth r9, r3, ror #0x18', {}),
+ (b'\x02\xf0\x20\xe3', 'wfe ', {}),
+ (b'\x02\xf0\x20\x83', 'wfehi ', {}),
+ (b'\x03\xf0\x20\xe3', 'wfi ', {}),
+ (b'\x03\xf0\x20\xb3', 'wfilt ', {}),
+ (b'\x01\xf0\x20\xe3', 'yield ', {}),
+ (b'\x01\xf0\x20\x13', 'yieldne ', {}),
+ (b'\x04\xf0\x20\xe3', 'sev ', {}),
+ (b'\x03\xf0\x20\xe3', 'wfi ', {}),
+ (b'\x02\xf0\x20\xe3', 'wfe ', {}),
+ (b'\x01\xf0\x20\xe3', 'yield ', {}),
+ (b'\x00\xf0\x20\xe3', 'nop ', {}),
+ (b'\xef\xf0\x20\xc3', 'hintgt #0xef', {}),
+ (b'\x42\x00\x01\xe1', 'crc32b r0, r1, r2', {}),
+ (b'\x42\x00\x21\xe1', 'crc32h r0, r1, r2', {}),
+ (b'\x42\x00\x41\xe1', 'crc32w r0, r1, r2', {}),
+ (b'\x42\x02\x01\xe1', 'crc32cb r0, r1, r2', {}),
+ (b'\x42\x02\x21\xe1', 'crc32ch r0, r1, r2', {}),
+ (b'\x42\x02\x41\xe1', 'crc32cw r0, r1, r2', {}),
+ (b'\x05\xb0\xa0\xe1', 'mov r11, r5', {}),
+ (b'\x06\x10\xa0\xe1', 'mov r1, r6', {}),
+ (b'\xe0\x3b\xb2\xee', 'vcvtt.f64.f16 d3, s1', {}),
+ (b'\xcc\x2b\xf3\xee', 'vcvtt.f16.f64 s5, d12', {}),
+ (b'\x60\x3b\xb2\xee', 'vcvtb.f64.f16 d3, s1', {}),
+ (b'\x41\x2b\xb3\xee', 'vcvtb.f16.f64 s4, d1', {}),
+ (b'\xe0\x3b\xb2\xae', 'vcvttge.f64.f16 d3, s1', {}),
+ (b'\xcc\x2b\xf3\xce', 'vcvttgt.f16.f64 s5, d12', {}),
+ (b'\x60\x3b\xb2\x0e', 'vcvtbeq.f64.f16 d3, s1', {}),
+ (b'\x41\x2b\xb3\xbe', 'vcvtblt.f16.f64 s4, d1', {}),
+ (b'\xe1\x1a\xbc\xfe', 'vcvta.s32.f32 s2, s3', {}),
+ (b'\xc3\x1b\xbc\xfe', 'vcvta.s32.f64 s2, d3', {}),
+ (b'\xeb\x3a\xbd\xfe', 'vcvtn.s32.f32 s6, s23', {}),
+ (b'\xe7\x3b\xbd\xfe', 'vcvtn.s32.f64 s6, d23', {}),
+ (b'\xc2\x0a\xbe\xfe', 'vcvtp.s32.f32 s0, s4', {}),
+ (b'\xc4\x0b\xbe\xfe', 'vcvtp.s32.f64 s0, d4', {}),
+ (b'\xc4\x8a\xff\xfe', 'vcvtm.s32.f32 s17, s8', {}),
+ (b'\xc8\x8b\xff\xfe', 'vcvtm.s32.f64 s17, d8', {}),
+ (b'\x61\x1a\xbc\xfe', 'vcvta.u32.f32 s2, s3', {}),
+ (b'\x43\x1b\xbc\xfe', 'vcvta.u32.f64 s2, d3', {}),
+ (b'\x6b\x3a\xbd\xfe', 'vcvtn.u32.f32 s6, s23', {}),
+ (b'\x67\x3b\xbd\xfe', 'vcvtn.u32.f64 s6, d23', {}),
+ (b'\x42\x0a\xbe\xfe', 'vcvtp.u32.f32 s0, s4', {}),
+ (b'\x44\x0b\xbe\xfe', 'vcvtp.u32.f64 s0, d4', {}),
+ (b'\x44\x8a\xff\xfe', 'vcvtm.u32.f32 s17, s8', {}),
+ (b'\x48\x8b\xff\xfe', 'vcvtm.u32.f64 s17, d8', {}),
+ (b'\xab\x2a\x20\xfe', 'vselge.f32 s4, s1, s23', {}),
+ (b'\xa7\xeb\x6f\xfe', 'vselge.f64 d30, d31, d23', {}),
+ (b'\x80\x0a\x30\xfe', 'vselgt.f32 s0, s1, s0', {}),
+ (b'\x24\x5b\x3a\xfe', 'vselgt.f64 d5, d10, d20', {}),
+ (b'\x2b\xfa\x0e\xfe', 'vseleq.f32 s30, s28, s23', {}),
+ (b'\x08\x2b\x04\xfe', 'vseleq.f64 d2, d4, d8', {}),
+ (b'\x07\xaa\x58\xfe', 'vselvs.f32 s21, s16, s14', {}),
+ (b'\x2f\x0b\x11\xfe', 'vselvs.f64 d0, d1, d31', {}),
+ (b'\x00\x2a\xc6\xfe', 'vmaxnm.f32 s5, s12, s0', {}),
+ (b'\xae\x5b\x86\xfe', 'vmaxnm.f64 d5, d22, d30', {}),
+ (b'\x46\x0a\x80\xfe', 'vminnm.f32 s0, s0, s12', {}),
+ (b'\x49\x4b\x86\xfe', 'vminnm.f64 d4, d6, d9', {}),
+ (b'\xcc\x3b\xb6\xae', 'vrintzge.f64 d3, d12', {}),
+ (b'\xcc\x1a\xf6\xee', 'vrintz.f32 s3, s24', {}),
+ (b'\x40\x5b\xb6\xbe', 'vrintrlt.f64 d5, d0', {}),
+ (b'\x64\x0a\xb6\xee', 'vrintr.f32 s0, s9', {}),
+ (b'\x6e\xcb\xf7\x0e', 'vrintxeq.f64 d28, d30', {}),
+ (b'\x47\x5a\xb7\x6e', 'vrintxvs.f32 s10, s14', {}),
+ (b'\x44\x3b\xb8\xfe', 'vrinta.f64 d3, d4', {}),
+ (b'\x60\x6a\xb8\xfe', 'vrinta.f32 s12, s1', {}),
+ (b'\x44\x3b\xb9\xfe', 'vrintn.f64 d3, d4', {}),
+ (b'\x60\x6a\xb9\xfe', 'vrintn.f32 s12, s1', {}),
+ (b'\x44\x3b\xba\xfe', 'vrintp.f64 d3, d4', {}),
+ (b'\x60\x6a\xba\xfe', 'vrintp.f32 s12, s1', {}),
+ (b'\x44\x3b\xbb\xfe', 'vrintm.f64 d3, d4', {}),
+ (b'\x60\x6a\xbb\xfe', 'vrintm.f32 s12, s1', {}),
+ (b'\x10\xda\xf5\xee', 'vmrs sp, mvfr2', {}),
+ (b'\x12\xf3\x11\xe7', 'sdiv r1, r2, r3', {}),
+ (b'\x14\xf5\x33\xe7', 'udiv r3, r4, r5', {}),
+ (b'\x93\x1e\xc4\xe1', 'strexb r1, r3, [r4]', {}),
+ (b'\x92\x4e\xe5\xe1', 'strexh r4, r2, [r5]', {}),
+ (b'\x91\x2e\x87\xe1', 'strex r2, r1, [r7]', {}),
+ (b'\x92\x6e\xa8\xe1', 'strexd r6, r2, r3, [r8]', {}),
+ (b'\x93\xfc\x80\xe1', 'strex pc, r3, [r0]', {}),
+ (b'\x92\xfc\xc1\xe1', 'strexb pc, r2, [r1]', {}),
+ (b'\x92\xfc\xe3\xe1', 'strexh pc, r2, [r3]', {}),
+ (b'\x00\xeb\x01\x00', 'andeq lr, r1, r0, lsl #0x16', {}),
+ (b'\x01\x00\x80\xe0', 'add r0, r0, r1', {}),
+ (b'\x40\x18\x00\x00', 'andeq r1, r0, r0, asr #0x10', {}),
+ (b'\x01\x00\x80\xe0', 'add r0, r0, r1', {}),
+ (b'\xa0\x0b\x71\xee', 'vadd.f64 d16, d17, d16', {}),
+ (b'\x80\x0a\x30\xee', 'vadd.f32 s0, s1, s0', {}),
+ (b'\xe0\x0b\x71\xee', 'vsub.f64 d16, d17, d16', {}),
+ (b'\xc0\x0a\x30\xee', 'vsub.f32 s0, s1, s0', {}),
+ (b'\xa0\x0b\xc1\xee', 'vdiv.f64 d16, d17, d16', {}),
+ (b'\x80\x0a\x80\xee', 'vdiv.f32 s0, s1, s0', {}),
+ (b'\xa3\x2a\xc2\xee', 'vdiv.f32 s5, s5, s7', {}),
+ (b'\x07\x5b\x85\xee', 'vdiv.f64 d5, d5, d7', {}),
+ (b'\xa0\x0b\x61\xee', 'vmul.f64 d16, d17, d16', {}),
+ (b'\xa1\x4b\x64\xee', 'vmul.f64 d20, d20, d17', {}),
+ (b'\x80\x0a\x20\xee', 'vmul.f32 s0, s1, s0', {}),
+ (b'\xaa\x5a\x65\xee', 'vmul.f32 s11, s11, s21', {}),
+ (b'\xe0\x0b\x61\xee', 'vnmul.f64 d16, d17, d16', {}),
+ (b'\xc0\x0a\x20\xee', 'vnmul.f32 s0, s1, s0', {}),
+ (b'\xe0\x1b\xf4\xee', 'vcmpe.f64 d17, d16', {}),
+ (b'\xc0\x0a\xf4\xee', 'vcmpe.f32 s1, s0', {}),
+ (b'\xc0\x0b\xf5\xee', 'vcmpe.f64 d16, #0', {}),
+ (b'\xc0\x0a\xb5\xee', 'vcmpe.f32 s0, #0', {}),
+ (b'\xe0\x0b\xf0\xee', 'vabs.f64 d16, d16', {}),
+ (b'\xc0\x0a\xb0\xee', 'vabs.f32 s0, s0', {}),
+ (b'\xe0\x0b\xb7\xee', 'vcvt.f32.f64 s0, d16', {}),
+ (b'\xc0\x0a\xf7\xee', 'vcvt.f64.f32 d16, s0', {}),
+ (b'\x60\x0b\xf1\xee', 'vneg.f64 d16, d16', {}),
+ (b'\x40\x0a\xb1\xee', 'vneg.f32 s0, s0', {}),
+ (b'\xe0\x0b\xf1\xee', 'vsqrt.f64 d16, d16', {}),
+ (b'\xc0\x0a\xb1\xee', 'vsqrt.f32 s0, s0', {}),
+ (b'\xc0\x0b\xf8\xee', 'vcvt.f64.s32 d16, s0', {}),
+ (b'\xc0\x0a\xb8\xee', 'vcvt.f32.s32 s0, s0', {}),
+ (b'\x40\x0b\xf8\xee', 'vcvt.f64.u32 d16, s0', {}),
+ (b'\x40\x0a\xb8\xee', 'vcvt.f32.u32 s0, s0', {}),
+ (b'\xe0\x0b\xbd\xee', 'vcvt.s32.f64 s0, d16', {}),
+ (b'\xc0\x0a\xbd\xee', 'vcvt.s32.f32 s0, s0', {}),
+ (b'\xe0\x0b\xbc\xee', 'vcvt.u32.f64 s0, d16', {}),
+ (b'\xc0\x0a\xbc\xee', 'vcvt.u32.f32 s0, s0', {}),
+ (b'\xa1\x0b\x42\xee', 'vmla.f64 d16, d18, d17', {}),
+ (b'\x00\x0a\x41\xee', 'vmla.f32 s1, s2, s0', {}),
+ (b'\xe1\x0b\x42\xee', 'vmls.f64 d16, d18, d17', {}),
+ (b'\x40\x0a\x41\xee', 'vmls.f32 s1, s2, s0', {}),
+ (b'\xe1\x0b\x52\xee', 'vnmla.f64 d16, d18, d17', {}),
+ (b'\x40\x0a\x51\xee', 'vnmla.f32 s1, s2, s0', {}),
+ (b'\xa1\x0b\x52\xee', 'vnmls.f64 d16, d18, d17', {}),
+ (b'\x00\x0a\x51\xee', 'vnmls.f32 s1, s2, s0', {}),
+ (b'\x10\xfa\xf1\xee', 'vmrs APSR_nzcv, fpscr', {}),
+ (b'\x10\xfa\xf1\xee', 'vmrs APSR_nzcv, fpscr', {}),
+ (b'\x10\xfa\xf1\xee', 'vmrs APSR_nzcv, fpscr', {}),
+ (b'\x10\x2a\xf0\xee', 'vmrs r2, fpsid', {}),
+ (b'\x10\x3a\xf0\xee', 'vmrs r3, fpsid', {}),
+ (b'\x10\x4a\xf7\xee', 'vmrs r4, mvfr0', {}),
+ (b'\x10\x5a\xf6\xee', 'vmrs r5, mvfr1', {}),
+ (b'\x60\x0b\xf1\x1e', 'vnegne.f64 d16, d16', {}),
+ (b'\x10\x0a\x00\x1e', 'vmovne s0, r0', {}),
+ (b'\x10\x1a\x00\x0e', 'vmoveq s0, r1', {}),
+ (b'\x10\x1a\x11\xee', 'vmov r1, s2', {}),
+ (b'\x10\x3a\x02\xee', 'vmov s4, r3', {}),
+ (b'\x12\x1b\x55\xec', 'vmov r1, r5, d2', {}),
+ (b'\x14\x3b\x49\xec', 'vmov d4, r3, r9', {}),
+ (b'\x10\x0a\xf1\xee', 'vmrs r0, fpscr', {}),
+ (b'\x10\x0a\xf8\xee', 'vmrs r0, fpexc', {}),
+ (b'\x10\x0a\xf0\xee', 'vmrs r0, fpsid', {}),
+ (b'\x10\x1a\xf9\xee', 'vmrs r1, fpinst', {}),
+ (b'\x10\x8a\xfa\xee', 'vmrs r8, fpinst2', {}),
+ (b'\x10\x0a\xe1\xee', 'vmsr fpscr, r0', {}),
+ (b'\x10\x0a\xe8\xee', 'vmsr fpexc, r0', {}),
+ (b'\x10\x0a\xe0\xee', 'vmsr fpsid, r0', {}),
+ (b'\x10\x3a\xe9\xee', 'vmsr fpinst, r3', {}),
+ (b'\x10\x4a\xea\xee', 'vmsr fpinst2, r4', {}),
+ (b'\x08\x0b\xf0\xee', 'vmov.f64 d16, #0x3.000000e+00', {}),
+ (b'\x08\x0a\xb0\xee', 'vmov.f32 s0, #0x3.000000e+00', {}),
+ (b'\x08\x0b\xf8\xee', 'vmov.f64 d16, #-3.000000e+00', {}),
+ (b'\x08\x0a\xb8\xee', 'vmov.f32 s0, #-3.000000e+00', {}),
+ (b'\x10\x0a\x00\xee', 'vmov s0, r0', {}),
+ (b'\x90\x1a\x00\xee', 'vmov s1, r1', {}),
+ (b'\x10\x2a\x01\xee', 'vmov s2, r2', {}),
+ (b'\x90\x3a\x01\xee', 'vmov s3, r3', {}),
+ (b'\x10\x0a\x10\xee', 'vmov r0, s0', {}),
+ (b'\x90\x1a\x10\xee', 'vmov r1, s1', {}),
+ (b'\x10\x2a\x11\xee', 'vmov r2, s2', {}),
+ (b'\x90\x3a\x11\xee', 'vmov r3, s3', {}),
+ (b'\x30\x0b\x51\xec', 'vmov r0, r1, d16', {}),
+ (b'\x31\x1a\x42\xec', 'vmov s3, s4, r1, r2', {}),
+ (b'\x11\x1a\x42\xec', 'vmov s2, s3, r1, r2', {}),
+ (b'\x31\x1a\x52\xec', 'vmov r1, r2, s3, s4', {}),
+ (b'\x11\x1a\x52\xec', 'vmov r1, r2, s2, s3', {}),
+ (b'\x1f\x1b\x42\xec', 'vmov d15, r1, r2', {}),
+ (b'\x30\x1b\x42\xec', 'vmov d16, r1, r2', {}),
+ (b'\x1f\x1b\x52\xec', 'vmov r1, r2, d15', {}),
+ (b'\x30\x1b\x52\xec', 'vmov r1, r2, d16', {}),
+ (b'\x00\x1b\xd0\xed', 'vldr d17, [r0]', {}),
+ (b'\x00\x0a\x9e\xed', 'vldr s0, [lr]', {}),
+ (b'\x00\x0b\x9e\xed', 'vldr d0, [lr]', {}),
+ (b'\x08\x1b\x92\xed', 'vldr d1, [r2, #0x20]', {}),
+ (b'\x08\x1b\x12\xed', 'vldr d1, [r2, ', {}),
+ (b'\x00\x2b\x93\xed', 'vldr d2, [r3]', {}),
+ (b'\x00\x3b\x9f\xed', 'vldr d3, [pc]', {}),
+ (b'\x00\x3b\x9f\xed', 'vldr d3, [pc]', {}),
+ (b'\x00\x3b\x1f\xed', 'vldr d3, [pc, #-0]', {}),
+ (b'\x00\x6a\xd0\xed', 'vldr s13, [r0]', {}),
+ (b'\x08\x0a\xd2\xed', 'vldr s1, [r2, #0x20]', {}),
+ (b'\x08\x0a\x52\xed', 'vldr s1, [r2, ', {}),
+ (b'\x00\x1a\x93\xed', 'vldr s2, [r3]', {}),
+ (b'\x00\x2a\xdf\xed', 'vldr s5, [pc]', {}),
+ (b'\x00\x2a\xdf\xed', 'vldr s5, [pc]', {}),
+ (b'\x00\x2a\x5f\xed', 'vldr s5, [pc, #-0]', {}),
+ (b'\x00\x4b\x81\xed', 'vstr d4, [r1]', {}),
+ (b'\x06\x4b\x81\xed', 'vstr d4, [r1, #0x18]', {}),
+ (b'\x06\x4b\x01\xed', 'vstr d4, [r1, ', {}),
+ (b'\x00\x0a\x8e\xed', 'vstr s0, [lr]', {}),
+ (b'\x00\x0b\x8e\xed', 'vstr d0, [lr]', {}),
+ (b'\x00\x2a\x81\xed', 'vstr s4, [r1]', {}),
+ (b'\x06\x2a\x81\xed', 'vstr s4, [r1, #0x18]', {}),
+ (b'\x06\x2a\x01\xed', 'vstr s4, [r1, ', {}),
+ (b'\x0c\x2b\x91\xec', 'vldmia r1, {d2, d3, d4, d5, d6, d7}', {}),
+ (b'\x06\x1a\x91\xec', 'vldmia r1, {s2, s3, s4, s5, s6, s7}', {}),
+ (b'\x0c\x2b\x81\xec', 'vstmia r1, {d2, d3, d4, d5, d6, d7}', {}),
+ (b'\x06\x1a\x81\xec', 'vstmia r1, {s2, s3, s4, s5, s6, s7}', {}),
+ (b'\x10\x8b\x2d\xed', 'vpush {d8, d9, d10, d11, d12, d13, d14, d15}', {}),
+ (b'\x07\x0b\xb5\xec', 'fldmiax r5!, {d0, d1, d2}', {}),
+ (b'\x05\x4b\x90\x0c', 'fldmiaxeq r0, {d4, d5}', {}),
+ (b'\x07\x4b\x35\x1d', 'fldmdbxne r5!, {d4, d5, d6}', {}),
+ (b'\x11\x0b\xa5\xec', 'fstmiax r5!, {d0, d1, d2, d3, d4, d5, d6, d7}', {}),
+ (b'\x05\x8b\x84\x0c', 'fstmiaxeq r4, {d8, d9}', {}),
+ (b'\x07\x2b\x27\x1d', 'fstmdbxne r7!, {d2, d3, d4}', {}),
+ (b'\x40\x0b\xbd\xee', 'vcvtr.s32.f64 s0, d0', {}),
+ (b'\x60\x0a\xbd\xee', 'vcvtr.s32.f32 s0, s1', {}),
+ (b'\x40\x0b\xbc\xee', 'vcvtr.u32.f64 s0, d0', {}),
+ (b'\x60\x0a\xbc\xee', 'vcvtr.u32.f32 s0, s1', {}),
+ (b'\x90\x8a\x00\xee', 'vmov s1, r8', {}),
+ (b'\x10\x4a\x01\xee', 'vmov s2, r4', {}),
+ (b'\x90\x6a\x01\xee', 'vmov s3, r6', {}),
+ (b'\x10\x1a\x02\xee', 'vmov s4, r1', {}),
+ (b'\x90\x2a\x02\xee', 'vmov s5, r2', {}),
+ (b'\x10\x3a\x03\xee', 'vmov s6, r3', {}),
+ (b'\x10\x1a\x14\xee', 'vmov r1, s8', {}),
+ (b'\x10\x2a\x12\xee', 'vmov r2, s4', {}),
+ (b'\x10\x3a\x13\xee', 'vmov r3, s6', {}),
+ (b'\x90\x4a\x10\xee', 'vmov r4, s1', {}),
+ (b'\x10\x5a\x11\xee', 'vmov r5, s2', {}),
+ (b'\x90\x6a\x11\xee', 'vmov r6, s3', {}),
+ (b'\xc6\x0a\xbb\xee', 'vcvt.f32.u32 s0, s0, #0x14', {}),
+ (b'\xc0\x0b\xba\xee', 'vcvt.f64.s32 d0, d0, #0x20', {}),
+ (b'\x67\x0a\xbb\xee', 'vcvt.f32.u16 s0, s0, #0x1', {}),
+ (b'\x40\x0b\xba\xee', 'vcvt.f64.s16 d0, d0, #0x10', {}),
+ (b'\xc6\x0a\xfa\xee', 'vcvt.f32.s32 s1, s1, #0x14', {}),
+ (b'\xc0\x4b\xfb\xee', 'vcvt.f64.u32 d20, d20, #0x20', {}),
+ (b'\x67\x8a\xfa\xee', 'vcvt.f32.s16 s17, s17, #0x1', {}),
+ (b'\x40\x7b\xfb\xee', 'vcvt.f64.u16 d23, d23, #0x10', {}),
+ (b'\xc6\x6a\xbf\xee', 'vcvt.u32.f32 s12, s12, #0x14', {}),
+ (b'\xc0\x2b\xbe\xee', 'vcvt.s32.f64 d2, d2, #0x20', {}),
+ (b'\x67\xea\xbf\xee', 'vcvt.u16.f32 s28, s28, #0x1', {}),
+ (b'\x40\xfb\xbe\xee', 'vcvt.s16.f64 d15, d15, #0x10', {}),
+ (b'\xc6\x0a\xfe\xee', 'vcvt.s32.f32 s1, s1, #0x14', {}),
+ (b'\xc0\x4b\xff\xee', 'vcvt.u32.f64 d20, d20, #0x20', {}),
+ (b'\x67\x8a\xfe\xee', 'vcvt.s16.f32 s17, s17, #0x1', {}),
+ (b'\x40\x7b\xff\xee', 'vcvt.u16.f64 d23, d23, #0x10', {}),
+ (b'\x10\x40\x80\xf2', 'vmov.i32 d4, #0', {}),
+ (b'\x12\x46\x84\xf2', 'vmov.i32 d4, #0x42000000', {}),
+ (b'\xa1\x0b\xe2\xee', 'vfma.f64 d16, d18, d17', {}),
+ (b'\x00\x1a\xa2\xee', 'vfma.f32 s2, s4, s0', {}),
+ (b'\xb1\x0c\x42\xf2', 'vfma.f32 d16, d18, d17', {}),
+ (b'\x50\x4c\x08\xf2', 'vfma.f32 q2, q4, q0', {}),
+ (b'\xe1\x0b\xd2\xee', 'vfnma.f64 d16, d18, d17', {}),
+ (b'\x40\x1a\x92\xee', 'vfnma.f32 s2, s4, s0', {}),
+ (b'\xe1\x0b\xe2\xee', 'vfms.f64 d16, d18, d17', {}),
+ (b'\x40\x1a\xa2\xee', 'vfms.f32 s2, s4, s0', {}),
+ (b'\xb1\x0c\x62\xf2', 'vfms.f32 d16, d18, d17', {}),
+ (b'\x50\x4c\x28\xf2', 'vfms.f32 q2, q4, q0', {}),
+ (b'\xa1\x0b\xd2\xee', 'vfnms.f64 d16, d18, d17', {}),
+ (b'\x00\x1a\x92\xee', 'vfnms.f32 s2, s4, s0', {}),
+ (b'\x0a\x8b\x2d\xed', 'vpush {d8, d9, d10, d11, d12}', {}),
+ (b'\x05\x4a\x2d\xed', 'vpush {s8, s9, s10, s11, s12}', {}),
+ (b'\x0a\x8b\xbd\xec', 'vpop {d8, d9, d10, d11, d12}', {}),
+ (b'\x05\x4a\xbd\xec', 'vpop {s8, s9, s10, s11, s12}', {}),
+ (b'\x0a\x8b\x2d\xed', 'vpush {d8, d9, d10, d11, d12}', {}),
+ (b'\x05\x4a\x2d\xed', 'vpush {s8, s9, s10, s11, s12}', {}),
+ (b'\x0a\x8b\xbd\xec', 'vpop {d8, d9, d10, d11, d12}', {}),
+ (b'\x05\x4a\xbd\xec', 'vpop {s8, s9, s10, s11, s12}', {}),
+)
+
+import os, sys, struct, platform, re
+from ctypes import *
+
+module = None
+disasm_buf = create_string_buffer(2048)
+inst_buf = create_string_buffer(2048)
+
+def disassemble_binja(insvalue, addr):
+ global module, disasm_buf, inst_buf
+ for a in range(len(disasm_buf)):
+ disasm_buf[a] = b'\0'
+ for a in range(len(inst_buf)):
+ inst_buf[a] = b'\0'
+ err = module.armv7_decompose(insvalue, inst_buf, addr, False)
+ if err == 1: return "decomposer failed"
+ elif err == 2: return "group decomposition failed"
+ elif err == 3: return "unimplemented"
+ elif err == 4: return "disassembler failed"
+ if module.armv7_disassemble(inst_buf, disasm_buf, 2048) == 0:
+ return disasm_buf.value.decode('utf-8')
+ return "disassembly failed"
+
+def distill(instxt):
+ instxt = re.sub(r'\s+', ' ', instxt)
+ return instxt
+
+if __name__ == '__main__':
+ if platform.system() == 'Linux': module = CDLL('disasm.so')
+ elif platform.system() == 'Windows': module = CDLL('disasm.dll')
+ # gcc -shared armv7.c -o disasm.dylib
+ elif platform.system() == "Darwin": module = CDLL('disasm.dylib')
+
+ for (test_i, (data, expected, options)) in enumerate(test_cases):
+ addr = options.get('addr', 0)
+ insvalue = struct.unpack('<I', data)[0]
+ actual = disassemble_binja(insvalue, addr)
+ actual = distill(actual)
+ if actual != expected:
+ print('MISMATCH AT TEST %d!' % test_i)
+ print('\t data: %s' % repr(data))
+ print('\t address: %08X' % addr)
+ print('\tinsvalue: 0x%08X' % insvalue)
+ print('\texpected: %s' % expected)
+ print('\t actual: %s' % actual)
+ sys.exit(-1)
+
+ print('success!')
+ sys.exit(0)
+