1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <array>
8 
9 #include "Common/CommonTypes.h"
10 #include "Core/PowerPC/CPUCoreBase.h"
11 #include "Core/PowerPC/Gekko.h"
12 
13 class Interpreter : public CPUCoreBase
14 {
15 public:
16   void Init() override;
17   void Shutdown() override;
18   void SingleStep() override;
19   int SingleStepInner();
20 
21   void Run() override;
22   void ClearCache() override;
23   const char* GetName() const override;
24 
25   static void unknown_instruction(UGeckoInstruction inst);
26 
27   // Branch Instructions
28   static void bx(UGeckoInstruction inst);
29   static void bcx(UGeckoInstruction inst);
30   static void bcctrx(UGeckoInstruction inst);
31   static void bclrx(UGeckoInstruction inst);
32   static void HLEFunction(UGeckoInstruction inst);
33 
34   // Syscall Instruction
35   static void sc(UGeckoInstruction inst);
36 
37   // Floating Point Instructions
38   static void faddsx(UGeckoInstruction inst);
39   static void fdivsx(UGeckoInstruction inst);
40   static void fmaddsx(UGeckoInstruction inst);
41   static void fmsubsx(UGeckoInstruction inst);
42   static void fmulsx(UGeckoInstruction inst);
43   static void fnmaddsx(UGeckoInstruction inst);
44   static void fnmsubsx(UGeckoInstruction inst);
45   static void fresx(UGeckoInstruction inst);
46   static void fsubsx(UGeckoInstruction inst);
47   static void fabsx(UGeckoInstruction inst);
48   static void fcmpo(UGeckoInstruction inst);
49   static void fcmpu(UGeckoInstruction inst);
50   static void fctiwx(UGeckoInstruction inst);
51   static void fctiwzx(UGeckoInstruction inst);
52   static void fmrx(UGeckoInstruction inst);
53   static void fnabsx(UGeckoInstruction inst);
54   static void fnegx(UGeckoInstruction inst);
55   static void frspx(UGeckoInstruction inst);
56   static void faddx(UGeckoInstruction inst);
57   static void fdivx(UGeckoInstruction inst);
58   static void fmaddx(UGeckoInstruction inst);
59   static void fmsubx(UGeckoInstruction inst);
60   static void fmulx(UGeckoInstruction inst);
61   static void fnmaddx(UGeckoInstruction inst);
62   static void fnmsubx(UGeckoInstruction inst);
63   static void frsqrtex(UGeckoInstruction inst);
64   static void fselx(UGeckoInstruction inst);
65   static void fsubx(UGeckoInstruction inst);
66 
67   // Integer Instructions
68   static void addi(UGeckoInstruction inst);
69   static void addic(UGeckoInstruction inst);
70   static void addic_rc(UGeckoInstruction inst);
71   static void addis(UGeckoInstruction inst);
72   static void andi_rc(UGeckoInstruction inst);
73   static void andis_rc(UGeckoInstruction inst);
74   static void cmpi(UGeckoInstruction inst);
75   static void cmpli(UGeckoInstruction inst);
76   static void mulli(UGeckoInstruction inst);
77   static void ori(UGeckoInstruction inst);
78   static void oris(UGeckoInstruction inst);
79   static void subfic(UGeckoInstruction inst);
80   static void twi(UGeckoInstruction inst);
81   static void xori(UGeckoInstruction inst);
82   static void xoris(UGeckoInstruction inst);
83   static void rlwimix(UGeckoInstruction inst);
84   static void rlwinmx(UGeckoInstruction inst);
85   static void rlwnmx(UGeckoInstruction inst);
86   static void andx(UGeckoInstruction inst);
87   static void andcx(UGeckoInstruction inst);
88   static void cmp(UGeckoInstruction inst);
89   static void cmpl(UGeckoInstruction inst);
90   static void cntlzwx(UGeckoInstruction inst);
91   static void eqvx(UGeckoInstruction inst);
92   static void extsbx(UGeckoInstruction inst);
93   static void extshx(UGeckoInstruction inst);
94   static void nandx(UGeckoInstruction inst);
95   static void norx(UGeckoInstruction inst);
96   static void orx(UGeckoInstruction inst);
97   static void orcx(UGeckoInstruction inst);
98   static void slwx(UGeckoInstruction inst);
99   static void srawx(UGeckoInstruction inst);
100   static void srawix(UGeckoInstruction inst);
101   static void srwx(UGeckoInstruction inst);
102   static void tw(UGeckoInstruction inst);
103   static void xorx(UGeckoInstruction inst);
104   static void addx(UGeckoInstruction inst);
105   static void addcx(UGeckoInstruction inst);
106   static void addex(UGeckoInstruction inst);
107   static void addmex(UGeckoInstruction inst);
108   static void addzex(UGeckoInstruction inst);
109   static void divwx(UGeckoInstruction inst);
110   static void divwux(UGeckoInstruction inst);
111   static void mulhwx(UGeckoInstruction inst);
112   static void mulhwux(UGeckoInstruction inst);
113   static void mullwx(UGeckoInstruction inst);
114   static void negx(UGeckoInstruction inst);
115   static void subfx(UGeckoInstruction inst);
116   static void subfcx(UGeckoInstruction inst);
117   static void subfex(UGeckoInstruction inst);
118   static void subfmex(UGeckoInstruction inst);
119   static void subfzex(UGeckoInstruction inst);
120 
121   // Load/Store Instructions
122   static void lbz(UGeckoInstruction inst);
123   static void lbzu(UGeckoInstruction inst);
124   static void lfd(UGeckoInstruction inst);
125   static void lfdu(UGeckoInstruction inst);
126   static void lfs(UGeckoInstruction inst);
127   static void lfsu(UGeckoInstruction inst);
128   static void lha(UGeckoInstruction inst);
129   static void lhau(UGeckoInstruction inst);
130   static void lhz(UGeckoInstruction inst);
131   static void lhzu(UGeckoInstruction inst);
132   static void lmw(UGeckoInstruction inst);
133   static void lwz(UGeckoInstruction inst);
134   static void lwzu(UGeckoInstruction inst);
135   static void stb(UGeckoInstruction inst);
136   static void stbu(UGeckoInstruction inst);
137   static void stfd(UGeckoInstruction inst);
138   static void stfdu(UGeckoInstruction inst);
139   static void stfs(UGeckoInstruction inst);
140   static void stfsu(UGeckoInstruction inst);
141   static void sth(UGeckoInstruction inst);
142   static void sthu(UGeckoInstruction inst);
143   static void stmw(UGeckoInstruction inst);
144   static void stw(UGeckoInstruction inst);
145   static void stwu(UGeckoInstruction inst);
146   static void dcba(UGeckoInstruction inst);
147   static void dcbf(UGeckoInstruction inst);
148   static void dcbi(UGeckoInstruction inst);
149   static void dcbst(UGeckoInstruction inst);
150   static void dcbt(UGeckoInstruction inst);
151   static void dcbtst(UGeckoInstruction inst);
152   static void dcbz(UGeckoInstruction inst);
153   static void eciwx(UGeckoInstruction inst);
154   static void ecowx(UGeckoInstruction inst);
155   static void eieio(UGeckoInstruction inst);
156   static void icbi(UGeckoInstruction inst);
157   static void lbzux(UGeckoInstruction inst);
158   static void lbzx(UGeckoInstruction inst);
159   static void lfdux(UGeckoInstruction inst);
160   static void lfdx(UGeckoInstruction inst);
161   static void lfsux(UGeckoInstruction inst);
162   static void lfsx(UGeckoInstruction inst);
163   static void lhaux(UGeckoInstruction inst);
164   static void lhax(UGeckoInstruction inst);
165   static void lhbrx(UGeckoInstruction inst);
166   static void lhzux(UGeckoInstruction inst);
167   static void lhzx(UGeckoInstruction inst);
168   static void lswi(UGeckoInstruction inst);
169   static void lswx(UGeckoInstruction inst);
170   static void lwarx(UGeckoInstruction inst);
171   static void lwbrx(UGeckoInstruction inst);
172   static void lwzux(UGeckoInstruction inst);
173   static void lwzx(UGeckoInstruction inst);
174   static void stbux(UGeckoInstruction inst);
175   static void stbx(UGeckoInstruction inst);
176   static void stfdux(UGeckoInstruction inst);
177   static void stfdx(UGeckoInstruction inst);
178   static void stfiwx(UGeckoInstruction inst);
179   static void stfsux(UGeckoInstruction inst);
180   static void stfsx(UGeckoInstruction inst);
181   static void sthbrx(UGeckoInstruction inst);
182   static void sthux(UGeckoInstruction inst);
183   static void sthx(UGeckoInstruction inst);
184   static void stswi(UGeckoInstruction inst);
185   static void stswx(UGeckoInstruction inst);
186   static void stwbrx(UGeckoInstruction inst);
187   static void stwcxd(UGeckoInstruction inst);
188   static void stwux(UGeckoInstruction inst);
189   static void stwx(UGeckoInstruction inst);
190   static void tlbie(UGeckoInstruction inst);
191   static void tlbsync(UGeckoInstruction inst);
192 
193   // Paired Instructions
194   static void psq_l(UGeckoInstruction inst);
195   static void psq_lu(UGeckoInstruction inst);
196   static void psq_st(UGeckoInstruction inst);
197   static void psq_stu(UGeckoInstruction inst);
198   static void psq_lx(UGeckoInstruction inst);
199   static void psq_stx(UGeckoInstruction inst);
200   static void psq_lux(UGeckoInstruction inst);
201   static void psq_stux(UGeckoInstruction inst);
202   static void ps_div(UGeckoInstruction inst);
203   static void ps_sub(UGeckoInstruction inst);
204   static void ps_add(UGeckoInstruction inst);
205   static void ps_sel(UGeckoInstruction inst);
206   static void ps_res(UGeckoInstruction inst);
207   static void ps_mul(UGeckoInstruction inst);
208   static void ps_rsqrte(UGeckoInstruction inst);
209   static void ps_msub(UGeckoInstruction inst);
210   static void ps_madd(UGeckoInstruction inst);
211   static void ps_nmsub(UGeckoInstruction inst);
212   static void ps_nmadd(UGeckoInstruction inst);
213   static void ps_neg(UGeckoInstruction inst);
214   static void ps_mr(UGeckoInstruction inst);
215   static void ps_nabs(UGeckoInstruction inst);
216   static void ps_abs(UGeckoInstruction inst);
217   static void ps_sum0(UGeckoInstruction inst);
218   static void ps_sum1(UGeckoInstruction inst);
219   static void ps_muls0(UGeckoInstruction inst);
220   static void ps_muls1(UGeckoInstruction inst);
221   static void ps_madds0(UGeckoInstruction inst);
222   static void ps_madds1(UGeckoInstruction inst);
223   static void ps_cmpu0(UGeckoInstruction inst);
224   static void ps_cmpo0(UGeckoInstruction inst);
225   static void ps_cmpu1(UGeckoInstruction inst);
226   static void ps_cmpo1(UGeckoInstruction inst);
227   static void ps_merge00(UGeckoInstruction inst);
228   static void ps_merge01(UGeckoInstruction inst);
229   static void ps_merge10(UGeckoInstruction inst);
230   static void ps_merge11(UGeckoInstruction inst);
231   static void dcbz_l(UGeckoInstruction inst);
232 
233   // System Registers Instructions
234   static void mcrfs(UGeckoInstruction inst);
235   static void mffsx(UGeckoInstruction inst);
236   static void mtfsb0x(UGeckoInstruction inst);
237   static void mtfsb1x(UGeckoInstruction inst);
238   static void mtfsfix(UGeckoInstruction inst);
239   static void mtfsfx(UGeckoInstruction inst);
240   static void mcrxr(UGeckoInstruction inst);
241   static void mfcr(UGeckoInstruction inst);
242   static void mfmsr(UGeckoInstruction inst);
243   static void mfsr(UGeckoInstruction inst);
244   static void mfsrin(UGeckoInstruction inst);
245   static void mtmsr(UGeckoInstruction inst);
246   static void mtsr(UGeckoInstruction inst);
247   static void mtsrin(UGeckoInstruction inst);
248   static void mfspr(UGeckoInstruction inst);
249   static void mftb(UGeckoInstruction inst);
250   static void mtcrf(UGeckoInstruction inst);
251   static void mtspr(UGeckoInstruction inst);
252   static void crand(UGeckoInstruction inst);
253   static void crandc(UGeckoInstruction inst);
254   static void creqv(UGeckoInstruction inst);
255   static void crnand(UGeckoInstruction inst);
256   static void crnor(UGeckoInstruction inst);
257   static void cror(UGeckoInstruction inst);
258   static void crorc(UGeckoInstruction inst);
259   static void crxor(UGeckoInstruction inst);
260   static void mcrf(UGeckoInstruction inst);
261   static void rfi(UGeckoInstruction inst);
262   static void sync(UGeckoInstruction inst);
263   static void isync(UGeckoInstruction inst);
264 
265   using Instruction = void (*)(UGeckoInstruction inst);
266   static std::array<Instruction, 64> m_op_table;
267   static std::array<Instruction, 1024> m_op_table4;
268   static std::array<Instruction, 1024> m_op_table19;
269   static std::array<Instruction, 1024> m_op_table31;
270   static std::array<Instruction, 32> m_op_table59;
271   static std::array<Instruction, 1024> m_op_table63;
272 
273   // singleton
274   static Interpreter* getInstance();
275 
276   static void RunTable4(UGeckoInstruction inst);
277   static void RunTable19(UGeckoInstruction inst);
278   static void RunTable31(UGeckoInstruction inst);
279   static void RunTable59(UGeckoInstruction inst);
280   static void RunTable63(UGeckoInstruction inst);
281 
282   static u32 Helper_Carry(u32 value1, u32 value2);
283 
284 private:
285   void CheckExceptions();
286 
287   static void InitializeInstructionTables();
288 
289   static bool HandleFunctionHooking(u32 address);
290 
291   // flag helper
292   static void Helper_UpdateCR0(u32 value);
293 
294   static void Helper_FloatCompareOrdered(UGeckoInstruction inst, double a, double b);
295   static void Helper_FloatCompareUnordered(UGeckoInstruction inst, double a, double b);
296 
297   UGeckoInstruction m_prev_inst{};
298 
299   static bool m_end_block;
300 
301   // TODO: These should really be in the save state, although it's unlikely to matter much.
302   // They are for lwarx and its friend stwcxd.
303   static bool m_reserve;
304   static u32 m_reserve_address;
305 };
306