1 // Copyright (c) 2012- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #include <cmath>
19 #include <limits>
20 
21 #include "Common/Math/math_util.h"
22 
23 #include "Common.h"
24 #include "Common/Serialize/Serializer.h"
25 #include "Common/Serialize/SerializeFuncs.h"
26 #include "Core/ConfigValues.h"
27 #include "Core/MIPS/MIPS.h"
28 #include "Core/MIPS/MIPSInt.h"
29 #include "Core/MIPS/MIPSTables.h"
30 #include "Core/MIPS/MIPSDebugInterface.h"
31 #include "Core/MIPS/MIPSVFPUUtils.h"
32 #include "Core/MIPS/IR/IRJit.h"
33 #include "Core/Reporting.h"
34 #include "Core/System.h"
35 #include "Core/HLE/sceDisplay.h"
36 #include "Core/MIPS/JitCommon/JitCommon.h"
37 #include "Core/CoreTiming.h"
38 
39 MIPSState mipsr4k;
40 MIPSState *currentMIPS = &mipsr4k;
41 MIPSDebugInterface debugr4k(&mipsr4k);
42 MIPSDebugInterface *currentDebugMIPS = &debugr4k;
43 
44 u8 voffset[128];
45 u8 fromvoffset[128];
46 
47 
48 #ifndef M_LOG2E
49 #define M_E        2.71828182845904523536f
50 #define M_LOG2E    1.44269504088896340736f
51 #define M_LOG10E   0.434294481903251827651f
GetCrashHandler()52 #define M_LN2      0.693147180559945309417f
53 #define M_LN10     2.30258509299404568402f
54 #undef M_PI
55 #define M_PI       3.14159265358979323846f
56 
57 #ifndef M_PI_2
58 #define M_PI_2     1.57079632679489661923f
59 #endif
60 #define M_PI_4     0.785398163397448309616f
61 #define M_1_PI     0.318309886183790671538f
62 #define M_2_PI     0.636619772367581343076f
63 #define M_2_SQRTPI 1.12837916709551257390f
64 #define M_SQRT2    1.41421356237309504880f
65 #define M_SQRT1_2  0.707106781186547524401f
66 #endif
67 
68 const float cst_constants[32] = {
69 	0,
70 	std::numeric_limits<float>::max(),  // all these are verified on real PSP
71 	sqrtf(2.0f),
72 	sqrtf(0.5f),
73 	2.0f/sqrtf((float)M_PI),
74 	2.0f/(float)M_PI,
75 	1.0f/(float)M_PI,
76 	(float)M_PI/4,
77 	(float)M_PI/2,
78 	(float)M_PI,
79 	(float)M_E,
80 	(float)M_LOG2E,
81 	(float)M_LOG10E,
82 	(float)M_LN2,
83 	(float)M_LN10,
84 	2*(float)M_PI,
85 	(float)M_PI/6,
86 	log10f(2.0f),
87 	logf(10.0f)/logf(2.0f),
88 	sqrtf(3.0f)/2.0f,
89 };
90 
Comp_DoNothing(MIPSOpcode op)91 
92 MIPSState::MIPSState() {
93 	MIPSComp::jit = 0;
94 
95 	// Initialize vorder
96 
97 	// This reordering of the VFPU registers in RAM means that instead of being like this:
98 
99 	// 0x00 0x20 0x40 0x60 -> "columns", the most common direction
100 	// 0x01 0x21 0x41 0x61
101 	// 0x02 0x22 0x42 0x62
102 	// 0x03 0x23 0x43 0x63
103 
104 	// 0x04 0x24 0x44 0x64
105 	// 0x06 0x26 0x45 0x65
106 	// ....
107 
108 	// the VPU registers are effectively organized like this:
109 	// 0x00 0x01 0x02 0x03
110 	// 0x04 0x05 0x06 0x07
111 	// 0x08 0x09 0x0a 0x0b
112 	// ....
113 
114 	// This is because the original indices look like this:
115 	// 0XXMMMYY where M is the matrix number.
116 
117 	// We will now map 0YYMMMXX to 0MMMXXYY.
118 
119 	// Advantages:
120 	// * Columns can be flushed and reloaded faster "at once"
121 	// * 4x4 Matrices are contiguous in RAM, making them, too, fast-loadable in NEON
122 
123 	// Disadvantages:
124 	// * Extra indirection, can be confusing and slower (interpreter only)
125 	// * Flushing and reloading row registers is now slower
126 
127 	int i = 0;
128 	for (int m = 0; m < 8; m++) {
129 		for (int y = 0; y < 4; y++) {
130 			for (int x = 0; x < 4; x++) {
131 				voffset[m * 4 + x * 32 + y] = i++;
132 			}
133 		}
134 	}
135 
136 	// And the inverse.
137 	for (int i = 0; i < 128; i++) {
138 		fromvoffset[voffset[i]] = i;
139 	}
140 
141 	// Sanity check that things that should be ordered are ordered.
142 	static const u8 firstThirtyTwo[] = {
143 		0x0, 0x20, 0x40, 0x60,
144 		0x1, 0x21, 0x41, 0x61,
145 		0x2, 0x22, 0x42, 0x62,
146 		0x3, 0x23, 0x43, 0x63,
147 
148 		0x4, 0x24, 0x44, 0x64,
149 		0x5, 0x25, 0x45, 0x65,
150 		0x6, 0x26, 0x46, 0x66,
151 		0x7, 0x27, 0x47, 0x67,
152 	};
153 
154 	for (int i = 0; i < (int)ARRAY_SIZE(firstThirtyTwo); i++) {
155 		if (voffset[firstThirtyTwo[i]] != i) {
156 			ERROR_LOG(CPU, "Wrong voffset order! %i: %i should have been %i", firstThirtyTwo[i], voffset[firstThirtyTwo[i]], i);
157 		}
158 	}
159 }
160 
161 MIPSState::~MIPSState() {
162 	Shutdown();
163 }
164 
165 void MIPSState::Shutdown() {
166 	if (MIPSComp::jit) {
167 		delete MIPSComp::jit;
168 		MIPSComp::jit = 0;
169 	}
170 }
171 
172 void MIPSState::Reset() {
173 	Shutdown();
174 	Init();
175 }
176 
177 void MIPSState::Init() {
178 	memset(r, 0, sizeof(r));
179 	memset(f, 0, sizeof(f));
180 	memset(v, 0, sizeof(v));
181 	memset(vfpuCtrl, 0, sizeof(vfpuCtrl));
182 
183 	vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; //passthru
184 	vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; //passthru
185 	vfpuCtrl[VFPU_CTRL_DPREFIX] = 0;
186 	vfpuCtrl[VFPU_CTRL_CC] = 0x3f;
187 	vfpuCtrl[VFPU_CTRL_INF4] = 0;
188 	vfpuCtrl[VFPU_CTRL_REV] = 0x7772ceab;
189 	vfpuCtrl[VFPU_CTRL_RCX0] = 0x3f800001;
190 	vfpuCtrl[VFPU_CTRL_RCX1] = 0x3f800002;
191 	vfpuCtrl[VFPU_CTRL_RCX2] = 0x3f800004;
192 	vfpuCtrl[VFPU_CTRL_RCX3] = 0x3f800008;
193 	vfpuCtrl[VFPU_CTRL_RCX4] = 0x3f800000;
194 	vfpuCtrl[VFPU_CTRL_RCX5] = 0x3f800000;
195 	vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000;
196 	vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000;
197 
198 	pc = 0;
199 	hi = 0;
200 	lo = 0;
201 	fpcond = 0;
202 	fcr31 = 0;
203 	debugCount = 0;
204 	currentMIPS = this;
205 	inDelaySlot = false;
206 	llBit = 0;
207 	nextPC = 0;
208 	downcount = 0;
209 	// Initialize the VFPU random number generator with .. something?
210 	rng.Init(0x1337);
211 
212 	if (PSP_CoreParameter().cpuCore == CPUCore::JIT) {
213 		MIPSComp::jit = MIPSComp::CreateNativeJit(this);
214 	} else if (PSP_CoreParameter().cpuCore == CPUCore::IR_JIT) {
215 		MIPSComp::jit = new MIPSComp::IRJit(this);
216 	} else {
217 		MIPSComp::jit = nullptr;
218 	}
219 }
220 
221 bool MIPSState::HasDefaultPrefix() const {
222 	return vfpuCtrl[VFPU_CTRL_SPREFIX] == 0xe4 && vfpuCtrl[VFPU_CTRL_TPREFIX] == 0xe4 && vfpuCtrl[VFPU_CTRL_DPREFIX] == 0;
223 }
224 
225 void MIPSState::UpdateCore(CPUCore desired) {
226 	if (PSP_CoreParameter().cpuCore == desired) {
227 		return;
228 	}
229 
230 	PSP_CoreParameter().cpuCore = desired;
231 	switch (PSP_CoreParameter().cpuCore) {
232 	case CPUCore::JIT:
233 		INFO_LOG(CPU, "Switching to JIT");
234 		if (MIPSComp::jit) {
235 			delete MIPSComp::jit;
236 		}
237 		MIPSComp::jit = MIPSComp::CreateNativeJit(this);
238 		break;
239 
240 	case CPUCore::IR_JIT:
241 		INFO_LOG(CPU, "Switching to IRJIT");
242 		if (MIPSComp::jit) {
243 			delete MIPSComp::jit;
244 		}
245 		MIPSComp::jit = new MIPSComp::IRJit(this);
246 		break;
247 
248 	case CPUCore::INTERPRETER:
249 		INFO_LOG(CPU, "Switching to interpreter");
250 		delete MIPSComp::jit;
251 		MIPSComp::jit = 0;
252 		break;
253 	}
254 }
255 
256 void MIPSState::DoState(PointerWrap &p) {
257 	auto s = p.Section("MIPSState", 1, 3);
258 	if (!s)
259 		return;
260 
261 	// Reset the jit if we're loading.
262 	if (p.mode == p.MODE_READ)
263 		Reset();
264 	if (MIPSComp::jit)
265 		MIPSComp::jit->DoState(p);
266 	else
267 		MIPSComp::DoDummyJitState(p);
268 
269 	DoArray(p, r, sizeof(r) / sizeof(r[0]));
270 	DoArray(p, f, sizeof(f) / sizeof(f[0]));
271 	if (s <= 2) {
272 		float vtemp[128];
273 		DoArray(p, vtemp, sizeof(v) / sizeof(v[0]));
274 		for (int i = 0; i < 128; i++) {
275 			v[voffset[i]] = vtemp[i];
276 		}
277 	} else {
278 		DoArray(p, v, sizeof(v) / sizeof(v[0]));
279 	}
280 	DoArray(p, vfpuCtrl, sizeof(vfpuCtrl) / sizeof(vfpuCtrl[0]));
281 	Do(p, pc);
282 	Do(p, nextPC);
283 	Do(p, downcount);
284 	// Reversed, but we can just leave it that way.
285 	Do(p, hi);
286 	Do(p, lo);
287 	Do(p, fpcond);
288 	if (s <= 1) {
289 		u32 fcr0_unused = 0;
290 		Do(p, fcr0_unused);
291 	}
292 	Do(p, fcr31);
293 	Do(p, rng.m_w);
294 	Do(p, rng.m_z);
295 	Do(p, inDelaySlot);
296 	Do(p, llBit);
297 	Do(p, debugCount);
298 
299 	if (p.mode == p.MODE_READ && MIPSComp::jit) {
300 		// Now that we've loaded fcr31, update any jit state associated.
301 		MIPSComp::jit->UpdateFCR31();
302 	}
303 }
304 
305 void MIPSState::SingleStep() {
306 	int cycles = MIPS_SingleStep();
307 	currentMIPS->downcount -= cycles;
308 	CoreTiming::Advance();
309 }
310 
311 // returns 1 if reached ticks limit
312 int MIPSState::RunLoopUntil(u64 globalTicks) {
313 	switch (PSP_CoreParameter().cpuCore) {
314 	case CPUCore::JIT:
315 	case CPUCore::IR_JIT:
316 		while (inDelaySlot) {
317 			// We must get out of the delay slot before going into jit.
318 			SingleStep();
319 		}
320 		MIPSComp::jit->RunLoopUntil(globalTicks);
321 		break;
322 
323 	case CPUCore::INTERPRETER:
324 		return MIPSInterpret_RunUntil(globalTicks);
325 	}
326 	return 1;
327 }
328 
329 void MIPSState::InvalidateICache(u32 address, int length) {
330 	// Only really applies to jit.
331 	if (MIPSComp::jit)
332 		MIPSComp::jit->InvalidateCacheAt(address, length);
333 }
334 
335 void MIPSState::ClearJitCache() {
336 	if (MIPSComp::jit)
337 		MIPSComp::jit->ClearCache();
338 }
339