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