psxmem: set fixed flag on mappings that really need it
[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])();
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_) != 0) {
505                 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
506                 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
507         }
508         else {
509                 _i32(_rLo_) = _i32(_rRs_) >= 0 ? 0xffffffff : 1;
510                 _i32(_rHi_) = _i32(_rRs_);
511         }
512 }
513
514 void psxDIVU() {
515         if (_rRt_ != 0) {
516                 _rLo_ = _rRs_ / _rRt_;
517                 _rHi_ = _rRs_ % _rRt_;
518         }
519         else {
520                 _i32(_rLo_) = 0xffffffff;
521                 _i32(_rHi_) = _i32(_rRs_);
522         }
523 }
524
525 void psxMULT() {
526         u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
527
528         psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
529         psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
530 }
531
532 void psxMULTU() {
533         u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
534
535         psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
536         psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
537 }
538
539 /*********************************************************
540 * Register branch logic                                  *
541 * Format:  OP rs, offset                                 *
542 *********************************************************/
543 #define RepZBranchi32(op)      if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
544 #define RepZBranchLinki32(op)  if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
545
546 void psxBGEZ()   { RepZBranchi32(>=) }      // Branch if Rs >= 0
547 void psxBGEZAL() { RepZBranchLinki32(>=) }  // Branch if Rs >= 0 and link
548 void psxBGTZ()   { RepZBranchi32(>) }       // Branch if Rs >  0
549 void psxBLEZ()   { RepZBranchi32(<=) }      // Branch if Rs <= 0
550 void psxBLTZ()   { RepZBranchi32(<) }       // Branch if Rs <  0
551 void psxBLTZAL() { RepZBranchLinki32(<) }   // Branch if Rs <  0 and link
552
553 /*********************************************************
554 * Shift arithmetic with constant shift                   *
555 * Format:  OP rd, rt, sa                                 *
556 *********************************************************/
557 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
558 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
559 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
560
561 /*********************************************************
562 * Shift arithmetic with variant register shift           *
563 * Format:  OP rd, rt, rs                                 *
564 *********************************************************/
565 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
566 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
567 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
568
569 /*********************************************************
570 * Load higher 16 bits of the first word in GPR with imm  *
571 * Format:  OP rt, immediate                              *
572 *********************************************************/
573 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
574
575 /*********************************************************
576 * Move from HI/LO to GPR                                 *
577 * Format:  OP rd                                         *
578 *********************************************************/
579 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
580 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
581
582 /*********************************************************
583 * Move to GPR to HI/LO & Register jump                   *
584 * Format:  OP rs                                         *
585 *********************************************************/
586 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
587 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
588
589 /*********************************************************
590 * Special purpose instructions                           *
591 * Format:  OP                                            *
592 *********************************************************/
593 void psxBREAK() {
594         // Break exception - psx rom doens't handles this
595 }
596
597 void psxSYSCALL() {
598         psxRegs.pc -= 4;
599         psxException(0x20, branch);
600 }
601
602 void psxRFE() {
603 //      SysPrintf("psxRFE\n");
604         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
605                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
606 }
607
608 /*********************************************************
609 * Register branch logic                                  *
610 * Format:  OP rs, rt, offset                             *
611 *********************************************************/
612 #define RepBranchi32(op)      if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
613
614 void psxBEQ() { RepBranchi32(==) }  // Branch if Rs == Rt
615 void psxBNE() { RepBranchi32(!=) }  // Branch if Rs != Rt
616
617 /*********************************************************
618 * Jump to target                                         *
619 * Format:  OP target                                     *
620 *********************************************************/
621 void psxJ()   {               doBranch(_JumpTarget_); }
622 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
623
624 /*********************************************************
625 * Register jump                                          *
626 * Format:  OP rs, rd                                     *
627 *********************************************************/
628 void psxJR()   {
629         doBranch(_u32(_rRs_));
630         psxJumpTest();
631 }
632
633 void psxJALR() {
634         u32 temp = _u32(_rRs_);
635         if (_Rd_) { _SetLink(_Rd_); }
636         doBranch(temp);
637 }
638
639 /*********************************************************
640 * Load and store for GPR                                 *
641 * Format:  OP rt, offset(base)                           *
642 *********************************************************/
643
644 #define _oB_ (_u32(_rRs_) + _Imm_)
645
646 void psxLB() {
647         if (_Rt_) {
648                 _i32(_rRt_) = (signed char)psxMemRead8(_oB_); 
649         } else {
650                 psxMemRead8(_oB_); 
651         }
652 }
653
654 void psxLBU() {
655         if (_Rt_) {
656                 _u32(_rRt_) = psxMemRead8(_oB_);
657         } else {
658                 psxMemRead8(_oB_); 
659         }
660 }
661
662 void psxLH() {
663         if (_Rt_) {
664                 _i32(_rRt_) = (short)psxMemRead16(_oB_);
665         } else {
666                 psxMemRead16(_oB_);
667         }
668 }
669
670 void psxLHU() {
671         if (_Rt_) {
672                 _u32(_rRt_) = psxMemRead16(_oB_);
673         } else {
674                 psxMemRead16(_oB_);
675         }
676 }
677
678 void psxLW() {
679         if (_Rt_) {
680                 _u32(_rRt_) = psxMemRead32(_oB_);
681         } else {
682                 psxMemRead32(_oB_);
683         }
684 }
685
686 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
687 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
688
689 void psxLWL() {
690         u32 addr = _oB_;
691         u32 shift = addr & 3;
692         u32 mem = psxMemRead32(addr & ~3);
693
694         if (!_Rt_) return;
695         _u32(_rRt_) =   ( _u32(_rRt_) & LWL_MASK[shift]) | 
696                                         ( mem << LWL_SHIFT[shift]);
697
698         /*
699         Mem = 1234.  Reg = abcd
700
701         0   4bcd   (mem << 24) | (reg & 0x00ffffff)
702         1   34cd   (mem << 16) | (reg & 0x0000ffff)
703         2   234d   (mem <<  8) | (reg & 0x000000ff)
704         3   1234   (mem      ) | (reg & 0x00000000)
705         */
706 }
707
708 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
709 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
710
711 void psxLWR() {
712         u32 addr = _oB_;
713         u32 shift = addr & 3;
714         u32 mem = psxMemRead32(addr & ~3);
715
716         if (!_Rt_) return;
717         _u32(_rRt_) =   ( _u32(_rRt_) & LWR_MASK[shift]) | 
718                                         ( mem >> LWR_SHIFT[shift]);
719
720         /*
721         Mem = 1234.  Reg = abcd
722
723         0   1234   (mem      ) | (reg & 0x00000000)
724         1   a123   (mem >>  8) | (reg & 0xff000000)
725         2   ab12   (mem >> 16) | (reg & 0xffff0000)
726         3   abc1   (mem >> 24) | (reg & 0xffffff00)
727         */
728 }
729
730 void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
731 void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
732 void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
733
734 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
735 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
736
737 void psxSWL() {
738         u32 addr = _oB_;
739         u32 shift = addr & 3;
740         u32 mem = psxMemRead32(addr & ~3);
741
742         psxMemWrite32(addr & ~3,  (_u32(_rRt_) >> SWL_SHIFT[shift]) |
743                              (  mem & SWL_MASK[shift]) );
744         /*
745         Mem = 1234.  Reg = abcd
746
747         0   123a   (reg >> 24) | (mem & 0xffffff00)
748         1   12ab   (reg >> 16) | (mem & 0xffff0000)
749         2   1abc   (reg >>  8) | (mem & 0xff000000)
750         3   abcd   (reg      ) | (mem & 0x00000000)
751         */
752 }
753
754 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
755 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
756
757 void psxSWR() {
758         u32 addr = _oB_;
759         u32 shift = addr & 3;
760         u32 mem = psxMemRead32(addr & ~3);
761
762         psxMemWrite32(addr & ~3,  (_u32(_rRt_) << SWR_SHIFT[shift]) |
763                              (  mem & SWR_MASK[shift]) );
764
765         /*
766         Mem = 1234.  Reg = abcd
767
768         0   abcd   (reg      ) | (mem & 0x00000000)
769         1   bcd4   (reg <<  8) | (mem & 0x000000ff)
770         2   cd34   (reg << 16) | (mem & 0x0000ffff)
771         3   d234   (reg << 24) | (mem & 0x00ffffff)
772         */
773 }
774
775 /*********************************************************
776 * Moves between GPR and COPx                             *
777 * Format:  OP rt, fs                                     *
778 *********************************************************/
779 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
780 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
781
782 void psxTestSWInts() {
783         // the next code is untested, if u know please
784         // tell me if it works ok or not (linuzappz)
785         if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
786                 psxRegs.CP0.n.Status & 0x1) {
787                 psxException(psxRegs.CP0.n.Cause, branch);
788         }
789 }
790
791 void MTC0(int reg, u32 val) {
792 //      SysPrintf("MTC0 %d: %x\n", reg, val);
793         switch (reg) {
794                 case 12: // Status
795                         psxRegs.CP0.r[12] = val;
796                         psxTestSWInts();
797                         break;
798
799                 case 13: // Cause
800                         psxRegs.CP0.n.Cause = val & ~(0xfc00);
801                         psxTestSWInts();
802                         break;
803
804                 default:
805                         psxRegs.CP0.r[reg] = val;
806                         break;
807         }
808 }
809
810 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
811 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
812
813 /*********************************************************
814 * Unknow instruction (would generate an exception)       *
815 * Format:  ?                                             *
816 *********************************************************/
817 void psxNULL() { 
818 #ifdef PSXCPU_LOG
819         PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
820 #endif
821 }
822
823 void psxSPECIAL() {
824         psxSPC[_Funct_]();
825 }
826
827 void psxREGIMM() {
828         psxREG[_Rt_]();
829 }
830
831 void psxCOP0() {
832         psxCP0[_Rs_]();
833 }
834
835 void psxCOP2() {
836         psxCP2[_Funct_]();
837 }
838
839 void psxBASIC() {
840         psxCP2BSC[_Rs_]();
841 }
842
843 void psxHLE() {
844 //      psxHLEt[psxRegs.code & 0xffff]();
845         psxHLEt[psxRegs.code & 0x07]();         // HDHOSHY experimental patch
846 }
847
848 void (*psxBSC[64])() = {
849         psxSPECIAL, psxREGIMM, psxJ   , psxJAL  , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
850         psxADDI   , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
851         psxCOP0   , psxNULL  , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
852         psxNULL   , psxNULL  , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
853         psxLB     , psxLH    , psxLWL , psxLW   , psxLBU , psxLHU , psxLWR , psxNULL,
854         psxSB     , psxSH    , psxSWL , psxSW   , psxNULL, psxNULL, psxSWR , psxNULL, 
855         psxNULL   , psxNULL  , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
856         psxNULL   , psxNULL  , gteSWC2, psxHLE  , psxNULL, psxNULL, psxNULL, psxNULL 
857 };
858
859
860 void (*psxSPC[64])() = {
861         psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV   , psxNULL , psxSRLV, psxSRAV,
862         psxJR  , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
863         psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL   , psxNULL , psxNULL, psxNULL,
864         psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL   , psxNULL , psxNULL, psxNULL,
865         psxADD , psxADDU , psxSUB , psxSUBU, psxAND    , psxOR   , psxXOR , psxNOR ,
866         psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL   , psxNULL , psxNULL, psxNULL,
867         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL,
868         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL
869 };
870
871 void (*psxREG[32])() = {
872         psxBLTZ  , psxBGEZ  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
873         psxNULL  , psxNULL  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
874         psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
875         psxNULL  , psxNULL  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
876 };
877
878 void (*psxCP0[32])() = {
879         psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
880         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
881         psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
882         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
883 };
884
885 void (*psxCP2[64])() = {
886         psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
887         psxNULL , psxNULL , psxNULL , psxNULL, gteOP  , psxNULL , psxNULL , psxNULL, // 08
888         gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
889         psxNULL , psxNULL , psxNULL , gteNCCS, gteCC  , psxNULL , gteNCS  , psxNULL, // 18
890         gteNCT  , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
891         gteSQR  , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28 
892         gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
893         psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF  , gteGPL  , gteNCCT  // 38
894 };
895
896 void (*psxCP2BSC[32])() = {
897         gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
898         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
899         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
900         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
901 };
902
903
904 ///////////////////////////////////////////
905
906 static int intInit() {
907         return 0;
908 }
909
910 static void intReset() {
911 }
912
913 void intExecute() {
914         extern int stop;
915         for (;!stop;) 
916                 execI();
917 }
918
919 void intExecuteBlock() {
920         branch2 = 0;
921         while (!branch2) execI();
922 }
923
924 static void intClear(u32 Addr, u32 Size) {
925 }
926
927 static void intShutdown() {
928 }
929
930 // interpreter execution
931 void execI() {
932         u32 *code = (u32 *)PSXM(psxRegs.pc);
933         psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
934
935         debugI();
936
937         if (Config.Debug) ProcessDebug();
938
939         psxRegs.pc += 4;
940         psxRegs.cycle += BIAS;
941
942         psxBSC[psxRegs.code >> 26]();
943 }
944
945 R3000Acpu psxInt = {
946         intInit,
947         intReset,
948         intExecute,
949         intExecuteBlock,
950         intClear,
951         intShutdown
952 };