cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / psxinterpreter.c
1 /***************************************************************************
2  *   Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team              *
3  *   Copyright (C) 2023 notaz                                              *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
19  ***************************************************************************/
20
21 /*
22  * PSX assembly interpreter.
23  */
24
25 #include "psxcommon.h"
26 #include "r3000a.h"
27 #include "gte.h"
28 #include "psxhle.h"
29 #include "psxinterpreter.h"
30 #include <stddef.h>
31 #include <assert.h>
32 #include "../include/compiler_features.h"
33
34 // these may cause issues: because of poor timing we may step
35 // on instructions that real hardware would never reach
36 #define DO_EXCEPTION_RESERVEDI
37 #define HANDLE_LOAD_DELAY
38
39 static int branchSeen = 0;
40
41 #ifdef __i386__
42 #define INT_ATTR __attribute__((regparm(2)))
43 #else
44 #define INT_ATTR
45 #endif
46 #ifndef INVALID_PTR
47 #define INVALID_PTR NULL
48 #endif
49
50 // Subsets
51 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code);
52 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code);
53
54 // load delay
55 static void doLoad(psxRegisters *regs, u32 r, u32 val)
56 {
57 #ifdef HANDLE_LOAD_DELAY
58         int sel = regs->dloadSel ^ 1;
59         assert(regs->dloadReg[sel] == 0);
60         regs->dloadReg[sel] = r;
61         regs->dloadVal[sel] = r ? val : 0;
62         if (regs->dloadReg[sel ^ 1] == r)
63                 regs->dloadVal[sel ^ 1] = regs->dloadReg[sel ^ 1] = 0;
64 #else
65         regs->GPR.r[r] = r ? val : 0;
66 #endif
67 }
68
69 static void dloadRt(psxRegisters *regs, u32 r, u32 val)
70 {
71 #ifdef HANDLE_LOAD_DELAY
72         int sel = regs->dloadSel;
73         if (unlikely(regs->dloadReg[sel] == r))
74                 regs->dloadVal[sel] = regs->dloadReg[sel] = 0;
75 #endif
76         regs->GPR.r[r] = r ? val : 0;
77 }
78
79 static void dloadStep(psxRegisters *regs)
80 {
81 #ifdef HANDLE_LOAD_DELAY
82         int sel = regs->dloadSel;
83         regs->GPR.r[regs->dloadReg[sel]] = regs->dloadVal[sel];
84         regs->dloadVal[sel] = regs->dloadReg[sel] = 0;
85         regs->dloadSel ^= 1;
86         assert(regs->GPR.r[0] == 0);
87 #endif
88 }
89
90 static void dloadFlush(psxRegisters *regs)
91 {
92 #ifdef HANDLE_LOAD_DELAY
93         regs->GPR.r[regs->dloadReg[0]] = regs->dloadVal[0];
94         regs->GPR.r[regs->dloadReg[1]] = regs->dloadVal[1];
95         regs->dloadVal[0] = regs->dloadVal[1] = 0;
96         regs->dloadReg[0] = regs->dloadReg[1] = 0;
97         assert(regs->GPR.r[0] == 0);
98 #endif
99 }
100
101 static void dloadClear(psxRegisters *regs)
102 {
103 #ifdef HANDLE_LOAD_DELAY
104         regs->dloadVal[0] = regs->dloadVal[1] = 0;
105         regs->dloadReg[0] = regs->dloadReg[1] = 0;
106         regs->dloadSel = 0;
107 #endif
108 }
109
110 static void intException(psxRegisters *regs, u32 pc, u32 cause)
111 {
112         if (cause != 0x20) {
113                 //FILE *f = fopen("/tmp/psx_ram.bin", "wb");
114                 //fwrite(psxM, 1, 0x200000, f); fclose(f);
115                 log_unhandled("exception %08x @%08x ra=%08x\n",
116                         cause, pc, regs->GPR.n.ra);
117         }
118         dloadFlush(regs);
119         regs->pc = pc;
120         psxException(cause, regs->branching, &regs->CP0);
121         regs->branching = R3000A_BRANCH_NONE_OR_EXCEPTION;
122 }
123
124 // exception caused by current instruction (excluding unkasking)
125 static void intExceptionInsn(psxRegisters *regs, u32 cause)
126 {
127         cause |= (regs->code & 0x0c000000) << 2;
128         intException(regs, regs->pc - 4, cause);
129 }
130
131 static noinline void intExceptionReservedInsn(psxRegisters *regs)
132 {
133 #ifdef DO_EXCEPTION_RESERVEDI
134         static u32 ppc_ = ~0u;
135         if (regs->pc != ppc_) {
136                 SysPrintf("reserved instruction %08x @%08x ra=%08x\n",
137                         regs->code, regs->pc - 4, regs->GPR.n.ra);
138                 ppc_ = regs->pc;
139         }
140         intExceptionInsn(regs, R3000E_RI << 2);
141 #endif
142 }
143
144 // 29  Enable for 80000000-ffffffff
145 // 30  Enable for 00000000-7fffffff
146 // 31  Enable exception
147 #define DBR_ABIT(dc, a)    ((dc) & (1u << (29+(((a)>>31)^1))))
148 #define DBR_EN_EXEC(dc, a) (((dc) & 0x01800000) == 0x01800000 && DBR_ABIT(dc, a))
149 #define DBR_EN_LD(dc, a)   (((dc) & 0x06800000) == 0x06800000 && DBR_ABIT(dc, a))
150 #define DBR_EN_ST(dc, a)   (((dc) & 0x0a800000) == 0x0a800000 && DBR_ABIT(dc, a))
151 static void intExceptionDebugBp(psxRegisters *regs, u32 pc)
152 {
153         psxCP0Regs *cp0 = &regs->CP0;
154         dloadFlush(regs);
155         cp0->n.Cause &= 0x300;
156         cp0->n.Cause |= (regs->branching << 30) | (R3000E_Bp << 2);
157         cp0->n.SR = (cp0->n.SR & ~0x3f) | ((cp0->n.SR & 0x0f) << 2);
158         cp0->n.EPC = regs->branching ? pc - 4 : pc;
159         psxRegs.pc = 0x80000040;
160 }
161
162 static int execBreakCheck(psxRegisters *regs, u32 pc)
163 {
164         if (unlikely(DBR_EN_EXEC(regs->CP0.n.DCIC, pc) &&
165             ((pc ^ regs->CP0.n.BPC) & regs->CP0.n.BPCM) == 0))
166         {
167                 regs->CP0.n.DCIC |= 0x03;
168                 if (regs->CP0.n.DCIC & (1u << 31)) {
169                         intExceptionDebugBp(regs, pc);
170                         return 1;
171                 }
172         }
173         return 0;
174 }
175
176 // get an opcode without triggering exceptions or affecting cache
177 u32 intFakeFetch(u32 pc)
178 {
179         u32 *code = (u32 *)psxm(pc & ~0x3, 0);
180         if (unlikely(code == INVALID_PTR))
181                 return 0; // nop
182         return SWAP32(*code);
183
184 }
185
186 static u32 INT_ATTR fetchNoCache(psxRegisters *regs, u8 **memRLUT, u32 pc)
187 {
188         u32 *code = (u32 *)psxm_lut(pc & ~0x3, 0, memRLUT);
189         if (unlikely(code == INVALID_PTR)) {
190                 SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra);
191                 intException(regs, pc, R3000E_IBE << 2);
192                 return 0; // execute as nop
193         }
194         return SWAP32(*code);
195 }
196
197 /*
198 Formula One 2001 :
199 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
200 */
201 static struct cache_entry {
202         u32 tag;
203         u32 data[4];
204 } ICache[256];
205
206 static u32 INT_ATTR fetchICache(psxRegisters *regs, u8 **memRLUT, u32 pc)
207 {
208         // cached?
209         if (pc < 0xa0000000)
210         {
211                 // this is not how the hardware works but whatever
212                 struct cache_entry *entry = &ICache[(pc & 0xff0) >> 4];
213
214                 if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag)
215                 {
216                         const u32 *code = (u32 *)psxm_lut(pc & ~0xf, 0, memRLUT);
217                         if (unlikely(code == INVALID_PTR)) {
218                                 SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra);
219                                 intException(regs, pc, R3000E_IBE << 2);
220                                 return 0; // execute as nop
221                         }
222
223                         entry->tag = pc;
224                         // treat as 4 words, although other configurations are said to be possible
225                         switch (pc & 0x0c)
226                         {
227                                 case 0x00: entry->data[0] = SWAP32(code[0]);
228                                 case 0x04: entry->data[1] = SWAP32(code[1]);
229                                 case 0x08: entry->data[2] = SWAP32(code[2]);
230                                 case 0x0c: entry->data[3] = SWAP32(code[3]);
231                         }
232                 }
233                 return entry->data[(pc & 0x0f) >> 2];
234         }
235
236         return fetchNoCache(regs, memRLUT, pc);
237 }
238
239 static u32 (INT_ATTR *fetch)(psxRegisters *regs_, u8 **memRLUT, u32 pc) = fetchNoCache;
240
241 // Make the timing events trigger faster as we are currently assuming everything
242 // takes one cycle, which is not the case on real hardware.
243 // FIXME: count cache misses, memory latencies, stalls to get rid of this
244 static inline void addCycle(psxRegisters *regs)
245 {
246         assert(regs->subCycleStep >= 0x10000);
247         regs->subCycle += regs->subCycleStep;
248         regs->cycle += regs->subCycle >> 16;
249         regs->subCycle &= 0xffff;
250 }
251
252 /**** R3000A Instruction Macros ****/
253 #define _PC_            regs_->pc       // The next PC to be executed
254
255 #define _fOp_(code)     ((code >> 26)       )  // The opcode part of the instruction register
256 #define _fFunct_(code)  ((code      ) & 0x3F)  // The funct part of the instruction register
257 #define _fRd_(code)     ((code >> 11) & 0x1F)  // The rd part of the instruction register
258 #define _fRt_(code)     ((code >> 16) & 0x1F)  // The rt part of the instruction register
259 #define _fRs_(code)     ((code >> 21) & 0x1F)  // The rs part of the instruction register
260 #define _fSa_(code)     ((code >>  6) & 0x1F)  // The sa part of the instruction register
261 #define _fIm_(code)     ((u16)code)            // The immediate part of the instruction register
262 #define _fTarget_(code) (code & 0x03ffffff)    // The target part of the instruction register
263
264 #define _fImm_(code)    ((s16)code)            // sign-extended immediate
265 #define _fImmU_(code)   (code&0xffff)          // zero-extended immediate
266
267 #define _Op_     _fOp_(code)
268 #define _Funct_  _fFunct_(code)
269 #define _Rd_     _fRd_(code)
270 #define _Rt_     _fRt_(code)
271 #define _Rs_     _fRs_(code)
272 #define _Sa_     _fSa_(code)
273 #define _Im_     _fIm_(code)
274 #define _Target_ _fTarget_(code)
275
276 #define _Imm_    _fImm_(code)
277 #define _ImmU_   _fImmU_(code)
278
279 #define _rRs_   regs_->GPR.r[_Rs_]   // Rs register
280 #define _rRt_   regs_->GPR.r[_Rt_]   // Rt register
281 #define _rSa_   regs_->GPR.r[_Sa_]   // Sa register
282
283 #define _rHi_   regs_->GPR.n.hi   // The HI register
284 #define _rLo_   regs_->GPR.n.lo   // The LO register
285
286 #define _JumpTarget_    ((_Target_ * 4) + (_PC_ & 0xf0000000))   // Calculates the target during a jump instruction
287 #define _BranchTarget_  ((s16)_Im_ * 4 + _PC_)                 // Calculates the target during a branch instruction
288
289 #define _SetLink(x)     dloadRt(regs_, x, _PC_ + 4);       // Sets the return address in the link register
290
291 #define OP(name) \
292         static inline INT_ATTR void name(psxRegisters *regs_, u32 code)
293
294 // this defines shall be used with the tmp 
295 // of the next func (instead of _Funct_...)
296 #define _tFunct_  ((tmp      ) & 0x3F)  // The funct part of the instruction register 
297 #define _tRd_     ((tmp >> 11) & 0x1F)  // The rd part of the instruction register 
298 #define _tRt_     ((tmp >> 16) & 0x1F)  // The rt part of the instruction register 
299 #define _tRs_     ((tmp >> 21) & 0x1F)  // The rs part of the instruction register 
300 #define _tSa_     ((tmp >>  6) & 0x1F)  // The sa part of the instruction register
301
302 #define _i32(x) (s32)(x)
303 #define _u32(x) (u32)(x)
304
305 #define isBranch(c_) \
306         ((1 <= ((c_) >> 26) && ((c_) >> 26) <= 7) || ((c_) & 0xfc00003e) == 8)
307 #define swap_(a_, b_) { u32 t_ = a_; a_ = b_; b_ = t_; }
308
309 // tar1 is main branch target, 'code' is opcode in DS
310 static u32 psxBranchNoDelay(psxRegisters *regs_, u32 tar1, u32 code, int *taken) {
311         u32 temp, rt;
312
313         assert(isBranch(code));
314         *taken = 1;
315         switch (code >> 26) {
316                 case 0x00: // SPECIAL
317                         switch (_Funct_) {
318                                 case 0x08: // JR
319                                         return _u32(_rRs_);
320                                 case 0x09: // JALR
321                                         temp = _u32(_rRs_);
322                                         if (_Rd_)
323                                                 regs_->GPR.r[_Rd_] = tar1 + 4;
324                                         return temp;
325                         }
326                         break;
327                 case 0x01: // REGIMM
328                         rt = _Rt_;
329                         switch (rt) {
330                                 case 0x10: // BLTZAL
331                                         regs_->GPR.n.ra = tar1 + 4;
332                                         if (_i32(_rRs_) < 0)
333                                                 return tar1 + (s16)_Im_ * 4;
334                                         break;
335                                 case 0x11: // BGEZAL
336                                         regs_->GPR.n.ra = tar1 + 4;
337                                         if (_i32(_rRs_) >= 0)
338                                                 return tar1 + (s16)_Im_ * 4;
339                                         break;
340                                 default:
341                                         if (rt & 1) { // BGEZ
342                                                 if (_i32(_rRs_) >= 0)
343                                                         return tar1 + (s16)_Im_ * 4;
344                                         }
345                                         else {        // BLTZ
346                                                 if (_i32(_rRs_) < 0)
347                                                         return tar1 + (s16)_Im_ * 4;
348                                         }
349                                         break;
350                         }
351                         break;
352                 case 0x02: // J
353                         return (tar1 & 0xf0000000u) + _Target_ * 4;
354                 case 0x03: // JAL
355                         regs_->GPR.n.ra = tar1 + 4;
356                         return (tar1 & 0xf0000000u) + _Target_ * 4;
357                 case 0x04: // BEQ
358                         if (_i32(_rRs_) == _i32(_rRt_))
359                                 return tar1 + (s16)_Im_ * 4;
360                         break;
361                 case 0x05: // BNE
362                         if (_i32(_rRs_) != _i32(_rRt_))
363                                 return tar1 + (s16)_Im_ * 4;
364                         break;
365                 case 0x06: // BLEZ
366                         if (_i32(_rRs_) <= 0)
367                                 return tar1 + (s16)_Im_ * 4;
368                         break;
369                 case 0x07: // BGTZ
370                         if (_i32(_rRs_) > 0)
371                                 return tar1 + (s16)_Im_ * 4;
372                         break;
373         }
374
375         *taken = 0;
376         return tar1;
377 }
378
379 static void psxDoDelayBranch(psxRegisters *regs, u32 tar1, u32 code1) {
380         u32 tar2, code;
381         int taken, lim;
382
383         tar2 = psxBranchNoDelay(regs, tar1, code1, &taken);
384         regs->pc = tar1;
385         if (!taken)
386                 return;
387
388         /*
389          * taken branch in delay slot:
390          * - execute 1 instruction at tar1
391          * - jump to tar2 (target of branch in delay slot; this branch
392          *   has no normal delay slot, instruction at tar1 was fetched instead)
393          */
394         for (lim = 0; lim < 8; lim++) {
395                 regs->code = code = fetch(regs, psxMemRLUT, tar1);
396                 addCycle(regs);
397                 if (likely(!isBranch(code))) {
398                         dloadStep(regs);
399                         psxBSC[code >> 26](regs, code);
400                         regs->pc = tar2;
401                         return;
402                 }
403                 tar1 = psxBranchNoDelay(regs, tar2, code, &taken);
404                 regs->pc = tar2;
405                 if (!taken)
406                         return;
407                 swap_(tar1, tar2);
408         }
409         SysPrintf("Evil chained DS branches @ %08x %08x %08x\n", regs->pc, tar1, tar2);
410 }
411
412 static void doBranch(psxRegisters *regs, u32 tar, enum R3000Abdt taken) {
413         u32 code, pc, pc_final;
414
415         branchSeen = regs->branching = taken;
416         pc_final = taken == R3000A_BRANCH_TAKEN ? tar : regs->pc + 4;
417
418         // fetch the delay slot
419         pc = regs->pc;
420         regs->pc = pc + 4;
421         regs->code = code = fetch(regs, psxMemRLUT, pc);
422
423         addCycle(regs);
424
425         // check for branch in delay slot
426         if (unlikely(isBranch(code))) {
427                 regs->pc = pc;
428                 if (taken == R3000A_BRANCH_TAKEN)
429                         psxDoDelayBranch(regs, tar, code);
430                 log_unhandled("branch in DS: %08x->%08x\n", pc, regs->pc);
431                 regs->branching = 0;
432                 psxBranchTest();
433                 return;
434         }
435
436         dloadStep(regs);
437         psxBSC[code >> 26](regs, code);
438
439         if (likely(regs->branching != R3000A_BRANCH_NONE_OR_EXCEPTION))
440                 regs->pc = pc_final;
441         else
442                 regs->CP0.n.Target = pc_final;
443         regs->branching = 0;
444
445         psxBranchTest();
446 }
447
448 static void doBranchReg(psxRegisters *regs, u32 tar) {
449         doBranch(regs, tar & ~3, R3000A_BRANCH_TAKEN);
450 }
451
452 static void doBranchRegE(psxRegisters *regs, u32 tar) {
453         if (unlikely(DBR_EN_EXEC(regs->CP0.n.DCIC, tar) &&
454             ((tar ^ regs->CP0.n.BPC) & regs->CP0.n.BPCM) == 0))
455                 regs->CP0.n.DCIC |= 0x03;
456         if (unlikely(tar & 3)) {
457                 SysPrintf("game crash @%08x, ra=%08x\n", tar, regs->GPR.n.ra);
458                 regs->CP0.n.BadVAddr = tar;
459                 intException(regs, tar, R3000E_AdEL << 2);
460                 return;
461         }
462         doBranch(regs, tar, R3000A_BRANCH_TAKEN);
463 }
464
465 static void addExc(psxRegisters *regs, u32 rt, s32 a1, s32 a2) {
466         s32 val;
467         if (add_overflow(a1, a2, val)) {
468                 //printf("ov %08x + %08x = %08x\n", a1, a2, val);
469                 intExceptionInsn(regs, R3000E_Ov << 2);
470                 return;
471         }
472         dloadRt(regs, rt, val);
473 }
474
475 static void subExc(psxRegisters *regs, u32 rt, s32 a1, s32 a2) {
476         s32 val;
477         if (sub_overflow(a1, a2, val)) {
478                 intExceptionInsn(regs, R3000E_Ov << 2);
479                 return;
480         }
481         dloadRt(regs, rt, val);
482 }
483
484 /*********************************************************
485 * Arithmetic with immediate operand                      *
486 * Format:  OP rt, rs, immediate                          *
487 *********************************************************/
488 OP(psxADDI)  { addExc (regs_, _Rt_, _i32(_rRs_), _Imm_); } // Rt = Rs + Im (Exception on Integer Overflow)
489 OP(psxADDIU) { dloadRt(regs_, _Rt_, _u32(_rRs_) + _Imm_ ); }  // Rt = Rs + Im
490 OP(psxANDI)  { dloadRt(regs_, _Rt_, _u32(_rRs_) & _ImmU_); }  // Rt = Rs And Im
491 OP(psxORI)   { dloadRt(regs_, _Rt_, _u32(_rRs_) | _ImmU_); }  // Rt = Rs Or  Im
492 OP(psxXORI)  { dloadRt(regs_, _Rt_, _u32(_rRs_) ^ _ImmU_); }  // Rt = Rs Xor Im
493 OP(psxSLTI)  { dloadRt(regs_, _Rt_, _i32(_rRs_) < _Imm_ ); }  // Rt = Rs < Im (Signed)
494 OP(psxSLTIU) { dloadRt(regs_, _Rt_, _u32(_rRs_) < ((u32)_Imm_)); } // Rt = Rs < Im (Unsigned)
495
496 /*********************************************************
497 * Register arithmetic                                    *
498 * Format:  OP rd, rs, rt                                 *
499 *********************************************************/
500 OP(psxADD)   { addExc (regs_, _Rd_, _i32(_rRs_), _i32(_rRt_)); } // Rd = Rs + Rt (Exception on Integer Overflow)
501 OP(psxSUB)   { subExc (regs_, _Rd_, _i32(_rRs_), _i32(_rRt_)); } // Rd = Rs - Rt (Exception on Integer Overflow)
502 OP(psxADDU)  { dloadRt(regs_, _Rd_, _u32(_rRs_) + _u32(_rRt_)); }  // Rd = Rs + Rt
503 OP(psxSUBU)  { dloadRt(regs_, _Rd_, _u32(_rRs_) - _u32(_rRt_)); }  // Rd = Rs - Rt
504 OP(psxAND)   { dloadRt(regs_, _Rd_, _u32(_rRs_) & _u32(_rRt_)); }  // Rd = Rs And Rt
505 OP(psxOR)    { dloadRt(regs_, _Rd_, _u32(_rRs_) | _u32(_rRt_)); }  // Rd = Rs Or  Rt
506 OP(psxXOR)   { dloadRt(regs_, _Rd_, _u32(_rRs_) ^ _u32(_rRt_)); }  // Rd = Rs Xor Rt
507 OP(psxNOR)   { dloadRt(regs_, _Rd_, ~_u32(_rRs_ | _u32(_rRt_))); } // Rd = Rs Nor Rt
508 OP(psxSLT)   { dloadRt(regs_, _Rd_, _i32(_rRs_) < _i32(_rRt_)); }  // Rd = Rs < Rt (Signed)
509 OP(psxSLTU)  { dloadRt(regs_, _Rd_, _u32(_rRs_) < _u32(_rRt_)); }  // Rd = Rs < Rt (Unsigned)
510
511 /*********************************************************
512 * Register mult/div & Register trap logic                *
513 * Format:  OP rs, rt                                     *
514 *********************************************************/
515 OP(psxDIV) {
516         if (!_rRt_) {
517                 _rHi_ = _rRs_;
518                 if (_rRs_ & 0x80000000) {
519                         _rLo_ = 1;
520                 } else {
521                         _rLo_ = 0xFFFFFFFF;
522                 }
523         }
524 #if !defined(__arm__) && !defined(__aarch64__)
525         else if (_rRs_ == 0x80000000 && _rRt_ == 0xFFFFFFFF) {
526                 _rLo_ = 0x80000000;
527                 _rHi_ = 0;
528         }
529 #endif
530         else {
531                 _rLo_ = _i32(_rRs_) / _i32(_rRt_);
532                 _rHi_ = _i32(_rRs_) % _i32(_rRt_);
533         }
534 }
535
536 OP(psxDIV_stall) {
537         regs_->muldivBusyCycle = regs_->cycle + 37;
538         psxDIV(regs_, code);
539 }
540
541 OP(psxDIVU) {
542         if (_rRt_ != 0) {
543                 _rLo_ = _rRs_ / _rRt_;
544                 _rHi_ = _rRs_ % _rRt_;
545         }
546         else {
547                 _rLo_ = 0xffffffff;
548                 _rHi_ = _rRs_;
549         }
550 }
551
552 OP(psxDIVU_stall) {
553         regs_->muldivBusyCycle = regs_->cycle + 37;
554         psxDIVU(regs_, code);
555 }
556
557 OP(psxMULT) {
558         u64 res = (s64)_i32(_rRs_) * _i32(_rRt_);
559
560         regs_->GPR.n.lo = (u32)res;
561         regs_->GPR.n.hi = (u32)(res >> 32);
562 }
563
564 OP(psxMULT_stall) {
565         // approximate, but maybe good enough
566         u32 rs = _rRs_;
567         u32 lz = __builtin_clz(((rs ^ ((s32)rs >> 21)) | 1));
568         u32 c = 7 + (2 - (lz / 11)) * 4;
569         regs_->muldivBusyCycle = regs_->cycle + c;
570         psxMULT(regs_, code);
571 }
572
573 OP(psxMULTU) {
574         u64 res = (u64)_u32(_rRs_) * _u32(_rRt_);
575
576         regs_->GPR.n.lo = (u32)(res & 0xffffffff);
577         regs_->GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
578 }
579
580 OP(psxMULTU_stall) {
581         // approximate, but maybe good enough
582         u32 lz = __builtin_clz(_rRs_ | 1);
583         u32 c = 7 + (2 - (lz / 11)) * 4;
584         regs_->muldivBusyCycle = regs_->cycle + c;
585         psxMULTU(regs_, code);
586 }
587
588 /*********************************************************
589 * Register branch logic                                  *
590 * Format:  OP rs, offset                                 *
591 *********************************************************/
592 #define BrCond(c) (c) ? R3000A_BRANCH_TAKEN : R3000A_BRANCH_NOT_TAKEN
593 #define RepZBranchi32(op) \
594         doBranch(regs_, _BranchTarget_, BrCond(_i32(_rRs_) op 0));
595 #define RepZBranchLinki32(op)  { \
596         s32 temp = _i32(_rRs_); \
597         dloadFlush(regs_); \
598         _SetLink(31); \
599         doBranch(regs_, _BranchTarget_, BrCond(temp op 0)); \
600 }
601
602 OP(psxBGEZ)   { RepZBranchi32(>=) }      // Branch if Rs >= 0
603 OP(psxBGEZAL) { RepZBranchLinki32(>=) }  // Branch if Rs >= 0 and link
604 OP(psxBGTZ)   { RepZBranchi32(>) }       // Branch if Rs >  0
605 OP(psxBLEZ)   { RepZBranchi32(<=) }      // Branch if Rs <= 0
606 OP(psxBLTZ)   { RepZBranchi32(<) }       // Branch if Rs <  0
607 OP(psxBLTZAL) { RepZBranchLinki32(<) }   // Branch if Rs <  0 and link
608
609 /*********************************************************
610 * Shift arithmetic with constant shift                   *
611 * Format:  OP rd, rt, sa                                 *
612 *********************************************************/
613 OP(psxSLL) { dloadRt(regs_, _Rd_, _u32(_rRt_) << _Sa_); } // Rd = Rt << sa
614 OP(psxSRA) { dloadRt(regs_, _Rd_, _i32(_rRt_) >> _Sa_); } // Rd = Rt >> sa (arithmetic)
615 OP(psxSRL) { dloadRt(regs_, _Rd_, _u32(_rRt_) >> _Sa_); } // Rd = Rt >> sa (logical)
616
617 /*********************************************************
618 * Shift arithmetic with variant register shift           *
619 * Format:  OP rd, rt, rs                                 *
620 *********************************************************/
621 OP(psxSLLV) { dloadRt(regs_, _Rd_, _u32(_rRt_) << (_u32(_rRs_) & 0x1F)); } // Rd = Rt << rs
622 OP(psxSRAV) { dloadRt(regs_, _Rd_, _i32(_rRt_) >> (_u32(_rRs_) & 0x1F)); } // Rd = Rt >> rs (arithmetic)
623 OP(psxSRLV) { dloadRt(regs_, _Rd_, _u32(_rRt_) >> (_u32(_rRs_) & 0x1F)); } // Rd = Rt >> rs (logical)
624
625 /*********************************************************
626 * Load higher 16 bits of the first word in GPR with imm  *
627 * Format:  OP rt, immediate                              *
628 *********************************************************/
629 OP(psxLUI) { dloadRt(regs_, _Rt_, code << 16); } // Upper halfword of Rt = Im
630
631 /*********************************************************
632 * Move from HI/LO to GPR                                 *
633 * Format:  OP rd                                         *
634 *********************************************************/
635 OP(psxMFHI) { dloadRt(regs_, _Rd_, _rHi_); } // Rd = Hi
636 OP(psxMFLO) { dloadRt(regs_, _Rd_, _rLo_); } // Rd = Lo
637
638 static void mflohiCheckStall(psxRegisters *regs_)
639 {
640         u32 left = regs_->muldivBusyCycle - regs_->cycle;
641         if (left <= 37) {
642                 //printf("muldiv stall %u\n", left);
643                 regs_->cycle = regs_->muldivBusyCycle;
644         }
645 }
646
647 OP(psxMFHI_stall) { mflohiCheckStall(regs_); psxMFHI(regs_, code); }
648 OP(psxMFLO_stall) { mflohiCheckStall(regs_); psxMFLO(regs_, code); }
649
650 /*********************************************************
651 * Move to GPR to HI/LO & Register jump                   *
652 * Format:  OP rs                                         *
653 *********************************************************/
654 OP(psxMTHI) { _rHi_ = _rRs_; } // Hi = Rs
655 OP(psxMTLO) { _rLo_ = _rRs_; } // Lo = Rs
656
657 /*********************************************************
658 * Special purpose instructions                           *
659 * Format:  OP                                            *
660 *********************************************************/
661 OP(psxBREAK) {
662         intExceptionInsn(regs_, R3000E_Bp << 2);
663 }
664
665 OP(psxSYSCALL) {
666         intExceptionInsn(regs_, R3000E_Syscall << 2);
667 }
668
669 static inline void execI_(u8 **memRLUT, psxRegisters *regs_);
670
671 static inline void psxTestSWInts(psxRegisters *regs_, int step) {
672         if ((regs_->CP0.n.Cause & regs_->CP0.n.SR & 0x0300) &&
673             (regs_->CP0.n.SR & 0x1)) {
674                 if (step)
675                         execI_(psxMemRLUT, regs_);
676                 regs_->CP0.n.Cause &= ~0x7c;
677                 intException(regs_, regs_->pc, regs_->CP0.n.Cause);
678         }
679 }
680
681 OP(psxRFE) {
682         regs_->CP0.n.SR = (regs_->CP0.n.SR & ~0x0f) | ((regs_->CP0.n.SR & 0x3c) >> 2);
683         psxTestSWInts(regs_, 0);
684 }
685
686 /*********************************************************
687 * Register branch logic                                  *
688 * Format:  OP rs, rt, offset                             *
689 *********************************************************/
690 #define RepBranchi32(op) \
691         doBranch(regs_, _BranchTarget_, BrCond(_i32(_rRs_) op _i32(_rRt_)));
692
693 OP(psxBEQ) { RepBranchi32(==) }  // Branch if Rs == Rt
694 OP(psxBNE) { RepBranchi32(!=) }  // Branch if Rs != Rt
695
696 /*********************************************************
697 * Jump to target                                         *
698 * Format:  OP target                                     *
699 *********************************************************/
700 OP(psxJ)   { doBranch(regs_, _JumpTarget_, R3000A_BRANCH_TAKEN); }
701 OP(psxJAL) {
702         dloadFlush(regs_);
703         _SetLink(31);
704         doBranch(regs_, _JumpTarget_, R3000A_BRANCH_TAKEN);
705 }
706
707 /*********************************************************
708 * Register jump                                          *
709 * Format:  OP rs, rd                                     *
710 *********************************************************/
711 OP(psxJR) {
712         doBranchReg(regs_, _rRs_);
713         psxJumpTest();
714 }
715
716 OP(psxJRe) {
717         doBranchRegE(regs_, _rRs_);
718         psxJumpTest();
719 }
720
721 OP(psxJALR) {
722         u32 temp = _u32(_rRs_);
723         dloadFlush(regs_);
724         if (_Rd_) { _SetLink(_Rd_); }
725         doBranchReg(regs_, temp);
726 }
727
728 OP(psxJALRe) {
729         u32 temp = _u32(_rRs_);
730         dloadFlush(regs_);
731         if (_Rd_) { _SetLink(_Rd_); }
732         doBranchRegE(regs_, temp);
733 }
734
735 /*********************************************************
736 *********************************************************/
737
738 // revisit: incomplete
739 #define BUS_LOCKED_ADDR(a) \
740         ((0x1fc80000u <= (a) && (a) < 0x80000000u) || \
741          (0xc0000000u <= (a) && (a) < 0xfffe0000u))
742
743 // exception checking order is important
744 static inline int checkLD(psxRegisters *regs, u32 addr, u32 m) {
745         int bpException = 0;
746         if (unlikely(DBR_EN_LD(regs->CP0.n.DCIC, addr) &&
747             ((addr ^ regs->CP0.n.BDA) & regs->CP0.n.BDAM) == 0)) {
748                 regs->CP0.n.DCIC |= 0x0d;
749                 bpException = regs->CP0.n.DCIC >> 31;
750         }
751         if (unlikely(addr & m)) {
752                 regs->CP0.n.BadVAddr = addr;
753                 intExceptionInsn(regs, R3000E_AdEL << 2);
754                 return 0;
755         }
756         if (unlikely(bpException)) {
757                 intExceptionDebugBp(regs, regs->pc - 4);
758                 return 0;
759         }
760         if (unlikely(BUS_LOCKED_ADDR(addr))) {
761                 intException(regs, regs->pc - 4, R3000E_DBE << 2);
762                 return 0;
763         }
764         return 1;
765 }
766
767 static inline int checkST(psxRegisters *regs, u32 addr, u32 m) {
768         int bpException = 0;
769         if (unlikely(DBR_EN_ST(regs->CP0.n.DCIC, addr) &&
770             ((addr ^ regs->CP0.n.BDA) & regs->CP0.n.BDAM) == 0)) {
771                 regs->CP0.n.DCIC |= 0x15;
772                 bpException = regs->CP0.n.DCIC >> 31;
773         }
774         if (unlikely(addr & m)) {
775                 regs->CP0.n.BadVAddr = addr;
776                 intExceptionInsn(regs, R3000E_AdES << 2);
777                 return 0;
778         }
779         if (unlikely(bpException)) {
780                 intExceptionDebugBp(regs, regs->pc - 4);
781                 return 0;
782         }
783         if (unlikely(BUS_LOCKED_ADDR(addr))) {
784                 intException(regs, regs->pc - 4, R3000E_DBE << 2);
785                 return 0;
786         }
787         return 1;
788 }
789
790 /*********************************************************
791 * Load and store for GPR                                 *
792 * Format:  OP rt, offset(base)                           *
793 *********************************************************/
794
795 /*********************************************************
796 * Load and store for GPR                                 *
797 * Format:  OP rt, offset(base)                           *
798 *********************************************************/
799
800 #define _oB_ (regs_->GPR.r[_Rs_] + _Imm_)
801
802 OP(psxLB)  { doLoad(regs_, _Rt_,  (s8)psxMemRead8(_oB_)); }
803 OP(psxLBU) { doLoad(regs_, _Rt_,      psxMemRead8(_oB_)); }
804 OP(psxLH)  { doLoad(regs_, _Rt_, (s16)psxMemRead16(_oB_ & ~1)); }
805 OP(psxLHU) { doLoad(regs_, _Rt_,      psxMemRead16(_oB_ & ~1)); }
806 OP(psxLW)  { doLoad(regs_, _Rt_,      psxMemRead32(_oB_ & ~3)); }
807
808 OP(psxLBe)  { if (checkLD(regs_, _oB_, 0)) doLoad(regs_, _Rt_,  (s8)psxMemRead8(_oB_)); }
809 OP(psxLBUe) { if (checkLD(regs_, _oB_, 0)) doLoad(regs_, _Rt_,      psxMemRead8(_oB_)); }
810 OP(psxLHe)  { if (checkLD(regs_, _oB_, 1)) doLoad(regs_, _Rt_, (s16)psxMemRead16(_oB_)); }
811 OP(psxLHUe) { if (checkLD(regs_, _oB_, 1)) doLoad(regs_, _Rt_,      psxMemRead16(_oB_)); }
812 OP(psxLWe)  { if (checkLD(regs_, _oB_, 3)) doLoad(regs_, _Rt_,      psxMemRead32(_oB_)); }
813
814 static void doLWL(psxRegisters *regs, u32 rt, u32 addr) {
815         static const u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
816         static const u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
817         u32 shift = addr & 3;
818         u32 val, mem;
819         u32 oldval = regs->GPR.r[rt];
820
821 #ifdef HANDLE_LOAD_DELAY
822         int sel = regs->dloadSel;
823         if (regs->dloadReg[sel] == rt)
824                 oldval = regs->dloadVal[sel];
825 #endif
826         mem = psxMemRead32(addr & ~3);
827         val = (oldval & LWL_MASK[shift]) | (mem << LWL_SHIFT[shift]);
828         doLoad(regs, rt, val);
829
830         /*
831         Mem = 1234.  Reg = abcd
832
833         0   4bcd   (mem << 24) | (reg & 0x00ffffff)
834         1   34cd   (mem << 16) | (reg & 0x0000ffff)
835         2   234d   (mem <<  8) | (reg & 0x000000ff)
836         3   1234   (mem      ) | (reg & 0x00000000)
837         */
838 }
839
840 static void doLWR(psxRegisters *regs, u32 rt, u32 addr) {
841         static const u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
842         static const u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
843         u32 shift = addr & 3;
844         u32 val, mem;
845         u32 oldval = regs->GPR.r[rt];
846
847 #ifdef HANDLE_LOAD_DELAY
848         int sel = regs->dloadSel;
849         if (regs->dloadReg[sel] == rt)
850                 oldval = regs->dloadVal[sel];
851 #endif
852         mem = psxMemRead32(addr & ~3);
853         val = (oldval & LWR_MASK[shift]) | (mem >> LWR_SHIFT[shift]);
854         doLoad(regs, rt, val);
855
856         /*
857         Mem = 1234.  Reg = abcd
858
859         0   1234   (mem      ) | (reg & 0x00000000)
860         1   a123   (mem >>  8) | (reg & 0xff000000)
861         2   ab12   (mem >> 16) | (reg & 0xffff0000)
862         3   abc1   (mem >> 24) | (reg & 0xffffff00)
863         */
864 }
865
866 OP(psxLWL) { doLWL(regs_, _Rt_, _oB_); }
867 OP(psxLWR) { doLWR(regs_, _Rt_, _oB_); }
868
869 OP(psxLWLe) { if (checkLD(regs_, _oB_ & ~3, 0)) doLWL(regs_, _Rt_, _oB_); }
870 OP(psxLWRe) { if (checkLD(regs_, _oB_     , 0)) doLWR(regs_, _Rt_, _oB_); }
871
872 OP(psxSB) { psxMemWrite8 (_oB_, _rRt_); }
873 OP(psxSH) { psxMemWrite16(_oB_, _rRt_); }
874 OP(psxSW) { psxMemWrite32(_oB_, _rRt_); }
875
876 OP(psxSBe) { if (checkST(regs_, _oB_, 0)) psxMemWrite8 (_oB_, _rRt_); }
877 OP(psxSHe) { if (checkST(regs_, _oB_, 1)) psxMemWrite16(_oB_, _rRt_); }
878 OP(psxSWe) { if (checkST(regs_, _oB_, 3)) psxMemWrite32(_oB_, _rRt_); }
879
880 static void doSWL(psxRegisters *regs, u32 rt, u32 addr) {
881         u32 val = regs->GPR.r[rt];
882         switch (addr & 3) {
883                 case 0: psxMemWrite8( addr     , val >> 24); break;
884                 case 1: psxMemWrite16(addr & ~3, val >> 16); break;
885                 case 2: // revisit: should be a single 24bit write
886                         psxMemWrite16(addr & ~3, (val >> 8) & 0xffff);
887                         psxMemWrite8( addr     , val >> 24); break;
888                 case 3: psxMemWrite32(addr & ~3, val);       break;
889         }
890         /*
891         Mem = 1234.  Reg = abcd
892
893         0   123a   (reg >> 24) | (mem & 0xffffff00)
894         1   12ab   (reg >> 16) | (mem & 0xffff0000)
895         2   1abc   (reg >>  8) | (mem & 0xff000000)
896         3   abcd   (reg      ) | (mem & 0x00000000)
897         */
898 }
899
900 static void doSWR(psxRegisters *regs, u32 rt, u32 addr) {
901         u32 val = regs->GPR.r[rt];
902         switch (addr & 3) {
903                 case 0: psxMemWrite32(addr    , val); break;
904                 case 1: // revisit: should be a single 24bit write
905                         psxMemWrite8 (addr    , val & 0xff);
906                         psxMemWrite16(addr + 1, (val >> 8) & 0xffff); break;
907                 case 2: psxMemWrite16(addr    , val & 0xffff); break;
908                 case 3: psxMemWrite8 (addr    , val & 0xff); break;
909         }
910
911         /*
912         Mem = 1234.  Reg = abcd
913
914         0   abcd   (reg      ) | (mem & 0x00000000)
915         1   bcd4   (reg <<  8) | (mem & 0x000000ff)
916         2   cd34   (reg << 16) | (mem & 0x0000ffff)
917         3   d234   (reg << 24) | (mem & 0x00ffffff)
918         */
919 }
920
921 OP(psxSWL) { doSWL(regs_, _Rt_, _oB_); }
922 OP(psxSWR) { doSWR(regs_, _Rt_, _oB_); }
923
924 OP(psxSWLe) { if (checkST(regs_, _oB_ & ~3, 0)) doSWL(regs_, _Rt_, _oB_); }
925 OP(psxSWRe) { if (checkST(regs_, _oB_     , 0)) doSWR(regs_, _Rt_, _oB_); }
926
927 /*********************************************************
928 * Moves between GPR and COPx                             *
929 * Format:  OP rt, fs                                     *
930 *********************************************************/
931 OP(psxMFC0) {
932         u32 r = _Rd_;
933         if (unlikely(0x00000417u & (1u << r)))
934                 intExceptionReservedInsn(regs_);
935         doLoad(regs_, _Rt_, regs_->CP0.r[r]);
936 }
937
938 static void setupCop(u32 sr);
939
940 void MTC0(psxRegisters *regs_, int reg, u32 val) {
941 //      SysPrintf("MTC0 %d: %x\n", reg, val);
942         switch (reg) {
943                 case 12: // SR
944                         if (unlikely((regs_->CP0.n.SR ^ val) & (1 << 16)))
945                                 psxMemOnIsolate((val >> 16) & 1);
946                         if (unlikely((regs_->CP0.n.SR ^ val) & (7 << 29)))
947                                 setupCop(val);
948                         regs_->CP0.n.SR = val;
949                         psxTestSWInts(regs_, 1);
950                         break;
951
952                 case 13: // Cause
953                         regs_->CP0.n.Cause &= ~0x0300;
954                         regs_->CP0.n.Cause |= val & 0x0300;
955                         psxTestSWInts(regs_, 0);
956                         break;
957
958                 case 7:
959                         if ((regs_->CP0.n.DCIC ^ val) & 0xff800000)
960                                 log_unhandled("DCIC: %08x->%08x\n", regs_->CP0.n.DCIC, val);
961                         goto default_;
962                 case 3:
963                         if (regs_->CP0.n.BPC != val)
964                                 log_unhandled("BPC: %08x->%08x\n", regs_->CP0.n.BPC, val);
965                         goto default_;
966
967                 default:
968                 default_:
969                         regs_->CP0.r[reg] = val;
970                         break;
971         }
972 }
973
974 OP(psxMTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); }
975
976 // no exception
977 static inline void psxNULLne(psxRegisters *regs) {
978         log_unhandled("unhandled op %08x @%08x\n", regs->code, regs->pc - 4);
979 }
980
981 /*********************************************************
982 * Unknown instruction (would generate an exception)      *
983 * Format:  ?                                             *
984 *********************************************************/
985
986 OP(psxNULL) {
987         psxNULLne(regs_);
988         intExceptionReservedInsn(regs_);
989 }
990
991 void gteNULL(struct psxCP2Regs *regs) {
992         psxRegisters *regs_ = (psxRegisters *)((u8 *)regs - offsetof(psxRegisters, CP2));
993         psxNULLne(regs_);
994 }
995
996 OP(psxSPECIAL) {
997         psxSPC[_Funct_](regs_, code);
998 }
999
1000 OP(psxCOP0) {
1001         u32 rs = _Rs_;
1002         if (rs & 0x10) {
1003                 u32 op2 = code & 0x1f;
1004                 switch (op2) {
1005                         case 0x01:
1006                         case 0x02:
1007                         case 0x06:
1008                         case 0x08: psxNULL(regs_, code); break;
1009                         case 0x10: psxRFE(regs_, code);  break;
1010                         default:   psxNULLne(regs_);     break;
1011                 }
1012                 return;
1013         }
1014         switch (rs) {
1015                 case 0x00: psxMFC0(regs_, code); break;
1016                 case 0x04: psxMTC0(regs_, code); break;
1017                 case 0x02:                              // CFC
1018                 case 0x06: psxNULL(regs_, code); break; // CTC -> exception
1019                 case 0x08:
1020                 case 0x0c: log_unhandled("BC0 %08x @%08x\n", code, regs_->pc - 4);
1021                 default:   psxNULLne(regs_);     break;
1022         }
1023 }
1024
1025 OP(psxCOP1) {
1026         // ??? what actually happens here?
1027         log_unhandled("COP1 %08x @%08x\n", code, regs_->pc - 4);
1028 }
1029
1030 OP(psxCOP2) {
1031         u32 rt = _Rt_, rd = _Rd_, rs = _Rs_;
1032         if (rs & 0x10) {
1033                 psxCP2[_Funct_](&regs_->CP2);
1034                 return;
1035         }
1036         switch (rs) {
1037                 case 0x00: doLoad(regs_, rt, MFC2(&regs_->CP2, rd)); break; // MFC2
1038                 case 0x02: doLoad(regs_, rt, regs_->CP2C.r[rd]);     break; // CFC2
1039                 case 0x04: MTC2(&regs_->CP2, regs_->GPR.r[rt], rd);  break; // MTC2
1040                 case 0x06: CTC2(&regs_->CP2, regs_->GPR.r[rt], rd);  break; // CTC2
1041                 case 0x08:
1042                 case 0x0c: log_unhandled("BC2 %08x @%08x\n", code, regs_->pc - 4);
1043                 default:   psxNULLne(regs_); break;
1044         }
1045 }
1046
1047 OP(psxCOP2_stall) {
1048         u32 f = _Funct_;
1049         gteCheckStall(f);
1050         psxCOP2(regs_, code);
1051 }
1052
1053 OP(gteLWC2) {
1054         MTC2(&regs_->CP2, psxMemRead32(_oB_), _Rt_);
1055 }
1056
1057 OP(gteLWC2_stall) {
1058         gteCheckStall(0);
1059         gteLWC2(regs_, code);
1060 }
1061
1062 OP(gteLWC2e_stall) {
1063         gteCheckStall(0);
1064         if (checkLD(regs_, _oB_, 3))
1065                 MTC2(&regs_->CP2, psxMemRead32(_oB_), _Rt_);
1066 }
1067
1068 OP(gteSWC2) {
1069         psxMemWrite32(_oB_, MFC2(&regs_->CP2, _Rt_));
1070 }
1071
1072 OP(gteSWC2_stall) {
1073         gteCheckStall(0);
1074         gteSWC2(regs_, code);
1075 }
1076
1077 OP(gteSWC2e_stall) {
1078         gteCheckStall(0);
1079         if (checkST(regs_, _oB_, 3))
1080                 gteSWC2(regs_, code);
1081 }
1082
1083 OP(psxCOP3) {
1084         // ??? what actually happens here?
1085         log_unhandled("COP3 %08x @%08x\n", code, regs_->pc - 4);
1086 }
1087
1088 OP(psxCOPd) {
1089         log_unhandled("disabled cop%d @%08x\n", (code >> 26) & 3, regs_->pc - 4);
1090 #ifdef DO_EXCEPTION_RESERVEDI
1091         intExceptionInsn(regs_, R3000E_CpU << 2);
1092 #endif
1093 }
1094
1095 OP(psxLWCx) {
1096         log_unhandled("LWCx %08x @%08x\n", code, regs_->pc - 4);
1097         checkLD(regs_, _oB_, 3);
1098 }
1099
1100 OP(psxSWCx) {
1101         // does this write something to memory?
1102         log_unhandled("SWCx %08x @%08x\n", code, regs_->pc - 4);
1103         checkST(regs_, _oB_, 3);
1104 }
1105
1106 OP(psxREGIMM) {
1107         u32 rt = _Rt_;
1108         switch (rt) {
1109                 case 0x10: psxBLTZAL(regs_, code); break;
1110                 case 0x11: psxBGEZAL(regs_, code); break;
1111                 default:
1112                         if (rt & 1)
1113                                 psxBGEZ(regs_, code);
1114                         else
1115                                 psxBLTZ(regs_, code);
1116         }
1117 }
1118
1119 OP(psxHLE) {
1120         u32 hleCode;
1121         if (unlikely(!Config.HLE)) {
1122                 psxSWCx(regs_, code);
1123                 return;
1124         }
1125         hleCode = code & 0x03ffffff;
1126         if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
1127                 psxSWCx(regs_, code);
1128                 return;
1129         }
1130         dloadFlush(regs_);
1131         psxHLEt[hleCode]();
1132         branchSeen = 1;
1133 }
1134
1135 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code) = {
1136         psxSPECIAL, psxREGIMM, psxJ   , psxJAL  , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
1137         psxADDI   , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
1138         psxCOP0   , psxCOPd  , psxCOP2, psxCOPd,  psxNULL, psxNULL, psxNULL, psxNULL,
1139         psxNULL   , psxNULL  , psxNULL, psxNULL,  psxNULL, psxNULL, psxNULL, psxNULL,
1140         psxLB     , psxLH    , psxLWL , psxLW   , psxLBU , psxLHU , psxLWR , psxNULL,
1141         psxSB     , psxSH    , psxSWL , psxSW   , psxNULL, psxNULL, psxSWR , psxNULL,
1142         psxLWCx   , psxLWCx  , gteLWC2, psxLWCx , psxNULL, psxNULL, psxNULL, psxNULL,
1143         psxSWCx   , psxSWCx  , gteSWC2, psxHLE  , psxNULL, psxNULL, psxNULL, psxNULL,
1144 };
1145
1146 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code) = {
1147         psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV   , psxNULL , psxSRLV, psxSRAV,
1148         psxJR  , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
1149         psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL   , psxNULL , psxNULL, psxNULL,
1150         psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL   , psxNULL , psxNULL, psxNULL,
1151         psxADD , psxADDU , psxSUB , psxSUBU, psxAND    , psxOR   , psxXOR , psxNOR ,
1152         psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL   , psxNULL , psxNULL, psxNULL,
1153         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL,
1154         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL
1155 };
1156
1157 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
1158         gteNULL , gteRTPS , gteNULL , gteNULL, gteNULL, gteNULL , gteNCLIP, gteNULL, // 00
1159         gteNULL , gteNULL , gteNULL , gteNULL, gteOP  , gteNULL , gteNULL , gteNULL, // 08
1160         gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , gteNULL , gteNCDT , gteNULL, // 10
1161         gteNULL , gteNULL , gteNULL , gteNCCS, gteCC  , gteNULL , gteNCS  , gteNULL, // 18
1162         gteNCT  , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 20
1163         gteSQR  , gteDCPL , gteDPCT , gteNULL, gteNULL, gteAVSZ3, gteAVSZ4, gteNULL, // 28
1164         gteRTPT , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 30
1165         gteNULL , gteNULL , gteNULL , gteNULL, gteNULL, gteGPF  , gteGPL  , gteNCCT  // 38
1166 };
1167
1168 ///////////////////////////////////////////
1169
1170 static int intInit() {
1171         return 0;
1172 }
1173
1174 static void intReset() {
1175         dloadClear(&psxRegs);
1176         psxRegs.subCycle = 0;
1177 }
1178
1179 static inline void execI_(u8 **memRLUT, psxRegisters *regs) {
1180         u32 pc = regs->pc;
1181
1182         addCycle(regs);
1183         dloadStep(regs);
1184
1185         regs->pc += 4;
1186         regs->code = fetch(regs, memRLUT, pc);
1187         psxBSC[regs->code >> 26](regs, regs->code);
1188 }
1189
1190 static inline void execIbp(u8 **memRLUT, psxRegisters *regs) {
1191         u32 pc = regs->pc;
1192
1193         addCycle(regs);
1194         dloadStep(regs);
1195
1196         if (execBreakCheck(regs, pc))
1197                 return;
1198
1199         regs->pc += 4;
1200         regs->code = fetch(regs, memRLUT, pc);
1201         psxBSC[regs->code >> 26](regs, regs->code);
1202 }
1203
1204 static void intExecute() {
1205         psxRegisters *regs_ = &psxRegs;
1206         u8 **memRLUT = psxMemRLUT;
1207         extern int stop;
1208
1209         while (!stop)
1210                 execI_(memRLUT, regs_);
1211 }
1212
1213 static void intExecuteBp() {
1214         psxRegisters *regs_ = &psxRegs;
1215         u8 **memRLUT = psxMemRLUT;
1216         extern int stop;
1217
1218         while (!stop)
1219                 execIbp(memRLUT, regs_);
1220 }
1221
1222 void intExecuteBlock(enum blockExecCaller caller) {
1223         psxRegisters *regs_ = &psxRegs;
1224         u8 **memRLUT = psxMemRLUT;
1225
1226         branchSeen = 0;
1227         while (!branchSeen)
1228                 execI_(memRLUT, regs_);
1229 }
1230
1231 static void intClear(u32 Addr, u32 Size) {
1232 }
1233
1234 static void intNotify(enum R3000Anote note, void *data) {
1235         switch (note) {
1236         case R3000ACPU_NOTIFY_BEFORE_SAVE:
1237                 dloadFlush(&psxRegs);
1238                 break;
1239         case R3000ACPU_NOTIFY_AFTER_LOAD:
1240                 dloadClear(&psxRegs);
1241                 psxRegs.subCycle = 0;
1242                 setupCop(psxRegs.CP0.n.SR);
1243                 // fallthrough
1244         case R3000ACPU_NOTIFY_CACHE_ISOLATED: // Armored Core?
1245                 memset(&ICache, 0xff, sizeof(ICache));
1246                 break;
1247         case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
1248                 break;
1249         }
1250 }
1251
1252 static void setupCop(u32 sr)
1253 {
1254         if (sr & (1u << 29))
1255                 psxBSC[17] = psxCOP1;
1256         else
1257                 psxBSC[17] = psxCOPd;
1258         if (sr & (1u << 30))
1259                 psxBSC[18] = Config.DisableStalls ? psxCOP2 : psxCOP2_stall;
1260         else
1261                 psxBSC[18] = psxCOPd;
1262         if (sr & (1u << 31))
1263                 psxBSC[19] = psxCOP3;
1264         else
1265                 psxBSC[19] = psxCOPd;
1266 }
1267
1268 void intApplyConfig() {
1269         int cycle_mult;
1270
1271         assert(psxSPC[16] == psxMFHI  || psxSPC[16] == psxMFHI_stall);
1272         assert(psxSPC[18] == psxMFLO  || psxSPC[18] == psxMFLO_stall);
1273         assert(psxSPC[24] == psxMULT  || psxSPC[24] == psxMULT_stall);
1274         assert(psxSPC[25] == psxMULTU || psxSPC[25] == psxMULTU_stall);
1275         assert(psxSPC[26] == psxDIV   || psxSPC[26] == psxDIV_stall);
1276         assert(psxSPC[27] == psxDIVU  || psxSPC[27] == psxDIVU_stall);
1277
1278         if (Config.DisableStalls) {
1279                 psxBSC[18] = psxCOP2;
1280                 psxBSC[50] = gteLWC2;
1281                 psxBSC[58] = gteSWC2;
1282                 psxSPC[16] = psxMFHI;
1283                 psxSPC[18] = psxMFLO;
1284                 psxSPC[24] = psxMULT;
1285                 psxSPC[25] = psxMULTU;
1286                 psxSPC[26] = psxDIV;
1287                 psxSPC[27] = psxDIVU;
1288         } else {
1289                 psxBSC[18] = psxCOP2_stall;
1290                 psxBSC[50] = gteLWC2_stall;
1291                 psxBSC[58] = gteSWC2_stall;
1292                 psxSPC[16] = psxMFHI_stall;
1293                 psxSPC[18] = psxMFLO_stall;
1294                 psxSPC[24] = psxMULT_stall;
1295                 psxSPC[25] = psxMULTU_stall;
1296                 psxSPC[26] = psxDIV_stall;
1297                 psxSPC[27] = psxDIVU_stall;
1298         }
1299         setupCop(psxRegs.CP0.n.SR);
1300
1301         if (Config.PreciseExceptions) {
1302                 psxBSC[0x20] = psxLBe;
1303                 psxBSC[0x21] = psxLHe;
1304                 psxBSC[0x22] = psxLWLe;
1305                 psxBSC[0x23] = psxLWe;
1306                 psxBSC[0x24] = psxLBUe;
1307                 psxBSC[0x25] = psxLHUe;
1308                 psxBSC[0x26] = psxLWRe;
1309                 psxBSC[0x28] = psxSBe;
1310                 psxBSC[0x29] = psxSHe;
1311                 psxBSC[0x2a] = psxSWLe;
1312                 psxBSC[0x2b] = psxSWe;
1313                 psxBSC[0x2e] = psxSWRe;
1314                 psxBSC[0x32] = gteLWC2e_stall;
1315                 psxBSC[0x3a] = gteSWC2e_stall;
1316                 psxSPC[0x08] = psxJRe;
1317                 psxSPC[0x09] = psxJALRe;
1318                 psxInt.Execute = intExecuteBp;
1319         } else {
1320                 psxBSC[0x20] = psxLB;
1321                 psxBSC[0x21] = psxLH;
1322                 psxBSC[0x22] = psxLWL;
1323                 psxBSC[0x23] = psxLW;
1324                 psxBSC[0x24] = psxLBU;
1325                 psxBSC[0x25] = psxLHU;
1326                 psxBSC[0x26] = psxLWR;
1327                 psxBSC[0x28] = psxSB;
1328                 psxBSC[0x29] = psxSH;
1329                 psxBSC[0x2a] = psxSWL;
1330                 psxBSC[0x2b] = psxSW;
1331                 psxBSC[0x2e] = psxSWR;
1332                 // LWC2, SWC2 handled by Config.DisableStalls
1333                 psxSPC[0x08] = psxJR;
1334                 psxSPC[0x09] = psxJALR;
1335                 psxInt.Execute = intExecute;
1336         }
1337
1338         // the dynarec may occasionally call the interpreter, in such a case the
1339         // cache won't work (cache only works right if all fetches go through it)
1340         if (!Config.icache_emulation || psxCpu != &psxInt)
1341                 fetch = fetchNoCache;
1342         else
1343                 fetch = fetchICache;
1344
1345         cycle_mult = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT
1346                 ? Config.cycle_multiplier_override : Config.cycle_multiplier;
1347         psxRegs.subCycleStep = 0x10000 * cycle_mult / 100;
1348 }
1349
1350 static void intShutdown() {
1351         dloadClear(&psxRegs);
1352 }
1353
1354 // single step (may do several ops in case of a branch or load delay)
1355 // called by asm/dynarec
1356 void execI(psxRegisters *regs) {
1357         do {
1358                 execIbp(psxMemRLUT, regs);
1359         } while (regs->dloadReg[0] || regs->dloadReg[1]);
1360 }
1361
1362 R3000Acpu psxInt = {
1363         intInit,
1364         intReset,
1365         intExecute,
1366         intExecuteBlock,
1367         intClear,
1368         intNotify,
1369         intApplyConfig,
1370         intShutdown
1371 };