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 <cstddef>
8 #include <iosfwd>
9 #include <tuple>
10 #include <type_traits>
11 #include <vector>
12 
13 #include "Common/CommonTypes.h"
14 
15 #include "Core/Debugger/PPCDebugInterface.h"
16 #include "Core/PowerPC/BreakPoints.h"
17 #include "Core/PowerPC/ConditionRegister.h"
18 #include "Core/PowerPC/Gekko.h"
19 #include "Core/PowerPC/PPCCache.h"
20 
21 class CPUCoreBase;
22 class PointerWrap;
23 
24 namespace PowerPC
25 {
26 // The gaps in the CPUCore numbering are from cores that only existed in the past.
27 // We avoid re-numbering cores so that settings will be compatible across versions.
28 enum class CPUCore
29 {
30   Interpreter = 0,
31   JIT64 = 1,
32   JITARM64 = 4,
33   CachedInterpreter = 5,
34 };
35 
36 // For reading from and writing to our config.
37 std::istream& operator>>(std::istream& is, CPUCore& core);
38 std::ostream& operator<<(std::ostream& os, CPUCore core);
39 
40 enum class CoreMode
41 {
42   Interpreter,
43   JIT,
44 };
45 
46 // TLB cache
47 constexpr size_t TLB_SIZE = 128;
48 constexpr size_t NUM_TLBS = 2;
49 constexpr size_t TLB_WAYS = 2;
50 
51 struct TLBEntry
52 {
53   static constexpr u32 INVALID_TAG = 0xffffffff;
54 
55   u32 tag[TLB_WAYS] = {INVALID_TAG, INVALID_TAG};
56   u32 paddr[TLB_WAYS] = {};
57   u32 pte[TLB_WAYS] = {};
58   u8 recent = 0;
59 };
60 
61 struct PairedSingle
62 {
PS0AsU64PairedSingle63   u64 PS0AsU64() const { return ps0; }
PS1AsU64PairedSingle64   u64 PS1AsU64() const { return ps1; }
65 
PS0AsU32PairedSingle66   u32 PS0AsU32() const { return static_cast<u32>(ps0); }
PS1AsU32PairedSingle67   u32 PS1AsU32() const { return static_cast<u32>(ps1); }
68 
69   double PS0AsDouble() const;
70   double PS1AsDouble() const;
71 
SetPS0PairedSingle72   void SetPS0(u64 value) { ps0 = value; }
73   void SetPS0(double value);
74 
SetPS1PairedSingle75   void SetPS1(u64 value) { ps1 = value; }
76   void SetPS1(double value);
77 
SetBothPairedSingle78   void SetBoth(u64 lhs, u64 rhs)
79   {
80     SetPS0(lhs);
81     SetPS1(rhs);
82   }
SetBothPairedSingle83   void SetBoth(double lhs, double rhs)
84   {
85     SetPS0(lhs);
86     SetPS1(rhs);
87   }
88 
FillPairedSingle89   void Fill(u64 value) { SetBoth(value, value); }
FillPairedSingle90   void Fill(double value) { SetBoth(value, value); }
91 
92   u64 ps0 = 0;
93   u64 ps1 = 0;
94 };
95 // Paired single must be standard layout in order for offsetof to work, which is used by the JITs
96 static_assert(std::is_standard_layout<PairedSingle>(), "PairedSingle must be standard layout");
97 
98 // This contains the entire state of the emulated PowerPC "Gekko" CPU.
99 struct PowerPCState
100 {
101   u32 gpr[32];  // General purpose registers. r1 = stack pointer.
102 
103   u32 pc;  // program counter
104   u32 npc;
105 
106   ConditionRegister cr;
107 
108   UReg_MSR msr;      // machine state register
109   UReg_FPSCR fpscr;  // floating point flags/status bits
110 
111   // Exception management.
112   u32 Exceptions;
113 
114   // Downcount for determining when we need to do timing
115   // This isn't quite the right location for it, but it is here to accelerate the ARM JIT
116   // This variable should be inside of the CoreTiming namespace if we wanted to be correct.
117   int downcount;
118 
119   // XER, reformatted into byte fields for easier access.
120   u8 xer_ca;
121   u8 xer_so_ov;  // format: (SO << 1) | OV
122   // The Broadway CPU implements bits 16-23 of the XER register... even though it doesn't support
123   // lscbx
124   u16 xer_stringctrl;
125 
126   // gather pipe pointer for JIT access
127   u8* gather_pipe_ptr;
128   u8* gather_pipe_base_ptr;
129 
130 #if _M_X86_64
131   // This member exists for the purpose of an assertion in x86 JitBase.cpp
132   // that its offset <= 0x100.  To minimize code size on x86, we want as much
133   // useful stuff in the one-byte offset range as possible - which is why ps
134   // is sitting down here.  It currently doesn't make a difference on other
135   // supported architectures.
136   std::tuple<> above_fits_in_first_0x100;
137 #endif
138 
139   // The paired singles are strange : PS0 is stored in the full 64 bits of each FPR
140   // but ps calculations are only done in 32-bit precision, and PS1 is only 32 bits.
141   // Since we want to use SIMD, SSE2 is the only viable alternative - 2x double.
142   alignas(16) PairedSingle ps[32];
143 
144   u32 sr[16];  // Segment registers.
145 
146   // special purpose registers - controls quantizers, DMA, and lots of other misc extensions.
147   // also for power management, but we don't care about that.
148   u32 spr[1024];
149 
150   // Storage for the stack pointer of the BLR optimization.
151   u8* stored_stack_pointer;
152 
153   std::array<std::array<TLBEntry, TLB_SIZE / TLB_WAYS>, NUM_TLBS> tlb;
154 
155   u32 pagetable_base;
156   u32 pagetable_hashmask;
157 
158   InstructionCache iCache;
159 
UpdateCR1PowerPCState160   void UpdateCR1()
161   {
162     cr.SetField(1, (fpscr.FX << 3) | (fpscr.FEX << 2) | (fpscr.VX << 1) | fpscr.OX);
163   }
164 
165   void SetSR(u32 index, u32 value);
166 };
167 
168 #if _M_X86_64
169 static_assert(offsetof(PowerPC::PowerPCState, above_fits_in_first_0x100) <= 0x100,
170               "top of PowerPCState too big");
171 #endif
172 
173 extern PowerPCState ppcState;
174 
175 extern BreakPoints breakpoints;
176 extern MemChecks memchecks;
177 extern PPCDebugInterface debug_interface;
178 
179 const std::vector<CPUCore>& AvailableCPUCores();
180 CPUCore DefaultCPUCore();
181 
182 void Init(CPUCore cpu_core);
183 void Reset();
184 void Shutdown();
185 void DoState(PointerWrap& p);
186 void ScheduleInvalidateCacheThreadSafe(u32 address);
187 
188 CoreMode GetMode();
189 // [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized
190 void SetMode(CoreMode _coreType);
191 const char* GetCPUName();
192 
193 // Set the current CPU Core to the given implementation until removed.
194 // Remove the current injected CPU Core by passing nullptr.
195 // While an external CPUCoreBase is injected, GetMode() will return CoreMode::Interpreter.
196 // Init() will be called when added and Shutdown() when removed.
197 // [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU
198 //  run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself
199 //  while it is in State::Running]
200 void InjectExternalCPUCore(CPUCoreBase* core);
201 
202 // Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread)
203 // It's not threadsafe otherwise.
204 void SingleStep();
205 void CheckExceptions();
206 void CheckExternalExceptions();
207 void CheckBreakPoints();
208 void RunLoop();
209 
210 u64 ReadFullTimeBaseValue();
211 void WriteFullTimeBaseValue(u64 value);
212 
213 void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst);
214 
215 // Easy register access macros.
216 #define HID0 ((UReg_HID0&)PowerPC::ppcState.spr[SPR_HID0])
217 #define HID2 ((UReg_HID2&)PowerPC::ppcState.spr[SPR_HID2])
218 #define HID4 ((UReg_HID4&)PowerPC::ppcState.spr[SPR_HID4])
219 #define DMAU (*(UReg_DMAU*)&PowerPC::ppcState.spr[SPR_DMAU])
220 #define DMAL (*(UReg_DMAL*)&PowerPC::ppcState.spr[SPR_DMAL])
221 #define MMCR0 ((UReg_MMCR0&)PowerPC::ppcState.spr[SPR_MMCR0])
222 #define MMCR1 ((UReg_MMCR1&)PowerPC::ppcState.spr[SPR_MMCR1])
223 #define THRM1 ((UReg_THRM12&)PowerPC::ppcState.spr[SPR_THRM1])
224 #define THRM2 ((UReg_THRM12&)PowerPC::ppcState.spr[SPR_THRM2])
225 #define THRM3 ((UReg_THRM3&)PowerPC::ppcState.spr[SPR_THRM3])
226 #define PC PowerPC::ppcState.pc
227 #define NPC PowerPC::ppcState.npc
228 #define FPSCR PowerPC::ppcState.fpscr
229 #define MSR PowerPC::ppcState.msr
230 #define GPR(n) PowerPC::ppcState.gpr[n]
231 
232 #define rGPR PowerPC::ppcState.gpr
233 #define rSPR(i) PowerPC::ppcState.spr[i]
234 #define LR PowerPC::ppcState.spr[SPR_LR]
235 #define CTR PowerPC::ppcState.spr[SPR_CTR]
236 #define rDEC PowerPC::ppcState.spr[SPR_DEC]
237 #define SRR0 PowerPC::ppcState.spr[SPR_SRR0]
238 #define SRR1 PowerPC::ppcState.spr[SPR_SRR1]
239 #define SPRG0 PowerPC::ppcState.spr[SPR_SPRG0]
240 #define SPRG1 PowerPC::ppcState.spr[SPR_SPRG1]
241 #define SPRG2 PowerPC::ppcState.spr[SPR_SPRG2]
242 #define SPRG3 PowerPC::ppcState.spr[SPR_SPRG3]
243 #define GQR(x) PowerPC::ppcState.spr[SPR_GQR0 + (x)]
244 #define TL PowerPC::ppcState.spr[SPR_TL]
245 #define TU PowerPC::ppcState.spr[SPR_TU]
246 
247 #define rPS(i) (PowerPC::ppcState.ps[(i)])
248 
SetCarry(u32 ca)249 inline void SetCarry(u32 ca)
250 {
251   PowerPC::ppcState.xer_ca = ca;
252 }
253 
GetCarry()254 inline u32 GetCarry()
255 {
256   return PowerPC::ppcState.xer_ca;
257 }
258 
GetXER()259 inline UReg_XER GetXER()
260 {
261   u32 xer = 0;
262   xer |= PowerPC::ppcState.xer_stringctrl;
263   xer |= PowerPC::ppcState.xer_ca << XER_CA_SHIFT;
264   xer |= PowerPC::ppcState.xer_so_ov << XER_OV_SHIFT;
265   return UReg_XER{xer};
266 }
267 
SetXER(UReg_XER new_xer)268 inline void SetXER(UReg_XER new_xer)
269 {
270   PowerPC::ppcState.xer_stringctrl = new_xer.BYTE_COUNT + (new_xer.BYTE_CMP << 8);
271   PowerPC::ppcState.xer_ca = new_xer.CA;
272   PowerPC::ppcState.xer_so_ov = (new_xer.SO << 1) + new_xer.OV;
273 }
274 
GetXER_SO()275 inline u32 GetXER_SO()
276 {
277   return PowerPC::ppcState.xer_so_ov >> 1;
278 }
279 
SetXER_SO(bool value)280 inline void SetXER_SO(bool value)
281 {
282   PowerPC::ppcState.xer_so_ov |= static_cast<u32>(value) << 1;
283 }
284 
GetXER_OV()285 inline u32 GetXER_OV()
286 {
287   return PowerPC::ppcState.xer_so_ov & 1;
288 }
289 
SetXER_OV(bool value)290 inline void SetXER_OV(bool value)
291 {
292   PowerPC::ppcState.xer_so_ov = (PowerPC::ppcState.xer_so_ov & 0xFE) | static_cast<u32>(value);
293   SetXER_SO(value);
294 }
295 
296 void UpdateFPRF(double dvalue);
297 
298 }  // namespace PowerPC
299