#pragma once #include #include #include "crash.h" #include "matcher.h" #include "operand.h" template struct OperandList { template using prefix = OperandList; }; template struct FilterOperand; template <> struct FilterOperand<> { using result = OperandList<>; }; template struct FilterOperandHelper; template struct FilterOperandHelper { using result = typename FilterOperand::result; }; template struct FilterOperandHelper { using result = typename FilterOperand::result ::template prefix; }; template struct FilterOperand { using result = typename FilterOperandHelper::result; }; template struct VisitorFunctionWithoutFilter; template struct VisitorFunctionWithoutFilter> { using type = typename V::instruction_return_type (V::*)(typename OperandAtT::FilterResult...); }; template struct VisitorFunction { using type = typename VisitorFunctionWithoutFilter::result>::type; }; template struct MatcherCreator { template struct Proxy; using F = typename VisitorFunction::type; template struct Proxy> { F func; auto operator()(V& visitor, [[maybe_unused]] u16 opcode, [[maybe_unused]] u16 expansion) const { return (visitor.*func)(OperandAtTs::Extract(opcode, expansion)...); } }; static Matcher Create(const char* name, F func) { // Operands shouldn't overlap each other, nor overlap with the expected ones static_assert(NoOverlap, "Error"); Proxy::result> proxy{func}; constexpr u16 mask = (~OperandAtT::Mask & ... & 0xFFFF); constexpr bool expanded = (OperandAtT::NeedExpansion || ...); return Matcher(name, mask, expected, expanded, proxy); } }; template struct RejectorCreator { static constexpr Rejector rejector{(OperandAtConstT::Mask | ...), (OperandAtConstT::Pad | ...)}; }; // clang-format off template std::vector> GetDecodeTable() { return { #define INST(name, ...) MatcherCreator::Create(#name, &V::name) #define EXCEPT(...) Except(RejectorCreator<__VA_ARGS__>::rejector) // <<< Misc >>> INST(nop, 0x0000), INST(norm, 0x94C0, At, At, At), INST(swap, 0x4980, At), INST(trap, 0x0020), // <<< ALM normal >>> INST(alm, 0xA000, At, At, At), INST(alm, 0x8080, At, At, At, At), INST(alm, 0x80A0, At, At, At), // <<< ALM r6 >>> INST(alm_r6, 0xD388, Const, At), INST(alm_r6, 0xD389, Const, At), INST(alm_r6, 0xD38A, Const, At), INST(alm_r6, 0xD38B, Const, At), INST(alm_r6, 0xD38C, Const, At), INST(alm_r6, 0xD38D, Const, At), INST(alm_r6, 0xD38E, Const, At), INST(alm_r6, 0xD38F, Const, At), INST(alm_r6, 0x9462, Const, At), INST(alm_r6, 0x9464, Const, At), INST(alm_r6, 0x9466, Const, At), INST(alm_r6, 0x5E23, Const, At), INST(alm_r6, 0x5E22, Const, At), INST(alm_r6, 0x5F41, Const, Const), INST(alm_r6, 0x9062, Const, At, Unused<0>), INST(alm_r6, 0x8A63, Const, At), // <<< ALU normal >>> INST(alu, 0xD4F8, At, At, At) .EXCEPT(AtConst).EXCEPT(AtConst), INST(alu, 0xD4D8, At, At, At) .EXCEPT(AtConst).EXCEPT(AtConst), INST(alu, 0x80C0, At, At, At) .EXCEPT(AtConst).EXCEPT(AtConst), INST(alu, 0xC000, At, At, At) .EXCEPT(AtConst).EXCEPT(AtConst), INST(alu, 0x4000, At, At, At) .EXCEPT(AtConst).EXCEPT(AtConst), // <<< OR Extra >>> INST(or_, 0xD291, At, At, At), INST(or_, 0xD4A4, At, At, At), INST(or_, 0xD3C4, At, At, At), // <<< ALB normal >>> INST(alb, 0xE100, At, At, At), INST(alb, 0x80E0, At, At, At, At), INST(alb, 0x81E0, At, At, At), INST(alb_r6, 0x47B8, At, At), // <<< ALB SttMod >>> INST(alb, 0x43C8, Const, At, At), INST(alb, 0x4388, Const, At, At), INST(alb, 0x0038, Const, At, At), //INST(alb, 0x????, Const, At, At), INST(alb, 0x9470, Const, At, At), INST(alb, 0x9478, Const, At, At), //INST(alb, 0x????, Const, At, At), //INST(alb, 0x????, Const, At, At), // <<< Add extra >>> INST(add, 0xD2DA, At, At), INST(add, 0x5DF0, At, At), INST(add_p1, 0xD782, At), INST(add, 0x5DF8, At, At), // <<< Sub extra >>> INST(sub, 0x8A61, At, At), INST(sub, 0x8861, At, At), INST(sub_p1, 0xD4B9, At), INST(sub, 0x8FD0, At, At), /// <<< addsub p0 p1 >>> INST(app, 0x5DC0, At, BZr, Add, PP, Add, PP), INST(app, 0x5DC1, At, BZr, Add, PP, Add, PA), INST(app, 0x4590, At, BAc, Add, PP, Add, PP), INST(app, 0x4592, At, BAc, Add, PP, Add, PA), INST(app, 0x4593, At, BAc, Add, PA, Add, PA), INST(app, 0x5DC2, At, BZr, Add, PP, Sub, PP), INST(app, 0x5DC3, At, BZr, Add, PP, Sub, PA), INST(app, 0x80C6, At, BAc, Sub, PP, Sub, PP), INST(app, 0x82C6, At, BAc, Sub, PP, Sub, PA), INST(app, 0x83C6, At, BAc, Sub, PA, Sub, PA), INST(app, 0x906C, At, BAc, Add, PP, Sub, PP), INST(app, 0x49C2, At, BAc, Sub, PP, Add, PP), INST(app, 0x916C, At, BAc, Add, PP, Sub, PA), INST(app, 0x49C3, At, BAc, Sub, PP, Add, PA), /// <<< add||sub >>> INST(add_add, 0x6F80, At, At, At, At), INST(add_sub, 0x6FA0, At, At, At, At), INST(sub_add, 0x6FC0, At, At, At, At), INST(sub_sub, 0x6FE0, At, At, At, At), /// <<< add||sub sv >>> INST(add_sub_sv, 0x5DB0, At, At, At), INST(sub_add_sv, 0x5DE0, At, At, At), /// <<< add||sub||mov sv >>> INST(sub_add_i_mov_j_sv, 0x8064, At, At, At, At), INST(sub_add_j_mov_i_sv, 0x5D80, At, At, At, At), INST(add_sub_i_mov_j, 0x9070, At, At, At, At), INST(add_sub_j_mov_i, 0x5E30, At, At, At, At), // <<< Mul >>> INST(mul, 0x8000, At, At, At, At, At), INST(mul_y0, 0x8020, At, At, At, At), INST(mul_y0, 0x8040, At, At, At), INST(mul, 0xD000, At, At, At, At, At, At), INST(mul_y0_r6, 0x5EA0, At, At), INST(mul_y0, 0xE000, At, At, At), // <<< Mul Extra >>> INST(mpyi, 0x0800, At), INST(msu, 0xD080, At, At, At, At, At), INST(msu, 0x90C0, At, At, At, At), INST(msusu, 0x8264, At, At, At), INST(mac_x1to0, 0x4D84, At, Unused<0>), INST(mac1, 0x5E28, At, At, At, At), // <<< MODA >>> INST(moda4, 0x6700, At, At, At) .EXCEPT(AtConst), INST(moda3, 0x6F00, At, At, At), INST(pacr1, 0xD7C2, At), INST(clr, 0x8ED0, At, At), INST(clrr, 0x8DD0, At, At), // <<< Block repeat >>> INST(bkrep, 0x5C00, At, At), INST(bkrep, 0x5D00, At, At, At), INST(bkrep_r6, 0x8FDC, At, At), INST(bkreprst, 0xDA9C, At), INST(bkreprst_memsp, 0x5F48, Unused<0>, Unused<1>), INST(bkrepsto, 0xDADC, At, Unused<10>), INST(bkrepsto_memsp, 0x9468, Unused<0>, Unused<1>, Unused<2>), // <<< Bank >>> INST(banke, 0x4B80, At), INST(bankr, 0x8CDF), INST(bankr, 0x8CDC, At), INST(bankr, 0x8CD0, At, At), INST(bankr, 0x8CD8, At), // <<< Bitrev >>> INST(bitrev, 0x5EB8, At), INST(bitrev_dbrv, 0xD7E8, At), INST(bitrev_ebrv, 0xD7E0, At), // <<< Branching >>> INST(br, 0x4180, At, At, At), INST(brr, 0x5000, At, At), // <<< Break >>> INST(break_, 0xD3C0), // <<< Call >>> INST(call, 0x41C0, At, At, At), INST(calla, 0xD480, At), INST(calla, 0xD381, At), INST(callr, 0x1000, At, At), // <<< Context >>> INST(cntx_s, 0xD380), INST(cntx_r, 0xD390), // <<< Return >>> INST(ret, 0x4580, At), INST(retd, 0xD780), INST(reti, 0x45C0, At), INST(retic, 0x45D0, At), INST(retid, 0xD7C0), INST(retidc, 0xD3C3), INST(rets, 0x0900, At), // <<< Load >>> INST(load_ps, 0x4D80, At), INST(load_stepi, 0xDB80, At), INST(load_stepj, 0xDF80, At), INST(load_page, 0x0400, At), INST(load_modi, 0x0200, At), INST(load_modj, 0x0A00, At), INST(load_movpd, 0xD7D8, At, Unused<0>), INST(load_ps01, 0x0010, At), // <<< Push >>> INST(push, 0x5F40, At), INST(push, 0x5E40, At), INST(push, 0xD7C8, At, Unused<0>), INST(push, 0xD3D0, At), INST(push_prpage, 0xD7FC, Unused<0>, Unused<1>), INST(push, 0xD78C, At, Unused<0>), INST(push_r6, 0xD4D7, Unused<5>), INST(push_repc, 0xD7F8, Unused<0>, Unused<1>), INST(push_x0, 0xD4D4, Unused<5>), INST(push_x1, 0xD4D5, Unused<5>), INST(push_y1, 0xD4D6, Unused<5>), INST(pusha, 0x4384, At, Unused<0>, Unused<1>), INST(pusha, 0xD788, At, Unused<0>), // <<< Pop >>> INST(pop, 0x5E60, At), INST(pop, 0x47B4, At), INST(pop, 0x80C7, At), INST(pop, 0x0006, At, Unused<0>), INST(pop_prpage, 0xD7F4, Unused<0>, Unused<1>), INST(pop, 0xD496, At), INST(pop_r6, 0x0024, Unused<0>), INST(pop_repc, 0xD7F0, Unused<0>, Unused<1>), INST(pop_x0, 0xD494), INST(pop_x1, 0xD495), INST(pop_y1, 0x0004, Unused<0>), INST(popa, 0x47B0, At), // <<< Repeat >>> INST(rep, 0x0C00, At), INST(rep, 0x0D00, At), INST(rep_r6, 0x0002, Unused<0>), // <<< Shift >>> INST(shfc, 0xD280, At, At, At), INST(shfi, 0x9240, At, At, At), // <<< TSTB >>> INST(tst4b, 0x80C1, At, At), INST(tst4b, 0x4780, At, At, At), INST(tstb, 0xF000, At, At), INST(tstb, 0x9020, At, At, At), INST(tstb, 0x9000, At, At) .EXCEPT(AtConst), // override by tstb_r6 INST(tstb_r6, 0x9018, At), INST(tstb, 0x0028, At, At), // unused12@20 // <<< AND Extra >>> INST(and_, 0x6770, At, At, At), // <<< Interrupt >>> INST(dint, 0x43C0), INST(eint, 0x4380), // <<< EXP >>> INST(exp, 0x9460, At), INST(exp, 0x9060, At, At), INST(exp, 0x9C40, At, At), INST(exp, 0x9840, At, At, At), INST(exp, 0x9440, At), INST(exp, 0x9040, At, At), INST(exp_r6, 0xD7C1), INST(exp_r6, 0xD382, At), // <<< MODR >>> INST(modr, 0x0080, At, At), INST(modr_dmod, 0x00A0, At, At), INST(modr_i2, 0x4990, At), INST(modr_i2_dmod, 0x4998, At), INST(modr_d2, 0x5DA0, At), INST(modr_d2_dmod, 0x5DA8, At), INST(modr_eemod, 0xD294, At, At, At), INST(modr_edmod, 0x0D80, At, At, At), INST(modr_demod, 0x8464, At, At, At), INST(modr_ddmod, 0x0D81, At, At, At), // <<< MOV >>> INST(mov, 0xD290, At, At), INST(mov_dvm, 0xD298, At), INST(mov_x0, 0xD2D8, At), INST(mov_x1, 0xD394, At), INST(mov_y1, 0xD384, At), INST(mov, 0x3000, At, At), INST(mov, 0xD4BC, At, At), INST(mov, 0xD49C, At, At), INST(mov, 0xDC80, At, At), INST(mov, 0xD4B8, At, At), INST(mov, 0x6100, At, At), INST(mov, 0x6200, At, At), INST(mov_eu, 0x6500, At, At), INST(mov, 0x6000, At, At), INST(mov_sv, 0x6D00, At), INST(mov_dvm_to, 0xD491, At), INST(mov_icr_to, 0xD492, At), INST(mov, 0x5E20, At, At), INST(mov, 0x5E00, At, At), INST(mov_icr, 0x4F80, At), INST(mov, 0x2500, At, At), INST(mov_ext0, 0x2900, At), INST(mov_ext1, 0x2D00, At), INST(mov_ext2, 0x3900, At), INST(mov_ext3, 0x3D00, At), INST(mov, 0x2300, At, At), INST(mov_sv, 0x0500, At), INST(mov, 0x2100, At, At), INST(mov, 0xD498, At, At), INST(mov, 0xD880, At, At), INST(mov, 0x98C0, At, At, At), INST(mov, 0x1C00, At, At, At), INST(mov_memsp_to, 0x47E0, At), INST(mov_mixp_to, 0x47C0, At), INST(mov, 0x2000, At, At), INST(mov_icr, 0x4FC0, At), INST(mov_mixp, 0x5E80, At), INST(mov, 0x1800, At, At, At) .EXCEPT(AtConst).EXCEPT(AtConst), // override by mov_r6(_to) INST(mov, 0x5EC0, At, At), INST(mov, 0x5800, At, At) .EXCEPT(AtConst).EXCEPT(AtConst), // override by mma_mov INST(mov_repc_to, 0xD490, At), INST(mov_sv_to, 0x7D00, At), INST(mov_x0_to, 0xD493, At), INST(mov_x1_to, 0x49C1, At), INST(mov_y1_to, 0xD299, At), // <<< MOV load >>> INST(mov, 0x0008, At, At), INST(mov_r6, 0x0023, At), INST(mov_repc, 0x0001, At), INST(mov_stepi0, 0x8971, At), INST(mov_stepj0, 0x8979, At), INST(mov, 0x0030, At, At), INST(mov_prpage, 0x5DD0, At), // <<< <<< MOV p/d >>> INST(movd, 0x5F80, At, At, At, At), INST(movp, 0x0040, At, At), INST(movp, 0x0D40, At, At), INST(movp, 0x0600, At, At, At, At), INST(movpdw, 0xD499, At), // <<< MOV 2 >>> INST(mov_a0h_stepi0, 0xD49B), INST(mov_a0h_stepj0, 0xD59B), INST(mov_stepi0_a0h, 0xD482), INST(mov_stepj0_a0h, 0xD582), INST(mov_prpage, 0x9164, At), INST(mov_repc, 0x9064, At), INST(mov, 0x9540, At, At), INST(mov, 0x9C60, At, At), INST(mov_prpage_to, 0x5EB0, At), INST(mov_repc_to, 0xD2D9, At), INST(mov, 0x9560, At, At), INST(mov, 0xD2F8, At, At), INST(mov_repc_to, 0xD7D0, At, At), INST(mov, 0xD488, At, At, At), INST(mov, 0x49A0, At, At, At), INST(mov_repc, 0xD7D4, At, At), INST(mov, 0x8062, At, At, At), INST(mov, 0x8063, At, At, At), INST(mov_repc_to, 0xD3C8, At, Unused<0>, Unused<1>, Unused<2>), INST(mov, 0x5F50, At, At), INST(mov_repc, 0xD2DC, At, Unused<0>, Unused<1>, Unused<10>), INST(mov, 0x4D90, At, At), INST(mov_pc, 0x886B, At), INST(mov_pc, 0x8863, At), INST(mov_mixp_to, 0x8A73, At), INST(mov_mixp_r6, 0x4381), INST(mov_p0h_to, 0x4382, At), INST(mov_p0h_r6, 0xD3C2), INST(mov_p0h_to, 0x4B60, At), INST(mov_p0, 0x8FD4, At), INST(mov_p1_to, 0x8FD8, At), INST(mov2, 0x88D0, At, At, At), INST(mov2s, 0x88D1, At, At, At), INST(mov2, 0xD292, At, At, At), INST(mova, 0x4DC0, At, At, At), INST(mova, 0x4BC0, At, At, At), INST(mov_r6_to, 0xD481, At), INST(mov_r6_mixp, 0x43C1), INST(mov_r6_to, 0x5F00, At), INST(mov_r6, 0x5F60, At), INST(mov_memsp_r6, 0xD29C, Unused<0>, Unused<1>, Unused<10>), INST(mov_r6_to, 0x1B00, At, At), INST(mov_r6, 0x1B20, At, At), INST(movs, 0x6300, At, At), INST(movs, 0x0180, At, At, At), INST(movs, 0x0100, At, At), INST(movs_r6_to, 0x5F42, At), INST(movsi, 0x4080, At, At, At), // <<< MOV MOV >>> INST(mov2_axh_m_y0_m, 0x4390, At, At, At), INST(mov2_ax_mij, 0x43A0, At, At, At, At), INST(mov2_ax_mji, 0x43E0, At, At, At, At), INST(mov2_mij_ax, 0x80C4, At, At, At, At), INST(mov2_mji_ax, 0xD4C0, At, At, At, At), INST(mov2_abh_m, 0x9D40, At, At, At, At), INST(exchange_iaj, 0x8C60, At, At, At, At), INST(exchange_riaj, 0x7F80, At, At, At, At), INST(exchange_jai, 0x4900, At, At, At, At), INST(exchange_rjai, 0x4800, At, At, At, At), // <<< MOVR >>> INST(movr, 0x8864, At, At, At), INST(movr, 0x9CE0, At, At, At), INST(movr, 0x9CC0, At, At), INST(movr, 0x5DF4, At, At), INST(movr_r6_to, 0x8961, At), // <<< LIM >>> INST(lim, 0x49C0, At, At), // <<< Viterbi >>> INST(vtrclr0, 0x5F45), INST(vtrclr1, 0x5F46), INST(vtrclr, 0x5F47), INST(vtrmov0, 0xD29A, At), INST(vtrmov1, 0xD69A, At), INST(vtrmov, 0xD383, At), INST(vtrshr, 0xD781), // <<< CLRP >>> INST(clrp0, 0x5DFE), INST(clrp1, 0x5DFD), INST(clrp, 0x5DFF), // <<< min/max >>> INST(max_ge, 0x8460, At, At), INST(max_gt, 0x8660, At, At), INST(min_le, 0x8860, At, At), INST(min_lt, 0x8A60, At, At), INST(max_ge_r0, 0x8060, At, At), INST(max_gt_r0, 0x8260, At, At), INST(min_le_r0, 0x47A0, At, At), INST(min_lt_r0, 0x47A4, At, At), // <<< Division Step >>> INST(divs, 0x0E00, At, At), // <<< Sqr >>> INST(sqr_sqr_add3, 0xD790, At, At), INST(sqr_sqr_add3, 0x4B00, At, At, At), INST(sqr_mpysu_add3a, 0x49C4, At, At), // <<< CMP Extra >>> INST(cmp, 0x4D8C, At, At), INST(cmp_b0_b1, 0xD483), INST(cmp_b1_b0, 0xD583), INST(cmp, 0xDA9A, At, At), INST(cmp_p1_to, 0x8B63, At), // <<< min||max||vtrshr >>> INST(max2_vtr, 0x5E21, At), INST(min2_vtr, 0x43C2, At), INST(max2_vtr, 0xD784, At, At), INST(min2_vtr, 0xD4BA, At, At), INST(max2_vtr_movl, 0x4A40, At, At, At, At), INST(max2_vtr_movh, 0x4A44, At, At, At, At), INST(max2_vtr_movl, 0x4A60, At, At, At, At), INST(max2_vtr_movh, 0x4A64, At, At, At, At), INST(min2_vtr_movl, 0x4A00, At, At, At, At), INST(min2_vtr_movh, 0x4A04, At, At, At, At), INST(min2_vtr_movl, 0x4A20, At, At, At, At), INST(min2_vtr_movh, 0x4A24, At, At, At, At), INST(max2_vtr_movij, 0xD590, At, At, At, At, At), INST(max2_vtr_movji, 0x45A0, At, At, At, At, At), INST(min2_vtr_movij, 0xD2B8, At, At, At, At, At), INST(min2_vtr_movji, 0x45E0, At, At, At, At, At), // <<< MOV ADDSUB >>> INST(mov_sv_app, 0x4B40, At, At, At, BSv, Sub, PP, Add, PP), INST(mov_sv_app, 0x9960, At, At, At, BSv, Sub, PP, Add, PP), INST(mov_sv_app, 0x4B42, At, At, At, BSr, Sub, PP, Add, PP), INST(mov_sv_app, 0x99E0, At, At, At, BSr, Sub, PP, Add, PP), INST(mov_sv_app, 0x5F4C, At, At, Const, BSv, Sub, PP, Sub, PP), INST(mov_sv_app, 0x8873, At, At, Const, BSv, Sub, PP, Sub, PP), INST(mov_sv_app, 0x9860, At, At, At, BSv, Sub, PP, Sub, PP), INST(mov_sv_app, 0xDE9C, At, At, Const, BSr, Sub, PP, Sub, PP), INST(mov_sv_app, 0xD4B4, At, At, Const, BSr, Sub, PP, Sub, PP), INST(mov_sv_app, 0x98E0, At, At, At, BSr, Sub, PP, Sub, PP), // <<< CBS >>> INST(cbs, 0x9068, At, At), INST(cbs, 0xD49E, At, At, At), INST(cbs, 0xD5C0, At, At, At, At), // [[[XXX_xy_XXX_xy_XXX]]] INST(mma, 0x4D88, AtNamed, SX, SY, SX, SY, BZr, Add, PP, Sub, PP), INST(mma, 0xD49D, AtNamed, SX, SY, SX, SY, BZr, Add, PP, Sub, PP), INST(mma, 0x5E24, AtNamed, SX, SY, SX, SY, BZr, Add, PP, Add, PP), INST(mma, 0x8061, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), INST(mma, 0x8071, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PA), INST(mma, 0x8461, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PP), INST(mma, 0x8471, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PA), INST(mma, 0xD484, AtNamed, SX, SY, SX, SY, BAc, Add, PA, Add, PA), INST(mma, 0xD4A0, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Sub, PP), INST(mma, 0x4D89, AtNamed, SX, SY, SX, UY, BZr, Add, PP, Sub, PP), INST(mma, 0xD59D, AtNamed, SX, SY, SX, UY, BZr, Add, PP, Sub, PP), INST(mma, 0x5F24, AtNamed, SX, SY, SX, UY, BZr, Add, PP, Add, PP), INST(mma, 0x8069, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PP), INST(mma, 0x8079, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PA), INST(mma, 0x8469, AtNamed, SX, SY, SX, UY, BAc, Sub, PP, Sub, PP), INST(mma, 0x8479, AtNamed, SX, SY, SX, UY, BAc, Sub, PP, Sub, PA), INST(mma, 0xD584, AtNamed, SX, SY, SX, UY, BAc, Add, PA, Add, PA), INST(mma, 0xD5A0, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Sub, PP), // [[[XXX_mm_XXX_mm_XXX]]] INST(mma, 0xCA00, At, At, At, EMod, EMod, AtNamed, UX, SY, UX, SY, BAc, Sub, PP, Sub, PA), INST(mma, 0xCA01, At, At, At, EMod, EMod, AtNamed, UX, SY, SX, UY, BAc, Sub, PP, Sub, PA), INST(mma, 0xCA02, At, At, At, EMod, EMod, AtNamed, UX, SY, UX, SY, BAc, Sub, PA, Sub, PA), INST(mma, 0xCA03, At, At, At, EMod, EMod, AtNamed, UX, SY, SX, UY, BAc, Sub, PA, Sub, PA), INST(mma, 0xCA04, At, At, At, EMod, EMod, AtNamed, UX, SY, UX, SY, BAc, Add, PP, Add, PA), INST(mma, 0xCA05, At, At, At, EMod, EMod, AtNamed, UX, SY, SX, UY, BAc, Add, PP, Add, PA), INST(mma, 0xCA06, At, At, At, EMod, EMod, AtNamed, UX, SY, UX, SY, BAc, Add, PA, Add, PA), INST(mma, 0xCA07, At, At, At, EMod, EMod, AtNamed, UX, SY, SX, UY, BAc, Add, PA, Add, PA), INST(mma, 0xCB00, At, At, At, EMod, EMod, AtNamed, SX, SY, UX, SY, BAc, Sub, PP, Sub, PP), INST(mma, 0xCB01, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, UY, BAc, Sub, PP, Sub, PP), INST(mma, 0xCB02, At, At, At, EMod, EMod, AtNamed, SX, SY, UX, SY, BAc, Sub, PP, Sub, PA), INST(mma, 0xCB03, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, UY, BAc, Sub, PP, Sub, PA), INST(mma, 0xCB04, At, At, At, EMod, EMod, AtNamed, SX, SY, UX, SY, BAc, Add, PP, Add, PP), INST(mma, 0xCB05, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PP), INST(mma, 0xCB06, At, At, At, EMod, EMod, AtNamed, SX, SY, UX, SY, BAc, Add, PP, Add, PA), INST(mma, 0xCB07, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PA), INST(mma, 0x0D30, At, At, At, EMod, DMod, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PA), INST(mma, 0x0D20, At, At, At, DMod, EMod, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PA), INST(mma, 0x4B50, At, At, At, DMod, DMod, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PA), INST(mma, 0x9861, At, At, At, EMod, DMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), INST(mma, 0x9862, At, At, At, DMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), INST(mma, 0x9863, At, At, At, DMod, DMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), INST(mma, 0x98E1, At, At, At, EMod, DMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PA), INST(mma, 0x98E2, At, At, At, DMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PA), INST(mma, 0x98E3, At, At, At, DMod, DMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PA), INST(mma, 0x80C8, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Sub, PP), INST(mma, 0x81C8, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Sub, PA), INST(mma, 0x82C8, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BZr, Add, PP, Add, PP), INST(mma, 0x83C8, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BZr, Add, PP, Add, PA), INST(mma, 0x80C2, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PA), INST(mma, 0x49C8, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PA), INST(mma, 0x00C0, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BZr, Add, PP, Sub, PP), INST(mma, 0x00C1, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BZr, Add, PP, Sub, PA), INST(mma, 0xD7A0, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BSv, Add, PP, Add, PP), INST(mma, 0xD7A1, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BSr, Add, PP, Add, PP), INST(mma, 0xC800, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), INST(mma, 0xC900, At, At, At, EMod, EMod, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PP), // [[[XXX_mx_XXX_xy_XXX]]] INST(mma_mx_xy, 0xD5E0, At, At, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PP), INST(mma_mx_xy, 0xD5E4, At, At, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), // [[[XXX_xy_XXX_mx_XXX]]] INST(mma_xy_mx, 0x8862, At, At, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PP), INST(mma_xy_mx, 0x8A62, At, At, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), // [[[XXX_my_XXX_my_XXX]]] INST(mma_my_my, 0x4DA0, At, At, AtNamed, SX, SY, SX, UY, BAc, Sub, PP, Sub, PP), INST(mma_my_my, 0x4DA1, At, At, AtNamed, SX, SY, SX, UY, BAc, Sub, PP, Sub, PA), INST(mma_my_my, 0x4DA2, At, At, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PP), INST(mma_my_my, 0x4DA3, At, At, AtNamed, SX, SY, SX, UY, BAc, Add, PP, Add, PA), INST(mma_my_my, 0x94E0, At, At, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PP), INST(mma_my_my, 0x94E1, At, At, AtNamed, SX, SY, UX, SY, BAc, Sub, PP, Sub, PP), INST(mma_my_my, 0x94E2, At, At, AtNamed, SX, SY, SX, SY, BAc, Sub, PP, Sub, PA), INST(mma_my_my, 0x94E3, At, At, AtNamed, SX, SY, UX, SY, BAc, Sub, PP, Sub, PA), INST(mma_my_my, 0x94E4, At, At, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), INST(mma_my_my, 0x94E5, At, At, AtNamed, SX, SY, UX, SY, BAc, Add, PP, Add, PP), INST(mma_my_my, 0x94E6, At, At, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PA), INST(mma_my_my, 0x94E7, At, At, AtNamed, SX, SY, UX, SY, BAc, Add, PP, Add, PA), // [[[XXX_xy_XXX_xy_XXX_mov]]] INST(mma_mov, 0x4FA0, At, At, At, At, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Add, PP), INST(mma_mov, 0xD3A0, At, At, At, At, AtNamed, SX, SY, SX, SY, BAc, Add, PP, Sub, PP), INST(mma_mov, 0x80D0, At, At, At, At, AtNamed, SX, SY, SX, SY, BSv, Add, PP, Sub, PP), INST(mma_mov, 0x80D1, At, At, At, At, AtNamed, SX, SY, SX, SY, BSr, Add, PP, Sub, PP), INST(mma_mov, 0x80D2, At, At, At, At, AtNamed, SX, SY, SX, SY, BSv, Add, PP, Add, PP), INST(mma_mov, 0x80D3, At, At, At, At, AtNamed, SX, SY, SX, SY, BSr, Add, PP, Add, PP), INST(mma_mov, 0x5818, At, At, AtNamed, SX, SY, SX, SY, BSv, Add, PP, Sub, PP), INST(mma_mov, 0x5838, At, At, AtNamed, SX, SY, SX, SY, BSr, Add, PP, Sub, PP), INST(addhp, 0x90E0, At, At, At, At), }; #undef INST #undef EXCEPT } // clang-format on template Matcher Decode(u16 instruction) { static const auto table = GetDecodeTable(); const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); }; auto iter = std::find_if(table.begin(), table.end(), matches_instruction); if (iter == table.end()) { return Matcher::AllMatcher([](V& v, u16 opcode, u16) { return v.undefined(opcode); }); } else { auto other = std::find_if(iter + 1, table.end(), matches_instruction); ASSERT(other == table.end()); return *iter; } } template std::vector> GetDecoderTable() { std::vector> table; table.reserve(0x10000); for (u32 i = 0; i < 0x10000; ++i) { table.push_back(Decode((u16)i)); } return table; }