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