1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include <array>
6 
7 #include "Core/PowerPC/Gekko.h"
8 #include "Core/PowerPC/Interpreter/Interpreter.h"
9 #include "Core/PowerPC/PPCTables.h"
10 
11 namespace
12 {
13 struct GekkoOPTemplate
14 {
15   int opcode;
16   Interpreter::Instruction Inst;
17   GekkoOPInfo opinfo;
18 };
19 }  // namespace
20 
21 // clang-format off
22 static GekkoOPInfo unknownopinfo = { "unknown_instruction", OpType::Unknown, FL_ENDBLOCK, 0, 0, 0, 0 };
23 
24 static std::array<GekkoOPTemplate, 54> primarytable =
25 {{
26 	{4,  Interpreter::RunTable4,    {"RunTable4",  OpType::Subtable, 0, 0, 0, 0, 0}},
27 	{19, Interpreter::RunTable19,   {"RunTable19", OpType::Subtable, 0, 0, 0, 0, 0}},
28 	{31, Interpreter::RunTable31,   {"RunTable31", OpType::Subtable, 0, 0, 0, 0, 0}},
29 	{59, Interpreter::RunTable59,   {"RunTable59", OpType::Subtable, 0, 0, 0, 0, 0}},
30 	{63, Interpreter::RunTable63,   {"RunTable63", OpType::Subtable, 0, 0, 0, 0, 0}},
31 
32 	{16, Interpreter::bcx,          {"bcx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}},
33 	{18, Interpreter::bx,           {"bx",  OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}},
34 
35 	{3,  Interpreter::twi,          {"twi", OpType::System, FL_ENDBLOCK, 1, 0, 0, 0}},
36 	{17, Interpreter::sc,           {"sc",  OpType::System, FL_ENDBLOCK, 2, 0, 0, 0}},
37 
38 	{7,  Interpreter::mulli,        {"mulli",    OpType::Integer, FL_OUT_D | FL_IN_A, 3, 0, 0, 0}},
39 	{8,  Interpreter::subfic,       {"subfic",   OpType::Integer, FL_OUT_D | FL_IN_A | FL_SET_CA, 1, 0, 0, 0}},
40 	{10, Interpreter::cmpli,        {"cmpli",    OpType::Integer, FL_IN_A | FL_SET_CRn, 1, 0, 0, 0}},
41 	{11, Interpreter::cmpi,         {"cmpi",     OpType::Integer, FL_IN_A | FL_SET_CRn, 1, 0, 0, 0}},
42 	{12, Interpreter::addic,        {"addic",    OpType::Integer, FL_OUT_D | FL_IN_A | FL_SET_CA, 1, 0, 0, 0}},
43 	{13, Interpreter::addic_rc,     {"addic_rc", OpType::Integer, FL_OUT_D | FL_IN_A | FL_SET_CA | FL_SET_CR0, 1, 0, 0, 0}},
44 	{14, Interpreter::addi,         {"addi",     OpType::Integer, FL_OUT_D | FL_IN_A0, 1, 0, 0, 0}},
45 	{15, Interpreter::addis,        {"addis",    OpType::Integer, FL_OUT_D | FL_IN_A0, 1, 0, 0, 0}},
46 
47 	{20, Interpreter::rlwimix,      {"rlwimix",  OpType::Integer, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
48 	{21, Interpreter::rlwinmx,      {"rlwinmx",  OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
49 	{23, Interpreter::rlwnmx,       {"rlwnmx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
50 
51 	{24, Interpreter::ori,          {"ori",      OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
52 	{25, Interpreter::oris,         {"oris",     OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
53 	{26, Interpreter::xori,         {"xori",     OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
54 	{27, Interpreter::xoris,        {"xoris",    OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
55 	{28, Interpreter::andi_rc,      {"andi_rc",  OpType::Integer, FL_OUT_A | FL_IN_S | FL_SET_CR0, 1, 0, 0, 0}},
56 	{29, Interpreter::andis_rc,     {"andis_rc", OpType::Integer, FL_OUT_A | FL_IN_S | FL_SET_CR0, 1, 0, 0, 0}},
57 
58 	{32, Interpreter::lwz,          {"lwz",  OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
59 	{33, Interpreter::lwzu,         {"lwzu", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
60 	{34, Interpreter::lbz,          {"lbz",  OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
61 	{35, Interpreter::lbzu,         {"lbzu", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
62 	{40, Interpreter::lhz,          {"lhz",  OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
63 	{41, Interpreter::lhzu,         {"lhzu", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
64 
65 	{42, Interpreter::lha,          {"lha",  OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
66 	{43, Interpreter::lhau,         {"lhau", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
67 
68 	{44, Interpreter::sth,          {"sth",  OpType::Store, FL_IN_A0 | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
69 	{45, Interpreter::sthu,         {"sthu", OpType::Store, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
70 	{36, Interpreter::stw,          {"stw",  OpType::Store, FL_IN_A0 | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
71 	{37, Interpreter::stwu,         {"stwu", OpType::Store, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
72 	{38, Interpreter::stb,          {"stb",  OpType::Store, FL_IN_A0 | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
73 	{39, Interpreter::stbu,         {"stbu", OpType::Store, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
74 
75 	{46, Interpreter::lmw,          {"lmw",   OpType::System, FL_EVIL | FL_IN_A0 | FL_LOADSTORE, 11, 0, 0, 0}},
76 	{47, Interpreter::stmw,         {"stmw",  OpType::System, FL_EVIL | FL_IN_A0 | FL_LOADSTORE, 11, 0, 0, 0}},
77 
78 	{48, Interpreter::lfs,          {"lfs",  OpType::LoadFP, FL_OUT_FLOAT_D | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
79 	{49, Interpreter::lfsu,         {"lfsu", OpType::LoadFP, FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
80 	{50, Interpreter::lfd,          {"lfd",  OpType::LoadFP, FL_INOUT_FLOAT_D | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
81 	{51, Interpreter::lfdu,         {"lfdu", OpType::LoadFP, FL_INOUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
82 
83 	{52, Interpreter::stfs,         {"stfs",  OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
84 	{53, Interpreter::stfsu,        {"stfsu", OpType::StoreFP, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
85 	{54, Interpreter::stfd,         {"stfd",  OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
86 	{55, Interpreter::stfdu,        {"stfdu", OpType::StoreFP, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
87 
88 	{56, Interpreter::psq_l,        {"psq_l",   OpType::LoadPS, FL_OUT_FLOAT_D | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
89 	{57, Interpreter::psq_lu,       {"psq_lu",  OpType::LoadPS, FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
90 	{60, Interpreter::psq_st,       {"psq_st",  OpType::StorePS, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
91 	{61, Interpreter::psq_stu,      {"psq_stu", OpType::StorePS, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
92 
93 	//missing: 0, 1, 2, 5, 6, 9, 22, 30, 62, 58
94 }};
95 
96 static std::array<GekkoOPTemplate, 13> table4 =
97 {{    //SUBOP10
98 	{0,    Interpreter::ps_cmpu0,   {"ps_cmpu0",   OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 1, 0, 0, 0}},
99 	{32,   Interpreter::ps_cmpo0,   {"ps_cmpo0",   OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 1, 0, 0, 0}},
100 	{40,   Interpreter::ps_neg,     {"ps_neg",     OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
101 	{136,  Interpreter::ps_nabs,    {"ps_nabs",    OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
102 	{264,  Interpreter::ps_abs,     {"ps_abs",     OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
103 	{64,   Interpreter::ps_cmpu1,   {"ps_cmpu1",   OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 1, 0, 0, 0}},
104 	{72,   Interpreter::ps_mr,      {"ps_mr",      OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
105 	{96,   Interpreter::ps_cmpo1,   {"ps_cmpo1",   OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 1, 0, 0, 0}},
106 	{528,  Interpreter::ps_merge00, {"ps_merge00", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
107 	{560,  Interpreter::ps_merge01, {"ps_merge01", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
108 	{592,  Interpreter::ps_merge10, {"ps_merge10", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
109 	{624,  Interpreter::ps_merge11, {"ps_merge11", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
110 
111 	{1014, Interpreter::dcbz_l,     {"dcbz_l",     OpType::System, FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
112 }};
113 
114 static std::array<GekkoOPTemplate, 17> table4_2 =
115 {{
116 	{10, Interpreter::ps_sum0,      {"ps_sum0",   OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
117 	{11, Interpreter::ps_sum1,      {"ps_sum1",   OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
118 	{12, Interpreter::ps_muls0,     {"ps_muls0",  OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
119 	{13, Interpreter::ps_muls1,     {"ps_muls1",  OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
120 	{14, Interpreter::ps_madds0,    {"ps_madds0", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
121 	{15, Interpreter::ps_madds1,    {"ps_madds1", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
122 	{18, Interpreter::ps_div,       {"ps_div",    OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 17, 0, 0, 0}},
123 	{20, Interpreter::ps_sub,       {"ps_sub",    OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
124 	{21, Interpreter::ps_add,       {"ps_add",    OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
125 	{23, Interpreter::ps_sel,       {"ps_sel",    OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
126 	{24, Interpreter::ps_res,       {"ps_res",    OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
127 	{25, Interpreter::ps_mul,       {"ps_mul",    OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
128 	{26, Interpreter::ps_rsqrte,    {"ps_rsqrte", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 2, 0, 0, 0}},
129 	{28, Interpreter::ps_msub,      {"ps_msub",   OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
130 	{29, Interpreter::ps_madd,      {"ps_madd",   OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
131 	{30, Interpreter::ps_nmsub,     {"ps_nmsub",  OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
132 	{31, Interpreter::ps_nmadd,     {"ps_nmadd",  OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
133 }};
134 
135 
136 static std::array<GekkoOPTemplate, 4> table4_3 =
137 {{
138 	{6,  Interpreter::psq_lx,       {"psq_lx",   OpType::LoadPS, FL_OUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
139 	{7,  Interpreter::psq_stx,      {"psq_stx",  OpType::StorePS, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
140 	{38, Interpreter::psq_lux,      {"psq_lux",  OpType::LoadPS, FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_AB | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
141 	{39, Interpreter::psq_stux,     {"psq_stux", OpType::StorePS, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_AB | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
142 }};
143 
144 static std::array<GekkoOPTemplate, 13> table19 =
145 {{
146 	{528, Interpreter::bcctrx,      {"bcctrx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}},
147 	{16,  Interpreter::bclrx,       {"bclrx",  OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}},
148 	{257, Interpreter::crand,       {"crand",  OpType::CR, FL_EVIL, 1, 0, 0, 0}},
149 	{129, Interpreter::crandc,      {"crandc", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
150 	{289, Interpreter::creqv,       {"creqv",  OpType::CR, FL_EVIL, 1, 0, 0, 0}},
151 	{225, Interpreter::crnand,      {"crnand", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
152 	{33,  Interpreter::crnor,       {"crnor",  OpType::CR, FL_EVIL, 1, 0, 0, 0}},
153 	{449, Interpreter::cror,        {"cror",   OpType::CR, FL_EVIL, 1, 0, 0, 0}},
154 	{417, Interpreter::crorc,       {"crorc",  OpType::CR, FL_EVIL, 1, 0, 0, 0}},
155 	{193, Interpreter::crxor,       {"crxor",  OpType::CR, FL_EVIL, 1, 0, 0, 0}},
156 
157 	{150, Interpreter::isync,       {"isync",  OpType::InstructionCache, FL_EVIL, 1, 0, 0, 0}},
158 	{0,   Interpreter::mcrf,        {"mcrf",   OpType::System, FL_EVIL | FL_SET_CRn, 1, 0, 0, 0}},
159 
160 	{50,  Interpreter::rfi,         {"rfi",    OpType::System, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 2, 0, 0, 0}},
161 }};
162 
163 static std::array<GekkoOPTemplate, 107> table31 =
164 {{
165 	{266,  Interpreter::addx,       {"addx",    OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 1, 0, 0, 0}},
166 	{778,  Interpreter::addx,       {"addox",   OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
167 	{10,   Interpreter::addcx,      {"addcx",   OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
168 	{522,  Interpreter::addcx,      {"addcox",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
169 	{138,  Interpreter::addex,      {"addex",   OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
170 	{650,  Interpreter::addex,      {"addeox",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
171 	{234,  Interpreter::addmex,     {"addmex",  OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
172 	{746,  Interpreter::addmex,     {"addmeox", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
173 	{202,  Interpreter::addzex,     {"addzex",  OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
174 	{714,  Interpreter::addzex,     {"addzeox", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
175 	{491,  Interpreter::divwx,      {"divwx",   OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 40, 0, 0, 0}},
176 	{1003, Interpreter::divwx,      {"divwox",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 40, 0, 0, 0}},
177 	{459,  Interpreter::divwux,     {"divwux",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 40, 0, 0, 0}},
178 	{971,  Interpreter::divwux,     {"divwuox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 40, 0, 0, 0}},
179 	{75,   Interpreter::mulhwx,     {"mulhwx",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 5, 0, 0, 0}},
180 	{11,   Interpreter::mulhwux,    {"mulhwux", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 5, 0, 0, 0}},
181 	{235,  Interpreter::mullwx,     {"mullwx",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 5, 0, 0, 0}},
182 	{747,  Interpreter::mullwx,     {"mullwox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 5, 0, 0, 0}},
183 	{104,  Interpreter::negx,       {"negx",    OpType::Integer, FL_OUT_D | FL_IN_A | FL_RC_BIT, 1, 0, 0, 0}},
184 	{616,  Interpreter::negx,       {"negox",   OpType::Integer, FL_OUT_D | FL_IN_A | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
185 	{40,   Interpreter::subfx,      {"subfx",   OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 1, 0, 0, 0}},
186 	{552,  Interpreter::subfx,      {"subfox",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
187 	{8,    Interpreter::subfcx,     {"subfcx",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
188 	{520,  Interpreter::subfcx,     {"subfcox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
189 	{136,  Interpreter::subfex,     {"subfex",  OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
190 	{648,  Interpreter::subfex,     {"subfeox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
191 	{232,  Interpreter::subfmex,    {"subfmex", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
192 	{744,  Interpreter::subfmex,    {"subfmeox",OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
193 	{200,  Interpreter::subfzex,    {"subfzex", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
194 	{712,  Interpreter::subfzex,    {"subfzeox",OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
195 
196 	{28,  Interpreter::andx,        {"andx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
197 	{60,  Interpreter::andcx,       {"andcx",  OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
198 	{444, Interpreter::orx,         {"orx",    OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
199 	{124, Interpreter::norx,        {"norx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
200 	{316, Interpreter::xorx,        {"xorx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
201 	{412, Interpreter::orcx,        {"orcx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
202 	{476, Interpreter::nandx,       {"nandx",  OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
203 	{284, Interpreter::eqvx,        {"eqvx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
204 	{0,   Interpreter::cmp,         {"cmp",    OpType::Integer, FL_IN_AB | FL_SET_CRn, 1, 0, 0, 0}},
205 	{32,  Interpreter::cmpl,        {"cmpl",   OpType::Integer, FL_IN_AB | FL_SET_CRn, 1, 0, 0, 0}},
206 	{26,  Interpreter::cntlzwx,     {"cntlzwx",OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
207 	{922, Interpreter::extshx,      {"extshx", OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
208 	{954, Interpreter::extsbx,      {"extsbx", OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
209 	{536, Interpreter::srwx,        {"srwx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
210 	{792, Interpreter::srawx,       {"srawx",  OpType::Integer, FL_OUT_A | FL_IN_SB | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
211 	{824, Interpreter::srawix,      {"srawix", OpType::Integer, FL_OUT_A | FL_IN_S | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
212 	{24,  Interpreter::slwx,        {"slwx",   OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
213 
214 	{54,   Interpreter::dcbst,      {"dcbst",  OpType::DataCache, FL_IN_A0B | FL_LOADSTORE, 5, 0, 0, 0}},
215 	{86,   Interpreter::dcbf,       {"dcbf",   OpType::DataCache, FL_IN_A0B | FL_LOADSTORE, 5, 0, 0, 0}},
216 	{246,  Interpreter::dcbtst,     {"dcbtst", OpType::DataCache, 0, 2, 0, 0, 0}},
217 	{278,  Interpreter::dcbt,       {"dcbt",   OpType::DataCache, 0, 2, 0, 0, 0}},
218 	{470,  Interpreter::dcbi,       {"dcbi",   OpType::DataCache, FL_IN_A0B | FL_LOADSTORE, 5, 0, 0, 0}},
219 	{758,  Interpreter::dcba,       {"dcba",   OpType::DataCache, 0, 5, 0, 0, 0}},
220 	{1014, Interpreter::dcbz,       {"dcbz",   OpType::DataCache, FL_IN_A0B | FL_LOADSTORE, 5, 0, 0, 0}},
221 
222 	//load word
223 	{23,  Interpreter::lwzx,        {"lwzx",  OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
224 	{55,  Interpreter::lwzux,       {"lwzux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
225 
226 	//load halfword
227 	{279, Interpreter::lhzx,        {"lhzx",  OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
228 	{311, Interpreter::lhzux,       {"lhzux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
229 
230 	//load halfword signextend
231 	{343, Interpreter::lhax,        {"lhax",  OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
232 	{375, Interpreter::lhaux,       {"lhaux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
233 
234 	//load byte
235 	{87,  Interpreter::lbzx,        {"lbzx",  OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
236 	{119, Interpreter::lbzux,       {"lbzux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
237 
238 	//load byte reverse
239 	{534, Interpreter::lwbrx,       {"lwbrx", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
240 	{790, Interpreter::lhbrx,       {"lhbrx", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
241 
242 	// Conditional load/store (Wii SMP)
243 	{150, Interpreter::stwcxd,      {"stwcxd", OpType::Store, FL_EVIL | FL_IN_S | FL_IN_A0B | FL_SET_CR0 | FL_LOADSTORE, 1, 0, 0, 0}},
244 	{20,  Interpreter::lwarx,       {"lwarx",  OpType::Load, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0 | FL_LOADSTORE, 1, 0, 0, 0}},
245 
246 	//load string (Inst these)
247 	{533, Interpreter::lswx,        {"lswx",  OpType::Load, FL_EVIL | FL_IN_A0B | FL_OUT_D | FL_LOADSTORE, 1, 0, 0, 0}},
248 	{597, Interpreter::lswi,        {"lswi",  OpType::Load, FL_EVIL | FL_IN_A0 | FL_OUT_D | FL_LOADSTORE, 1, 0, 0, 0}},
249 
250 	//store word
251 	{151, Interpreter::stwx,        {"stwx",   OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
252 	{183, Interpreter::stwux,       {"stwux",  OpType::Store, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
253 
254 	//store halfword
255 	{407, Interpreter::sthx,        {"sthx",   OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
256 	{439, Interpreter::sthux,       {"sthux",  OpType::Store, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
257 
258 	//store byte
259 	{215, Interpreter::stbx,        {"stbx",   OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
260 	{247, Interpreter::stbux,       {"stbux",  OpType::Store, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
261 
262 	//store bytereverse
263 	{662, Interpreter::stwbrx,      {"stwbrx", OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
264 	{918, Interpreter::sthbrx,      {"sthbrx", OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
265 
266 	{661, Interpreter::stswx,       {"stswx",  OpType::Store, FL_EVIL | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
267 	{725, Interpreter::stswi,       {"stswi",  OpType::Store, FL_EVIL | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
268 
269 	// fp load/store
270 	{535, Interpreter::lfsx,        {"lfsx",  OpType::LoadFP, FL_OUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
271 	{567, Interpreter::lfsux,       {"lfsux", OpType::LoadFP, FL_OUT_FLOAT_D | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
272 	{599, Interpreter::lfdx,        {"lfdx",  OpType::LoadFP, FL_INOUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
273 	{631, Interpreter::lfdux,       {"lfdux", OpType::LoadFP, FL_INOUT_FLOAT_D | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
274 
275 	{663, Interpreter::stfsx,       {"stfsx",  OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
276 	{695, Interpreter::stfsux,      {"stfsux", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
277 	{727, Interpreter::stfdx,       {"stfdx",  OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
278 	{759, Interpreter::stfdux,      {"stfdux", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
279 	{983, Interpreter::stfiwx,      {"stfiwx", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
280 
281 	{19,  Interpreter::mfcr,        {"mfcr",   OpType::System, FL_OUT_D, 1, 0, 0, 0}},
282 	{83,  Interpreter::mfmsr,       {"mfmsr",  OpType::System, FL_OUT_D, 1, 0, 0, 0}},
283 	{144, Interpreter::mtcrf,       {"mtcrf",  OpType::System, FL_IN_S | FL_SET_CRn, 1, 0, 0, 0}},
284 	{146, Interpreter::mtmsr,       {"mtmsr",  OpType::System, FL_IN_S | FL_ENDBLOCK, 1, 0, 0, 0}},
285 	{210, Interpreter::mtsr,        {"mtsr",   OpType::System, FL_IN_S, 1, 0, 0, 0}},
286 	{242, Interpreter::mtsrin,      {"mtsrin", OpType::System, FL_IN_SB, 1, 0, 0, 0}},
287 	{339, Interpreter::mfspr,       {"mfspr",  OpType::SPR, FL_OUT_D, 1, 0, 0, 0}},
288 	{467, Interpreter::mtspr,       {"mtspr",  OpType::SPR, FL_IN_S, 2, 0, 0, 0}},
289 	{371, Interpreter::mftb,        {"mftb",   OpType::System, FL_OUT_D | FL_TIMER, 1, 0, 0, 0}},
290 	{512, Interpreter::mcrxr,       {"mcrxr",  OpType::System, FL_SET_CRn | FL_READ_CA | FL_SET_CA, 1, 0, 0, 0}},
291 	{595, Interpreter::mfsr,        {"mfsr",   OpType::System, FL_OUT_D, 3, 0, 0, 0}},
292 	{659, Interpreter::mfsrin,      {"mfsrin", OpType::System, FL_OUT_D | FL_IN_B, 3, 0, 0, 0}},
293 
294 	{4,   Interpreter::tw,          {"tw",     OpType::System, FL_IN_AB | FL_ENDBLOCK, 2, 0, 0, 0}},
295 	{598, Interpreter::sync,        {"sync",   OpType::System, 0, 3, 0, 0, 0}},
296 	{982, Interpreter::icbi,        {"icbi",   OpType::System, FL_IN_A0B | FL_ENDBLOCK | FL_LOADSTORE, 4, 0, 0, 0}},
297 
298 	// Unused instructions on GC
299 	{310, Interpreter::eciwx,       {"eciwx",   OpType::System, FL_IN_A0B | FL_OUT_D | FL_LOADSTORE, 1, 0, 0, 0}},
300 	{438, Interpreter::ecowx,       {"ecowx",   OpType::System, FL_IN_A0B | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
301 	{854, Interpreter::eieio,       {"eieio",   OpType::System, 0, 1, 0, 0, 0}},
302 	{306, Interpreter::tlbie,       {"tlbie",   OpType::System, FL_IN_B, 1, 0, 0, 0}},
303 	{566, Interpreter::tlbsync,     {"tlbsync", OpType::System, 0, 1, 0, 0, 0}},
304 }};
305 
306 static std::array<GekkoOPTemplate, 9> table59 =
307 {{
308 	{18, Interpreter::fdivsx,       {"fdivsx",   OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 17, 0, 0, 0}}, // TODO
309 	{20, Interpreter::fsubsx,       {"fsubsx",   OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
310 	{21, Interpreter::faddsx,       {"faddsx",   OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
311 	{24, Interpreter::fresx,        {"fresx",    OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
312 	{25, Interpreter::fmulsx,       {"fmulsx",   OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
313 	{28, Interpreter::fmsubsx,      {"fmsubsx",  OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
314 	{29, Interpreter::fmaddsx,      {"fmaddsx",  OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
315 	{30, Interpreter::fnmsubsx,     {"fnmsubsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
316 	{31, Interpreter::fnmaddsx,     {"fnmaddsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
317 }};
318 
319 static std::array<GekkoOPTemplate, 15> table63 =
320 {{
321 	{264, Interpreter::fabsx,       {"fabsx",   OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
322 
323 	// FIXME: fcmp modifies the FPRF flags, but if the flags are clobbered later,
324 	// we don't actually need to calculate or store them here. So FL_READ_FPRF and FL_SET_FPRF is not
325 	// an ideal representation of fcmp's effect on FPRF flags and might result in
326 	// slightly sub-optimal code.
327 	{32,  Interpreter::fcmpo,       {"fcmpo",   OpType::DoubleFP, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 1, 0, 0, 0}},
328 	{0,   Interpreter::fcmpu,       {"fcmpu",   OpType::DoubleFP, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 1, 0, 0, 0}},
329 
330 	{14,  Interpreter::fctiwx,      {"fctiwx",  OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
331 	{15,  Interpreter::fctiwzx,     {"fctiwzx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
332 	{72,  Interpreter::fmrx,        {"fmrx",    OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
333 	{136, Interpreter::fnabsx,      {"fnabsx",  OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
334 	{40,  Interpreter::fnegx,       {"fnegx",   OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
335 	{12,  Interpreter::frspx,       {"frspx",   OpType::DoubleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
336 
337 	{64,  Interpreter::mcrfs,       {"mcrfs",   OpType::SystemFP, FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF, 1, 0, 0, 0}},
338 	{583, Interpreter::mffsx,       {"mffsx",   OpType::SystemFP, FL_RC_BIT_F | FL_INOUT_FLOAT_D | FL_USE_FPU | FL_READ_FPRF, 1, 0, 0, 0}},
339 	{70,  Interpreter::mtfsb0x,     {"mtfsb0x", OpType::SystemFP, FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 3, 0, 0, 0}},
340 	{38,  Interpreter::mtfsb1x,     {"mtfsb1x", OpType::SystemFP, FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 3, 0, 0, 0}},
341 	{134, Interpreter::mtfsfix,     {"mtfsfix", OpType::SystemFP, FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 3, 0, 0, 0}},
342 	{711, Interpreter::mtfsfx,      {"mtfsfx",  OpType::SystemFP, FL_RC_BIT_F | FL_IN_FLOAT_B | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 3, 0, 0, 0}},
343 }};
344 
345 static std::array<GekkoOPTemplate, 10> table63_2 =
346 {{
347 	{18, Interpreter::fdivx,        {"fdivx",    OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 31, 0, 0, 0}},
348 	{20, Interpreter::fsubx,        {"fsubx",    OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
349 	{21, Interpreter::faddx,        {"faddx",    OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
350 	{23, Interpreter::fselx,        {"fselx",    OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
351 	{25, Interpreter::fmulx,        {"fmulx",    OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
352 	{26, Interpreter::frsqrtex,     {"frsqrtex", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
353 	{28, Interpreter::fmsubx,       {"fmsubx",   OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
354 	{29, Interpreter::fmaddx,       {"fmaddx",   OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
355 	{30, Interpreter::fnmsubx,      {"fnmsubx",  OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
356 	{31, Interpreter::fnmaddx,      {"fnmaddx",  OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF, 1, 0, 0, 0}},
357 }};
358 // clang-format on
359 
TotalInstructionFunctionCount()360 constexpr size_t TotalInstructionFunctionCount()
361 {
362   return primarytable.size() + table4_2.size() + table4_3.size() + table4.size() + table31.size() +
363          table19.size() + table59.size() + table63.size() + table63_2.size();
364 }
365 
366 static_assert(TotalInstructionFunctionCount() < m_allInstructions.size(),
367               "m_allInstructions is too small");
368 
InitializeInstructionTables()369 void Interpreter::InitializeInstructionTables()
370 {
371   // once initialized, tables are read-only
372   static bool initialized = false;
373   if (initialized)
374     return;
375 
376   // clear
377   for (int i = 0; i < 64; i++)
378   {
379     m_op_table[i] = Interpreter::unknown_instruction;
380     m_infoTable[i] = &unknownopinfo;
381   }
382 
383   for (int i = 0; i < 32; i++)
384   {
385     m_op_table59[i] = Interpreter::unknown_instruction;
386     m_infoTable59[i] = &unknownopinfo;
387   }
388 
389   for (int i = 0; i < 1024; i++)
390   {
391     m_op_table4[i] = Interpreter::unknown_instruction;
392     m_op_table19[i] = Interpreter::unknown_instruction;
393     m_op_table31[i] = Interpreter::unknown_instruction;
394     m_op_table63[i] = Interpreter::unknown_instruction;
395     m_infoTable4[i] = &unknownopinfo;
396     m_infoTable19[i] = &unknownopinfo;
397     m_infoTable31[i] = &unknownopinfo;
398     m_infoTable63[i] = &unknownopinfo;
399   }
400 
401   for (auto& tpl : primarytable)
402   {
403     m_op_table[tpl.opcode] = tpl.Inst;
404     m_infoTable[tpl.opcode] = &tpl.opinfo;
405   }
406 
407   for (int i = 0; i < 32; i++)
408   {
409     int fill = i << 5;
410     for (auto& tpl : table4_2)
411     {
412       int op = fill + tpl.opcode;
413       m_op_table4[op] = tpl.Inst;
414       m_infoTable4[op] = &tpl.opinfo;
415     }
416   }
417 
418   for (int i = 0; i < 16; i++)
419   {
420     int fill = i << 6;
421     for (auto& tpl : table4_3)
422     {
423       int op = fill + tpl.opcode;
424       m_op_table4[op] = tpl.Inst;
425       m_infoTable4[op] = &tpl.opinfo;
426     }
427   }
428 
429   for (auto& tpl : table4)
430   {
431     int op = tpl.opcode;
432     m_op_table4[op] = tpl.Inst;
433     m_infoTable4[op] = &tpl.opinfo;
434   }
435 
436   for (auto& tpl : table31)
437   {
438     int op = tpl.opcode;
439     m_op_table31[op] = tpl.Inst;
440     m_infoTable31[op] = &tpl.opinfo;
441   }
442 
443   for (auto& tpl : table19)
444   {
445     int op = tpl.opcode;
446     m_op_table19[op] = tpl.Inst;
447     m_infoTable19[op] = &tpl.opinfo;
448   }
449 
450   for (auto& tpl : table59)
451   {
452     int op = tpl.opcode;
453     m_op_table59[op] = tpl.Inst;
454     m_infoTable59[op] = &tpl.opinfo;
455   }
456 
457   for (auto& tpl : table63)
458   {
459     int op = tpl.opcode;
460     m_op_table63[op] = tpl.Inst;
461     m_infoTable63[op] = &tpl.opinfo;
462   }
463 
464   for (int i = 0; i < 32; i++)
465   {
466     int fill = i << 5;
467     for (auto& tpl : table63_2)
468     {
469       int op = fill + tpl.opcode;
470       m_op_table63[op] = tpl.Inst;
471       m_infoTable63[op] = &tpl.opinfo;
472     }
473   }
474 
475   m_numInstructions = 0;
476   for (auto& tpl : primarytable)
477     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
478   for (auto& tpl : table4_2)
479     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
480   for (auto& tpl : table4_3)
481     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
482   for (auto& tpl : table4)
483     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
484   for (auto& tpl : table31)
485     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
486   for (auto& tpl : table19)
487     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
488   for (auto& tpl : table59)
489     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
490   for (auto& tpl : table63)
491     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
492   for (auto& tpl : table63_2)
493     m_allInstructions[m_numInstructions++] = &tpl.opinfo;
494 
495   initialized = true;
496 }
497