~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to Core/MIPS/MIPS.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

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