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