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