#pragma once #include "../../../Utilities/BitField.h" #include enum class arm_encoding { T1, T2, T3, T4, A1, A2, }; // Get Thumb instruction size inline bool arm_op_thumb_is_32(u32 op16) { return (op16 >> 11) >= 29; } namespace arm_code { inline namespace arm_encoding_alias { constexpr auto T1 = arm_encoding ::T1; constexpr auto T2 = arm_encoding ::T2; constexpr auto T3 = arm_encoding ::T3; constexpr auto T4 = arm_encoding ::T4; constexpr auto A1 = arm_encoding ::A1; constexpr auto A2 = arm_encoding ::A2; } // Bitfield aliases (because only u32 base type is used) template using bf = bf_t; template using sf = bf_t; template using ff = ff_t; template using cf = cf_t; // Nullary op template struct nullary { static inline u32 extract() { return F::extract(0); } }; // Pair op: first field selection template struct from_first { static inline u32 extract(u32 first, u32) { return F::extract(first); } }; // Pair op: second field selection template struct from_second { static inline u32 extract(u32, u32 second) { return F::extract(second); } }; // No operation struct nopf { static inline u32 extract(u32 value) { return value; } }; // Negate unary op template struct negatef : bf_base { static inline u32 extract(u32 value) { return (0u - F::extract(value)) & (~0u >> (32 - N)); } }; // NOT unary op template struct notf : bf_base { static inline u32 extract(u32 value) { return F::extract(value) ^ (~0u >> (32 - N)); } }; // XOR binary op template struct xorf : bf_base { static inline u32 extract(u32 value) { return F1::extract(value) ^ F2::extract(value); } }; // AND binary op template struct andf : bf_base { static inline u32 extract(u32 value) { return F1::extract(value) & F2::extract(value); } }; // OR binary op template struct orf : bf_base { static inline u32 extract(u32 value) { return F1::extract(value) | F2::extract(value); } }; // SHL binary op template struct shlf : bf_base { static inline u32 extract(u32 value) { return F1::extract(value) << F2::extract(value); } }; // EQ with constant binary op template struct eqcf : bf_base { static inline u32 extract(u32 value) { return F1::extract(value) == C; } }; using imm12i38 = cf, bf<12, 3>, bf<0, 8>>; // ThumbExpandImm(...) struct thumb_expand_imm { static constexpr uint bitsize() { return 32; } static u32 extract(u32 value) { const u32 imm12 = imm12i38::extract(value); if ((imm12 & 0xc00) >> 10) { const u32 x = (imm12 & 0x7f) | 0x80; const u32 s = (imm12 & 0xf80) >> 7; const u32 r = x >> s | x << (32 - s); // Rotate return r; } else { const u32 imm8 = imm12 & 0xff; switch ((imm12 & 0x300) >> 8) { case 0: return imm8; case 1: return imm8 << 16 | imm8; case 2: return imm8 << 24 | imm8 << 8; default: return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8; } } } }; // ThumbExpandImm_C(..., carry) -> carry struct thumb_expand_imm_c { static u32 extract(u32 value, u32 carry_in) { const u32 imm12 = imm12i38::extract(value); if ((imm12 & 0xc00) >> 10) { const u32 x = (imm12 & 0x7f) | 0x80; const u32 s = (imm12 & 0xf80) >> 7; const u32 r = x >> s | x << (32 - s); // Rotate return (s ? r >> 31 : carry_in) & 1; } else { return carry_in & 1; } } }; // ARMExpandImm(...) struct arm_expand_imm { static constexpr uint bitsize() { return 32; } static u32 extract(u32 value) { const u32 imm12 = bf<0, 12>::extract(value); const u32 x = imm12 & 0xff; const u32 s = (imm12 & 0xf00) >> 7; const u32 r = x >> s | x << (32 - s); // Rotate return r; } }; // ARMExpandImm_C(..., carry) -> carry struct arm_expand_imm_c { static u32 extract(u32 value, u32 carry_in) { const u32 imm12 = bf<0, 12>::extract(value); const u32 x = imm12 & 0xff; const u32 s = (imm12 & 0xf00) >> 7; const u32 r = x >> s | x << (32 - s); // Rotate return (s ? r >> 31 : carry_in) & 1; } }; // !InITBlock() struct not_in_it_block { static u32 extract(u32 value, u32 cond) { return cond != 0xf; } }; enum SRType : u32 { SRType_LSL, SRType_LSR, SRType_ASR, SRType_ROR, SRType_RRX, }; template struct decode_imm_shift_type { static u32 extract(u32 value) { const u32 type = T::extract(value); const u32 imm5 = N::extract(value); return type < SRType_ROR ? type : (imm5 ? SRType_ROR : SRType_RRX); } }; template struct decode_imm_shift_num { static u32 extract(u32 value) { const u32 type = T::extract(value); const u32 imm5 = N::extract(value); return imm5 || type == SRType_LSL ? imm5 : (type < SRType_ROR ? 32 : 1); } }; using decode_imm_shift_type_thumb = decode_imm_shift_type, cf, bf<6, 2>>>; using decode_imm_shift_num_thumb = decode_imm_shift_num, cf, bf<6, 2>>>; using decode_imm_shift_type_arm = decode_imm_shift_type, bf<7, 5>>; using decode_imm_shift_num_arm = decode_imm_shift_num, bf<7, 5>>; template struct it; // template<> struct it { using mask = bf<0, 4>; using first = bf<4, 4>; using skip_if = eqcf; // Skip if mask==0 }; template struct hack; // template<> struct hack { using index = bf<0, 16>; using skip_if = void; }; template<> struct hack { using index = cf, bf<0, 4>>; using skip_if = void; }; template struct mrc; // template<> struct mrc { using t = bf<12, 4>; using cp = bf<8, 4>; using opc1 = bf<21, 3>; using opc2 = bf<5, 3>; using cn = bf<16, 4>; using cm = bf<0, 4>; using skip_if = eqcf, 5>; }; template<> struct mrc : mrc { using skip_if = void; }; template<> struct mrc : mrc { using skip_if = eqcf, 5>; }; template<> struct mrc : mrc { using skip_if = void; }; template struct add_imm; // template<> struct add_imm { using d = bf<0, 3>; using n = bf<3, 3>; using set_flags = not_in_it_block; using imm32 = bf<6, 3>; using skip_if = void; }; template<> struct add_imm { using d = bf<8, 3>; using n = d; using set_flags = not_in_it_block; using imm32 = bf<0, 8>; using skip_if = void; }; template<> struct add_imm { using d = bf<8, 4>; using n = bf<16, 4>; using set_flags = from_first>; using imm32 = thumb_expand_imm; using skip_if = orf, bf<20, 1>>, eqcf>; }; template<> struct add_imm : add_imm { using add_imm::n; using set_flags = from_first>; using imm32 = imm12i38; using skip_if = orf, eqcf>; }; template<> struct add_imm { using d = bf<12, 4>; using n = bf<16, 4>; using set_flags = from_first>; using imm32 = arm_expand_imm; using skip_if = orf, notf>>, eqcf>, andf, bf<20, 1>>>; }; template struct add_reg; // template<> struct add_reg { using d = bf<0, 3>; using n = bf<3, 3>; using m = bf<6, 3>; using set_flags = not_in_it_block; using shift_t = ff; using shift_n = ff<0u>; using skip_if = void; }; template<> struct add_reg { using d = cf, bf<0, 3>>; using n = d; using m = bf<3, 4>; using set_flags = from_first>; using shift_t = ff; using shift_n = ff<0u>; using skip_if = orf, eqcf>; }; template<> struct add_reg { using d = bf<8, 4>; using n = bf<16, 4>; using m = bf<0, 4>; using set_flags = from_first>; using shift_t = decode_imm_shift_type_thumb; using shift_n = decode_imm_shift_num_thumb; using skip_if = orf, bf<20, 1>>, eqcf>; }; template<> struct add_reg : add_reg { using d = bf<12, 4>; using n = bf<16, 4>; using shift_t = decode_imm_shift_type_arm; using shift_n = decode_imm_shift_num_arm; using skip_if = orf, bf<20, 1>>, eqcf>; }; template struct add_spi; // template<> struct add_spi { using d = bf<8, 3>; using set_flags = from_first>; using imm32 = cf, ff<0u, 2>>; using skip_if = void; }; template<> struct add_spi { using d = ff<13u>; using set_flags = from_first>; using imm32 = cf, ff<0u, 2>>; using skip_if = void; }; template<> struct add_spi { using d = bf<8, 4>; using set_flags = from_first>; using imm32 = thumb_expand_imm; using skip_if = andf, bf<20, 1>>; }; template<> struct add_spi { using d = bf<8, 4>; using set_flags = from_first>; using imm32 = imm12i38; using skip_if = void; }; template<> struct add_spi { using d = bf<12, 4>; using set_flags = from_first>; using imm32 = arm_expand_imm; using skip_if = andf, bf<20, 1>>; }; template struct add_spr; // template<> struct add_spr { using d = cf, bf<0, 3>>; using m = d; using set_flags = from_first>; using shift_t = ff; using shift_n = ff<0u>; using skip_if = void; }; template<> struct add_spr { using d = ff<13u>; using m = bf<3, 4>; using set_flags = from_first>; using shift_t = ff; using shift_n = ff<0u>; using skip_if = eqcf; }; template<> struct add_spr { using d = bf<8, 4>; using m = bf<0, 4>; using set_flags = from_first>; using shift_t = decode_imm_shift_type_thumb; using shift_n = decode_imm_shift_num_thumb; using skip_if = void; }; template<> struct add_spr { using d = bf<12, 4>; using m = bf<0, 4>; using set_flags = from_first>; using shift_t = decode_imm_shift_type_arm; using shift_n = decode_imm_shift_num_arm; using skip_if = andf, bf<20, 1>>; }; template struct adc_imm; // template<> struct adc_imm : add_imm { using skip_if = void; }; template<> struct adc_imm : add_imm { using skip_if = void; }; template struct adc_reg; // template<> struct adc_reg { using d = bf<0, 3>; using n = d; using m = bf<3, 3>; using set_flags = not_in_it_block; using shift_t = ff; using shift_n = ff<0u>; using skip_if = void; }; template<> struct adc_reg : add_reg { using skip_if = void; }; template<> struct adc_reg : add_reg { using add_reg::d; using skip_if = andf, bf<20, 1>>; }; template struct adr; // template<> struct adr { using d = bf<8, 3>; using i = cf, ff<0u, 2>>; using skip_if = void; }; template<> struct adr { using d = bf<8, 4>; using i = negatef; using skip_if = void; }; template<> struct adr { using d = bf<8, 4>; using i = imm12i38; using skip_if = void; }; template<> struct adr { using d = bf<12, 4>; using i = arm_expand_imm; using skip_if = void; }; template<> struct adr { using d = bf<12, 4>; using i = negatef; using skip_if = void; }; template struct and_imm; // template<> struct and_imm { using d = bf<8, 4>; using n = bf<16, 4>; using set_flags = from_first>; using imm32 = thumb_expand_imm; using carry = thumb_expand_imm_c; using skip_if = andf, bf<20, 1>>; }; template<> struct and_imm : and_imm { using d = bf<12, 4>; using imm32 = arm_expand_imm; using carry = arm_expand_imm_c; using skip_if = andf, bf<20, 1>>; }; template struct and_reg; // template<> struct and_reg : adc_reg { using skip_if = void; }; template<> struct and_reg : adc_reg { using adc_reg::d; using skip_if = andf, bf<20, 1>>; }; template<> struct and_reg : adc_reg { using adc_reg::d; using skip_if = andf, bf<20, 1>>; }; template struct b; // template<> struct b { using imm32 = cf, ff<0u, 1>>; using cond = from_first>; using skip_if = eqcf; }; template<> struct b { using imm32 = cf, ff<0u, 1>>; using cond = from_second<>; using skip_if = void; }; template<> struct b { using imm32 = cf, bf<11, 1>, bf<13, 1>, bf<16, 6>, bf<0, 11>, ff<0u, 1>>; using cond = from_first>; using skip_if = eqcf, 7>; }; template<> struct b { using imm32 = cf, notf, bf<26, 1>>>, notf, bf<26, 1>>>, bf<16, 10>, bf<0, 11>, ff<0u, 1>>; using cond = from_second<>; using skip_if = void; }; template<> struct b { using imm32 = cf, ff<0u, 2>>; using cond = from_second<>; using skip_if = void; }; template struct bic_imm; // template<> struct bic_imm : and_imm { using skip_if = void; }; template<> struct bic_imm : and_imm { using and_imm::d; using skip_if = andf, bf<20, 1>>; }; template struct bic_reg; // template<> struct bic_reg : adc_reg { using skip_if = void; }; template<> struct bic_reg : adc_reg { using skip_if = void; }; template<> struct bic_reg : adc_reg { using adc_reg::d; using skip_if = andf, bf<20, 1>>; }; template struct bl; // template<> struct bl { using imm32 = b::imm32; using to_arm = nullary>; using skip_if = void; }; template<> struct bl { using imm32 = cf, notf, bf<26, 1>>>, notf, bf<26, 1>>>, bf<16, 10>, bf<1, 10>, ff<0u, 2>>; using to_arm = nullary>; using skip_if = void; }; template<> struct bl { using imm32 = b::imm32; using to_arm = nullary>; using skip_if = void; }; template<> struct bl { using imm32 = cf, bf<24, 1>, ff<0u, 1>>; using to_arm = nullary>; using skip_if = void; }; template struct blx; // template<> struct blx { using m = bf<3, 4>; using skip_if = void; }; template<> struct blx { using m = bf<0, 4>; using skip_if = void; }; template struct bx; // template<> struct bx : blx { using skip_if = void; }; template<> struct bx : blx { using skip_if = void; }; template struct cb_z; // template<> struct cb_z { using n = bf<0, 3>; using imm32 = cf, bf<3, 5>, ff<0u, 1>>; using nonzero = bf<11, 1>; using skip_if = void; }; template struct clz; // template<> struct clz { using d = bf<8, 4>; using m = bf<0, 4>; using skip_if = void; }; template<> struct clz { using d = bf<12, 4>; using m = bf<0, 4>; using skip_if = void; }; template struct cmp_imm; // template<> struct cmp_imm { using n = bf<8, 3>; using imm32 = bf<0, 8>; using skip_if = void; }; template<> struct cmp_imm { using n = bf<16, 4>; using imm32 = thumb_expand_imm; using skip_if = void; }; template<> struct cmp_imm { using n = bf<16, 4>; using imm32 = arm_expand_imm; using skip_if = void; }; template struct cmp_reg; // template<> struct cmp_reg { using n = bf<0, 3>; using m = bf<3, 3>; using shift_t = ff; using shift_n = ff<0u>; using skip_if = void; }; template<> struct cmp_reg : cmp_reg { using n = cf, bf<0, 3>>; using m = bf<3, 4>; using skip_if = void; }; template<> struct cmp_reg { using n = bf<16, 4>; using m = bf<0, 4>; using shift_t = decode_imm_shift_type_thumb; using shift_n = decode_imm_shift_num_thumb; using skip_if = void; }; template<> struct cmp_reg : cmp_reg { using shift_t = decode_imm_shift_type_arm; using shift_n = decode_imm_shift_num_arm; using skip_if = void; }; template struct eor_imm; // template<> struct eor_imm : and_imm { using and_imm::d; using skip_if = andf, bf<20, 1>>; }; template<> struct eor_imm : and_imm { using and_imm::d; using skip_if = andf, bf<20, 1>>; }; template struct eor_reg; // template<> struct eor_reg : adc_reg { using skip_if = void; }; template<> struct eor_reg : adc_reg { using adc_reg::d; using skip_if = andf, bf<20, 1>>; }; template<> struct eor_reg : adc_reg { using adc_reg::d; using skip_if = andf, bf<20, 1>>; }; template struct ldm; // template<> struct ldm { using n = bf<8, 3>; using registers = bf<0, 8>; using wback = ff; // TODO using skip_if = void; }; template<> struct ldm { using n = bf<16, 4>; using registers = andf, ff<0xdfffu, 16>>; // TODO using wback = bf<21, 1>; using skip_if = andf>; }; template<> struct ldm : ldm { using registers = bf<0, 16>; using skip_if = class TODO; }; template struct ldr_imm; // template<> struct ldr_imm { using t = bf<0, 3>; using n = bf<3, 3>; using imm32 = cf, ff<0u, 2>>; using index = ff; using add = ff; using wback = ff; using skip_if = void; }; template<> struct ldr_imm : ldr_imm { using t = bf<8, 3>; using n = ff<13u>; using imm32 = cf, ff<0u, 2>>; using skip_if = void; }; template<> struct ldr_imm : ldr_imm { using t = bf<12, 4>; using n = bf<16, 4>; using imm32 = bf<0, 12>; using skip_if = eqcf; }; template<> struct ldr_imm { using t = bf<12, 4>; using n = bf<16, 4>; using imm32 = bf<0, 8>; using index = bf<10, 1>; using add = bf<9, 1>; using wback = bf<8, 1>; using skip_if = orf, orf, 6>, andf, eqcf, 512 + 256 + 4>>>>; }; template<> struct ldr_imm : ldr_imm { using imm32 = bf<0, 12>; using index = bf<24, 1>; using add = bf<23, 1>; using wback = orf>, bf<21, 1>>; using skip_if = class TODO; }; template struct ldr_lit; // template<> struct ldr_lit { using t = bf<8, 3>; using imm32 = cf, ff<0u, 2>>; using add = ff; using skip_if = void; }; template<> struct ldr_lit { using t = bf<12, 4>; using imm32 = bf<0, 12>; using add = bf<23, 1>; using skip_if = void; }; template<> struct ldr_lit : ldr_lit { using skip_if = void; }; template struct ldr_reg; // template<> struct ldr_reg { using t = bf<0, 3>; using n = bf<3, 3>; using m = bf<6, 3>; using index = ff; using add = ff; using wback = ff; using shift_t = ff; using shift_n = ff<0u>; using skip_if = void; }; template<> struct ldr_reg : ldr_reg { using t = bf<12, 4>; using n = bf<16, 4>; using m = bf<0, 4>; using shift_n = bf<4, 2>; using skip_if = eqcf; }; template<> struct ldr_reg : ldr_reg { using index = bf<24, 1>; using add = bf<23, 1>; using wback = orf>, bf<21, 1>>; using shift_t = decode_imm_shift_type_arm; using shift_n = decode_imm_shift_num_arm; using skip_if = class TODO; }; template struct ldrb_imm; // template<> struct ldrb_imm : ldr_imm { using imm32 = bf<6, 5>; using skip_if = void; }; template<> struct ldrb_imm : ldr_imm { using ldr_imm::t; using ldr_imm::n; using skip_if = orf, eqcf>; }; template<> struct ldrb_imm : ldr_imm { using ldr_imm::t; using ldr_imm::n; using skip_if = orf, eqcf, 4>>, orf, eqcf, 6>>>; }; template<> struct ldrb_imm : ldr_imm { using skip_if = class TODO; }; template struct ldrb_reg; // template<> struct ldrb_reg : ldr_reg { using skip_if = void; }; template<> struct ldrb_reg : ldr_reg { using ldr_reg::t; using ldr_reg::n; using skip_if = orf, eqcf>; }; template<> struct ldrb_reg : ldr_reg { using skip_if = class TODO; }; template struct ldrd_imm; // template<> struct ldrd_imm { using t = bf<12, 4>; using t2 = bf<8, 4>; using n = bf<16, 4>; using imm32 = cf, ff<0u, 2>>; using index = bf<24, 1>; using add = bf<23, 1>; using wback = bf<21, 1>; }; template<> struct ldrd_imm : ldrd_imm { using t2 = orf, ff<1u, 4>>; // t+1 for even t using imm32 = cf, bf<0, 4>>; using wback = orf>, bf<21, 1>>; }; template struct ldrd_lit; // template<> struct ldrd_lit { using t = bf<12, 4>; using t2 = bf<8, 4>; using imm32 = cf, ff<0u, 2>>; using add = bf<23, 1>; }; template<> struct ldrd_lit : ldrd_lit { using t2 = orf, ff<1u, 4>>; // t+1 for even t using imm32 = cf, bf<0, 4>>; }; template struct ldrh_imm; // template<> struct ldrh_imm : ldr_imm { using imm32 = cf, ff<0u, 1>>; }; template<> struct ldrh_imm : ldr_imm {}; template<> struct ldrh_imm : ldr_imm {}; template<> struct ldrh_imm : ldr_imm { using imm32 = cf, bf<0, 4>>; }; template struct ldrh_reg; // template<> struct ldrh_reg : ldr_reg {}; template<> struct ldrh_reg : ldr_reg {}; template<> struct ldrh_reg : ldr_reg { using shift_t = ff; // ??? using shift_n = ff<0u>; }; template struct ldrsb_imm; // template<> struct ldrsb_imm : ldr_imm {}; template<> struct ldrsb_imm : ldr_imm {}; template<> struct ldrsb_imm : ldrh_imm {}; template struct ldrex; // template<> struct ldrex { using t = bf<12, 4>; using n = bf<16, 4>; using imm32 = cf, ff<0u, 2>>; }; template<> struct ldrex : ldrex { using imm32 = ff<0u>; // Zero offset }; template struct _shift_imm; // template struct _shift_imm { using d = bf<0, 3>; using m = bf<3, 3>; using set_flags = not_in_it_block; using shift_n = decode_imm_shift_num, bf<6, 5>>; }; template struct _shift_imm { using d = bf<8, 4>; using m = bf<0, 4>; using set_flags = from_first>; using shift_n = decode_imm_shift_num, cf, bf<6, 2>>>; }; template struct _shift_imm : _shift_imm { using d = bf<12, 4>; using shift_n = decode_imm_shift_num, bf<7, 5>>; }; template struct lsl_imm : _shift_imm {}; // template struct lsr_imm : _shift_imm {}; // template struct asr_imm : _shift_imm {}; // template struct lsl_reg; // template<> struct lsl_reg { using d = bf<0, 3>; using n = d; using m = bf<3, 3>; using set_flags = not_in_it_block; }; template<> struct lsl_reg { using d = bf<8, 4>; using n = bf<16, 4>; using m = bf<0, 4>; using set_flags = from_first>; }; template<> struct lsl_reg : lsl_reg { using d = bf<12, 4>; using n = bf<0, 4>; using m = bf<8, 4>; }; template struct lsr_reg; // template<> struct lsr_reg : lsl_reg {}; template<> struct lsr_reg : lsl_reg {}; template<> struct lsr_reg : lsl_reg {}; //template struct asr_reg; // //template<> struct asr_reg : lsl_reg {}; //template<> struct asr_reg : lsl_reg {}; //template<> struct asr_reg : lsl_reg {}; template struct mov_imm; // template<> struct mov_imm { using d = bf<8, 3>; using set_flags = not_in_it_block; using imm32 = bf<0, 8>; using carry = from_second<>; }; template<> struct mov_imm { using d = bf<8, 4>; using set_flags = from_first>; using imm32 = thumb_expand_imm; using carry = thumb_expand_imm_c; }; template<> struct mov_imm { using d = bf<8, 4>; using set_flags = from_first>; using imm32 = cf, imm12i38>; using carry = from_second<>; }; template<> struct mov_imm { using d = bf<12, 4>; using set_flags = from_first>; using imm32 = arm_expand_imm; using carry = arm_expand_imm_c; }; template<> struct mov_imm { using d = bf<12, 4>; using set_flags = from_first>; using imm32 = cf, bf<0, 12>>; using carry = from_second<>; }; template struct mov_reg; // template<> struct mov_reg { using d = cf, bf<0, 3>>; using m = bf<3, 4>; using set_flags = from_first>; }; template<> struct mov_reg { using d = bf<0, 3>; using m = bf<3, 3>; using set_flags = from_first>; }; template<> struct mov_reg { using d = bf<8, 4>; using m = bf<0, 4>; using set_flags = from_first>; }; template<> struct mov_reg : mov_reg { using d = bf<12, 4>; }; template struct movt; // template<> struct movt { using d = bf<8, 4>; using imm16 = cf, imm12i38>; }; template<> struct movt { using d = bf<12, 4>; using imm16 = cf, bf<0, 12>>; }; template struct mul; // template<> struct mul { using d = bf<0, 3>; using n = bf<3, 3>; using m = d; using set_flags = not_in_it_block; }; template<> struct mul { using d = bf<8, 4>; using n = bf<16, 4>; using m = bf<0, 4>; using set_flags = from_first>; }; template<> struct mul { using d = bf<16, 4>; using n = bf<0, 4>; using m = bf<8, 4>; using set_flags = from_first>; }; template struct mvn_imm; // template<> struct mvn_imm : mov_imm {}; template<> struct mvn_imm : mov_imm {}; template struct mvn_reg; // template<> struct mvn_reg { using d = bf<0, 3>; using m = bf<3, 3>; using set_flags = not_in_it_block; using shift_t = ff; using shift_n = ff<0u>; }; template<> struct mvn_reg { using d = bf<8, 4>; using m = bf<0, 4>; using set_flags = from_first>; using shift_t = decode_imm_shift_type_thumb; using shift_n = decode_imm_shift_num_thumb; }; template<> struct mvn_reg : mvn_reg { using d = bf<12, 4>; using shift_t = decode_imm_shift_type_arm; using shift_n = decode_imm_shift_num_arm; }; template struct orr_imm; // template<> struct orr_imm : and_imm {}; template<> struct orr_imm : and_imm {}; template struct orr_reg; // template<> struct orr_reg : adc_reg {}; template<> struct orr_reg : adc_reg {}; template<> struct orr_reg : adc_reg {}; template struct pop; // template<> struct pop { using registers = cf, ff<0u, 7>, bf<0, 8>>; }; template<> struct pop { using registers = andf, ff<0xdfffu, 16>>; }; template<> struct pop { using registers = shlf, bf<12, 4>>; // 1 << Rt }; template<> struct pop { using registers = bf<0, 16>; }; template<> struct pop : pop { }; template struct push; // template<> struct push { using registers = cf, ff<0u, 6>, bf<0, 8>>; }; template<> struct push { using registers = andf, ff<0x5fffu, 16>>; }; template<> struct push : pop {}; template<> struct push : pop {}; template<> struct push : pop {}; template struct rev; // template<> struct rev { using d = bf<0, 3>; using m = bf<3, 3>; }; template<> struct rev : clz {}; template<> struct rev : clz {}; template struct ror_imm; // template<> struct ror_imm : _shift_imm {}; template<> struct ror_imm : _shift_imm {}; template struct ror_reg; // template<> struct ror_reg : lsl_reg {}; template<> struct ror_reg : lsl_reg {}; template<> struct ror_reg : lsl_reg {}; template struct rsb_imm; // template<> struct rsb_imm : add_imm { using imm32 = ff<0u>; }; template<> struct rsb_imm : add_imm {}; template<> struct rsb_imm : add_imm {}; template struct stm; // template<> struct stm : ldm { using wback = ff; }; template<> struct stm : ldm { using registers = andf, ff<0x5fffu, 16>>; // TODO }; template<> struct stm : ldm {}; template struct str_imm; // template<> struct str_imm : ldr_imm {}; template<> struct str_imm : ldr_imm {}; template<> struct str_imm : ldr_imm {}; template<> struct str_imm : ldr_imm {}; template<> struct str_imm : ldr_imm {}; template struct str_reg; // template<> struct str_reg : ldr_reg {}; template<> struct str_reg : ldr_reg {}; template<> struct str_reg : ldr_reg {}; template struct strb_imm; // template<> struct strb_imm : ldrb_imm {}; template<> struct strb_imm : ldrb_imm {}; template<> struct strb_imm : ldrb_imm {}; template<> struct strb_imm : ldrb_imm {}; template struct strb_reg; // template<> struct strb_reg : ldrb_reg {}; template<> struct strb_reg : ldrb_reg {}; template<> struct strb_reg : ldrb_reg {}; template struct strd_imm; // template<> struct strd_imm : ldrd_imm {}; template<> struct strd_imm : ldrd_imm {}; template struct strh_imm; // template<> struct strh_imm : ldrh_imm {}; template<> struct strh_imm : ldrh_imm {}; template<> struct strh_imm : ldrh_imm {}; template<> struct strh_imm : ldrh_imm {}; template struct strh_reg; // template<> struct strh_reg : ldrh_reg {}; template<> struct strh_reg : ldrh_reg {}; template<> struct strh_reg : ldrh_reg {}; template struct strex; // template<> struct strex { using d = bf<8, 4>; using t = bf<12, 4>; using n = bf<16, 4>; using imm32 = cf, ff<0u, 2>>; }; template<> struct strex { using d = bf<12, 4>; using t = bf<0, 4>; using n = bf<16, 4>; using imm32 = ff<0u>; // Zero offset }; template struct sub_imm; // template<> struct sub_imm : add_imm {}; template<> struct sub_imm : add_imm {}; template<> struct sub_imm : add_imm {}; template<> struct sub_imm : add_imm {}; template<> struct sub_imm : add_imm {}; template struct sub_reg; // template<> struct sub_reg : add_reg {}; template<> struct sub_reg : add_reg {}; template<> struct sub_reg : add_reg {}; template struct sub_spi; // template<> struct sub_spi : add_spi {}; template<> struct sub_spi : add_spi {}; template<> struct sub_spi : add_spi {}; template<> struct sub_spi : add_spi {}; template struct tst_imm; // template<> struct tst_imm { using n = bf<16, 4>; using imm32 = thumb_expand_imm; using carry = thumb_expand_imm_c; }; template<> struct tst_imm { using n = bf<16, 4>; using imm32 = arm_expand_imm; using carry = arm_expand_imm_c; }; template struct umull; // template<> struct umull { using d0 = bf<12, 4>; using d1 = bf<8, 4>; using n = bf<16, 4>; using m = bf<0, 4>; using set_flags = from_first>; }; template<> struct umull { using d0 = bf<12, 4>; using d1 = bf<16, 4>; using n = bf<0, 4>; using m = bf<8, 4>; using set_flags = from_first>; }; template struct uxtb; // template<> struct uxtb { using d = bf<0, 3>; using m = bf<3, 3>; using rotation = ff<0u, 5>; }; template<> struct uxtb { using d = bf<8, 4>; using m = bf<0, 4>; using rotation = cf, ff<0u, 3>>; }; template<> struct uxtb { using d = bf<12, 4>; using m = bf<0, 4>; using rotation = cf, ff<0u, 3>>; }; } // TODO #define SKIP_IF(cond) [](u32 c) -> bool { return cond; } #define BF(start, end) ((c << (31 - (end))) >> ((start) + 31 - (end))) #define BT(pos) ((c >> (pos)) & 1) // ARMv7 decoder object. D provides function templates. T is function pointer type returned. template class arm_decoder { // Fast lookup table for 2-byte Thumb instructions std::array m_op16_table{}; // Fix for std::initializer_list (???) static inline T fix(T ptr) { return ptr; } struct instruction_info { u32 mask; u32 code; T pointer; bool(*skip)(u32 code); // TODO (if not nullptr, must be specified yet) bool match(u32 op) const { return (op & mask) == code && (!skip || !skip(op)); } }; // Lookup table for 4-byte Thumb instructions (points to the best appropriate position in sorted vector) std::array::const_iterator, 0x10000> m_op32_table{}; std::vector m_op16_list; std::vector m_op32_list; std::vector m_arm_list; public: arm_decoder() { using namespace arm_code::arm_encoding_alias; m_op16_list.assign( { { 0xffc0, 0x4140, fix(&D:: template ADC_REG), nullptr }, { 0xfe00, 0x1c00, fix(&D:: template ADD_IMM), nullptr }, { 0xf800, 0x3000, fix(&D:: template ADD_IMM), nullptr }, { 0xfe00, 0x1800, fix(&D:: template ADD_REG), nullptr }, { 0xff00, 0x4400, fix(&D:: template ADD_REG), SKIP_IF((c & 0x87) == 0x85 || BF(3, 6) == 13) }, { 0xf800, 0xa800, fix(&D:: template ADD_SPI), nullptr }, { 0xff80, 0xb000, fix(&D:: template ADD_SPI), nullptr }, { 0xff78, 0x4468, fix(&D:: template ADD_SPR), nullptr }, { 0xff87, 0x4485, fix(&D:: template ADD_SPR), SKIP_IF(BF(3, 6) == 13) }, { 0xf800, 0xa000, fix(&D:: template ADR), nullptr }, { 0xffc0, 0x4000, fix(&D:: template AND_REG), nullptr }, { 0xf800, 0x1000, fix(&D:: template ASR_IMM), nullptr }, { 0xffc0, 0x4100, fix(&D:: template ASR_REG), nullptr }, { 0xf000, 0xd000, fix(&D:: template B), SKIP_IF(BF(9, 11) == 0x7) }, { 0xf800, 0xe000, fix(&D:: template B), nullptr }, { 0xffc0, 0x4380, fix(&D:: template BIC_REG), nullptr }, { 0xff00, 0xbe00, fix(&D:: template BKPT), nullptr }, { 0xff80, 0x4780, fix(&D:: template BLX), nullptr }, { 0xff87, 0x4700, fix(&D:: template BX), nullptr }, { 0xf500, 0xb100, fix(&D:: template CB_Z), nullptr }, { 0xffc0, 0x42c0, fix(&D:: template CMN_REG), nullptr }, { 0xf800, 0x2800, fix(&D:: template CMP_IMM), nullptr }, { 0xffc0, 0x4280, fix(&D:: template CMP_REG), nullptr }, { 0xff00, 0x4500, fix(&D:: template CMP_REG), nullptr }, { 0xffc0, 0x4040, fix(&D:: template EOR_REG), nullptr }, { 0xff00, 0xbf00, fix(&D:: template IT), SKIP_IF(BF(0, 3) == 0) }, { 0xf800, 0xc800, fix(&D:: template LDM), nullptr }, { 0xf800, 0x6800, fix(&D:: template LDR_IMM), nullptr }, { 0xf800, 0x9800, fix(&D:: template LDR_IMM), nullptr }, { 0xf800, 0x4800, fix(&D:: template LDR_LIT), nullptr }, { 0xfe00, 0x5800, fix(&D:: template LDR_REG), nullptr }, { 0xf800, 0x7800, fix(&D:: template LDRB_IMM) }, { 0xfe00, 0x5c00, fix(&D:: template LDRB_REG) }, { 0xf800, 0x8800, fix(&D:: template LDRH_IMM) }, { 0xfe00, 0x5a00, fix(&D:: template LDRH_REG) }, { 0xfe00, 0x5600, fix(&D:: template LDRSB_REG) }, { 0xfe00, 0x5e00, fix(&D:: template LDRSH_REG) }, { 0xf800, 0x0000, fix(&D:: template LSL_IMM) }, { 0xffc0, 0x4080, fix(&D:: template LSL_REG) }, { 0xf800, 0x0800, fix(&D:: template LSR_IMM) }, { 0xffc0, 0x40c0, fix(&D:: template LSR_REG) }, { 0xf800, 0x2000, fix(&D:: template MOV_IMM) }, { 0xff00, 0x4600, fix(&D:: template MOV_REG) }, { 0xffc0, 0x0000, fix(&D:: template MOV_REG) }, { 0xffc0, 0x4340, fix(&D:: template MUL) }, { 0xffc0, 0x43c0, fix(&D:: template MVN_REG) }, { 0xffff, 0xbf00, fix(&D:: template NOP) }, { 0xffc0, 0x4300, fix(&D:: template ORR_REG) }, { 0xfe00, 0xbc00, fix(&D:: template POP) }, { 0xfe00, 0xb400, fix(&D:: template PUSH) }, { 0xffc0, 0xba00, fix(&D:: template REV) }, { 0xffc0, 0xba40, fix(&D:: template REV16) }, { 0xffc0, 0xbac0, fix(&D:: template REVSH) }, { 0xffc0, 0x41c0, fix(&D:: template ROR_REG) }, { 0xffc0, 0x4240, fix(&D:: template RSB_IMM) }, { 0xffc0, 0x4180, fix(&D:: template SBC_REG) }, { 0xf800, 0xc000, fix(&D:: template STM) }, { 0xf800, 0x6000, fix(&D:: template STR_IMM) }, { 0xf800, 0x9000, fix(&D:: template STR_IMM) }, { 0xfe00, 0x5000, fix(&D:: template STR_REG) }, { 0xf800, 0x7000, fix(&D:: template STRB_IMM) }, { 0xfe00, 0x5400, fix(&D:: template STRB_REG) }, { 0xf800, 0x8000, fix(&D:: template STRH_IMM) }, { 0xfe00, 0x5200, fix(&D:: template STRH_REG) }, { 0xfe00, 0x1e00, fix(&D:: template SUB_IMM) }, { 0xf800, 0x3800, fix(&D:: template SUB_IMM) }, { 0xfe00, 0x1a00, fix(&D:: template SUB_REG) }, { 0xff80, 0xb080, fix(&D:: template SUB_SPI) }, { 0xff00, 0xdf00, fix(&D:: template SVC) }, { 0xffc0, 0xb240, fix(&D:: template SXTB) }, { 0xffc0, 0xb200, fix(&D:: template SXTH) }, { 0xffc0, 0x4200, fix(&D:: template TST_REG) }, { 0xffc0, 0xb2c0, fix(&D:: template UXTB) }, { 0xffc0, 0xb280, fix(&D:: template UXTH) }, { 0xffff, 0xbf20, fix(&D:: template WFE) }, { 0xffff, 0xbf30, fix(&D:: template WFI) }, { 0xffff, 0xbf10, fix(&D:: template YIELD) }, }); m_op32_list.assign( { { 0xffff0000, 0xf8700000, fix(&D:: template HACK), nullptr }, // "Undefined" Thumb opcode used { 0xfbe08000, 0xf1400000, fix(&D:: template ADC_IMM), nullptr }, { 0xffe08000, 0xeb400000, fix(&D:: template ADC_REG), nullptr }, { 0xfbe08000, 0xf1000000, fix(&D:: template ADD_IMM), SKIP_IF((BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13) }, { 0xfbf08000, 0xf2000000, fix(&D:: template ADD_IMM), SKIP_IF((BF(16, 19) & 13) == 13) }, { 0xffe08000, 0xeb000000, fix(&D:: template ADD_REG), SKIP_IF((BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13) }, { 0xfbef8000, 0xf10d0000, fix(&D:: template ADD_SPI), SKIP_IF(BF(8, 11) == 15 && BT(20)) }, { 0xfbff8000, 0xf20d0000, fix(&D:: template ADD_SPI), nullptr }, { 0xffef8000, 0xeb0d0000, fix(&D:: template ADD_SPR), nullptr }, { 0xfbff8000, 0xf2af0000, fix(&D:: template ADR), nullptr }, { 0xfbff8000, 0xf20f0000, fix(&D:: template ADR), nullptr }, { 0xfbe08000, 0xf0000000, fix(&D:: template AND_IMM), SKIP_IF(BF(8, 11) == 15 && BT(20)) }, { 0xffe08000, 0xea000000, fix(&D:: template AND_REG), SKIP_IF(BF(8, 11) == 15 && BT(20)) }, { 0xffef8030, 0xea4f0020, fix(&D:: template ASR_IMM), nullptr }, { 0xffe0f0f0, 0xfa40f000, fix(&D:: template ASR_REG), nullptr }, { 0xf800d000, 0xf0008000, fix(&D:: template B), SKIP_IF(BF(23, 25) == 0x7) }, { 0xf800d000, 0xf0009000, fix(&D:: template B), nullptr }, { 0xffff8020, 0xf36f0000, fix(&D:: template BFC), nullptr }, { 0xfff08020, 0xf3600000, fix(&D:: template BFI), SKIP_IF(BF(16, 19) == 15) }, { 0xfbe08000, 0xf0200000, fix(&D:: template BIC_IMM), nullptr }, { 0xffe08000, 0xea200000, fix(&D:: template BIC_REG), nullptr }, { 0xf800d000, 0xf000d000, fix(&D:: template BL), nullptr }, { 0xf800c001, 0xf000c000, fix(&D:: template BL), nullptr }, { 0xfff0f0f0, 0xfab0f080, fix(&D:: template CLZ), nullptr }, { 0xfbf08f00, 0xf1100f00, fix(&D:: template CMN_IMM), nullptr }, { 0xfff08f00, 0xeb100f00, fix(&D:: template CMN_REG), nullptr }, { 0xfbf08f00, 0xf1b00f00, fix(&D:: template CMP_IMM), nullptr }, { 0xfff08f00, 0xebb00f00, fix(&D:: template CMP_REG), nullptr }, { 0xfffffff0, 0xf3af80f0, fix(&D:: template DBG), nullptr }, { 0xfffffff0, 0xf3bf8f50, fix(&D:: template DMB), nullptr }, { 0xfffffff0, 0xf3bf8f40, fix(&D:: template DSB), nullptr }, { 0xfbe08000, 0xf0800000, fix(&D:: template EOR_IMM), SKIP_IF(BF(8, 11) == 15 && BT(20)) }, { 0xffe08000, 0xea800000, fix(&D:: template EOR_REG), SKIP_IF(BF(8, 11) == 15 && BT(20)) }, { 0xffd02000, 0xe8900000, fix(&D:: template LDM), SKIP_IF(BT(21) && BF(16, 19) == 13) }, { 0xffd02000, 0xe9100000, fix(&D:: template LDMDB), nullptr }, { 0xfff00000, 0xf8d00000, fix(&D:: template LDR_IMM), SKIP_IF(BF(16, 19) == 15) }, { 0xfff00800, 0xf8500800, fix(&D:: template LDR_IMM), SKIP_IF(BF(16, 19) == 15 || BF(8, 10) == 6 || (c & 0xf07ff) == 0xd0304 || (c & 0x500) == 0) }, { 0xff7f0000, 0xf85f0000, fix(&D:: template LDR_LIT), nullptr }, { 0xfff00fc0, 0xf8500000, fix(&D:: template LDR_REG), SKIP_IF(BF(16, 19) == 15) }, { 0xfff00000, 0xf8900000, fix(&D:: template LDRB_IMM) }, { 0xfff00800, 0xf8100800, fix(&D:: template LDRB_IMM) }, { 0xff7f0000, 0xf81f0000, fix(&D:: template LDRB_LIT) }, { 0xfff00fc0, 0xf8100000, fix(&D:: template LDRB_REG) }, { 0xfe500000, 0xe8500000, fix(&D:: template LDRD_IMM), SKIP_IF((!BT(21) && !BT(24)) || BF(16, 19) == 15) }, { 0xfe7f0000, 0xe85f0000, fix(&D:: template LDRD_LIT) }, { 0xfff00f00, 0xe8500f00, fix(&D:: template LDREX) }, { 0xfff00fff, 0xe8d00f4f, fix(&D:: template LDREXB) }, { 0xfff000ff, 0xe8d0007f, fix(&D:: template LDREXD) }, { 0xfff00fff, 0xe8d00f5f, fix(&D:: template LDREXH) }, { 0xfff00000, 0xf8b00000, fix(&D:: template LDRH_IMM) }, { 0xfff00800, 0xf8300800, fix(&D:: template LDRH_IMM) }, { 0xff7f0000, 0xf83f0000, fix(&D:: template LDRH_LIT) }, { 0xfff00fc0, 0xf8300000, fix(&D:: template LDRH_REG) }, { 0xfff00000, 0xf9900000, fix(&D:: template LDRSB_IMM) }, { 0xfff00800, 0xf9100800, fix(&D:: template LDRSB_IMM) }, { 0xff7f0000, 0xf91f0000, fix(&D:: template LDRSB_LIT) }, { 0xfff00fc0, 0xf9100000, fix(&D:: template LDRSB_REG) }, { 0xfff00000, 0xf9b00000, fix(&D:: template LDRSH_IMM) }, { 0xfff00800, 0xf9300800, fix(&D:: template LDRSH_IMM) }, { 0xff7f0000, 0xf93f0000, fix(&D:: template LDRSH_LIT) }, { 0xfff00fc0, 0xf9300000, fix(&D:: template LDRSH_REG) }, { 0xffef8030, 0xea4f0000, fix(&D:: template LSL_IMM) }, { 0xffe0f0f0, 0xfa00f000, fix(&D:: template LSL_REG) }, { 0xffef8030, 0xea4f0010, fix(&D:: template LSR_IMM) }, { 0xffe0f0f0, 0xfa20f000, fix(&D:: template LSR_REG) }, { 0xfff000f0, 0xfb000000, fix(&D:: template MLA), SKIP_IF(BF(12, 15) == 15) }, { 0xfff000f0, 0xfb000010, fix(&D:: template MLS) }, { 0xfbef8000, 0xf04f0000, fix(&D:: template MOV_IMM) }, { 0xfbf08000, 0xf2400000, fix(&D:: template MOV_IMM) }, { 0xffeff0f0, 0xea4f0000, fix(&D:: template MOV_REG) }, { 0xfbf08000, 0xf2c00000, fix(&D:: template MOVT) }, { 0xff100010, 0xee100010, fix(&D:: template MRC_) }, { 0xff100010, 0xfe100010, fix(&D:: template MRC_) }, { 0xfffff0ff, 0xf3ef8000, fix(&D:: template MRS) }, { 0xfff0f3ff, 0xf3808000, fix(&D:: template MSR_REG) }, { 0xfff0f0f0, 0xfb00f000, fix(&D:: template MUL) }, { 0xfbef8000, 0xf06f0000, fix(&D:: template MVN_IMM) }, { 0xffef8000, 0xea6f0000, fix(&D:: template MVN_REG) }, { 0xffffffff, 0xf3af8000, fix(&D:: template NOP) }, { 0xfbe08000, 0xf0600000, fix(&D:: template ORN_IMM) }, { 0xffe08000, 0xea600000, fix(&D:: template ORN_REG) }, { 0xfbe08000, 0xf0400000, fix(&D:: template ORR_IMM) }, { 0xffe08000, 0xea400000, fix(&D:: template ORR_REG), SKIP_IF(BF(16, 19) == 15) }, { 0xfff08010, 0xeac00000, fix(&D:: template PKH) }, { 0xffff0000, 0xe8bd0000, fix(&D:: template POP) }, { 0xffff0fff, 0xf85d0b04, fix(&D:: template POP) }, { 0xffff0000, 0xe92d0000, fix(&D:: template PUSH) }, // had an error in arch ref { 0xffff0fff, 0xf84d0d04, fix(&D:: template PUSH) }, { 0xfff0f0f0, 0xfa80f080, fix(&D:: template QADD) }, { 0xfff0f0f0, 0xfa90f010, fix(&D:: template QADD16) }, { 0xfff0f0f0, 0xfa80f010, fix(&D:: template QADD8) }, { 0xfff0f0f0, 0xfaa0f010, fix(&D:: template QASX) }, { 0xfff0f0f0, 0xfa80f090, fix(&D:: template QDADD) }, { 0xfff0f0f0, 0xfa80f0b0, fix(&D:: template QDSUB) }, { 0xfff0f0f0, 0xfae0f010, fix(&D:: template QSAX) }, { 0xfff0f0f0, 0xfa80f0a0, fix(&D:: template QSUB) }, { 0xfff0f0f0, 0xfad0f010, fix(&D:: template QSUB16) }, { 0xfff0f0f0, 0xfac0f010, fix(&D:: template QSUB8) }, { 0xfff0f0f0, 0xfa90f0a0, fix(&D:: template RBIT) }, { 0xfff0f0f0, 0xfa90f080, fix(&D:: template REV) }, { 0xfff0f0f0, 0xfa90f090, fix(&D:: template REV16) }, { 0xfff0f0f0, 0xfa90f0b0, fix(&D:: template REVSH) }, { 0xffef8030, 0xea4f0030, fix(&D:: template ROR_IMM) }, { 0xffe0f0f0, 0xfa60f000, fix(&D:: template ROR_REG) }, { 0xffeff0f0, 0xea4f0030, fix(&D:: template RRX) }, { 0xfbe08000, 0xf1c00000, fix(&D:: template RSB_IMM) }, { 0xffe08000, 0xebc00000, fix(&D:: template RSB_REG) }, { 0xfff0f0f0, 0xfa90f000, fix(&D:: template SADD16) }, { 0xfff0f0f0, 0xfa80f000, fix(&D:: template SADD8) }, { 0xfff0f0f0, 0xfaa0f000, fix(&D:: template SASX) }, { 0xfbe08000, 0xf1600000, fix(&D:: template SBC_IMM) }, { 0xffe08000, 0xeb600000, fix(&D:: template SBC_REG) }, { 0xfff08020, 0xf3400000, fix(&D:: template SBFX) }, { 0xfff0f0f0, 0xfb90f0f0, fix(&D:: template SDIV) }, // ??? { 0xfff0f0f0, 0xfaa0f080, fix(&D:: template SEL) }, { 0xfff0f0f0, 0xfa90f020, fix(&D:: template SHADD16) }, { 0xfff0f0f0, 0xfa80f020, fix(&D:: template SHADD8) }, { 0xfff0f0f0, 0xfaa0f020, fix(&D:: template SHASX) }, { 0xfff0f0f0, 0xfae0f020, fix(&D:: template SHSAX) }, { 0xfff0f0f0, 0xfad0f020, fix(&D:: template SHSUB16) }, { 0xfff0f0f0, 0xfac0f020, fix(&D:: template SHSUB8) }, { 0xfff000c0, 0xfb100000, fix(&D:: template SMLA__) }, { 0xfff000e0, 0xfb200000, fix(&D:: template SMLAD) }, { 0xfff000f0, 0xfbc00000, fix(&D:: template SMLAL) }, { 0xfff000c0, 0xfbc00080, fix(&D:: template SMLAL__) }, { 0xfff000e0, 0xfbc000c0, fix(&D:: template SMLALD) }, { 0xfff000e0, 0xfb300000, fix(&D:: template SMLAW_) }, { 0xfff000e0, 0xfb400000, fix(&D:: template SMLSD) }, { 0xfff000e0, 0xfbd000c0, fix(&D:: template SMLSLD) }, { 0xfff000e0, 0xfb500000, fix(&D:: template SMMLA) }, { 0xfff000e0, 0xfb600000, fix(&D:: template SMMLS) }, { 0xfff0f0e0, 0xfb50f000, fix(&D:: template SMMUL) }, { 0xfff0f0e0, 0xfb20f000, fix(&D:: template SMUAD) }, { 0xfff0f0c0, 0xfb10f000, fix(&D:: template SMUL__) }, { 0xfff000f0, 0xfb800000, fix(&D:: template SMULL) }, { 0xfff0f0e0, 0xfb30f000, fix(&D:: template SMULW_) }, { 0xfff0f0e0, 0xfb40f000, fix(&D:: template SMUSD) }, { 0xffd08020, 0xf3000000, fix(&D:: template SSAT) }, { 0xfff0f0e0, 0xf3200000, fix(&D:: template SSAT16) }, { 0xfff0f0f0, 0xfae0f000, fix(&D:: template SSAX) }, { 0xfff0f0f0, 0xfad0f000, fix(&D:: template SSUB16) }, { 0xfff0f0f0, 0xfac0f000, fix(&D:: template SSUB8) }, { 0xffd0a000, 0xe8800000, fix(&D:: template STM) }, { 0xffd0a000, 0xe9000000, fix(&D:: template STMDB) }, { 0xfff00000, 0xf8c00000, fix(&D:: template STR_IMM) }, { 0xfff00800, 0xf8400800, fix(&D:: template STR_IMM) }, { 0xfff00fc0, 0xf8400000, fix(&D:: template STR_REG) }, { 0xfff00000, 0xf8800000, fix(&D:: template STRB_IMM) }, { 0xfff00800, 0xf8000800, fix(&D:: template STRB_IMM) }, { 0xfff00fc0, 0xf8000000, fix(&D:: template STRB_REG) }, { 0xfe500000, 0xe8400000, fix(&D:: template STRD_IMM), SKIP_IF(!BT(21) && !BT(24)) }, { 0xfff00000, 0xe8400000, fix(&D:: template STREX) }, { 0xfff00ff0, 0xe8c00f40, fix(&D:: template STREXB) }, { 0xfff000f0, 0xe8c00070, fix(&D:: template STREXD) }, { 0xfff00ff0, 0xe8c00f50, fix(&D:: template STREXH) }, { 0xfff00000, 0xf8a00000, fix(&D:: template STRH_IMM) }, { 0xfff00800, 0xf8200800, fix(&D:: template STRH_IMM) }, { 0xfff00fc0, 0xf8200000, fix(&D:: template STRH_REG) }, { 0xfbe08000, 0xf1a00000, fix(&D:: template SUB_IMM), SKIP_IF((BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13) }, { 0xfbf08000, 0xf2a00000, fix(&D:: template SUB_IMM) }, { 0xffe08000, 0xeba00000, fix(&D:: template SUB_REG), SKIP_IF((BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13) }, { 0xfbef8000, 0xf1ad0000, fix(&D:: template SUB_SPI) }, { 0xfbff8000, 0xf2ad0000, fix(&D:: template SUB_SPI) }, { 0xffef8000, 0xebad0000, fix(&D:: template SUB_SPR) }, { 0xfff0f0c0, 0xfa40f080, fix(&D:: template SXTAB) }, { 0xfff0f0c0, 0xfa20f080, fix(&D:: template SXTAB16) }, { 0xfff0f0c0, 0xfa00f080, fix(&D:: template SXTAH) }, { 0xfffff0c0, 0xfa4ff080, fix(&D:: template SXTB) }, { 0xfffff0c0, 0xfa2ff080, fix(&D:: template SXTB16) }, { 0xfffff0c0, 0xfa0ff080, fix(&D:: template SXTH) }, { 0xfff0ffe0, 0xe8d0f000, fix(&D:: template TB_) }, { 0xfbf08f00, 0xf0900f00, fix(&D:: template TEQ_IMM) }, { 0xfff08f00, 0xea900f00, fix(&D:: template TEQ_REG) }, { 0xfbf08f00, 0xf0100f00, fix(&D:: template TST_IMM) }, { 0xfff08f00, 0xea100f00, fix(&D:: template TST_REG) }, { 0xfff0f0f0, 0xfa90f040, fix(&D:: template UADD16) }, { 0xfff0f0f0, 0xfa80f040, fix(&D:: template UADD8) }, { 0xfff0f0f0, 0xfaa0f040, fix(&D:: template UASX) }, { 0xfff08020, 0xf3c00000, fix(&D:: template UBFX) }, { 0xfff0f0f0, 0xfbb0f0f0, fix(&D:: template UDIV) }, // ??? { 0xfff0f0f0, 0xfa90f060, fix(&D:: template UHADD16) }, { 0xfff0f0f0, 0xfa80f060, fix(&D:: template UHADD8) }, { 0xfff0f0f0, 0xfaa0f060, fix(&D:: template UHASX) }, { 0xfff0f0f0, 0xfae0f060, fix(&D:: template UHSAX) }, { 0xfff0f0f0, 0xfad0f060, fix(&D:: template UHSUB16) }, { 0xfff0f0f0, 0xfac0f060, fix(&D:: template UHSUB8) }, { 0xfff000f0, 0xfbe00060, fix(&D:: template UMAAL) }, { 0xfff000f0, 0xfbe00000, fix(&D:: template UMLAL) }, { 0xfff000f0, 0xfba00000, fix(&D:: template UMULL) }, { 0xfff0f0f0, 0xfa90f050, fix(&D:: template UQADD16) }, { 0xfff0f0f0, 0xfa80f050, fix(&D:: template UQADD8) }, { 0xfff0f0f0, 0xfaa0f050, fix(&D:: template UQASX) }, { 0xfff0f0f0, 0xfae0f050, fix(&D:: template UQSAX) }, { 0xfff0f0f0, 0xfad0f050, fix(&D:: template UQSUB16) }, { 0xfff0f0f0, 0xfac0f050, fix(&D:: template UQSUB8) }, { 0xfff0f0f0, 0xfb70f000, fix(&D:: template USAD8) }, { 0xfff000f0, 0xfb700000, fix(&D:: template USADA8) }, { 0xffd08020, 0xf3800000, fix(&D:: template USAT) }, { 0xfff0f0e0, 0xf3a00000, fix(&D:: template USAT16) }, { 0xfff0f0f0, 0xfae0f040, fix(&D:: template USAX) }, { 0xfff0f0f0, 0xfad0f040, fix(&D:: template USUB16) }, { 0xfff0f0f0, 0xfac0f040, fix(&D:: template USUB8) }, { 0xfff0f0c0, 0xfa50f080, fix(&D:: template UXTAB), SKIP_IF(BF(16, 19) == 15) }, { 0xfff0f0c0, 0xfa30f080, fix(&D:: template UXTAB16) }, { 0xfff0f0c0, 0xfa10f080, fix(&D:: template UXTAH) }, { 0xfffff0c0, 0xfa5ff080, fix(&D:: template UXTB) }, { 0xfffff0c0, 0xfa3ff080, fix(&D:: template UXTB16) }, { 0xfffff0c0, 0xfa1ff080, fix(&D:: template UXTH) }, { 0xef800f10, 0xef000710, fix(&D:: template VABA_) }, { 0xef800f50, 0xef800500, fix(&D:: template VABA_) }, { 0xef800f10, 0xef000700, fix(&D:: template VABD_) }, { 0xef800f50, 0xef800700, fix(&D:: template VABD_) }, { 0xffa00f10, 0xff200d00, fix(&D:: template VABD_FP) }, { 0xffb30b90, 0xffb10300, fix(&D:: template VABS) }, { 0xffbf0ed0, 0xeeb00ac0, fix(&D:: template VABS) }, { 0xff800f10, 0xff000e10, fix(&D:: template VAC__) }, { 0xff800f10, 0xef000800, fix(&D:: template VADD) }, { 0xffa00f10, 0xef000d00, fix(&D:: template VADD_FP) }, { 0xffb00e50, 0xee300a00, fix(&D:: template VADD_FP) }, { 0xff800f50, 0xef800400, fix(&D:: template VADDHN) }, { 0xef800e50, 0xef800000, fix(&D:: template VADD_) }, { 0xffb00f10, 0xef000110, fix(&D:: template VAND) }, { 0xefb800b0, 0xef800030, fix(&D:: template VBIC_IMM) }, { 0xffb00f10, 0xef100110, fix(&D:: template VBIC_REG) }, { 0xff800f10, 0xff000110, fix(&D:: template VB__) }, { 0xff800f10, 0xff000810, fix(&D:: template VCEQ_REG) }, { 0xffa00f10, 0xef000e00, fix(&D:: template VCEQ_REG) }, { 0xffb30b90, 0xffb10100, fix(&D:: template VCEQ_ZERO) }, { 0xef800f10, 0xef000310, fix(&D:: template VCGE_REG) }, { 0xffa00f10, 0xff000e00, fix(&D:: template VCGE_REG) }, { 0xffb30b90, 0xffb10080, fix(&D:: template VCGE_ZERO) }, { 0xef800f10, 0xef000300, fix(&D:: template VCGT_REG) }, { 0xffa00f10, 0xff200e00, fix(&D:: template VCGT_REG) }, { 0xffb30b90, 0xffb10000, fix(&D:: template VCGT_ZERO) }, { 0xffb30b90, 0xffb10180, fix(&D:: template VCLE_ZERO) }, { 0xffb30f90, 0xffb00400, fix(&D:: template VCLS) }, { 0xffb30b90, 0xffb10200, fix(&D:: template VCLT_ZERO) }, { 0xffb30f90, 0xffb00480, fix(&D:: template VCLZ) }, { 0xffbf0e50, 0xeeb40a40, fix(&D:: template VCMP_) }, { 0xffbf0e7f, 0xeeb50a40, fix(&D:: template VCMP_) }, { 0xffb30f90, 0xffb00500, fix(&D:: template VCNT) }, { 0xffb30e10, 0xffb30600, fix(&D:: template VCVT_FIA) }, { 0xffb80e50, 0xeeb80a40, fix(&D:: template VCVT_FIF) }, { 0xef800e90, 0xef800e10, fix(&D:: template VCVT_FFA) }, { 0xffba0e50, 0xeeba0a40, fix(&D:: template VCVT_FFF) }, { 0xffbf0ed0, 0xeeb70ac0, fix(&D:: template VCVT_DF) }, { 0xffb30ed0, 0xffb20600, fix(&D:: template VCVT_HFA) }, { 0xffbe0f50, 0xeeb20a40, fix(&D:: template VCVT_HFF) }, { 0xffb00e50, 0xee800a00, fix(&D:: template VDIV) }, { 0xffb00f90, 0xffb00c00, fix(&D:: template VDUP_S) }, { 0xff900f5f, 0xee800b10, fix(&D:: template VDUP_R) }, { 0xffb00f10, 0xff000110, fix(&D:: template VEOR) }, { 0xffb00010, 0xefb00000, fix(&D:: template VEXT) }, { 0xef800b10, 0xef000000, fix(&D:: template VHADDSUB) }, { 0xffb00000, 0xf9200000, fix(&D:: template VLD__MS) }, // VLD1, VLD2, VLD3, VLD4 { 0xffb00f00, 0xf9a00c00, fix(&D:: template VLD1_SAL) }, { 0xffb00300, 0xf9a00000, fix(&D:: template VLD1_SL) }, { 0xffb00f00, 0xf9a00d00, fix(&D:: template VLD2_SAL) }, { 0xffb00300, 0xf9a00100, fix(&D:: template VLD2_SL) }, { 0xffb00f00, 0xf9a00e00, fix(&D:: template VLD3_SAL) }, { 0xffb00300, 0xf9a00200, fix(&D:: template VLD3_SL) }, { 0xffb00f00, 0xf9a00f00, fix(&D:: template VLD4_SAL) }, { 0xffb00300, 0xf9a00300, fix(&D:: template VLD4_SL) }, { 0xfe100f00, 0xec100b00, fix(&D:: template VLDM) }, { 0xfe100f00, 0xec100a00, fix(&D:: template VLDM) }, { 0xff300f00, 0xed100b00, fix(&D:: template VLDR) }, { 0xff300f00, 0xed100a00, fix(&D:: template VLDR) }, { 0xef800f00, 0xef000600, fix(&D:: template VMAXMIN) }, { 0xff800f10, 0xef000f00, fix(&D:: template VMAXMIN_FP) }, { 0xef800f10, 0xef000900, fix(&D:: template VML__) }, { 0xef800d50, 0xef800800, fix(&D:: template VML__) }, { 0xff800f10, 0xef000d10, fix(&D:: template VML__FP) }, { 0xffb00e10, 0xee000a00, fix(&D:: template VML__FP) }, { 0xef800a50, 0xef800040, fix(&D:: template VML__S) }, { 0xef800b50, 0xef800240, fix(&D:: template VML__S) }, { 0xefb80090, 0xef800010, fix(&D:: template VMOV_IMM) }, { 0xffb00ef0, 0xeeb00a00, fix(&D:: template VMOV_IMM) }, { 0xffb00f10, 0xef200110, fix(&D:: template VMOV_REG) }, { 0xffbf0ed0, 0xeeb00a40, fix(&D:: template VMOV_REG) }, { 0xff900f1f, 0xee000b10, fix(&D:: template VMOV_RS) }, { 0xff100f1f, 0xee100b10, fix(&D:: template VMOV_SR) }, { 0xffe00f7f, 0xee000a10, fix(&D:: template VMOV_RF) }, { 0xffe00fd0, 0xec400a10, fix(&D:: template VMOV_2RF) }, { 0xffe00fd0, 0xec400b10, fix(&D:: template VMOV_2RD) }, { 0xef870fd0, 0xef800a10, fix(&D:: template VMOVL) }, { 0xffb30fd0, 0xffb20200, fix(&D:: template VMOVN) }, { 0xffff0fff, 0xeef10a10, fix(&D:: template VMRS) }, { 0xffff0fff, 0xeee10a10, fix(&D:: template VMSR) }, { 0xef800f10, 0xef000910, fix(&D:: template VMUL_) }, { 0xef800d50, 0xef800c00, fix(&D:: template VMUL_) }, { 0xffa00f10, 0xff000d10, fix(&D:: template VMUL_FP) }, { 0xffb00e50, 0xee200a00, fix(&D:: template VMUL_FP) }, { 0xef800e50, 0xef800840, fix(&D:: template VMUL_S) }, { 0xef800f50, 0xef800a40, fix(&D:: template VMUL_S) }, { 0xefb800b0, 0xef800030, fix(&D:: template VMVN_IMM) }, { 0xffb30f90, 0xffb00580, fix(&D:: template VMVN_REG) }, { 0xffb30b90, 0xffb10380, fix(&D:: template VNEG) }, { 0xffbf0ed0, 0xeeb10a40, fix(&D:: template VNEG) }, { 0xffb00e10, 0xee100a00, fix(&D:: template VNM__) }, { 0xffb00e50, 0xee200a40, fix(&D:: template VNM__) }, { 0xffb00f10, 0xef300110, fix(&D:: template VORN_REG) }, { 0xefb800b0, 0xef800010, fix(&D:: template VORR_IMM) }, { 0xffb00f10, 0xef200110, fix(&D:: template VORR_REG) }, { 0xffb30f10, 0xffb00600, fix(&D:: template VPADAL) }, { 0xff800f10, 0xef000b10, fix(&D:: template VPADD) }, { 0xffa00f10, 0xff000d00, fix(&D:: template VPADD_FP) }, { 0xffb30f10, 0xffb00200, fix(&D:: template VPADDL) }, { 0xef800f00, 0xef000a00, fix(&D:: template VPMAXMIN) }, { 0xff800f10, 0xff000f00, fix(&D:: template VPMAXMIN_FP) }, { 0xffbf0f00, 0xecbd0b00, fix(&D:: template VPOP) }, { 0xffbf0f00, 0xecbd0a00, fix(&D:: template VPOP) }, { 0xffbf0f00, 0xed2d0b00, fix(&D:: template VPUSH) }, { 0xffbf0f00, 0xed2d0a00, fix(&D:: template VPUSH) }, { 0xffb30f90, 0xffb00700, fix(&D:: template VQABS) }, { 0xef800f10, 0xef000010, fix(&D:: template VQADD) }, { 0xff800d50, 0xef800900, fix(&D:: template VQDML_L) }, { 0xff800b50, 0xef800340, fix(&D:: template VQDML_L) }, { 0xff800f10, 0xef000b00, fix(&D:: template VQDMULH) }, { 0xef800f50, 0xef800c40, fix(&D:: template VQDMULH) }, { 0xff800f50, 0xef800d00, fix(&D:: template VQDMULL) }, { 0xff800f50, 0xef800b40, fix(&D:: template VQDMULL) }, { 0xffb30f10, 0xffb20200, fix(&D:: template VQMOV_N) }, { 0xffb30f90, 0xffb00780, fix(&D:: template VQNEG) }, { 0xff800f10, 0xff000b00, fix(&D:: template VQRDMULH) }, { 0xef800f50, 0xef800d40, fix(&D:: template VQRDMULH) }, { 0xef800f10, 0xef000510, fix(&D:: template VQRSHL) }, { 0xef800ed0, 0xef800850, fix(&D:: template VQRSHR_N) }, { 0xef800f10, 0xef000410, fix(&D:: template VQSHL_REG) }, { 0xef800e10, 0xef800610, fix(&D:: template VQSHL_IMM) }, { 0xef800ed0, 0xef800810, fix(&D:: template VQSHR_N) }, { 0xef800f10, 0xef000210, fix(&D:: template VQSUB) }, { 0xff800f50, 0xff800400, fix(&D:: template VRADDHN) }, { 0xffb30e90, 0xffb30400, fix(&D:: template VRECPE) }, { 0xffa00f10, 0xef000f10, fix(&D:: template VRECPS) }, { 0xffb30e10, 0xffb00000, fix(&D:: template VREV__) }, { 0xef800f10, 0xef000100, fix(&D:: template VRHADD) }, { 0xef800f10, 0xef000500, fix(&D:: template VRSHL) }, { 0xef800f10, 0xef800210, fix(&D:: template VRSHR) }, { 0xff800fd0, 0xef800850, fix(&D:: template VRSHRN) }, { 0xffb30e90, 0xffb30480, fix(&D:: template VRSQRTE) }, { 0xffa00f10, 0xef200f10, fix(&D:: template VRSQRTS) }, { 0xef800f10, 0xef800310, fix(&D:: template VRSRA) }, { 0xff800f50, 0xff800600, fix(&D:: template VRSUBHN) }, { 0xff800f10, 0xef800510, fix(&D:: template VSHL_IMM) }, { 0xef800f10, 0xef000400, fix(&D:: template VSHL_REG) }, { 0xef800fd0, 0xef800a10, fix(&D:: template VSHLL) }, { 0xffb30fd0, 0xffb20300, fix(&D:: template VSHLL) }, { 0xef800f10, 0xef800010, fix(&D:: template VSHR) }, { 0xff800fd0, 0xef800810, fix(&D:: template VSHRN) }, { 0xff800f10, 0xff800510, fix(&D:: template VSLI) }, { 0xffbf0ed0, 0xeeb10ac0, fix(&D:: template VSQRT) }, { 0xef800f10, 0xef800110, fix(&D:: template VSRA) }, { 0xff800f10, 0xff800410, fix(&D:: template VSRI) }, { 0xffb00000, 0xf9000000, fix(&D:: template VST__MS) }, // VST1, VST2, VST3, VST4 { 0xffb00300, 0xf9800000, fix(&D:: template VST1_SL) }, { 0xffb00300, 0xf9800100, fix(&D:: template VST2_SL) }, { 0xffb00300, 0xf9800200, fix(&D:: template VST3_SL) }, { 0xffb00300, 0xf9800300, fix(&D:: template VST4_SL) }, { 0xfe100f00, 0xec000b00, fix(&D:: template VSTM) }, { 0xfe100f00, 0xec000a00, fix(&D:: template VSTM) }, { 0xff300f00, 0xed000b00, fix(&D:: template VSTR) }, { 0xff300f00, 0xed000a00, fix(&D:: template VSTR) }, { 0xff800f10, 0xff000800, fix(&D:: template VSUB) }, { 0xffa00f10, 0xef200d00, fix(&D:: template VSUB_FP) }, { 0xffb00e50, 0xee300a40, fix(&D:: template VSUB_FP) }, { 0xff800f50, 0xef800600, fix(&D:: template VSUBHN) }, { 0xef800e50, 0xef800200, fix(&D:: template VSUB_) }, { 0xffb30f90, 0xffb20000, fix(&D:: template VSWP) }, { 0xffb00c10, 0xffb00800, fix(&D:: template VTB_) }, { 0xffb30f90, 0xffb20080, fix(&D:: template VTRN) }, { 0xff800f10, 0xef000810, fix(&D:: template VTST) }, { 0xffb30f90, 0xffb20100, fix(&D:: template VUZP) }, { 0xffb30f90, 0xffb20180, fix(&D:: template VZIP) }, { 0xffffffff, 0xf3af8002, fix(&D:: template WFE) }, { 0xffffffff, 0xf3af8003, fix(&D:: template WFI) }, { 0xffffffff, 0xf3af8001, fix(&D:: template YIELD) }, }); m_arm_list.assign( { { 0x0ff000f0, 0x00700090, fix(&D:: template HACK), nullptr }, // "Undefined" ARM opcode used { 0x0ffffff0, 0x012fff10, fix(&D:: template BX), nullptr }, { 0x0fe00000, 0x02a00000, fix(&D:: template ADC_IMM) }, { 0x0fe00010, 0x00a00000, fix(&D:: template ADC_REG) }, { 0x0fe00090, 0x00a00010, fix(&D:: template ADC_RSR) }, { 0x0fe00000, 0x02800000, fix(&D:: template ADD_IMM) }, { 0x0fe00010, 0x00800000, fix(&D:: template ADD_REG) }, { 0x0fe00090, 0x00800010, fix(&D:: template ADD_RSR) }, { 0x0fef0000, 0x028d0000, fix(&D:: template ADD_SPI) }, { 0x0fef0010, 0x008d0000, fix(&D:: template ADD_SPR) }, { 0x0fff0000, 0x028f0000, fix(&D:: template ADR) }, { 0x0fff0000, 0x024f0000, fix(&D:: template ADR) }, { 0x0fe00000, 0x02000000, fix(&D:: template AND_IMM) }, { 0x0fe00010, 0x00000000, fix(&D:: template AND_REG) }, { 0x0fe00090, 0x00000010, fix(&D:: template AND_RSR) }, { 0x0fef0070, 0x01a00040, fix(&D:: template ASR_IMM) }, { 0x0fef00f0, 0x01a00050, fix(&D:: template ASR_REG) }, { 0x0f000000, 0x0a000000, fix(&D:: template B) }, { 0x0fe0007f, 0x07c0001f, fix(&D:: template BFC) }, { 0x0fe00070, 0x07c00010, fix(&D:: template BFI) }, { 0x0fe00000, 0x03c00000, fix(&D:: template BIC_IMM) }, { 0x0fe00010, 0x01c00000, fix(&D:: template BIC_REG) }, { 0x0fe00090, 0x01c00010, fix(&D:: template BIC_RSR) }, { 0x0ff000f0, 0x01200070, fix(&D:: template BKPT) }, { 0x0f000000, 0x0b000000, fix(&D:: template BL) }, { 0xfe000000, 0xfa000000, fix(&D:: template BL) }, { 0x0ffffff0, 0x012fff30, fix(&D:: template BLX) }, { 0x0fff0ff0, 0x016f0f10, fix(&D:: template CLZ) }, { 0x0ff0f000, 0x03700000, fix(&D:: template CMN_IMM) }, { 0x0ff0f010, 0x01700000, fix(&D:: template CMN_REG) }, { 0x0ff0f090, 0x01700010, fix(&D:: template CMN_RSR) }, { 0x0ff0f000, 0x03500000, fix(&D:: template CMP_IMM) }, { 0x0ff0f010, 0x01500000, fix(&D:: template CMP_REG) }, { 0x0ff0f090, 0x01500010, fix(&D:: template CMP_RSR) }, { 0x0ffffff0, 0x0320f0f0, fix(&D:: template DBG) }, { 0xfffffff0, 0xf57ff050, fix(&D:: template DMB) }, { 0xfffffff0, 0xf57ff040, fix(&D:: template DSB) }, { 0x0fe00000, 0x02200000, fix(&D:: template EOR_IMM) }, { 0x0fe00010, 0x00200000, fix(&D:: template EOR_REG) }, { 0x0fe00090, 0x00200010, fix(&D:: template EOR_RSR) }, { 0x0fd00000, 0x08900000, fix(&D:: template LDM) }, { 0x0fd00000, 0x08100000, fix(&D:: template LDMDA) }, { 0x0fd00000, 0x09100000, fix(&D:: template LDMDB) }, { 0x0fd00000, 0x09900000, fix(&D:: template LDMIB) }, { 0x0e500000, 0x04100000, fix(&D:: template LDR_IMM) }, { 0x0f7f0000, 0x051f0000, fix(&D:: template LDR_LIT) }, { 0x0e500010, 0x06100000, fix(&D:: template LDR_REG) }, { 0x0e500000, 0x04500000, fix(&D:: template LDRB_IMM) }, { 0x0f7f0000, 0x055f0000, fix(&D:: template LDRB_LIT) }, { 0x0e500010, 0x06500000, fix(&D:: template LDRB_REG) }, { 0x0e5000f0, 0x004000d0, fix(&D:: template LDRD_IMM) }, { 0x0f7f00f0, 0x014f00d0, fix(&D:: template LDRD_LIT) }, { 0x0e500ff0, 0x000000d0, fix(&D:: template LDRD_REG) }, { 0x0ff00fff, 0x01900f9f, fix(&D:: template LDREX) }, { 0x0ff00fff, 0x01d00f9f, fix(&D:: template LDREXB) }, { 0x0ff00fff, 0x01b00f9f, fix(&D:: template LDREXD) }, { 0x0ff00fff, 0x01f00f9f, fix(&D:: template LDREXH) }, { 0x0e5000f0, 0x005000b0, fix(&D:: template LDRH_IMM) }, { 0x0f7f00f0, 0x015f00b0, fix(&D:: template LDRH_LIT) }, { 0x0e500ff0, 0x001000b0, fix(&D:: template LDRH_REG) }, { 0x0e5000f0, 0x005000d0, fix(&D:: template LDRSB_IMM) }, { 0x0f7f00f0, 0x015f00d0, fix(&D:: template LDRSB_LIT) }, { 0x0e500ff0, 0x001000d0, fix(&D:: template LDRSB_REG) }, { 0x0e5000f0, 0x005000f0, fix(&D:: template LDRSH_IMM) }, { 0x0f7f00f0, 0x015f00f0, fix(&D:: template LDRSH_LIT) }, { 0x0e500ff0, 0x001000f0, fix(&D:: template LDRSH_REG) }, { 0x0fef0070, 0x01a00000, fix(&D:: template LSL_IMM) }, { 0x0fef00f0, 0x01a00010, fix(&D:: template LSL_REG) }, { 0x0fef0030, 0x01a00020, fix(&D:: template LSR_IMM) }, { 0x0fef00f0, 0x01a00030, fix(&D:: template LSR_REG) }, { 0x0fe000f0, 0x00200090, fix(&D:: template MLA) }, { 0x0ff000f0, 0x00600090, fix(&D:: template MLS) }, { 0x0fef0000, 0x03a00000, fix(&D:: template MOV_IMM) }, { 0x0ff00000, 0x03000000, fix(&D:: template MOV_IMM) }, { 0x0fef0ff0, 0x01a00000, fix(&D:: template MOV_REG) }, { 0x0ff00000, 0x03400000, fix(&D:: template MOVT) }, { 0x0f100010, 0x0e100010, fix(&D:: template MRC_) }, { 0xff100010, 0xfe100010, fix(&D:: template MRC_) }, { 0x0fff0fff, 0x010f0000, fix(&D:: template MRS) }, { 0x0ff3f000, 0x0320f000, fix(&D:: template MSR_IMM) }, { 0x0ff3fff0, 0x0120f000, fix(&D:: template MSR_REG) }, { 0x0fe0f0f0, 0x00000090, fix(&D:: template MUL) }, { 0x0fef0000, 0x03e00000, fix(&D:: template MVN_IMM) }, { 0xffef0010, 0x01e00000, fix(&D:: template MVN_REG) }, { 0x0fef0090, 0x01e00010, fix(&D:: template MVN_RSR) }, { 0x0fffffff, 0x0320f000, fix(&D:: template NOP) }, { 0x0fe00000, 0x03800000, fix(&D:: template ORR_IMM) }, { 0x0fe00010, 0x01800000, fix(&D:: template ORR_REG) }, { 0x0fe00090, 0x01800010, fix(&D:: template ORR_RSR) }, { 0x0ff00030, 0x06800010, fix(&D:: template PKH) }, { 0x0fff0000, 0x08bd0000, fix(&D:: template POP) }, { 0x0fff0fff, 0x049d0004, fix(&D:: template POP) }, { 0x0fff0000, 0x092d0000, fix(&D:: template PUSH) }, { 0x0fff0fff, 0x052d0004, fix(&D:: template PUSH) }, { 0x0ff00ff0, 0x01000050, fix(&D:: template QADD) }, { 0x0ff00ff0, 0x06200f10, fix(&D:: template QADD16) }, { 0x0ff00ff0, 0x06200f90, fix(&D:: template QADD8) }, { 0x0ff00ff0, 0x06200f30, fix(&D:: template QASX) }, { 0x0ff00ff0, 0x01400050, fix(&D:: template QDADD) }, { 0x0ff00ff0, 0x01600050, fix(&D:: template QDSUB) }, { 0x0ff00ff0, 0x06200f50, fix(&D:: template QSAX) }, { 0x0ff00ff0, 0x01200050, fix(&D:: template QSUB) }, { 0x0ff00ff0, 0x06200f70, fix(&D:: template QSUB16) }, { 0x0ff00ff0, 0x06200ff0, fix(&D:: template QSUB8) }, { 0x0fff0ff0, 0x06ff0f30, fix(&D:: template RBIT) }, { 0x0fff0ff0, 0x06bf0f30, fix(&D:: template REV) }, { 0x0fff0ff0, 0x06bf0fb0, fix(&D:: template REV16) }, { 0x0fff0ff0, 0x06ff0fb0, fix(&D:: template REVSH) }, { 0x0fef0070, 0x01a00060, fix(&D:: template ROR_IMM) }, { 0x0fef00f0, 0x01a00070, fix(&D:: template ROR_REG) }, { 0x0fef0ff0, 0x01a00060, fix(&D:: template RRX) }, { 0x0fe00000, 0x02600000, fix(&D:: template RSB_IMM) }, { 0x0fe00010, 0x00600000, fix(&D:: template RSB_REG) }, { 0x0fe00090, 0x00600010, fix(&D:: template RSB_RSR) }, { 0x0fe00000, 0x02e00000, fix(&D:: template RSC_IMM) }, { 0x0fe00010, 0x00e00000, fix(&D:: template RSC_REG) }, { 0x0fe00090, 0x00e00010, fix(&D:: template RSC_RSR) }, { 0x0ff00ff0, 0x06100f10, fix(&D:: template SADD16) }, { 0x0ff00ff0, 0x06100f90, fix(&D:: template SADD8) }, { 0x0ff00ff0, 0x06100f30, fix(&D:: template SASX) }, { 0x0fe00000, 0x02c00000, fix(&D:: template SBC_IMM) }, { 0x0fe00010, 0x00c00000, fix(&D:: template SBC_REG) }, { 0x0fe00090, 0x00c00010, fix(&D:: template SBC_RSR) }, { 0x0fe00070, 0x07a00050, fix(&D:: template SBFX) }, { 0x0ff00ff0, 0x06800fb0, fix(&D:: template SEL) }, { 0x0ff00ff0, 0x06300f10, fix(&D:: template SHADD16) }, { 0x0ff00ff0, 0x06300f90, fix(&D:: template SHADD8) }, { 0x0ff00ff0, 0x06300f30, fix(&D:: template SHASX) }, { 0x0ff00ff0, 0x06300f50, fix(&D:: template SHSAX) }, { 0x0ff00ff0, 0x06300f70, fix(&D:: template SHSUB16) }, { 0x0ff00ff0, 0x06300ff0, fix(&D:: template SHSUB8) }, { 0x0ff00090, 0x01000080, fix(&D:: template SMLA__) }, { 0x0ff000d0, 0x07000010, fix(&D:: template SMLAD) }, { 0x0fe000f0, 0x00e00090, fix(&D:: template SMLAL) }, { 0x0ff00090, 0x01400080, fix(&D:: template SMLAL__) }, { 0x0ff000d0, 0x07400010, fix(&D:: template SMLALD) }, { 0x0ff000b0, 0x01200080, fix(&D:: template SMLAW_) }, { 0x0ff000d0, 0x07000050, fix(&D:: template SMLSD) }, { 0x0ff000d0, 0x07400050, fix(&D:: template SMLSLD) }, { 0x0ff000d0, 0x07500010, fix(&D:: template SMMLA) }, { 0x0ff000d0, 0x075000d0, fix(&D:: template SMMLS) }, { 0x0ff0f0d0, 0x0750f010, fix(&D:: template SMMUL) }, { 0x0ff0f0d0, 0x0700f010, fix(&D:: template SMUAD) }, { 0x0ff0f090, 0x01600080, fix(&D:: template SMUL__) }, { 0x0fe000f0, 0x00c00090, fix(&D:: template SMULL) }, { 0x0ff0f0b0, 0x012000a0, fix(&D:: template SMULW_) }, { 0x0ff0f0d0, 0x0700f050, fix(&D:: template SMUSD) }, { 0x0fe00030, 0x06a00010, fix(&D:: template SSAT) }, { 0x0ff00ff0, 0x06a00f30, fix(&D:: template SSAT16) }, { 0x0ff00ff0, 0x06100f50, fix(&D:: template SSAX) }, { 0x0ff00ff0, 0x06100f70, fix(&D:: template SSUB16) }, { 0x0ff00ff0, 0x06100ff0, fix(&D:: template SSUB8) }, { 0x0fd00000, 0x08800000, fix(&D:: template STM) }, { 0x0fd00000, 0x08000000, fix(&D:: template STMDA) }, { 0x0fd00000, 0x09000000, fix(&D:: template STMDB) }, { 0x0fd00000, 0x09800000, fix(&D:: template STMIB) }, { 0x0e500000, 0x04000000, fix(&D:: template STR_IMM) }, { 0x0e500010, 0x06000000, fix(&D:: template STR_REG) }, { 0x0e500000, 0x04400000, fix(&D:: template STRB_IMM) }, { 0x0e500010, 0x06400000, fix(&D:: template STRB_REG) }, { 0x0e5000f0, 0x004000f0, fix(&D:: template STRD_IMM) }, { 0x0e500ff0, 0x000000f0, fix(&D:: template STRD_REG) }, { 0x0ff00ff0, 0x01800f90, fix(&D:: template STREX) }, { 0x0ff00ff0, 0x01c00f90, fix(&D:: template STREXB) }, { 0x0ff00ff0, 0x01a00f90, fix(&D:: template STREXD) }, { 0x0ff00ff0, 0x01e00f90, fix(&D:: template STREXH) }, { 0x0e5000f0, 0x004000b0, fix(&D:: template STRH_IMM) }, { 0x0e500ff0, 0x000000b0, fix(&D:: template STRH_REG) }, { 0x0fe00000, 0x02400000, fix(&D:: template SUB_IMM) }, { 0x0fe00010, 0x00400000, fix(&D:: template SUB_REG) }, { 0x0fe00090, 0x00400010, fix(&D:: template SUB_RSR) }, { 0x0fef0000, 0x024d0000, fix(&D:: template SUB_SPI) }, { 0x0fef0010, 0x004d0000, fix(&D:: template SUB_SPR) }, { 0x0f000000, 0x0f000000, fix(&D:: template SVC) }, { 0x0ff003f0, 0x06a00070, fix(&D:: template SXTAB) }, { 0x0ff003f0, 0x06800070, fix(&D:: template SXTAB16) }, { 0x0ff003f0, 0x06b00070, fix(&D:: template SXTAH) }, { 0x0fff03f0, 0x06af0070, fix(&D:: template SXTB) }, { 0x0fff03f0, 0x068f0070, fix(&D:: template SXTB16) }, { 0x0fff03f0, 0x06bf0070, fix(&D:: template SXTH) }, { 0x0ff0f000, 0x03300000, fix(&D:: template TEQ_IMM) }, { 0x0ff0f010, 0x01300000, fix(&D:: template TEQ_REG) }, { 0x0ff0f090, 0x01300010, fix(&D:: template TEQ_RSR) }, { 0x0ff0f000, 0x03100000, fix(&D:: template TST_IMM) }, { 0x0ff0f010, 0x01100000, fix(&D:: template TST_REG) }, { 0x0ff0f090, 0x01100010, fix(&D:: template TST_RSR) }, { 0x0ff00ff0, 0x06500f10, fix(&D:: template UADD16) }, { 0x0ff00ff0, 0x06500f90, fix(&D:: template UADD8) }, { 0x0ff00ff0, 0x06500f30, fix(&D:: template UASX) }, { 0x0fe00070, 0x07e00050, fix(&D:: template UBFX) }, { 0x0ff00ff0, 0x06700f10, fix(&D:: template UHADD16) }, { 0x0ff00ff0, 0x06700f90, fix(&D:: template UHADD8) }, { 0x0ff00ff0, 0x06700f30, fix(&D:: template UHASX) }, { 0x0ff00ff0, 0x06700f50, fix(&D:: template UHSAX) }, { 0x0ff00ff0, 0x06700f70, fix(&D:: template UHSUB16) }, { 0x0ff00ff0, 0x06700ff0, fix(&D:: template UHSUB8) }, { 0x0ff000f0, 0x00400090, fix(&D:: template UMAAL) }, { 0x0fe000f0, 0x00a00090, fix(&D:: template UMLAL) }, { 0x0fe000f0, 0x00800090, fix(&D:: template UMULL) }, { 0x0ff00ff0, 0x06600f10, fix(&D:: template UQADD16) }, { 0x0ff00ff0, 0x06600f90, fix(&D:: template UQADD8) }, { 0x0ff00ff0, 0x06600f30, fix(&D:: template UQASX) }, { 0x0ff00ff0, 0x06600f50, fix(&D:: template UQSAX) }, { 0x0ff00ff0, 0x06600f70, fix(&D:: template UQSUB16) }, { 0x0ff00ff0, 0x06600ff0, fix(&D:: template UQSUB8) }, { 0x0ff0f0f0, 0x0780f010, fix(&D:: template USAD8) }, { 0x0ff000f0, 0x07800010, fix(&D:: template USADA8) }, { 0x0fe00030, 0x06e00010, fix(&D:: template USAT) }, { 0x0ff00ff0, 0x06e00f30, fix(&D:: template USAT16) }, { 0x0ff00ff0, 0x06500f50, fix(&D:: template USAX) }, { 0x0ff00ff0, 0x06500f70, fix(&D:: template USUB16) }, { 0x0ff00ff0, 0x06500ff0, fix(&D:: template USUB8) }, { 0x0ff003f0, 0x06e00070, fix(&D:: template UXTAB), SKIP_IF(BF(16, 19) == 15) }, { 0x0ff003f0, 0x06c00070, fix(&D:: template UXTAB16) }, { 0x0ff003f0, 0x06f00070, fix(&D:: template UXTAH) }, { 0x0fff03f0, 0x06ef0070, fix(&D:: template UXTB) }, { 0x0fff03f0, 0x06cf0070, fix(&D:: template UXTB16) }, { 0x0fff03f0, 0x06ff0070, fix(&D:: template UXTH) }, { 0xfe800f10, 0xf2000710, fix(&D:: template VABA_) }, { 0xfe800f50, 0xf2800500, fix(&D:: template VABA_) }, { 0xfe800f10, 0xf2000700, fix(&D:: template VABD_) }, { 0xfe800f50, 0xf2800700, fix(&D:: template VABD_) }, { 0xffa00f10, 0xf3200d00, fix(&D:: template VABD_FP) }, { 0xffb30b90, 0xf3b10300, fix(&D:: template VABS) }, { 0x0fbf0ed0, 0x0eb00ac0, fix(&D:: template VABS) }, { 0xff800f10, 0xf3000e10, fix(&D:: template VAC__) }, { 0xff800f10, 0xf2000800, fix(&D:: template VADD) }, { 0xffa00f10, 0xf2000d00, fix(&D:: template VADD_FP) }, { 0x0fb00e50, 0x0e300a00, fix(&D:: template VADD_FP) }, { 0xff800f50, 0xf2800400, fix(&D:: template VADDHN) }, { 0xfe800e50, 0xf2800000, fix(&D:: template VADD_) }, { 0xffb00f10, 0xf2000110, fix(&D:: template VAND) }, { 0xfeb000b0, 0xf2800030, fix(&D:: template VBIC_IMM) }, { 0xffb00f10, 0xf2100110, fix(&D:: template VBIC_REG) }, { 0xff800f10, 0xf3000110, fix(&D:: template VB__) }, { 0xff800f10, 0xf3000810, fix(&D:: template VCEQ_REG) }, { 0xffa00f10, 0xf2000e00, fix(&D:: template VCEQ_REG) }, { 0xffb30b90, 0xf3b10100, fix(&D:: template VCEQ_ZERO) }, { 0xfe800f10, 0xf2000310, fix(&D:: template VCGE_REG) }, { 0xffa00f10, 0xf3000e00, fix(&D:: template VCGE_REG) }, { 0xffb30b90, 0xf3b10080, fix(&D:: template VCGE_ZERO) }, { 0xfe800f10, 0xf2000300, fix(&D:: template VCGT_REG) }, { 0xffa00f10, 0xf3200e00, fix(&D:: template VCGT_REG) }, { 0xffb30b90, 0xf3b10000, fix(&D:: template VCGT_ZERO) }, { 0xffb30b90, 0xf3b10180, fix(&D:: template VCLE_ZERO) }, { 0xffb30f90, 0xf3b00400, fix(&D:: template VCLS) }, { 0xffb30b90, 0xf3b10200, fix(&D:: template VCLT_ZERO) }, { 0xffb30f90, 0xf3b00480, fix(&D:: template VCLZ) }, { 0x0fbf0e50, 0x0eb40a40, fix(&D:: template VCMP_) }, { 0x0fbf0e7f, 0x0eb50a40, fix(&D:: template VCMP_) }, { 0xffb30f90, 0xf3b00500, fix(&D:: template VCNT) }, { 0xffb30e10, 0xf3b30600, fix(&D:: template VCVT_FIA) }, { 0x0fb80e50, 0x0eb80a40, fix(&D:: template VCVT_FIF) }, { 0xfe800e90, 0xf2800e10, fix(&D:: template VCVT_FFA) }, { 0x0fba0e50, 0x0eba0a40, fix(&D:: template VCVT_FFF) }, { 0x0fbf0ed0, 0x0eb70ac0, fix(&D:: template VCVT_DF) }, { 0xffb30ed0, 0xf3b20600, fix(&D:: template VCVT_HFA) }, { 0x0fbe0f50, 0x0eb20a40, fix(&D:: template VCVT_HFF) }, { 0x0fb00e50, 0x0e800a00, fix(&D:: template VDIV) }, { 0xffb00f90, 0xf3b00c00, fix(&D:: template VDUP_S) }, { 0x0f900f5f, 0x0e800b10, fix(&D:: template VDUP_R) }, { 0xffb00f10, 0xf3000110, fix(&D:: template VEOR) }, { 0xffb00010, 0xf2b00000, fix(&D:: template VEXT) }, { 0xfe800b10, 0xf2000000, fix(&D:: template VHADDSUB) }, { 0xffb00000, 0xf4200000, fix(&D:: template VLD__MS) }, { 0xffb00f00, 0xf4a00c00, fix(&D:: template VLD1_SAL) }, { 0xffb00300, 0xf4a00000, fix(&D:: template VLD1_SL) }, { 0xffb00f00, 0xf4a00d00, fix(&D:: template VLD2_SAL) }, { 0xffb00300, 0xf4a00100, fix(&D:: template VLD2_SL) }, { 0xffb00f00, 0xf4a00e00, fix(&D:: template VLD3_SAL) }, { 0xffb00300, 0xf4a00200, fix(&D:: template VLD3_SL) }, { 0xffb00f00, 0xf4a00f00, fix(&D:: template VLD4_SAL) }, { 0xffb00300, 0xf4a00300, fix(&D:: template VLD4_SL) }, { 0x0e100f00, 0x0c100b00, fix(&D:: template VLDM) }, { 0x0e100f00, 0x0c100a00, fix(&D:: template VLDM) }, { 0x0f300f00, 0x0d100b00, fix(&D:: template VLDR) }, { 0x0f300f00, 0x0d100a00, fix(&D:: template VLDR) }, { 0xfe800f00, 0xf2000600, fix(&D:: template VMAXMIN) }, { 0xff800f10, 0xf2000f00, fix(&D:: template VMAXMIN_FP) }, { 0xfe800f10, 0xf2000900, fix(&D:: template VML__) }, { 0xfe800d50, 0xf2800800, fix(&D:: template VML__) }, { 0xff800f10, 0xf2000d10, fix(&D:: template VML__FP) }, { 0x0fb00e10, 0x0e000a00, fix(&D:: template VML__FP) }, { 0xfe800a50, 0xf2800040, fix(&D:: template VML__S) }, { 0xfe800b50, 0xf2800240, fix(&D:: template VML__S) }, { 0xfeb80090, 0xf2800010, fix(&D:: template VMOV_IMM) }, { 0x0fb00ef0, 0x0eb00a00, fix(&D:: template VMOV_IMM) }, { 0xffb00f10, 0xf2200110, fix(&D:: template VMOV_REG) }, { 0x0fbf0ed0, 0x0eb00a40, fix(&D:: template VMOV_REG) }, { 0x0f900f1f, 0x0e000b10, fix(&D:: template VMOV_RS) }, { 0x0f100f1f, 0x0e100b10, fix(&D:: template VMOV_SR) }, { 0x0fe00f7f, 0x0e000a10, fix(&D:: template VMOV_RF) }, { 0x0fe00fd0, 0x0c400a10, fix(&D:: template VMOV_2RF) }, { 0x0fe00fd0, 0x0c400b10, fix(&D:: template VMOV_2RD) }, { 0xfe870fd0, 0xf2800a10, fix(&D:: template VMOVL) }, { 0xffb30fd0, 0xf3b20200, fix(&D:: template VMOVN) }, { 0x0fff0fff, 0x0ef10a10, fix(&D:: template VMRS) }, { 0x0fff0fff, 0x0ee10a10, fix(&D:: template VMSR) }, { 0xfe800f10, 0xf2000910, fix(&D:: template VMUL_) }, { 0xfe800d50, 0xf2800c00, fix(&D:: template VMUL_) }, { 0xffa00f10, 0xf3000d10, fix(&D:: template VMUL_FP) }, { 0x0fb00e50, 0x0e200a00, fix(&D:: template VMUL_FP) }, { 0xfe800e50, 0xf2800840, fix(&D:: template VMUL_S) }, { 0xfe800f50, 0xf2800a40, fix(&D:: template VMUL_S) }, { 0xfeb800b0, 0xf2800030, fix(&D:: template VMVN_IMM) }, { 0xffb30f90, 0xf3b00580, fix(&D:: template VMVN_REG) }, { 0xffb30b90, 0xf3b10380, fix(&D:: template VNEG) }, { 0x0fbf0ed0, 0x0eb10a40, fix(&D:: template VNEG) }, { 0x0fb00e10, 0x0e100a00, fix(&D:: template VNM__) }, { 0x0fb00e50, 0x0e200a40, fix(&D:: template VNM__) }, { 0xffb00f10, 0xf2300110, fix(&D:: template VORN_REG) }, { 0xfeb800b0, 0xf2800010, fix(&D:: template VORR_IMM) }, { 0xffb00f10, 0xf2200110, fix(&D:: template VORR_REG) }, { 0xffb30f10, 0xf3b00600, fix(&D:: template VPADAL) }, { 0xff800f10, 0xf2000b10, fix(&D:: template VPADD) }, { 0xffa00f10, 0xf3000d00, fix(&D:: template VPADD_FP) }, { 0xffb30f10, 0xf3b00200, fix(&D:: template VPADDL) }, { 0xfe800f00, 0xf2000a00, fix(&D:: template VPMAXMIN) }, { 0xff800f10, 0xf3000f00, fix(&D:: template VPMAXMIN_FP) }, { 0x0fbf0f00, 0x0cbd0b00, fix(&D:: template VPOP) }, { 0x0fbf0f00, 0x0cbd0a00, fix(&D:: template VPOP) }, { 0x0fbf0f00, 0x0d2d0b00, fix(&D:: template VPUSH) }, { 0x0fbf0f00, 0x0d2d0a00, fix(&D:: template VPUSH) }, // TODO: VQ* instructions { 0xff800f50, 0xf3800400, fix(&D:: template VRADDHN) }, { 0xffb30e90, 0xf3b30400, fix(&D:: template VRECPE) }, { 0xffa00f10, 0xf2000f10, fix(&D:: template VRECPS) }, { 0xffb30e10, 0xf3b00000, fix(&D:: template VREV__) }, { 0xfe800f10, 0xf2000100, fix(&D:: template VRHADD) }, { 0xfe800f10, 0xf2000500, fix(&D:: template VRSHL) }, { 0xfe800f10, 0xf2800210, fix(&D:: template VRSHR) }, { 0xff800fd0, 0xf2800850, fix(&D:: template VRSHRN) }, { 0xffb30e90, 0xf3b30480, fix(&D:: template VRSQRTE) }, { 0xffa00f10, 0xf2200f10, fix(&D:: template VRSQRTS) }, { 0xfe800f10, 0xf2800310, fix(&D:: template VRSRA) }, { 0xff800f50, 0xf3800600, fix(&D:: template VRSUBHN) }, { 0xff800f10, 0xf2800510, fix(&D:: template VSHL_IMM) }, { 0xfe800f10, 0xf2000400, fix(&D:: template VSHL_REG) }, { 0xfe800fd0, 0xf2800a10, fix(&D:: template VSHLL) }, { 0xffb30fd0, 0xf3b20300, fix(&D:: template VSHLL) }, { 0xfe800f10, 0xf2800010, fix(&D:: template VSHR) }, { 0xff800fd0, 0xf2800810, fix(&D:: template VSHRN) }, { 0xff800f10, 0xf3800510, fix(&D:: template VSLI) }, { 0x0fbf0ed0, 0x0eb10ac0, fix(&D:: template VSQRT) }, { 0xfe800f10, 0xf2800110, fix(&D:: template VSRA) }, { 0xff800f10, 0xf3800410, fix(&D:: template VSRI) }, { 0xffb00000, 0xf4000000, fix(&D:: template VST__MS) }, { 0xffb00300, 0xf4800000, fix(&D:: template VST1_SL) }, { 0xffb00300, 0xf4800100, fix(&D:: template VST2_SL) }, { 0xffb00300, 0xf4800200, fix(&D:: template VST3_SL) }, { 0xffb00300, 0xf4800300, fix(&D:: template VST4_SL) }, { 0x0e100f00, 0x0c000b00, fix(&D:: template VSTM) }, { 0x0e100f00, 0x0c000a00, fix(&D:: template VSTM) }, { 0x0f300f00, 0x0d000b00, fix(&D:: template VSTR) }, { 0x0f300f00, 0x0d000a00, fix(&D:: template VSTR) }, { 0xff800f10, 0xf3000800, fix(&D:: template VSUB) }, { 0xffa00f10, 0xf2200d00, fix(&D:: template VSUB_FP) }, { 0x0fb00e50, 0x0e300a40, fix(&D:: template VSUB_FP) }, { 0xff800f50, 0xf2800600, fix(&D:: template VSUBHN) }, { 0xfe800e50, 0xf2800200, fix(&D:: template VSUB_) }, { 0xffb30f90, 0xf3b20000, fix(&D:: template VSWP) }, { 0xffb00c10, 0xf3b00800, fix(&D:: template VTB_) }, { 0xffb30f90, 0xf3b20080, fix(&D:: template VTRN) }, { 0xff800f10, 0xf2000810, fix(&D:: template VTST) }, { 0xffb30f90, 0xf3b20100, fix(&D:: template VUZP) }, { 0xffb30f90, 0xf3b20180, fix(&D:: template VZIP) }, { 0x0fffffff, 0x0320f002, fix(&D:: template WFE) }, { 0x0fffffff, 0x0320f003, fix(&D:: template WFI) }, { 0x0fffffff, 0x0320f001, fix(&D:: template YIELD) }, }); m_op32_table.fill(m_op32_list.cbegin()); for (u32 i = 0; i < 0x10000; i++) { for (auto& opcode : m_op16_list) { if (opcode.match(i)) { m_op16_table[i] = opcode.pointer; break; } } if (!m_op16_table[i] && !arm_op_thumb_is_32(i)) { m_op16_table[i] = &D::UNK; } } std::set> result; for (u32 i = 0xe800; i < 0x10000; i++) { if (m_op16_table[i]) LOG_ERROR(ARMv7, "Invalid m_op16_table entry 0x%04x", i); //std::set matches; //for (u32 j = 0; j < 0x10000; j++) //{ // for (auto& o : m_op32_list) // { // if (o.match(i << 16 | j)) // { // matches.emplace(&o); // break; // } // } //} //result.emplace(std::move(matches)); } for (const auto& s : result) { LOG_NOTICE(ARMv7, "Set found (%u):", s.size()); for (const auto& e : s) { LOG_NOTICE(ARMv7, "** 0x%08x, 0x%08x", e->mask, e->code); } } } // First chance T decode_thumb(u16 op16) const { return m_op16_table[op16]; } // Second step T decode_thumb(u32 op32) const { for (auto i = m_op32_table[op32 >> 16], end = m_op32_list.end(); i != end; i++) { if (i->match(op32)) { return i->pointer; } } return &D::UNK; } T decode_arm(u32 op) const { for (auto& i : m_arm_list) { if (i.match(op)) { return i.pointer; } } return &D::UNK; } }; #undef SKIP_IF #undef BF #undef BT