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