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