ea20cab97ce4a77bb27383d0de9fe2699b6cd1fd
[pcsx_rearmed.git] / libpcsxcore / psxinterpreter.c
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 /*
21  * PSX assembly interpreter.
22  */
23
24 #include "psxcommon.h"
25 #include "r3000a.h"
26 #include "gte.h"
27 #include "psxhle.h"
28 #include "psxinterpreter.h"
29 #include <stddef.h>
30 #include <assert.h>
31 //#include "debug.h"
32 #define ProcessDebug()
33
34 static int branch = 0;
35 static int branch2 = 0;
36 static u32 branchPC;
37
38 // These macros are used to assemble the repassembler functions
39
40 #ifdef PSXCPU_LOG
41 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); 
42 #else
43 #define debugI()
44 #endif
45
46 #ifdef __i386__
47 #define INT_ATTR __attribute__((regparm(2)))
48 #else
49 #define INT_ATTR
50 #endif
51 #ifndef INVALID_PTR
52 #define INVALID_PTR NULL
53 #endif
54
55 // Subsets
56 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code);
57 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code);
58
59 static u32 INT_ATTR fetchNoCache(u8 **memRLUT, u32 pc)
60 {
61         u8 *base = memRLUT[pc >> 16];
62         if (base == INVALID_PTR)
63                 return 0;
64         u32 *code = (u32 *)(base + (pc & 0xfffc));
65         return SWAP32(*code);
66 }
67
68 /*
69 Formula One 2001 :
70 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
71 */
72 static struct cache_entry {
73         u32 tag;
74         u32 data[4];
75 } ICache[256];
76
77 static u32 INT_ATTR fetchICache(u8 **memRLUT, u32 pc)
78 {
79         // cached?
80         if (pc < 0xa0000000)
81         {
82                 // this is not how the hardware works but whatever
83                 struct cache_entry *entry = &ICache[(pc & 0xff0) >> 4];
84
85                 if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag)
86                 {
87                         const u8 *base = memRLUT[pc >> 16];
88                         const u32 *code;
89                         if (base == INVALID_PTR)
90                                 return 0;
91                         code = (u32 *)(base + (pc & 0xfff0));
92
93                         entry->tag = pc;
94                         // treat as 4 words, although other configurations are said to be possible
95                         switch (pc & 0x0c)
96                         {
97                                 case 0x00: entry->data[0] = SWAP32(code[0]);
98                                 case 0x04: entry->data[1] = SWAP32(code[1]);
99                                 case 0x08: entry->data[2] = SWAP32(code[2]);
100                                 case 0x0c: entry->data[3] = SWAP32(code[3]);
101                         }
102                 }
103                 return entry->data[(pc & 0x0f) >> 2];
104         }
105
106         return fetchNoCache(memRLUT, pc);
107 }
108
109 static u32 (INT_ATTR *fetch)(u8 **memRLUT, u32 pc) = fetchNoCache;
110
111 static void delayRead(int reg, u32 bpc) {
112         u32 rold, rnew;
113
114 //      SysPrintf("delayRead at %x!\n", psxRegs.pc);
115
116         rold = psxRegs.GPR.r[reg];
117         psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code); // branch delay load
118         rnew = psxRegs.GPR.r[reg];
119
120         psxRegs.pc = bpc;
121
122         branch = 0;
123
124         psxRegs.GPR.r[reg] = rold;
125         execI(); // first branch opcode
126         psxRegs.GPR.r[reg] = rnew;
127
128         psxBranchTest();
129 }
130
131 static void delayWrite(int reg, u32 bpc) {
132
133 /*      SysPrintf("delayWrite at %x!\n", psxRegs.pc);
134
135         SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
136         SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
137
138         // no changes from normal behavior
139
140         psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
141
142         branch = 0;
143         psxRegs.pc = bpc;
144
145         psxBranchTest();
146 }
147
148 static void delayReadWrite(int reg, u32 bpc) {
149
150 //      SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
151
152         // the branch delay load is skipped
153
154         branch = 0;
155         psxRegs.pc = bpc;
156
157         psxBranchTest();
158 }
159
160 /**** R3000A Instruction Macros ****/
161 #define _PC_            regs_->pc       // The next PC to be executed
162
163 #define _fOp_(code)     ((code >> 26)       )  // The opcode part of the instruction register
164 #define _fFunct_(code)  ((code      ) & 0x3F)  // The funct part of the instruction register
165 #define _fRd_(code)     ((code >> 11) & 0x1F)  // The rd part of the instruction register
166 #define _fRt_(code)     ((code >> 16) & 0x1F)  // The rt part of the instruction register
167 #define _fRs_(code)     ((code >> 21) & 0x1F)  // The rs part of the instruction register
168 #define _fSa_(code)     ((code >>  6) & 0x1F)  // The sa part of the instruction register
169 #define _fIm_(code)     ((u16)code)            // The immediate part of the instruction register
170 #define _fTarget_(code) (code & 0x03ffffff)    // The target part of the instruction register
171
172 #define _fImm_(code)    ((s16)code)            // sign-extended immediate
173 #define _fImmU_(code)   (code&0xffff)          // zero-extended immediate
174
175 #define _Op_     _fOp_(code)
176 #define _Funct_  _fFunct_(code)
177 #define _Rd_     _fRd_(code)
178 #define _Rt_     _fRt_(code)
179 #define _Rs_     _fRs_(code)
180 #define _Sa_     _fSa_(code)
181 #define _Im_     _fIm_(code)
182 #define _Target_ _fTarget_(code)
183
184 #define _Imm_    _fImm_(code)
185 #define _ImmU_   _fImmU_(code)
186
187 #define _rRs_   regs_->GPR.r[_Rs_]   // Rs register
188 #define _rRt_   regs_->GPR.r[_Rt_]   // Rt register
189 #define _rRd_   regs_->GPR.r[_Rd_]   // Rd register
190 #define _rSa_   regs_->GPR.r[_Sa_]   // Sa register
191 #define _rFs_   regs_->CP0.r[_Rd_]   // Fs register
192
193 #define _rHi_   regs_->GPR.n.hi   // The HI register
194 #define _rLo_   regs_->GPR.n.lo   // The LO register
195
196 #define _JumpTarget_    ((_Target_ * 4) + (_PC_ & 0xf0000000))   // Calculates the target during a jump instruction
197 #define _BranchTarget_  ((s16)_Im_ * 4 + _PC_)                 // Calculates the target during a branch instruction
198
199 #define _SetLink(x)     regs_->GPR.r[x] = _PC_ + 4;       // Sets the return address in the link register
200
201 #define OP(name) \
202         static inline INT_ATTR void name(psxRegisters *regs_, u32 code)
203
204 // this defines shall be used with the tmp 
205 // of the next func (instead of _Funct_...)
206 #define _tFunct_  ((tmp      ) & 0x3F)  // The funct part of the instruction register 
207 #define _tRd_     ((tmp >> 11) & 0x1F)  // The rd part of the instruction register 
208 #define _tRt_     ((tmp >> 16) & 0x1F)  // The rt part of the instruction register 
209 #define _tRs_     ((tmp >> 21) & 0x1F)  // The rs part of the instruction register 
210 #define _tSa_     ((tmp >>  6) & 0x1F)  // The sa part of the instruction register
211
212 #define _i32(x) (s32)(x)
213 #define _u32(x) (u32)(x)
214
215 static int psxTestLoadDelay(int reg, u32 tmp) {
216         if (tmp == 0) return 0; // NOP
217         switch (tmp >> 26) {
218                 case 0x00: // SPECIAL
219                         switch (_tFunct_) {
220                                 case 0x00: // SLL
221                                 case 0x02: case 0x03: // SRL/SRA
222                                         if (_tRd_ == reg && _tRt_ == reg) return 1; else
223                                         if (_tRt_ == reg) return 2; else
224                                         if (_tRd_ == reg) return 3;
225                                         break;
226
227                                 case 0x08: // JR
228                                         if (_tRs_ == reg) return 2;
229                                         break;
230                                 case 0x09: // JALR
231                                         if (_tRd_ == reg && _tRs_ == reg) return 1; else
232                                         if (_tRs_ == reg) return 2; else
233                                         if (_tRd_ == reg) return 3;
234                                         break;
235
236                                 // SYSCALL/BREAK just a break;
237
238                                 case 0x20: case 0x21: case 0x22: case 0x23:
239                                 case 0x24: case 0x25: case 0x26: case 0x27: 
240                                 case 0x2a: case 0x2b: // ADD/ADDU...
241                                 case 0x04: case 0x06: case 0x07: // SLLV...
242                                         if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
243                                         if (_tRt_ == reg || _tRs_ == reg) return 2; else
244                                         if (_tRd_ == reg) return 3;
245                                         break;
246
247                                 case 0x10: case 0x12: // MFHI/MFLO
248                                         if (_tRd_ == reg) return 3;
249                                         break;
250                                 case 0x11: case 0x13: // MTHI/MTLO
251                                         if (_tRs_ == reg) return 2;
252                                         break;
253
254                                 case 0x18: case 0x19:
255                                 case 0x1a: case 0x1b: // MULT/DIV...
256                                         if (_tRt_ == reg || _tRs_ == reg) return 2;
257                                         break;
258                         }
259                         break;
260
261                 case 0x01: // REGIMM
262                         switch (_tRt_) {
263                                 case 0x00: case 0x01:
264                                 case 0x10: case 0x11: // BLTZ/BGEZ...
265                                         // Xenogears - lbu v0 / beq v0
266                                         // - no load delay (fixes battle loading)
267                                         break;
268
269                                         if (_tRs_ == reg) return 2;
270                                         break;
271                         }
272                         break;
273
274                 // J would be just a break;
275                 case 0x03: // JAL
276                         if (31 == reg) return 3;
277                         break;
278
279                 case 0x04: case 0x05: // BEQ/BNE
280                         // Xenogears - lbu v0 / beq v0
281                         // - no load delay (fixes battle loading)
282                         break;
283
284                         if (_tRs_ == reg || _tRt_ == reg) return 2;
285                         break;
286
287                 case 0x06: case 0x07: // BLEZ/BGTZ
288                         // Xenogears - lbu v0 / beq v0
289                         // - no load delay (fixes battle loading)
290                         break;
291
292                         if (_tRs_ == reg) return 2;
293                         break;
294
295                 case 0x08: case 0x09: case 0x0a: case 0x0b:
296                 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
297                         if (_tRt_ == reg && _tRs_ == reg) return 1; else
298                         if (_tRs_ == reg) return 2; else
299                         if (_tRt_ == reg) return 3;
300                         break;
301
302                 case 0x0f: // LUI
303                         if (_tRt_ == reg) return 3;
304                         break;
305
306                 case 0x10: // COP0
307                         switch (_tFunct_) {
308                                 case 0x00: // MFC0
309                                         if (_tRt_ == reg) return 3;
310                                         break;
311                                 case 0x02: // CFC0
312                                         if (_tRt_ == reg) return 3;
313                                         break;
314                                 case 0x04: // MTC0
315                                         if (_tRt_ == reg) return 2;
316                                         break;
317                                 case 0x06: // CTC0
318                                         if (_tRt_ == reg) return 2;
319                                         break;
320                                 // RFE just a break;
321                         }
322                         break;
323
324                 case 0x12: // COP2
325                         switch (_tFunct_) {
326                                 case 0x00: 
327                                         switch (_tRs_) {
328                                                 case 0x00: // MFC2
329                                                         if (_tRt_ == reg) return 3;
330                                                         break;
331                                                 case 0x02: // CFC2
332                                                         if (_tRt_ == reg) return 3;
333                                                         break;
334                                                 case 0x04: // MTC2
335                                                         if (_tRt_ == reg) return 2;
336                                                         break;
337                                                 case 0x06: // CTC2
338                                                         if (_tRt_ == reg) return 2;
339                                                         break;
340                                         }
341                                         break;
342                                 // RTPS... break;
343                         }
344                         break;
345
346                 case 0x22: case 0x26: // LWL/LWR
347                         if (_tRt_ == reg) return 3; else
348                         if (_tRs_ == reg) return 2;
349                         break;
350
351                 case 0x20: case 0x21: case 0x23:
352                 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
353                         if (_tRt_ == reg && _tRs_ == reg) return 1; else
354                         if (_tRs_ == reg) return 2; else
355                         if (_tRt_ == reg) return 3;
356                         break;
357
358                 case 0x28: case 0x29: case 0x2a:
359                 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
360                         if (_tRt_ == reg || _tRs_ == reg) return 2;
361                         break;
362
363                 case 0x32: case 0x3a: // LWC2/SWC2
364                         if (_tRs_ == reg) return 2;
365                         break;
366         }
367
368         return 0;
369 }
370
371 static void psxDelayTest(int reg, u32 bpc) {
372         u32 tmp = fetch(psxMemRLUT, bpc);
373         branch = 1;
374
375         switch (psxTestLoadDelay(reg, tmp)) {
376                 case 1:
377                         delayReadWrite(reg, bpc); return;
378                 case 2:
379                         delayRead(reg, bpc); return;
380                 case 3:
381                         delayWrite(reg, bpc); return;
382         }
383         psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
384
385         branch = 0;
386         psxRegs.pc = bpc;
387
388         psxBranchTest();
389 }
390
391 static u32 psxBranchNoDelay(psxRegisters *regs_) {
392         u32 temp, code;
393
394         regs_->code = code = fetch(psxMemRLUT, regs_->pc);
395         switch (_Op_) {
396                 case 0x00: // SPECIAL
397                         switch (_Funct_) {
398                                 case 0x08: // JR
399                                         return _u32(_rRs_);
400                                 case 0x09: // JALR
401                                         temp = _u32(_rRs_);
402                                         if (_Rd_) { _SetLink(_Rd_); }
403                                         return temp;
404                         }
405                         break;
406                 case 0x01: // REGIMM
407                         switch (_Rt_) {
408                                 case 0x00: // BLTZ
409                                         if (_i32(_rRs_) < 0)
410                                                 return _BranchTarget_;
411                                         break;
412                                 case 0x01: // BGEZ
413                                         if (_i32(_rRs_) >= 0)
414                                                 return _BranchTarget_;
415                                         break;
416                                 case 0x08: // BLTZAL
417                                         if (_i32(_rRs_) < 0) {
418                                                 _SetLink(31);
419                                                 return _BranchTarget_;
420                                         }
421                                         break;
422                                 case 0x09: // BGEZAL
423                                         if (_i32(_rRs_) >= 0) {
424                                                 _SetLink(31);
425                                                 return _BranchTarget_;
426                                         }
427                                         break;
428                         }
429                         break;
430                 case 0x02: // J
431                         return _JumpTarget_;
432                 case 0x03: // JAL
433                         _SetLink(31);
434                         return _JumpTarget_;
435                 case 0x04: // BEQ
436                         if (_i32(_rRs_) == _i32(_rRt_))
437                                 return _BranchTarget_;
438                         break;
439                 case 0x05: // BNE
440                         if (_i32(_rRs_) != _i32(_rRt_))
441                                 return _BranchTarget_;
442                         break;
443                 case 0x06: // BLEZ
444                         if (_i32(_rRs_) <= 0)
445                                 return _BranchTarget_;
446                         break;
447                 case 0x07: // BGTZ
448                         if (_i32(_rRs_) > 0)
449                                 return _BranchTarget_;
450                         break;
451         }
452
453         return (u32)-1;
454 }
455
456 static int psxDelayBranchExec(u32 tar) {
457         execI();
458
459         branch = 0;
460         psxRegs.pc = tar;
461         psxRegs.cycle += BIAS;
462         psxBranchTest();
463         return 1;
464 }
465
466 static int psxDelayBranchTest(u32 tar1) {
467         u32 tar2, tmp1, tmp2;
468
469         tar2 = psxBranchNoDelay(&psxRegs);
470         if (tar2 == (u32)-1)
471                 return 0;
472
473         debugI();
474
475         /*
476          * Branch in delay slot:
477          * - execute 1 instruction at tar1
478          * - jump to tar2 (target of branch in delay slot; this branch
479          *   has no normal delay slot, instruction at tar1 was fetched instead)
480          */
481         psxRegs.pc = tar1;
482         tmp1 = psxBranchNoDelay(&psxRegs);
483         if (tmp1 == (u32)-1) {
484                 return psxDelayBranchExec(tar2);
485         }
486         debugI();
487         psxRegs.cycle += BIAS;
488
489         /*
490          * Got a branch at tar1:
491          * - execute 1 instruction at tar2
492          * - jump to target of that branch (tmp1)
493          */
494         psxRegs.pc = tar2;
495         tmp2 = psxBranchNoDelay(&psxRegs);
496         if (tmp2 == (u32)-1) {
497                 return psxDelayBranchExec(tmp1);
498         }
499         debugI();
500         psxRegs.cycle += BIAS;
501
502         /*
503          * Got a branch at tar2:
504          * - execute 1 instruction at tmp1
505          * - jump to target of that branch (tmp2)
506          */
507         psxRegs.pc = tmp1;
508         return psxDelayBranchExec(tmp2);
509 }
510
511 static void doBranch(u32 tar) {
512         u32 tmp, code;
513
514         branch2 = branch = 1;
515         branchPC = tar;
516
517         // check for branch in delay slot
518         if (psxDelayBranchTest(tar))
519                 return;
520
521         psxRegs.code = code = fetch(psxMemRLUT, psxRegs.pc);
522
523         debugI();
524
525         psxRegs.pc += 4;
526         psxRegs.cycle += BIAS;
527
528         // check for load delay
529         tmp = psxRegs.code >> 26;
530         switch (tmp) {
531                 case 0x10: // COP0
532                         switch (_Rs_) {
533                                 case 0x00: // MFC0
534                                 case 0x02: // CFC0
535                                         psxDelayTest(_Rt_, branchPC);
536                                         return;
537                         }
538                         break;
539                 case 0x12: // COP2
540                         switch (_Funct_) {
541                                 case 0x00:
542                                         switch (_Rs_) {
543                                                 case 0x00: // MFC2
544                                                 case 0x02: // CFC2
545                                                         psxDelayTest(_Rt_, branchPC);
546                                                         return;
547                                         }
548                                         break;
549                         }
550                         break;
551                 case 0x32: // LWC2
552                         psxDelayTest(_Rt_, branchPC);
553                         return;
554                 default:
555                         if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
556                                 psxDelayTest(_Rt_, branchPC);
557                                 return;
558                         }
559                         break;
560         }
561
562         psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
563
564         branch = 0;
565         psxRegs.pc = branchPC;
566
567         psxBranchTest();
568 }
569
570 /*********************************************************
571 * Arithmetic with immediate operand                      *
572 * Format:  OP rt, rs, immediate                          *
573 *********************************************************/
574 OP(psxADDI)  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; }  // Rt = Rs + Im      (Exception on Integer Overflow)
575 OP(psxADDIU) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; }  // Rt = Rs + Im
576 OP(psxANDI)  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; }  // Rt = Rs And Im
577 OP(psxORI)   { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; }  // Rt = Rs Or  Im
578 OP(psxXORI)  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; }  // Rt = Rs Xor Im
579 OP(psxSLTI)  { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; }  // Rt = Rs < Im              (Signed)
580 OP(psxSLTIU) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im         (Unsigned)
581
582 /*********************************************************
583 * Register arithmetic                                    *
584 * Format:  OP rd, rs, rt                                 *
585 *********************************************************/
586 OP(psxADD)   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); }  // Rd = Rs + Rt         (Exception on Integer Overflow)
587 OP(psxADDU)  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); }  // Rd = Rs + Rt
588 OP(psxSUB)   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); }  // Rd = Rs - Rt         (Exception on Integer Overflow)
589 OP(psxSUBU)  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); }  // Rd = Rs - Rt
590 OP(psxAND)   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); }  // Rd = Rs And Rt
591 OP(psxOR)    { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); }  // Rd = Rs Or  Rt
592 OP(psxXOR)   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); }  // Rd = Rs Xor Rt
593 OP(psxNOR)   { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
594 OP(psxSLT)   { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); }  // Rd = Rs < Rt         (Signed)
595 OP(psxSLTU)  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); }  // Rd = Rs < Rt         (Unsigned)
596
597 /*********************************************************
598 * Register mult/div & Register trap logic                *
599 * Format:  OP rs, rt                                     *
600 *********************************************************/
601 OP(psxDIV) {
602         if (!_rRt_) {
603                 _rHi_ = _rRs_;
604                 if (_rRs_ & 0x80000000) {
605                         _rLo_ = 1;
606                 } else {
607                         _rLo_ = 0xFFFFFFFF;
608                 }
609         }
610 #if !defined(__arm__) && !defined(__aarch64__)
611         else if (_rRs_ == 0x80000000 && _rRt_ == 0xFFFFFFFF) {
612                 _rLo_ = 0x80000000;
613                 _rHi_ = 0;
614         }
615 #endif
616         else {
617                 _rLo_ = _i32(_rRs_) / _i32(_rRt_);
618                 _rHi_ = _i32(_rRs_) % _i32(_rRt_);
619         }
620 }
621
622 OP(psxDIV_stall) {
623         regs_->muldivBusyCycle = regs_->cycle + 37;
624         psxDIV(regs_, code);
625 }
626
627 OP(psxDIVU) {
628         if (_rRt_ != 0) {
629                 _rLo_ = _rRs_ / _rRt_;
630                 _rHi_ = _rRs_ % _rRt_;
631         }
632         else {
633                 _rLo_ = 0xffffffff;
634                 _rHi_ = _rRs_;
635         }
636 }
637
638 OP(psxDIVU_stall) {
639         regs_->muldivBusyCycle = regs_->cycle + 37;
640         psxDIVU(regs_, code);
641 }
642
643 OP(psxMULT) {
644         u64 res = (s64)_i32(_rRs_) * _i32(_rRt_);
645
646         regs_->GPR.n.lo = (u32)res;
647         regs_->GPR.n.hi = (u32)(res >> 32);
648 }
649
650 OP(psxMULT_stall) {
651         // approximate, but maybe good enough
652         u32 rs = _rRs_;
653         u32 lz = __builtin_clz(((rs ^ ((s32)rs >> 21)) | 1));
654         u32 c = 7 + (2 - (lz / 11)) * 4;
655         regs_->muldivBusyCycle = regs_->cycle + c;
656         psxMULT(regs_, code);
657 }
658
659 OP(psxMULTU) {
660         u64 res = (u64)_u32(_rRs_) * _u32(_rRt_);
661
662         regs_->GPR.n.lo = (u32)(res & 0xffffffff);
663         regs_->GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
664 }
665
666 OP(psxMULTU_stall) {
667         // approximate, but maybe good enough
668         u32 lz = __builtin_clz(_rRs_ | 1);
669         u32 c = 7 + (2 - (lz / 11)) * 4;
670         regs_->muldivBusyCycle = regs_->cycle + c;
671         psxMULTU(regs_, code);
672 }
673
674 /*********************************************************
675 * Register branch logic                                  *
676 * Format:  OP rs, offset                                 *
677 *********************************************************/
678 #define RepZBranchi32(op)      if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
679 #define RepZBranchLinki32(op)  { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } }
680
681 OP(psxBGEZ)   { RepZBranchi32(>=) }      // Branch if Rs >= 0
682 OP(psxBGEZAL) { RepZBranchLinki32(>=) }  // Branch if Rs >= 0 and link
683 OP(psxBGTZ)   { RepZBranchi32(>) }       // Branch if Rs >  0
684 OP(psxBLEZ)   { RepZBranchi32(<=) }      // Branch if Rs <= 0
685 OP(psxBLTZ)   { RepZBranchi32(<) }       // Branch if Rs <  0
686 OP(psxBLTZAL) { RepZBranchLinki32(<) }   // Branch if Rs <  0 and link
687
688 /*********************************************************
689 * Shift arithmetic with constant shift                   *
690 * Format:  OP rd, rt, sa                                 *
691 *********************************************************/
692 OP(psxSLL) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
693 OP(psxSRA) { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
694 OP(psxSRL) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
695
696 /*********************************************************
697 * Shift arithmetic with variant register shift           *
698 * Format:  OP rd, rt, rs                                 *
699 *********************************************************/
700 OP(psxSLLV) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs
701 OP(psxSRAV) { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic)
702 OP(psxSRLV) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical)
703
704 /*********************************************************
705 * Load higher 16 bits of the first word in GPR with imm  *
706 * Format:  OP rt, immediate                              *
707 *********************************************************/
708 OP(psxLUI) { if (!_Rt_) return; _rRt_ = code << 16; } // Upper halfword of Rt = Im
709
710 /*********************************************************
711 * Move from HI/LO to GPR                                 *
712 * Format:  OP rd                                         *
713 *********************************************************/
714 OP(psxMFHI) { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
715 OP(psxMFLO) { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
716
717 static void mflohiCheckStall(psxRegisters *regs_)
718 {
719         u32 left = regs_->muldivBusyCycle - regs_->cycle;
720         if (left <= 37) {
721                 //printf("muldiv stall %u\n", left);
722                 regs_->cycle = regs_->muldivBusyCycle;
723         }
724 }
725
726 OP(psxMFHI_stall) { mflohiCheckStall(regs_); psxMFHI(regs_, code); }
727 OP(psxMFLO_stall) { mflohiCheckStall(regs_); psxMFLO(regs_, code); }
728
729 /*********************************************************
730 * Move to GPR to HI/LO & Register jump                   *
731 * Format:  OP rs                                         *
732 *********************************************************/
733 OP(psxMTHI) { _rHi_ = _rRs_; } // Hi = Rs
734 OP(psxMTLO) { _rLo_ = _rRs_; } // Lo = Rs
735
736 /*********************************************************
737 * Special purpose instructions                           *
738 * Format:  OP                                            *
739 *********************************************************/
740 OP(psxBREAK) {
741         regs_->pc -= 4;
742         psxException(0x24, branch);
743 }
744
745 OP(psxSYSCALL) {
746         regs_->pc -= 4;
747         psxException(0x20, branch);
748 }
749
750 static inline void psxTestSWInts(psxRegisters *regs_) {
751         if (regs_->CP0.n.Cause & regs_->CP0.n.Status & 0x0300 &&
752            regs_->CP0.n.Status & 0x1) {
753                 regs_->CP0.n.Cause &= ~0x7c;
754                 psxException(regs_->CP0.n.Cause, branch);
755         }
756 }
757
758 OP(psxRFE) {
759 //      SysPrintf("psxRFE\n");
760         regs_->CP0.n.Status = (regs_->CP0.n.Status & 0xfffffff0) |
761                               ((regs_->CP0.n.Status & 0x3c) >> 2);
762         psxTestSWInts(regs_);
763 }
764
765 /*********************************************************
766 * Register branch logic                                  *
767 * Format:  OP rs, rt, offset                             *
768 *********************************************************/
769 #define RepBranchi32(op)      if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
770
771 OP(psxBEQ) { RepBranchi32(==) }  // Branch if Rs == Rt
772 OP(psxBNE) { RepBranchi32(!=) }  // Branch if Rs != Rt
773
774 /*********************************************************
775 * Jump to target                                         *
776 * Format:  OP target                                     *
777 *********************************************************/
778 OP(psxJ)   {               doBranch(_JumpTarget_); }
779 OP(psxJAL) { _SetLink(31); doBranch(_JumpTarget_); }
780
781 /*********************************************************
782 * Register jump                                          *
783 * Format:  OP rs, rd                                     *
784 *********************************************************/
785 OP(psxJR) {
786         doBranch(_rRs_ & ~3);
787         psxJumpTest();
788 }
789
790 OP(psxJALR) {
791         u32 temp = _u32(_rRs_);
792         if (_Rd_) { _SetLink(_Rd_); }
793         doBranch(temp & ~3);
794 }
795
796 /*********************************************************
797 * Load and store for GPR                                 *
798 * Format:  OP rt, offset(base)                           *
799 *********************************************************/
800
801 #define _oB_ (regs_->GPR.r[_Rs_] + _Imm_)
802
803 OP(psxLB)  { u32 v =  (s8)psxMemRead8(_oB_);  if (_Rt_) _rRt_ = v; }
804 OP(psxLBU) { u32 v =      psxMemRead8(_oB_);  if (_Rt_) _rRt_ = v; }
805 OP(psxLH)  { u32 v = (s16)psxMemRead16(_oB_); if (_Rt_) _rRt_ = v; }
806 OP(psxLHU) { u32 v =      psxMemRead16(_oB_); if (_Rt_) _rRt_ = v; }
807 OP(psxLW)  { u32 v =      psxMemRead32(_oB_); if (_Rt_) _rRt_ = v; }
808
809 OP(psxLWL) {
810         static const u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
811         static const u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
812         u32 addr = _oB_;
813         u32 shift = addr & 3;
814         u32 mem = psxMemRead32(addr & ~3);
815
816         if (!_Rt_) return;
817         _rRt_ = (_u32(_rRt_) & LWL_MASK[shift]) | (mem << LWL_SHIFT[shift]);
818
819         /*
820         Mem = 1234.  Reg = abcd
821
822         0   4bcd   (mem << 24) | (reg & 0x00ffffff)
823         1   34cd   (mem << 16) | (reg & 0x0000ffff)
824         2   234d   (mem <<  8) | (reg & 0x000000ff)
825         3   1234   (mem      ) | (reg & 0x00000000)
826         */
827 }
828
829 OP(psxLWR) {
830         static const u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
831         static const u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
832         u32 addr = _oB_;
833         u32 shift = addr & 3;
834         u32 mem = psxMemRead32(addr & ~3);
835
836         if (!_Rt_) return;
837         _rRt_ = (_u32(_rRt_) & LWR_MASK[shift]) | (mem >> LWR_SHIFT[shift]);
838
839         /*
840         Mem = 1234.  Reg = abcd
841
842         0   1234   (mem      ) | (reg & 0x00000000)
843         1   a123   (mem >>  8) | (reg & 0xff000000)
844         2   ab12   (mem >> 16) | (reg & 0xffff0000)
845         3   abc1   (mem >> 24) | (reg & 0xffffff00)
846         */
847 }
848
849 OP(psxSB) { psxMemWrite8 (_oB_, _rRt_ &   0xff); }
850 OP(psxSH) { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
851 OP(psxSW) { psxMemWrite32(_oB_, _rRt_); }
852
853 OP(psxSWL) {
854         static const u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
855         static const u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
856         u32 addr = _oB_;
857         u32 shift = addr & 3;
858         u32 mem = psxMemRead32(addr & ~3);
859
860         psxMemWrite32(addr & ~3,  (_u32(_rRt_) >> SWL_SHIFT[shift]) |
861                              (  mem & SWL_MASK[shift]) );
862         /*
863         Mem = 1234.  Reg = abcd
864
865         0   123a   (reg >> 24) | (mem & 0xffffff00)
866         1   12ab   (reg >> 16) | (mem & 0xffff0000)
867         2   1abc   (reg >>  8) | (mem & 0xff000000)
868         3   abcd   (reg      ) | (mem & 0x00000000)
869         */
870 }
871
872 OP(psxSWR) {
873         static const u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
874         static const u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
875         u32 addr = _oB_;
876         u32 shift = addr & 3;
877         u32 mem = psxMemRead32(addr & ~3);
878
879         psxMemWrite32(addr & ~3,  (_u32(_rRt_) << SWR_SHIFT[shift]) |
880                              (  mem & SWR_MASK[shift]) );
881
882         /*
883         Mem = 1234.  Reg = abcd
884
885         0   abcd   (reg      ) | (mem & 0x00000000)
886         1   bcd4   (reg <<  8) | (mem & 0x000000ff)
887         2   cd34   (reg << 16) | (mem & 0x0000ffff)
888         3   d234   (reg << 24) | (mem & 0x00ffffff)
889         */
890 }
891
892 /*********************************************************
893 * Moves between GPR and COPx                             *
894 * Format:  OP rt, fs                                     *
895 *********************************************************/
896 OP(psxMFC0) { if (!_Rt_) return; _rRt_ = _rFs_; }
897 OP(psxCFC0) { if (!_Rt_) return; _rRt_ = _rFs_; }
898
899 void MTC0(psxRegisters *regs_, int reg, u32 val) {
900 //      SysPrintf("MTC0 %d: %x\n", reg, val);
901         switch (reg) {
902                 case 12: // Status
903                         regs_->CP0.r[12] = val;
904                         psxTestSWInts(regs_);
905                         break;
906
907                 case 13: // Cause
908                         regs_->CP0.n.Cause &= ~0x0300;
909                         regs_->CP0.n.Cause |= val & 0x0300;
910                         psxTestSWInts(regs_);
911                         break;
912
913                 default:
914                         regs_->CP0.r[reg] = val;
915                         break;
916         }
917 }
918
919 OP(psxMTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); }
920 OP(psxCTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); }
921
922 /*********************************************************
923 * Unknow instruction (would generate an exception)       *
924 * Format:  ?                                             *
925 *********************************************************/
926 static inline void psxNULL_(void) {
927 #ifdef PSXCPU_LOG
928         PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
929 #endif
930 }
931
932 OP(psxNULL) { psxNULL_(); }
933 void gteNULL(struct psxCP2Regs *regs) { psxNULL_(); }
934
935 OP(psxSPECIAL) {
936         psxSPC[_Funct_](regs_, code);
937 }
938
939 OP(psxCOP0) {
940         switch (_Rs_) {
941                 case 0x00: psxMFC0(regs_, code); break;
942                 case 0x02: psxCFC0(regs_, code); break;
943                 case 0x04: psxMTC0(regs_, code); break;
944                 case 0x06: psxCTC0(regs_, code); break;
945                 case 0x10: psxRFE(regs_, code);  break;
946                 default:   psxNULL_();           break;
947         }
948 }
949
950 OP(psxCOP2) {
951         psxCP2[_Funct_](&regs_->CP2);
952 }
953
954 OP(psxCOP2_stall) {
955         u32 f = _Funct_;
956         gteCheckStall(f);
957         psxCP2[f](&regs_->CP2);
958 }
959
960 OP(gteMFC2) {
961         if (!_Rt_) return;
962         regs_->GPR.r[_Rt_] = MFC2(&regs_->CP2, _Rd_);
963 }
964
965 OP(gteCFC2) {
966         if (!_Rt_) return;
967         regs_->GPR.r[_Rt_] = regs_->CP2C.r[_Rd_];
968 }
969
970 OP(gteMTC2) {
971         MTC2(&regs_->CP2, regs_->GPR.r[_Rt_], _Rd_);
972 }
973
974 OP(gteCTC2) {
975         CTC2(&regs_->CP2, regs_->GPR.r[_Rt_], _Rd_);
976 }
977
978 OP(gteLWC2) {
979         MTC2(&regs_->CP2, psxMemRead32(_oB_), _Rt_);
980 }
981
982 OP(gteSWC2) {
983         psxMemWrite32(_oB_, MFC2(&regs_->CP2, _Rt_));
984 }
985
986 OP(gteLWC2_stall) {
987         gteCheckStall(0);
988         gteLWC2(regs_, code);
989 }
990
991 OP(gteSWC2_stall) {
992         gteCheckStall(0);
993         gteSWC2(regs_, code);
994 }
995
996 static void psxBASIC(struct psxCP2Regs *cp2regs) {
997         psxRegisters *regs_ = (void *)((char *)cp2regs - offsetof(psxRegisters, CP2));
998         u32 code = regs_->code;
999         assert(regs_ == &psxRegs);
1000         switch (_Rs_) {
1001                 case 0x00: gteMFC2(regs_, code); break;
1002                 case 0x02: gteCFC2(regs_, code); break;
1003                 case 0x04: gteMTC2(regs_, code); break;
1004                 case 0x06: gteCTC2(regs_, code); break;
1005                 default:   psxNULL_();           break;
1006         }
1007 }
1008
1009 OP(psxREGIMM) {
1010         switch (_Rt_) {
1011                 case 0x00: psxBLTZ(regs_, code);   break;
1012                 case 0x01: psxBGEZ(regs_, code);   break;
1013                 case 0x10: psxBLTZAL(regs_, code); break;
1014                 case 0x11: psxBGEZAL(regs_, code); break;
1015                 default:   psxNULL_();             break;
1016         }
1017 }
1018
1019 OP(psxHLE) {
1020     uint32_t hleCode = code & 0x03ffffff;
1021     if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
1022         psxNULL_();
1023     } else {
1024         psxHLEt[hleCode]();
1025     }
1026 }
1027
1028 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code) = {
1029         psxSPECIAL, psxREGIMM, psxJ   , psxJAL  , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
1030         psxADDI   , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
1031         psxCOP0   , psxNULL  , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1032         psxNULL   , psxNULL  , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1033         psxLB     , psxLH    , psxLWL , psxLW   , psxLBU , psxLHU , psxLWR , psxNULL,
1034         psxSB     , psxSH    , psxSWL , psxSW   , psxNULL, psxNULL, psxSWR , psxNULL, 
1035         psxNULL   , psxNULL  , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1036         psxNULL   , psxNULL  , gteSWC2, psxHLE  , psxNULL, psxNULL, psxNULL, psxNULL 
1037 };
1038
1039 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code) = {
1040         psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV   , psxNULL , psxSRLV, psxSRAV,
1041         psxJR  , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
1042         psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL   , psxNULL , psxNULL, psxNULL,
1043         psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL   , psxNULL , psxNULL, psxNULL,
1044         psxADD , psxADDU , psxSUB , psxSUBU, psxAND    , psxOR   , psxXOR , psxNOR ,
1045         psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL   , psxNULL , psxNULL, psxNULL,
1046         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL,
1047         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL
1048 };
1049
1050 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
1051         psxBASIC, gteRTPS , gteNULL , gteNULL, gteNULL, gteNULL , gteNCLIP, gteNULL, // 00
1052         gteNULL , gteNULL , gteNULL , gteNULL, gteOP  , gteNULL , gteNULL , gteNULL, // 08
1053         gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , gteNULL , gteNCDT , gteNULL, // 10
1054         gteNULL , gteNULL , gteNULL , gteNCCS, gteCC  , gteNULL , gteNCS  , gteNULL, // 18
1055         gteNCT  , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 20
1056         gteSQR  , gteDCPL , gteDPCT , gteNULL, gteNULL, gteAVSZ3, gteAVSZ4, gteNULL, // 28
1057         gteRTPT , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 30
1058         gteNULL , gteNULL , gteNULL , gteNULL, gteNULL, gteGPF  , gteGPL  , gteNCCT  // 38
1059 };
1060
1061 ///////////////////////////////////////////
1062
1063 static int intInit() {
1064         return 0;
1065 }
1066
1067 static void intReset() {
1068         memset(&ICache, 0xff, sizeof(ICache));
1069 }
1070
1071 static inline void execI_(u8 **memRLUT, psxRegisters *regs_) {
1072         regs_->code = fetch(memRLUT, regs_->pc);
1073
1074         debugI();
1075
1076         if (Config.Debug) ProcessDebug();
1077
1078         regs_->pc += 4;
1079         regs_->cycle += BIAS;
1080
1081         psxBSC[regs_->code >> 26](regs_, regs_->code);
1082 }
1083
1084 static void intExecute() {
1085         psxRegisters *regs_ = &psxRegs;
1086         u8 **memRLUT = psxMemRLUT;
1087         extern int stop;
1088
1089         while (!stop)
1090                 execI_(memRLUT, regs_);
1091 }
1092
1093 static void intExecuteBlock() {
1094         psxRegisters *regs_ = &psxRegs;
1095         u8 **memRLUT = psxMemRLUT;
1096
1097         branch2 = 0;
1098         while (!branch2)
1099                 execI_(memRLUT, regs_);
1100 }
1101
1102 static void intClear(u32 Addr, u32 Size) {
1103 }
1104
1105 void intNotify (int note, void *data) {
1106         /* Gameblabla - Only clear the icache if it's isolated */
1107         if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED)
1108         {
1109                 memset(&ICache, 0xff, sizeof(ICache));
1110         }
1111 }
1112
1113 void intApplyConfig() {
1114         assert(psxBSC[18] == psxCOP2  || psxBSC[18] == psxCOP2_stall);
1115         assert(psxBSC[50] == gteLWC2  || psxBSC[50] == gteLWC2_stall);
1116         assert(psxBSC[58] == gteSWC2  || psxBSC[58] == gteSWC2_stall);
1117         assert(psxSPC[16] == psxMFHI  || psxSPC[16] == psxMFHI_stall);
1118         assert(psxSPC[18] == psxMFLO  || psxSPC[18] == psxMFLO_stall);
1119         assert(psxSPC[24] == psxMULT  || psxSPC[24] == psxMULT_stall);
1120         assert(psxSPC[25] == psxMULTU || psxSPC[25] == psxMULTU_stall);
1121         assert(psxSPC[26] == psxDIV   || psxSPC[26] == psxDIV_stall);
1122         assert(psxSPC[27] == psxDIVU  || psxSPC[27] == psxDIVU_stall);
1123
1124         if (Config.DisableStalls) {
1125                 psxBSC[18] = psxCOP2;
1126                 psxBSC[50] = gteLWC2;
1127                 psxBSC[58] = gteSWC2;
1128                 psxSPC[16] = psxMFHI;
1129                 psxSPC[18] = psxMFLO;
1130                 psxSPC[24] = psxMULT;
1131                 psxSPC[25] = psxMULTU;
1132                 psxSPC[26] = psxDIV;
1133                 psxSPC[27] = psxDIVU;
1134         } else {
1135                 psxBSC[18] = psxCOP2_stall;
1136                 psxBSC[50] = gteLWC2_stall;
1137                 psxBSC[58] = gteSWC2_stall;
1138                 psxSPC[16] = psxMFHI_stall;
1139                 psxSPC[18] = psxMFLO_stall;
1140                 psxSPC[24] = psxMULT_stall;
1141                 psxSPC[25] = psxMULTU_stall;
1142                 psxSPC[26] = psxDIV_stall;
1143                 psxSPC[27] = psxDIVU_stall;
1144         }
1145
1146         // dynarec may occasionally call the interpreter, in such a case the
1147         // cache won't work (cache only works right if all fetches go through it)
1148         if (!Config.icache_emulation || psxCpu != &psxInt)
1149                 fetch = fetchNoCache;
1150         else
1151                 fetch = fetchICache;
1152 }
1153
1154 static void intShutdown() {
1155 }
1156
1157 // single step (may do several ops in case of a branch)
1158 void execI() {
1159         execI_(psxMemRLUT, &psxRegs);
1160 }
1161
1162 R3000Acpu psxInt = {
1163         intInit,
1164         intReset,
1165         intExecute,
1166         intExecuteBlock,
1167         intClear,
1168         intNotify,
1169         intApplyConfig,
1170         intShutdown
1171 };