drc: avoid excessive recursion in hle mode
[pcsx_rearmed.git] / libpcsxcore / r3000a.h
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 02111-1307 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
29 enum R3000Aexception {
30         R3000E_Int = 0,      // Interrupt
31         R3000E_AdEL = 4,     // Address error (on load/I-fetch)
32         R3000E_AdES = 5,     // Address error (on store)
33         R3000E_IBE = 6,      // Bus error (instruction fetch)
34         R3000E_DBE = 7,      // Bus error (data load/store)
35         R3000E_Syscall = 8,  // syscall instruction
36         R3000E_Bp = 9,       // Breakpoint - a break instruction
37         R3000E_RI = 10,      // reserved instruction
38         R3000E_CpU = 11,     // Co-Processor unusable
39         R3000E_Ov = 12       // arithmetic overflow
40 };
41
42 enum R3000Anote {
43         R3000ACPU_NOTIFY_CACHE_ISOLATED = 0,
44         R3000ACPU_NOTIFY_CACHE_UNISOLATED = 1,
45         R3000ACPU_NOTIFY_BEFORE_SAVE,  // data arg - hle if non-null
46         R3000ACPU_NOTIFY_AFTER_LOAD,
47 };
48
49 enum blockExecCaller {
50         EXEC_CALLER_BOOT,
51         EXEC_CALLER_HLE,
52 };
53
54 typedef struct {
55         int  (*Init)();
56         void (*Reset)();
57         void (*Execute)();
58         void (*ExecuteBlock)(enum blockExecCaller caller); /* executes up to a jump */
59         void (*Clear)(u32 Addr, u32 Size);
60         void (*Notify)(enum R3000Anote note, void *data);
61         void (*ApplyConfig)();
62         void (*Shutdown)();
63 } R3000Acpu;
64
65 extern R3000Acpu *psxCpu;
66 extern R3000Acpu psxInt;
67 extern R3000Acpu psxRec;
68
69 typedef union {
70 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
71         struct { u8 h3, h2, h, l; } b;
72         struct { s8 h3, h2, h, l; } sb;
73         struct { u16 h, l; } w;
74         struct { s16 h, l; } sw;
75 #else
76         struct { u8 l, h, h2, h3; } b;
77         struct { u16 l, h; } w;
78         struct { s8 l, h, h2, h3; } sb;
79         struct { s16 l, h; } sw;
80 #endif
81 } PAIR;
82
83 typedef union {
84         struct {
85                 u32   r0, at, v0, v1, a0, a1, a2, a3,
86                                                 t0, t1, t2, t3, t4, t5, t6, t7,
87                                                 s0, s1, s2, s3, s4, s5, s6, s7,
88                                                 t8, t9, k0, k1, gp, sp, fp, ra, lo, hi;
89         } n;
90         u32 r[34]; /* Lo, Hi in r[32] and r[33] */
91         PAIR p[34];
92 } psxGPRRegs;
93
94 typedef union psxCP0Regs_ {
95         struct {
96                 u32 Reserved0, Reserved1, Reserved2,  BPC,
97                     Reserved4, BDA,       Target,     DCIC,
98                     BadVAddr,  BDAM,      Reserved10, BPCM,
99                     SR,        Cause,     EPC,        PRid,
100                     Reserved16[16];
101         } n;
102         u32 r[32];
103         PAIR p[32];
104 } psxCP0Regs;
105
106 typedef struct {
107         short x, y;
108 } SVector2D;
109
110 typedef struct {
111         short z, pad;
112 } SVector2Dz;
113
114 typedef struct {
115         short x, y, z, pad;
116 } SVector3D;
117
118 typedef struct {
119         short x, y, z, pad;
120 } LVector3D;
121
122 typedef struct {
123         unsigned char r, g, b, c;
124 } CBGR;
125
126 typedef struct {
127         short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad;
128 } SMatrix3D;
129
130 typedef union {
131         struct {
132                 SVector3D     v0, v1, v2;
133                 CBGR          rgb;
134                 s32          otz;
135                 s32          ir0, ir1, ir2, ir3;
136                 SVector2D     sxy0, sxy1, sxy2, sxyp;
137                 SVector2Dz    sz0, sz1, sz2, sz3;
138                 CBGR          rgb0, rgb1, rgb2;
139                 s32          reserved;
140                 s32          mac0, mac1, mac2, mac3;
141                 u32 irgb, orgb;
142                 s32          lzcs, lzcr;
143         } n;
144         u32 r[32];
145         PAIR p[32];
146 } psxCP2Data;
147
148 typedef union {
149         struct {
150                 SMatrix3D rMatrix;
151                 s32      trX, trY, trZ;
152                 SMatrix3D lMatrix;
153                 s32      rbk, gbk, bbk;
154                 SMatrix3D cMatrix;
155                 s32      rfc, gfc, bfc;
156                 s32      ofx, ofy;
157                 s32      h;
158                 s32      dqa, dqb;
159                 s32      zsf3, zsf4;
160                 s32      flag;
161         } n;
162         u32 r[32];
163         PAIR p[32];
164 } psxCP2Ctrl;
165
166 enum {
167         PSXINT_SIO = 0,
168         PSXINT_CDR,
169         PSXINT_CDREAD,
170         PSXINT_GPUDMA,
171         PSXINT_MDECOUTDMA,
172         PSXINT_SPUDMA,
173         PSXINT_GPUBUSY,
174         PSXINT_MDECINDMA,
175         PSXINT_GPUOTCDMA,
176         PSXINT_CDRDMA,
177         PSXINT_NEWDRC_CHECK,
178         PSXINT_RCNT,
179         PSXINT_CDRLID,
180         PSXINT_IRQ10,
181         PSXINT_SPU_UPDATE,
182         PSXINT_COUNT
183 };
184
185 enum R3000Abdt {
186         // corresponds to bits 31,30 of Cause reg
187         R3000A_BRANCH_TAKEN = 3,
188         R3000A_BRANCH_NOT_TAKEN = 2,
189         // none or tells that there was an exception in DS back to doBranch
190         R3000A_BRANCH_NONE_OR_EXCEPTION = 0,
191 };
192
193 typedef struct psxCP2Regs {
194         psxCP2Data CP2D;        /* Cop2 data registers */
195         psxCP2Ctrl CP2C;        /* Cop2 control registers */
196 } psxCP2Regs;
197
198 typedef struct {
199         // note: some cores like lightrec don't keep their data here,
200         // so use R3000ACPU_NOTIFY_BEFORE_SAVE to sync
201         psxGPRRegs GPR;         /* General Purpose Registers */
202         psxCP0Regs CP0;         /* Coprocessor0 Registers */
203         union {
204                 struct {
205                         psxCP2Data CP2D;        /* Cop2 data registers */
206                         psxCP2Ctrl CP2C;        /* Cop2 control registers */
207                 };
208                 psxCP2Regs CP2;
209         };
210         u32 pc;                         /* Program counter */
211         u32 code;                       /* The instruction */
212         u32 cycle;
213         u32 interrupt;
214         struct { u32 sCycle, cycle; } intCycle[32];
215         u32 gteBusyCycle;
216         u32 muldivBusyCycle;
217         u32 subCycle;       /* interpreter cycle counting */
218         u32 subCycleStep;
219         u32 biuReg;
220         u8  branching;      /* interp. R3000A_BRANCH_TAKEN / not, 0 if not branch */
221         u8  dloadSel;       /* interp. delay load state */
222         u8  dloadReg[2];
223         u32 dloadVal[2];
224         u32 biosBranchCheck;
225         u32 cpuInRecursion;
226         u32 reserved[2];
227         // warning: changing anything in psxRegisters requires update of all
228         // asm in libpcsxcore/new_dynarec/
229 } psxRegisters;
230
231 extern psxRegisters psxRegs;
232
233 /* new_dynarec stuff */
234 extern u32 event_cycles[PSXINT_COUNT];
235 extern u32 next_interupt;
236
237 void new_dyna_freeze(void *f, int mode);
238
239 #define new_dyna_set_event_abs(e, abs) { \
240         u32 abs_ = abs; \
241         s32 di_ = next_interupt - abs_; \
242         event_cycles[e] = abs_; \
243         if (di_ > 0) { \
244                 /*printf("%u: next_interupt %u -> %u\n", psxRegs.cycle, next_interupt, abs_);*/ \
245                 next_interupt = abs_; \
246         } \
247 }
248
249 #define new_dyna_set_event(e, c) \
250         new_dyna_set_event_abs(e, psxRegs.cycle + (c))
251
252 int  psxInit();
253 void psxReset();
254 void psxShutdown();
255 void psxException(u32 code, enum R3000Abdt bdt, psxCP0Regs *cp0);
256 void psxBranchTest();
257 void psxExecuteBios();
258 void psxJumpTest();
259
260 void irq10Interrupt();
261 void psxScheduleIrq10(int irq_count, int x_cycles, int y);
262
263 #ifdef __cplusplus
264 }
265 #endif
266 #endif