summaryrefslogtreecommitdiff
path: root/arch/armv7/armv7_disasm/armv7.c
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2024-03-05 19:50:13 -0500
committerRusty Wagner <rusty.wagner@gmail.com>2024-03-05 20:34:34 -0500
commite093c21ed880ac3eb72119be15093ee04f8ce299 (patch)
tree9f720ebdc0ae415734b1199ed341668c69710a94 /arch/armv7/armv7_disasm/armv7.c
parent0609276712622908254065546102381466033141 (diff)
Move architecture modules into the API repo
Diffstat (limited to 'arch/armv7/armv7_disasm/armv7.c')
-rw-r--r--arch/armv7/armv7_disasm/armv7.c8478
1 files changed, 8478 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;
+}