1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 ***************************************************************************/
19
20 #ifndef __R3000A_H__
21 #define __R3000A_H__
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 #include "psxcommon.h"
28 #include "psxmem.h"
29 #include "psxcounters.h"
30 #include "psxbios.h"
31
32 typedef struct {
33 int (*Init)();
34 void (*Reset)();
35 void (*Execute)(); /* executes up to a break */
36 void (*ExecuteBlock)(); /* executes up to a jump */
37 void (*Clear)(u32 Addr, u32 Size);
38 void (*Shutdown)();
39 } R3000Acpu;
40
41 extern R3000Acpu *psxCpu;
42 extern R3000Acpu psxInt;
43 #if (defined(__x86_64__) || defined(__i386__) || defined(__sh__) || defined(__ppc__)) && !defined(NOPSXREC)
44 extern R3000Acpu psxRec;
45 #define PSXREC
46 #endif
47
48 typedef union {
49 #if defined(__BIGENDIAN__)
50 struct { u8 h3, h2, h, l; } b;
51 struct { s8 h3, h2, h, l; } sb;
52 struct { u16 h, l; } w;
53 struct { s16 h, l; } sw;
54 #else
55 struct { u8 l, h, h2, h3; } b;
56 struct { u16 l, h; } w;
57 struct { s8 l, h, h2, h3; } sb;
58 struct { s16 l, h; } sw;
59 #endif
60 u32 d;
61 s32 sd;
62 } PAIR;
63
64 typedef union {
65 struct {
66 u32 r0, at, v0, v1, a0, a1, a2, a3,
67 t0, t1, t2, t3, t4, t5, t6, t7,
68 s0, s1, s2, s3, s4, s5, s6, s7,
69 t8, t9, k0, k1, gp, sp, s8, ra, lo, hi;
70 } n;
71 u32 r[34]; /* Lo, Hi in r[32] and r[33] */
72 PAIR p[34];
73 } psxGPRRegs;
74
75 typedef union {
76 struct {
77 u32 Index, Random, EntryLo0, BPC,
78 Context, BDA, PIDMask, DCIC,
79 BadVAddr, BDAM, EntryHi, BPCM,
80 Status, Cause, EPC, PRid,
81 Config, LLAddr, WatchLO, WatchHI,
82 XContext, Reserved1, Reserved2, Reserved3,
83 Reserved4, Reserved5, ECC, CacheErr,
84 TagLo, TagHi, ErrorEPC, Reserved6;
85 } n;
86 u32 r[32];
87 } psxCP0Regs;
88
89 typedef struct {
90 short x, y;
91 } SVector2D;
92
93 typedef struct {
94 short z, pad;
95 } SVector2Dz;
96
97 typedef struct {
98 short x, y, z, pad;
99 } SVector3D;
100
101 typedef struct {
102 short x, y, z, pad;
103 } LVector3D;
104
105 typedef struct {
106 unsigned char r, g, b, c;
107 } CBGR;
108
109 typedef struct {
110 short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad;
111 } SMatrix3D;
112
113 typedef union {
114 struct {
115 SVector3D v0, v1, v2;
116 CBGR rgb;
117 s32 otz;
118 s32 ir0, ir1, ir2, ir3;
119 SVector2D sxy0, sxy1, sxy2, sxyp;
120 SVector2Dz sz0, sz1, sz2, sz3;
121 CBGR rgb0, rgb1, rgb2;
122 s32 reserved;
123 s32 mac0, mac1, mac2, mac3;
124 u32 irgb, orgb;
125 s32 lzcs, lzcr;
126 } n;
127 u32 r[32];
128 PAIR p[32];
129 } psxCP2Data;
130
131 typedef union {
132 struct {
133 SMatrix3D rMatrix;
134 s32 trX, trY, trZ;
135 SMatrix3D lMatrix;
136 s32 rbk, gbk, bbk;
137 SMatrix3D cMatrix;
138 s32 rfc, gfc, bfc;
139 s32 ofx, ofy;
140 s32 h;
141 s32 dqa, dqb;
142 s32 zsf3, zsf4;
143 s32 flag;
144 } n;
145 u32 r[32];
146 PAIR p[32];
147 } psxCP2Ctrl;
148
149 enum {
150 PSXINT_SIO = 0,
151 PSXINT_CDR,
152 PSXINT_CDREAD,
153 PSXINT_GPUDMA,
154 PSXINT_MDECOUTDMA,
155 PSXINT_SPUDMA,
156 PSXINT_GPUBUSY,
157 PSXINT_MDECINDMA,
158 PSXINT_GPUOTCDMA,
159 PSXINT_CDRDMA,
160 PSXINT_SPUASYNC,
161 PSXINT_CDRDBUF,
162 PSXINT_CDRLID,
163 PSXINT_CDRPLAY
164 };
165
166 typedef struct {
167 psxGPRRegs GPR; /* General Purpose Registers */
168 psxCP0Regs CP0; /* Coprocessor0 Registers */
169 psxCP2Data CP2D; /* Cop2 data registers */
170 psxCP2Ctrl CP2C; /* Cop2 control registers */
171 u32 pc; /* Program counter */
172 u32 code; /* The instruction */
173 u32 cycle;
174 u32 interrupt;
175 struct { u32 sCycle, cycle; } intCycle[32];
176 u8 ICache_Addr[0x1000];
177 u8 ICache_Code[0x1000];
178 boolean ICache_valid;
179 } psxRegisters;
180
181 extern psxRegisters psxRegs;
182
183 /*
184 Formula One 2001
185 - Use old CPU cache code when the RAM location is
186 updated with new code (affects in-game racing)
187
188 TODO:
189 - I-cache / D-cache swapping
190 - Isolate D-cache from RAM
191 */
192
Read_ICache(u32 pc,boolean isolate)193 static inline u32 *Read_ICache(u32 pc, boolean isolate) {
194 u32 pc_bank, pc_offset, pc_cache;
195 u8 *IAddr, *ICode;
196
197 pc_bank = pc >> 24;
198 pc_offset = pc & 0xffffff;
199 pc_cache = pc & 0xfff;
200
201 IAddr = psxRegs.ICache_Addr;
202 ICode = psxRegs.ICache_Code;
203
204 // clear I-cache
205 if (!psxRegs.ICache_valid) {
206 memset(psxRegs.ICache_Addr, 0xff, sizeof(psxRegs.ICache_Addr));
207 memset(psxRegs.ICache_Code, 0xff, sizeof(psxRegs.ICache_Code));
208
209 psxRegs.ICache_valid = TRUE;
210 }
211
212 // uncached
213 if (pc_bank >= 0xa0)
214 return (u32 *)PSXM(pc);
215
216 // cached - RAM
217 if (pc_bank == 0x80 || pc_bank == 0x00) {
218 if (SWAP32(*(u32 *)(IAddr + pc_cache)) == pc_offset) {
219 // Cache hit - return last opcode used
220 return (u32 *)(ICode + pc_cache);
221 } else {
222 // Cache miss - addresses don't match
223 // - default: 0xffffffff (not init)
224
225 if (!isolate) {
226 // cache line is 4 bytes wide
227 pc_offset &= ~0xf;
228 pc_cache &= ~0xf;
229
230 // address line
231 *(u32 *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
232 *(u32 *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
233 *(u32 *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
234 *(u32 *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
235
236 // opcode line
237 pc_offset = pc & ~0xf;
238 *(u32 *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
239 *(u32 *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
240 *(u32 *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
241 *(u32 *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
242 }
243
244 // normal code
245 return (u32 *)PSXM(pc);
246 }
247 }
248
249 /*
250 TODO: Probably should add cached BIOS
251 */
252
253 // default
254 return (u32 *)PSXM(pc);
255 }
256
257 // U64 and S64 are used to wrap long integer constants.
258 #if defined __GNUC__ || defined _MSC_VER_
259 #define U64(val) val##ULL
260 #define S64(val) val##LL
261 #else
262 #define U64(val) val
263 #define S64(val) val
264 #endif
265
266 #if defined(__BIGENDIAN__)
267
268 #define _i32(x) *(s32 *)&x
269 #define _u32(x) x
270
271 #define _i16(x) (((short *)&x)[1])
272 #define _u16(x) (((unsigned short *)&x)[1])
273
274 #define _i8(x) (((char *)&x)[3])
275 #define _u8(x) (((unsigned char *)&x)[3])
276
277 #else
278
279 #define _i32(x) *(s32 *)&x
280 #define _u32(x) x
281
282 #define _i16(x) *(short *)&x
283 #define _u16(x) *(unsigned short *)&x
284
285 #define _i8(x) *(char *)&x
286 #define _u8(x) *(unsigned char *)&x
287
288 #endif
289
290 /**** R3000A Instruction Macros ****/
291 #define _PC_ psxRegs.pc // The next PC to be executed
292
293 #define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register
294 #define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register
295 #define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register
296 #define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register
297 #define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register
298 #define _fSa_(code) ((code >> 6) & 0x1F) // The sa part of the instruction register
299 #define _fIm_(code) ((u16)code) // The immediate part of the instruction register
300 #define _fTarget_(code) (code & 0x03ffffff) // The target part of the instruction register
301
302 #define _fImm_(code) ((s16)code) // sign-extended immediate
303 #define _fImmU_(code) (code&0xffff) // zero-extended immediate
304 #define _fImmLU_(code) (code<<16) // LUI
305
306 #define _Op_ _fOp_(psxRegs.code)
307 #define _Funct_ _fFunct_(psxRegs.code)
308 #define _Rd_ _fRd_(psxRegs.code)
309 #define _Rt_ _fRt_(psxRegs.code)
310 #define _Rs_ _fRs_(psxRegs.code)
311 #define _Sa_ _fSa_(psxRegs.code)
312 #define _Im_ _fIm_(psxRegs.code)
313 #define _Target_ _fTarget_(psxRegs.code)
314
315 #define _Imm_ _fImm_(psxRegs.code)
316 #define _ImmU_ _fImmU_(psxRegs.code)
317 #define _ImmLU_ _fImmLU_(psxRegs.code)
318
319 #define _rRs_ psxRegs.GPR.r[_Rs_] // Rs register
320 #define _rRt_ psxRegs.GPR.r[_Rt_] // Rt register
321 #define _rRd_ psxRegs.GPR.r[_Rd_] // Rd register
322 #define _rSa_ psxRegs.GPR.r[_Sa_] // Sa register
323 #define _rFs_ psxRegs.CP0.r[_Rd_] // Fs register
324
325 #define _c2dRs_ psxRegs.CP2D.r[_Rs_] // Rs cop2 data register
326 #define _c2dRt_ psxRegs.CP2D.r[_Rt_] // Rt cop2 data register
327 #define _c2dRd_ psxRegs.CP2D.r[_Rd_] // Rd cop2 data register
328 #define _c2dSa_ psxRegs.CP2D.r[_Sa_] // Sa cop2 data register
329
330 #define _rHi_ psxRegs.GPR.n.hi // The HI register
331 #define _rLo_ psxRegs.GPR.n.lo // The LO register
332
333 #define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction
334 #define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction
335
336 #define _SetLink(x) psxRegs.GPR.r[x] = _PC_ + 4; // Sets the return address in the link register
337
338 int psxInit();
339 void psxReset();
340 void psxShutdown();
341 void psxException(u32 code, u32 bd);
342 void psxBranchTest();
343 void psxExecuteBios();
344 int psxTestLoadDelay(int reg, u32 tmp);
345 void psxDelayTest(int reg, u32 bpc);
346 void psxTestSWInts();
347 void psxJumpTest();
348
349 #ifdef __cplusplus
350 }
351 #endif
352 #endif
353