diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-05 19:50:13 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-05 20:34:34 -0500 |
| commit | e093c21ed880ac3eb72119be15093ee04f8ce299 (patch) | |
| tree | 9f720ebdc0ae415734b1199ed341668c69710a94 /arch/armv7/armv7_disasm | |
| parent | 0609276712622908254065546102381466033141 (diff) | |
Move architecture modules into the API repo
Diffstat (limited to 'arch/armv7/armv7_disasm')
| -rw-r--r-- | arch/armv7/armv7_disasm/armv7.c | 8478 | ||||
| -rw-r--r-- | arch/armv7/armv7_disasm/armv7.h | 959 | ||||
| -rw-r--r-- | arch/armv7/armv7_disasm/test.c | 38 | ||||
| -rwxr-xr-x | arch/armv7/armv7_disasm/test.py | 1635 |
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) + |
