refactor OSD code and PCNT stuff
[pcsx_rearmed.git] / libpcsxcore / psxinterpreter.c
CommitLineData
ef79bbde
P
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
29static int branch = 0;
30static int branch2 = 0;
31static 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
41inline void execI();
42
43// Subsets
44void (*psxBSC[64])();
45void (*psxSPC[64])();
46void (*psxREG[32])();
47void (*psxCP0[32])();
48void (*psxCP2[64])();
49void (*psxCP2BSC[32])();
50
51static 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
71static 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
88static 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
108int 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
252void 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*********************************************************/
337void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
338void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
339void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
340void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
341void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
342void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
343void 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*********************************************************/
349void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
350void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
351void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
352void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
353void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
354void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
355void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
356void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
357void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
358void 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*********************************************************/
364void psxDIV() {
365 if (_i32(_rRt_) != 0) {
366 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
367 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
368 }
369}
370
371void psxDIVU() {
372 if (_rRt_ != 0) {
373 _rLo_ = _rRs_ / _rRt_;
374 _rHi_ = _rRs_ % _rRt_;
375 }
376}
377
378void 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
385void 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
399void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
400void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
401void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
402void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
403void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
404void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
405
406/*********************************************************
407* Shift arithmetic with constant shift *
408* Format: OP rd, rt, sa *
409*********************************************************/
410void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
411void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
412void 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*********************************************************/
418void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
419void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
420void 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*********************************************************/
426void 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*********************************************************/
432void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
433void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
434
435/*********************************************************
436* Move to GPR to HI/LO & Register jump *
437* Format: OP rs *
438*********************************************************/
439void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
440void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
441
442/*********************************************************
443* Special purpose instructions *
444* Format: OP *
445*********************************************************/
446void psxBREAK() {
447 // Break exception - psx rom doens't handles this
448}
449
450void psxSYSCALL() {
451 psxRegs.pc -= 4;
452 psxException(0x20, branch);
453}
454
455void 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
467void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
468void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
469
470/*********************************************************
471* Jump to target *
472* Format: OP target *
473*********************************************************/
474void psxJ() { doBranch(_JumpTarget_); }
475void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
476
477/*********************************************************
478* Register jump *
479* Format: OP rs, rd *
480*********************************************************/
481void psxJR() {
482 doBranch(_u32(_rRs_));
483 psxJumpTest();
484}
485
486void 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
499void psxLB() {
500 if (_Rt_) {
501 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
502 } else {
503 psxMemRead8(_oB_);
504 }
505}
506
507void psxLBU() {
508 if (_Rt_) {
509 _u32(_rRt_) = psxMemRead8(_oB_);
510 } else {
511 psxMemRead8(_oB_);
512 }
513}
514
515void psxLH() {
516 if (_Rt_) {
517 _i32(_rRt_) = (short)psxMemRead16(_oB_);
518 } else {
519 psxMemRead16(_oB_);
520 }
521}
522
523void psxLHU() {
524 if (_Rt_) {
525 _u32(_rRt_) = psxMemRead16(_oB_);
526 } else {
527 psxMemRead16(_oB_);
528 }
529}
530
531void psxLW() {
532 if (_Rt_) {
533 _u32(_rRt_) = psxMemRead32(_oB_);
534 } else {
535 psxMemRead32(_oB_);
536 }
537}
538
539u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
540u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
541
542void 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
561u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
562u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
563
564void 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
583void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
584void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
585void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
586
587u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
588u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
589
590void 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
607u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
608u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
609
610void 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*********************************************************/
632void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
633void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
634
635void 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
663void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
664void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
665
666/*********************************************************
667* Unknow instruction (would generate an exception) *
668* Format: ? *
669*********************************************************/
670void psxNULL() {
671#ifdef PSXCPU_LOG
672 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
673#endif
674}
675
676void psxSPECIAL() {
677 psxSPC[_Funct_]();
678}
679
680void psxREGIMM() {
681 psxREG[_Rt_]();
682}
683
684void psxCOP0() {
685 psxCP0[_Rs_]();
686}
687
688void psxCOP2() {
689 psxCP2[_Funct_]();
690}
691
692void psxBASIC() {
693 psxCP2BSC[_Rs_]();
694}
695
696void psxHLE() {
697// psxHLEt[psxRegs.code & 0xffff]();
698 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
699}
700
701void (*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
713void (*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
724void (*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
731void (*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
738void (*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
749void (*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
759static int intInit() {
760 return 0;
761}
762
763static void intReset() {
764}
765
766static void intExecute() {
767 for (;;)
768 execI();
769}
770
771static void intExecuteBlock() {
772 branch2 = 0;
773 while (!branch2) execI();
774}
775
776static void intClear(u32 Addr, u32 Size) {
777}
778
779static void intShutdown() {
780}
781
782// interpreter execution
783inline 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
797R3000Acpu psxInt = {
798 intInit,
799 intReset,
800 intExecute,
801 intExecuteBlock,
802 intClear,
803 intShutdown
804};