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