Always look up verify_dirty literals from offsets by neonloop (#194)
[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 "debug.h"
29
30 static int branch = 0;
31 static int branch2 = 0;
32 static u32 branchPC;
33
34 // These macros are used to assemble the repassembler functions
35
36 #ifdef PSXCPU_LOG
37 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); 
38 #else
39 #define debugI()
40 #endif
41
42 void execI();
43
44 // Subsets
45 void (*psxBSC[64])();
46 void (*psxSPC[64])();
47 void (*psxREG[32])();
48 void (*psxCP0[32])();
49 void (*psxCP2[64])(struct psxCP2Regs *regs);
50 void (*psxCP2BSC[32])();
51
52 static void delayRead(int reg, u32 bpc) {
53         u32 rold, rnew;
54
55 //      SysPrintf("delayRead at %x!\n", psxRegs.pc);
56
57         rold = psxRegs.GPR.r[reg];
58         psxBSC[psxRegs.code >> 26](); // branch delay load
59         rnew = psxRegs.GPR.r[reg];
60
61         psxRegs.pc = bpc;
62
63         branch = 0;
64
65         psxRegs.GPR.r[reg] = rold;
66         execI(); // first branch opcode
67         psxRegs.GPR.r[reg] = rnew;
68
69         psxBranchTest();
70 }
71
72 static void delayWrite(int reg, u32 bpc) {
73
74 /*      SysPrintf("delayWrite at %x!\n", psxRegs.pc);
75
76         SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
77         SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
78
79         // no changes from normal behavior
80
81         psxBSC[psxRegs.code >> 26]();
82
83         branch = 0;
84         psxRegs.pc = bpc;
85
86         psxBranchTest();
87 }
88
89 static void delayReadWrite(int reg, u32 bpc) {
90
91 //      SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
92
93         // the branch delay load is skipped
94
95         branch = 0;
96         psxRegs.pc = bpc;
97
98         psxBranchTest();
99 }
100
101 // this defines shall be used with the tmp 
102 // of the next func (instead of _Funct_...)
103 #define _tFunct_  ((tmp      ) & 0x3F)  // The funct part of the instruction register 
104 #define _tRd_     ((tmp >> 11) & 0x1F)  // The rd part of the instruction register 
105 #define _tRt_     ((tmp >> 16) & 0x1F)  // The rt part of the instruction register 
106 #define _tRs_     ((tmp >> 21) & 0x1F)  // The rs part of the instruction register 
107 #define _tSa_     ((tmp >>  6) & 0x1F)  // The sa part of the instruction register
108
109 int psxTestLoadDelay(int reg, u32 tmp) {
110         if (tmp == 0) return 0; // NOP
111         switch (tmp >> 26) {
112                 case 0x00: // SPECIAL
113                         switch (_tFunct_) {
114                                 case 0x00: // SLL
115                                 case 0x02: case 0x03: // SRL/SRA
116                                         if (_tRd_ == reg && _tRt_ == reg) return 1; else
117                                         if (_tRt_ == reg) return 2; else
118                                         if (_tRd_ == reg) return 3;
119                                         break;
120
121                                 case 0x08: // JR
122                                         if (_tRs_ == reg) return 2;
123                                         break;
124                                 case 0x09: // JALR
125                                         if (_tRd_ == reg && _tRs_ == reg) return 1; else
126                                         if (_tRs_ == reg) return 2; else
127                                         if (_tRd_ == reg) return 3;
128                                         break;
129
130                                 // SYSCALL/BREAK just a break;
131
132                                 case 0x20: case 0x21: case 0x22: case 0x23:
133                                 case 0x24: case 0x25: case 0x26: case 0x27: 
134                                 case 0x2a: case 0x2b: // ADD/ADDU...
135                                 case 0x04: case 0x06: case 0x07: // SLLV...
136                                         if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
137                                         if (_tRt_ == reg || _tRs_ == reg) return 2; else
138                                         if (_tRd_ == reg) return 3;
139                                         break;
140
141                                 case 0x10: case 0x12: // MFHI/MFLO
142                                         if (_tRd_ == reg) return 3;
143                                         break;
144                                 case 0x11: case 0x13: // MTHI/MTLO
145                                         if (_tRs_ == reg) return 2;
146                                         break;
147
148                                 case 0x18: case 0x19:
149                                 case 0x1a: case 0x1b: // MULT/DIV...
150                                         if (_tRt_ == reg || _tRs_ == reg) return 2;
151                                         break;
152                         }
153                         break;
154
155                 case 0x01: // REGIMM
156                         switch (_tRt_) {
157                                 case 0x00: case 0x01:
158                                 case 0x10: case 0x11: // BLTZ/BGEZ...
159                                         // Xenogears - lbu v0 / beq v0
160                                         // - no load delay (fixes battle loading)
161                                         break;
162
163                                         if (_tRs_ == reg) return 2;
164                                         break;
165                         }
166                         break;
167
168                 // J would be just a break;
169                 case 0x03: // JAL
170                         if (31 == reg) return 3;
171                         break;
172
173                 case 0x04: case 0x05: // BEQ/BNE
174                         // Xenogears - lbu v0 / beq v0
175                         // - no load delay (fixes battle loading)
176                         break;
177
178                         if (_tRs_ == reg || _tRt_ == reg) return 2;
179                         break;
180
181                 case 0x06: case 0x07: // BLEZ/BGTZ
182                         // Xenogears - lbu v0 / beq v0
183                         // - no load delay (fixes battle loading)
184                         break;
185
186                         if (_tRs_ == reg) return 2;
187                         break;
188
189                 case 0x08: case 0x09: case 0x0a: case 0x0b:
190                 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
191                         if (_tRt_ == reg && _tRs_ == reg) return 1; else
192                         if (_tRs_ == reg) return 2; else
193                         if (_tRt_ == reg) return 3;
194                         break;
195
196                 case 0x0f: // LUI
197                         if (_tRt_ == reg) return 3;
198                         break;
199
200                 case 0x10: // COP0
201                         switch (_tFunct_) {
202                                 case 0x00: // MFC0
203                                         if (_tRt_ == reg) return 3;
204                                         break;
205                                 case 0x02: // CFC0
206                                         if (_tRt_ == reg) return 3;
207                                         break;
208                                 case 0x04: // MTC0
209                                         if (_tRt_ == reg) return 2;
210                                         break;
211                                 case 0x06: // CTC0
212                                         if (_tRt_ == reg) return 2;
213                                         break;
214                                 // RFE just a break;
215                         }
216                         break;
217
218                 case 0x12: // COP2
219                         switch (_tFunct_) {
220                                 case 0x00: 
221                                         switch (_tRs_) {
222                                                 case 0x00: // MFC2
223                                                         if (_tRt_ == reg) return 3;
224                                                         break;
225                                                 case 0x02: // CFC2
226                                                         if (_tRt_ == reg) return 3;
227                                                         break;
228                                                 case 0x04: // MTC2
229                                                         if (_tRt_ == reg) return 2;
230                                                         break;
231                                                 case 0x06: // CTC2
232                                                         if (_tRt_ == reg) return 2;
233                                                         break;
234                                         }
235                                         break;
236                                 // RTPS... break;
237                         }
238                         break;
239
240                 case 0x22: case 0x26: // LWL/LWR
241                         if (_tRt_ == reg) return 3; else
242                         if (_tRs_ == reg) return 2;
243                         break;
244
245                 case 0x20: case 0x21: case 0x23:
246                 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
247                         if (_tRt_ == reg && _tRs_ == reg) return 1; else
248                         if (_tRs_ == reg) return 2; else
249                         if (_tRt_ == reg) return 3;
250                         break;
251
252                 case 0x28: case 0x29: case 0x2a:
253                 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
254                         if (_tRt_ == reg || _tRs_ == reg) return 2;
255                         break;
256
257                 case 0x32: case 0x3a: // LWC2/SWC2
258                         if (_tRs_ == reg) return 2;
259                         break;
260         }
261
262         return 0;
263 }
264
265 void psxDelayTest(int reg, u32 bpc) {
266         u32 *code;
267         u32 tmp;
268
269         code = (u32 *)PSXM(bpc);
270         tmp = ((code == NULL) ? 0 : SWAP32(*code));
271         branch = 1;
272
273         switch (psxTestLoadDelay(reg, tmp)) {
274                 case 1:
275                         delayReadWrite(reg, bpc); return;
276                 case 2:
277                         delayRead(reg, bpc); return;
278                 case 3:
279                         delayWrite(reg, bpc); return;
280         }
281         psxBSC[psxRegs.code >> 26]();
282
283         branch = 0;
284         psxRegs.pc = bpc;
285
286         psxBranchTest();
287 }
288
289 static u32 psxBranchNoDelay(void) {
290         u32 *code;
291         u32 temp;
292
293         code = (u32 *)PSXM(psxRegs.pc);
294         psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
295         switch (_Op_) {
296                 case 0x00: // SPECIAL
297                         switch (_Funct_) {
298                                 case 0x08: // JR
299                                         return _u32(_rRs_);
300                                 case 0x09: // JALR
301                                         temp = _u32(_rRs_);
302                                         if (_Rd_) { _SetLink(_Rd_); }
303                                         return temp;
304                         }
305                         break;
306                 case 0x01: // REGIMM
307                         switch (_Rt_) {
308                                 case 0x00: // BLTZ
309                                         if (_i32(_rRs_) < 0)
310                                                 return _BranchTarget_;
311                                         break;
312                                 case 0x01: // BGEZ
313                                         if (_i32(_rRs_) >= 0)
314                                                 return _BranchTarget_;
315                                         break;
316                                 case 0x08: // BLTZAL
317                                         if (_i32(_rRs_) < 0) {
318                                                 _SetLink(31);
319                                                 return _BranchTarget_;
320                                         }
321                                         break;
322                                 case 0x09: // BGEZAL
323                                         if (_i32(_rRs_) >= 0) {
324                                                 _SetLink(31);
325                                                 return _BranchTarget_;
326                                         }
327                                         break;
328                         }
329                         break;
330                 case 0x02: // J
331                         return _JumpTarget_;
332                 case 0x03: // JAL
333                         _SetLink(31);
334                         return _JumpTarget_;
335                 case 0x04: // BEQ
336                         if (_i32(_rRs_) == _i32(_rRt_))
337                                 return _BranchTarget_;
338                         break;
339                 case 0x05: // BNE
340                         if (_i32(_rRs_) != _i32(_rRt_))
341                                 return _BranchTarget_;
342                         break;
343                 case 0x06: // BLEZ
344                         if (_i32(_rRs_) <= 0)
345                                 return _BranchTarget_;
346                         break;
347                 case 0x07: // BGTZ
348                         if (_i32(_rRs_) > 0)
349                                 return _BranchTarget_;
350                         break;
351         }
352
353         return (u32)-1;
354 }
355
356 static int psxDelayBranchExec(u32 tar) {
357         execI();
358
359         branch = 0;
360         psxRegs.pc = tar;
361         psxRegs.cycle += BIAS;
362         psxBranchTest();
363         return 1;
364 }
365
366 static int psxDelayBranchTest(u32 tar1) {
367         u32 tar2, tmp1, tmp2;
368
369         tar2 = psxBranchNoDelay();
370         if (tar2 == (u32)-1)
371                 return 0;
372
373         debugI();
374
375         /*
376          * Branch in delay slot:
377          * - execute 1 instruction at tar1
378          * - jump to tar2 (target of branch in delay slot; this branch
379          *   has no normal delay slot, instruction at tar1 was fetched instead)
380          */
381         psxRegs.pc = tar1;
382         tmp1 = psxBranchNoDelay();
383         if (tmp1 == (u32)-1) {
384                 return psxDelayBranchExec(tar2);
385         }
386         debugI();
387         psxRegs.cycle += BIAS;
388
389         /*
390          * Got a branch at tar1:
391          * - execute 1 instruction at tar2
392          * - jump to target of that branch (tmp1)
393          */
394         psxRegs.pc = tar2;
395         tmp2 = psxBranchNoDelay();
396         if (tmp2 == (u32)-1) {
397                 return psxDelayBranchExec(tmp1);
398         }
399         debugI();
400         psxRegs.cycle += BIAS;
401
402         /*
403          * Got a branch at tar2:
404          * - execute 1 instruction at tmp1
405          * - jump to target of that branch (tmp2)
406          */
407         psxRegs.pc = tmp1;
408         return psxDelayBranchExec(tmp2);
409 }
410
411 static void doBranch(u32 tar) {
412         u32 *code;
413         u32 tmp;
414
415         branch2 = branch = 1;
416         branchPC = tar;
417
418         // check for branch in delay slot
419         if (psxDelayBranchTest(tar))
420                 return;
421
422         code = (u32 *)PSXM(psxRegs.pc);
423         psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
424
425         debugI();
426
427         psxRegs.pc += 4;
428         psxRegs.cycle += BIAS;
429
430         // check for load delay
431         tmp = psxRegs.code >> 26;
432         switch (tmp) {
433                 case 0x10: // COP0
434                         switch (_Rs_) {
435                                 case 0x00: // MFC0
436                                 case 0x02: // CFC0
437                                         psxDelayTest(_Rt_, branchPC);
438                                         return;
439                         }
440                         break;
441                 case 0x12: // COP2
442                         switch (_Funct_) {
443                                 case 0x00:
444                                         switch (_Rs_) {
445                                                 case 0x00: // MFC2
446                                                 case 0x02: // CFC2
447                                                         psxDelayTest(_Rt_, branchPC);
448                                                         return;
449                                         }
450                                         break;
451                         }
452                         break;
453                 case 0x32: // LWC2
454                         psxDelayTest(_Rt_, branchPC);
455                         return;
456                 default:
457                         if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
458                                 psxDelayTest(_Rt_, branchPC);
459                                 return;
460                         }
461                         break;
462         }
463
464         psxBSC[psxRegs.code >> 26]();
465
466         branch = 0;
467         psxRegs.pc = branchPC;
468
469         psxBranchTest();
470 }
471
472 /*********************************************************
473 * Arithmetic with immediate operand                      *
474 * Format:  OP rt, rs, immediate                          *
475 *********************************************************/
476 void psxADDI()  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; }            // Rt = Rs + Im         (Exception on Integer Overflow)
477 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; }            // Rt = Rs + Im
478 void psxANDI()  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; }            // Rt = Rs And Im
479 void psxORI()   { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; }            // Rt = Rs Or  Im
480 void psxXORI()  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; }            // Rt = Rs Xor Im
481 void psxSLTI()  { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; }            // Rt = Rs < Im         (Signed)
482 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); }              // Rt = Rs < Im         (Unsigned)
483
484 /*********************************************************
485 * Register arithmetic                                    *
486 * Format:  OP rd, rs, rt                                 *
487 *********************************************************/
488 void psxADD()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); }       // Rd = Rs + Rt         (Exception on Integer Overflow)
489 void psxADDU()  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); }       // Rd = Rs + Rt
490 void psxSUB()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); }       // Rd = Rs - Rt         (Exception on Integer Overflow)
491 void psxSUBU()  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); }       // Rd = Rs - Rt
492 void psxAND()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); }       // Rd = Rs And Rt
493 void psxOR()    { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); }       // Rd = Rs Or  Rt
494 void psxXOR()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); }       // Rd = Rs Xor Rt
495 void psxNOR()   { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
496 void psxSLT()   { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); }       // Rd = Rs < Rt         (Signed)
497 void psxSLTU()  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); }       // Rd = Rs < Rt         (Unsigned)
498
499 /*********************************************************
500 * Register mult/div & Register trap logic                *
501 * Format:  OP rs, rt                                     *
502 *********************************************************/
503 void psxDIV() {
504     if (!_i32(_rRt_)) {
505         _i32(_rHi_) = _i32(_rRs_);
506         if (_i32(_rRs_) & 0x80000000) {
507             _i32(_rLo_) = 1;
508         } else {
509             _i32(_rLo_) = 0xFFFFFFFF;
510         }
511 /*
512  * Notaz said that this was "not needed" for ARM platforms and could slow it down so let's disable for ARM. 
513  * This fixes a crash issue that can happen when running Amidog's CPU test.
514  * (It still stays stuck to a black screen but at least it doesn't crash anymore)
515  */
516 #if !defined(__arm__) && !defined(__aarch64__)
517     } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
518         _i32(_rLo_) = 0x80000000;
519         _i32(_rHi_) = 0;
520 #endif
521     } else {
522         _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
523         _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
524     }
525 }
526
527 void psxDIVU() {
528         if (_rRt_ != 0) {
529                 _rLo_ = _rRs_ / _rRt_;
530                 _rHi_ = _rRs_ % _rRt_;
531         }
532         else {
533                 _i32(_rLo_) = 0xffffffff;
534                 _i32(_rHi_) = _i32(_rRs_);
535         }
536 }
537
538 void psxMULT() {
539         u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
540
541         psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
542         psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
543 }
544
545 void psxMULTU() {
546         u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
547
548         psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
549         psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
550 }
551
552 /*********************************************************
553 * Register branch logic                                  *
554 * Format:  OP rs, offset                                 *
555 *********************************************************/
556 #define RepZBranchi32(op)      if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
557 #define RepZBranchLinki32(op)  if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
558
559 void psxBGEZ()   { RepZBranchi32(>=) }      // Branch if Rs >= 0
560 void psxBGEZAL() { RepZBranchLinki32(>=) }  // Branch if Rs >= 0 and link
561 void psxBGTZ()   { RepZBranchi32(>) }       // Branch if Rs >  0
562 void psxBLEZ()   { RepZBranchi32(<=) }      // Branch if Rs <= 0
563 void psxBLTZ()   { RepZBranchi32(<) }       // Branch if Rs <  0
564 void psxBLTZAL() { RepZBranchLinki32(<) }   // Branch if Rs <  0 and link
565
566 /*********************************************************
567 * Shift arithmetic with constant shift                   *
568 * Format:  OP rd, rt, sa                                 *
569 *********************************************************/
570 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
571 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
572 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
573
574 /*********************************************************
575 * Shift arithmetic with variant register shift           *
576 * Format:  OP rd, rt, rs                                 *
577 *********************************************************/
578 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
579 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
580 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
581
582 /*********************************************************
583 * Load higher 16 bits of the first word in GPR with imm  *
584 * Format:  OP rt, immediate                              *
585 *********************************************************/
586 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
587
588 /*********************************************************
589 * Move from HI/LO to GPR                                 *
590 * Format:  OP rd                                         *
591 *********************************************************/
592 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
593 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
594
595 /*********************************************************
596 * Move to GPR to HI/LO & Register jump                   *
597 * Format:  OP rs                                         *
598 *********************************************************/
599 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
600 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
601
602 /*********************************************************
603 * Special purpose instructions                           *
604 * Format:  OP                                            *
605 *********************************************************/
606 void psxBREAK() {
607         // Break exception - psx rom doens't handles this
608 }
609
610 void psxSYSCALL() {
611         psxRegs.pc -= 4;
612         psxException(0x20, branch);
613 }
614
615 void psxRFE() {
616 //      SysPrintf("psxRFE\n");
617         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
618                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
619 }
620
621 /*********************************************************
622 * Register branch logic                                  *
623 * Format:  OP rs, rt, offset                             *
624 *********************************************************/
625 #define RepBranchi32(op)      if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
626
627 void psxBEQ() { RepBranchi32(==) }  // Branch if Rs == Rt
628 void psxBNE() { RepBranchi32(!=) }  // Branch if Rs != Rt
629
630 /*********************************************************
631 * Jump to target                                         *
632 * Format:  OP target                                     *
633 *********************************************************/
634 void psxJ()   {               doBranch(_JumpTarget_); }
635 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
636
637 /*********************************************************
638 * Register jump                                          *
639 * Format:  OP rs, rd                                     *
640 *********************************************************/
641 void psxJR()   {
642         doBranch(_u32(_rRs_));
643         psxJumpTest();
644 }
645
646 void psxJALR() {
647         u32 temp = _u32(_rRs_);
648         if (_Rd_) { _SetLink(_Rd_); }
649         doBranch(temp);
650 }
651
652 /*********************************************************
653 * Load and store for GPR                                 *
654 * Format:  OP rt, offset(base)                           *
655 *********************************************************/
656
657 #define _oB_ (_u32(_rRs_) + _Imm_)
658
659 void psxLB() {
660         if (_Rt_) {
661                 _i32(_rRt_) = (signed char)psxMemRead8(_oB_); 
662         } else {
663                 psxMemRead8(_oB_); 
664         }
665 }
666
667 void psxLBU() {
668         if (_Rt_) {
669                 _u32(_rRt_) = psxMemRead8(_oB_);
670         } else {
671                 psxMemRead8(_oB_); 
672         }
673 }
674
675 void psxLH() {
676         if (_Rt_) {
677                 _i32(_rRt_) = (short)psxMemRead16(_oB_);
678         } else {
679                 psxMemRead16(_oB_);
680         }
681 }
682
683 void psxLHU() {
684         if (_Rt_) {
685                 _u32(_rRt_) = psxMemRead16(_oB_);
686         } else {
687                 psxMemRead16(_oB_);
688         }
689 }
690
691 void psxLW() {
692         if (_Rt_) {
693                 _u32(_rRt_) = psxMemRead32(_oB_);
694         } else {
695                 psxMemRead32(_oB_);
696         }
697 }
698
699 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
700 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
701
702 void psxLWL() {
703         u32 addr = _oB_;
704         u32 shift = addr & 3;
705         u32 mem = psxMemRead32(addr & ~3);
706
707         if (!_Rt_) return;
708         _u32(_rRt_) =   ( _u32(_rRt_) & LWL_MASK[shift]) | 
709                                         ( mem << LWL_SHIFT[shift]);
710
711         /*
712         Mem = 1234.  Reg = abcd
713
714         0   4bcd   (mem << 24) | (reg & 0x00ffffff)
715         1   34cd   (mem << 16) | (reg & 0x0000ffff)
716         2   234d   (mem <<  8) | (reg & 0x000000ff)
717         3   1234   (mem      ) | (reg & 0x00000000)
718         */
719 }
720
721 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
722 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
723
724 void psxLWR() {
725         u32 addr = _oB_;
726         u32 shift = addr & 3;
727         u32 mem = psxMemRead32(addr & ~3);
728
729         if (!_Rt_) return;
730         _u32(_rRt_) =   ( _u32(_rRt_) & LWR_MASK[shift]) | 
731                                         ( mem >> LWR_SHIFT[shift]);
732
733         /*
734         Mem = 1234.  Reg = abcd
735
736         0   1234   (mem      ) | (reg & 0x00000000)
737         1   a123   (mem >>  8) | (reg & 0xff000000)
738         2   ab12   (mem >> 16) | (reg & 0xffff0000)
739         3   abc1   (mem >> 24) | (reg & 0xffffff00)
740         */
741 }
742
743 void psxSB() { psxMemWrite8 (_oB_, _rRt_ &   0xff); }
744 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
745 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
746
747 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
748 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
749
750 void psxSWL() {
751         u32 addr = _oB_;
752         u32 shift = addr & 3;
753         u32 mem = psxMemRead32(addr & ~3);
754
755         psxMemWrite32(addr & ~3,  (_u32(_rRt_) >> SWL_SHIFT[shift]) |
756                              (  mem & SWL_MASK[shift]) );
757         /*
758         Mem = 1234.  Reg = abcd
759
760         0   123a   (reg >> 24) | (mem & 0xffffff00)
761         1   12ab   (reg >> 16) | (mem & 0xffff0000)
762         2   1abc   (reg >>  8) | (mem & 0xff000000)
763         3   abcd   (reg      ) | (mem & 0x00000000)
764         */
765 }
766
767 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
768 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
769
770 void psxSWR() {
771         u32 addr = _oB_;
772         u32 shift = addr & 3;
773         u32 mem = psxMemRead32(addr & ~3);
774
775         psxMemWrite32(addr & ~3,  (_u32(_rRt_) << SWR_SHIFT[shift]) |
776                              (  mem & SWR_MASK[shift]) );
777
778         /*
779         Mem = 1234.  Reg = abcd
780
781         0   abcd   (reg      ) | (mem & 0x00000000)
782         1   bcd4   (reg <<  8) | (mem & 0x000000ff)
783         2   cd34   (reg << 16) | (mem & 0x0000ffff)
784         3   d234   (reg << 24) | (mem & 0x00ffffff)
785         */
786 }
787
788 /*********************************************************
789 * Moves between GPR and COPx                             *
790 * Format:  OP rt, fs                                     *
791 *********************************************************/
792 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
793 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
794
795 void psxTestSWInts() {
796         if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
797            psxRegs.CP0.n.Status & 0x1) {
798                 psxRegs.CP0.n.Cause &= ~0x7c;
799                 psxException(psxRegs.CP0.n.Cause, branch);
800         }
801 }
802
803 void MTC0(int reg, u32 val) {
804 //      SysPrintf("MTC0 %d: %x\n", reg, val);
805         switch (reg) {
806                 case 12: // Status
807                         psxRegs.CP0.r[12] = val;
808                         psxTestSWInts();
809                         break;
810
811                 case 13: // Cause
812                         psxRegs.CP0.n.Cause &= ~0x0300;
813                         psxRegs.CP0.n.Cause |= val & 0x0300;
814                         psxTestSWInts();
815                         break;
816
817                 default:
818                         psxRegs.CP0.r[reg] = val;
819                         break;
820         }
821 }
822
823 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
824 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
825
826 /*********************************************************
827 * Unknow instruction (would generate an exception)       *
828 * Format:  ?                                             *
829 *********************************************************/
830 void psxNULL() { 
831 #ifdef PSXCPU_LOG
832         PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
833 #endif
834 }
835
836 void psxSPECIAL() {
837         psxSPC[_Funct_]();
838 }
839
840 void psxREGIMM() {
841         psxREG[_Rt_]();
842 }
843
844 void psxCOP0() {
845         psxCP0[_Rs_]();
846 }
847
848 void psxCOP2() {
849         psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
850 }
851
852 void psxBASIC(struct psxCP2Regs *regs) {
853         psxCP2BSC[_Rs_]();
854 }
855
856 void psxHLE() {
857 //      psxHLEt[psxRegs.code & 0xffff]();
858 //      psxHLEt[psxRegs.code & 0x07]();         // HDHOSHY experimental patch
859     uint32_t hleCode = psxRegs.code & 0x03ffffff;
860     if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
861         psxNULL();
862     } else {
863         psxHLEt[hleCode]();
864     }
865 }
866
867 void (*psxBSC[64])() = {
868         psxSPECIAL, psxREGIMM, psxJ   , psxJAL  , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
869         psxADDI   , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
870         psxCOP0   , psxNULL  , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
871         psxNULL   , psxNULL  , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
872         psxLB     , psxLH    , psxLWL , psxLW   , psxLBU , psxLHU , psxLWR , psxNULL,
873         psxSB     , psxSH    , psxSWL , psxSW   , psxNULL, psxNULL, psxSWR , psxNULL, 
874         psxNULL   , psxNULL  , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
875         psxNULL   , psxNULL  , gteSWC2, psxHLE  , psxNULL, psxNULL, psxNULL, psxNULL 
876 };
877
878
879 void (*psxSPC[64])() = {
880         psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV   , psxNULL , psxSRLV, psxSRAV,
881         psxJR  , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
882         psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL   , psxNULL , psxNULL, psxNULL,
883         psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL   , psxNULL , psxNULL, psxNULL,
884         psxADD , psxADDU , psxSUB , psxSUBU, psxAND    , psxOR   , psxXOR , psxNOR ,
885         psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL   , psxNULL , psxNULL, psxNULL,
886         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL,
887         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL
888 };
889
890 void (*psxREG[32])() = {
891         psxBLTZ  , psxBGEZ  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
892         psxNULL  , psxNULL  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
893         psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
894         psxNULL  , psxNULL  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
895 };
896
897 void (*psxCP0[32])() = {
898         psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
899         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
900         psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
901         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
902 };
903
904 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
905         psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
906         psxNULL , psxNULL , psxNULL , psxNULL, gteOP  , psxNULL , psxNULL , psxNULL, // 08
907         gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
908         psxNULL , psxNULL , psxNULL , gteNCCS, gteCC  , psxNULL , gteNCS  , psxNULL, // 18
909         gteNCT  , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
910         gteSQR  , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28 
911         gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
912         psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF  , gteGPL  , gteNCCT  // 38
913 };
914
915 void (*psxCP2BSC[32])() = {
916         gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
917         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
918         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
919         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
920 };
921
922
923 ///////////////////////////////////////////
924
925 static int intInit() {
926         return 0;
927 }
928
929 static void intReset() {
930 }
931
932 void intExecute() {
933         extern int stop;
934         for (;!stop;) 
935                 execI();
936 }
937
938 void intExecuteBlock() {
939         branch2 = 0;
940         while (!branch2) execI();
941 }
942
943 static void intClear(u32 Addr, u32 Size) {
944 }
945
946 static void intShutdown() {
947 }
948
949 // interpreter execution
950 void execI() {
951         u32 *code = (u32 *)PSXM(psxRegs.pc);
952         psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
953
954         debugI();
955
956         if (Config.Debug) ProcessDebug();
957
958         psxRegs.pc += 4;
959         psxRegs.cycle += BIAS;
960
961         psxBSC[psxRegs.code >> 26]();
962 }
963
964 R3000Acpu psxInt = {
965         intInit,
966         intReset,
967         intExecute,
968         intExecuteBlock,
969         intClear,
970         intShutdown
971 };