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