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