1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
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. *
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. *
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 ***************************************************************************/
21 * PSX assembly interpreter.
24 #include "psxcommon.h"
28 #include "psxinterpreter.h"
31 #include "../include/compiler_features.h"
33 // these may cause issues: because of poor timing we may step
34 // on instructions that real hardware would never reach
35 #define DO_EXCEPTION_RESERVEDI
36 #define DO_EXCEPTION_ADDR_ERR
38 static int branch = 0;
39 static int branch2 = 0;
43 #define INT_ATTR __attribute__((regparm(2)))
48 #define INVALID_PTR NULL
52 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code);
53 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code);
55 // get an opcode without triggering exceptions or affecting cache
56 u32 intFakeFetch(u32 pc)
58 u8 *base = psxMemRLUT[pc >> 16];
60 if (unlikely(base == INVALID_PTR))
62 code = (u32 *)(base + (pc & 0xfffc));
67 static u32 INT_ATTR fetchNoCache(psxRegisters *regs, u8 **memRLUT, u32 pc)
69 u8 *base = memRLUT[pc >> 16];
71 if (unlikely(base == INVALID_PTR)) {
72 SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra);
74 psxException(R3000E_IBE << 2, branch, ®s->CP0);
75 return 0; // execute as nop
77 code = (u32 *)(base + (pc & 0xfffc));
83 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
85 static struct cache_entry {
90 static u32 INT_ATTR fetchICache(psxRegisters *regs, u8 **memRLUT, u32 pc)
95 // this is not how the hardware works but whatever
96 struct cache_entry *entry = &ICache[(pc & 0xff0) >> 4];
98 if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag)
100 const u8 *base = memRLUT[pc >> 16];
102 if (unlikely(base == INVALID_PTR)) {
103 SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra);
105 psxException(R3000E_IBE << 2, branch, ®s->CP0);
106 return 0; // execute as nop
108 code = (u32 *)(base + (pc & 0xfff0));
111 // treat as 4 words, although other configurations are said to be possible
114 case 0x00: entry->data[0] = SWAP32(code[0]);
115 case 0x04: entry->data[1] = SWAP32(code[1]);
116 case 0x08: entry->data[2] = SWAP32(code[2]);
117 case 0x0c: entry->data[3] = SWAP32(code[3]);
120 return entry->data[(pc & 0x0f) >> 2];
123 return fetchNoCache(regs, memRLUT, pc);
126 static u32 (INT_ATTR *fetch)(psxRegisters *regs_, u8 **memRLUT, u32 pc) = fetchNoCache;
128 // Make the timing events trigger faster as we are currently assuming everything
129 // takes one cycle, which is not the case on real hardware.
130 // FIXME: count cache misses, memory latencies, stalls to get rid of this
131 static inline void addCycle(void)
133 assert(psxRegs.subCycleStep >= 0x10000);
134 psxRegs.subCycle += psxRegs.subCycleStep;
135 psxRegs.cycle += psxRegs.subCycle >> 16;
136 psxRegs.subCycle &= 0xffff;
139 static void delayRead(int reg, u32 bpc) {
142 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
144 rold = psxRegs.GPR.r[reg];
145 psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code); // branch delay load
146 rnew = psxRegs.GPR.r[reg];
152 psxRegs.GPR.r[reg] = rold;
153 execI(); // first branch opcode
154 psxRegs.GPR.r[reg] = rnew;
159 static void delayWrite(int reg, u32 bpc) {
161 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
163 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
164 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
166 // no changes from normal behavior
168 psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
176 static void delayReadWrite(int reg, u32 bpc) {
178 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
180 // the branch delay load is skipped
188 /**** R3000A Instruction Macros ****/
189 #define _PC_ regs_->pc // The next PC to be executed
191 #define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register
192 #define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register
193 #define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register
194 #define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register
195 #define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register
196 #define _fSa_(code) ((code >> 6) & 0x1F) // The sa part of the instruction register
197 #define _fIm_(code) ((u16)code) // The immediate part of the instruction register
198 #define _fTarget_(code) (code & 0x03ffffff) // The target part of the instruction register
200 #define _fImm_(code) ((s16)code) // sign-extended immediate
201 #define _fImmU_(code) (code&0xffff) // zero-extended immediate
203 #define _Op_ _fOp_(code)
204 #define _Funct_ _fFunct_(code)
205 #define _Rd_ _fRd_(code)
206 #define _Rt_ _fRt_(code)
207 #define _Rs_ _fRs_(code)
208 #define _Sa_ _fSa_(code)
209 #define _Im_ _fIm_(code)
210 #define _Target_ _fTarget_(code)
212 #define _Imm_ _fImm_(code)
213 #define _ImmU_ _fImmU_(code)
215 #define _rRs_ regs_->GPR.r[_Rs_] // Rs register
216 #define _rRt_ regs_->GPR.r[_Rt_] // Rt register
217 #define _rRd_ regs_->GPR.r[_Rd_] // Rd register
218 #define _rSa_ regs_->GPR.r[_Sa_] // Sa register
219 #define _rFs_ regs_->CP0.r[_Rd_] // Fs register
221 #define _rHi_ regs_->GPR.n.hi // The HI register
222 #define _rLo_ regs_->GPR.n.lo // The LO register
224 #define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction
225 #define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction
227 #define _SetLink(x) regs_->GPR.r[x] = _PC_ + 4; // Sets the return address in the link register
230 static inline INT_ATTR void name(psxRegisters *regs_, u32 code)
232 // this defines shall be used with the tmp
233 // of the next func (instead of _Funct_...)
234 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
235 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
236 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
237 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
238 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
240 #define _i32(x) (s32)(x)
241 #define _u32(x) (u32)(x)
243 static int psxTestLoadDelay(int reg, u32 tmp) {
244 if (tmp == 0) return 0; // NOP
246 case 0x00: // SPECIAL
249 case 0x02: case 0x03: // SRL/SRA
250 if (_tRd_ == reg && _tRt_ == reg) return 1; else
251 if (_tRt_ == reg) return 2; else
252 if (_tRd_ == reg) return 3;
256 if (_tRs_ == reg) return 2;
259 if (_tRd_ == reg && _tRs_ == reg) return 1; else
260 if (_tRs_ == reg) return 2; else
261 if (_tRd_ == reg) return 3;
264 // SYSCALL/BREAK just a break;
266 case 0x20: case 0x21: case 0x22: case 0x23:
267 case 0x24: case 0x25: case 0x26: case 0x27:
268 case 0x2a: case 0x2b: // ADD/ADDU...
269 case 0x04: case 0x06: case 0x07: // SLLV...
270 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
271 if (_tRt_ == reg || _tRs_ == reg) return 2; else
272 if (_tRd_ == reg) return 3;
275 case 0x10: case 0x12: // MFHI/MFLO
276 if (_tRd_ == reg) return 3;
278 case 0x11: case 0x13: // MTHI/MTLO
279 if (_tRs_ == reg) return 2;
282 case 0x18: case 0x19:
283 case 0x1a: case 0x1b: // MULT/DIV...
284 if (_tRt_ == reg || _tRs_ == reg) return 2;
289 case 0x01: // REGIMM - BLTZ/BGEZ...
290 // Xenogears - lbu v0 / beq v0
291 // - no load delay (fixes battle loading)
294 // J would be just a break;
296 if (31 == reg) return 3;
299 case 0x06: case 0x07: // BLEZ/BGTZ
300 case 0x04: case 0x05: // BEQ/BNE
301 // Xenogears - lbu v0 / beq v0
302 // - no load delay (fixes battle loading)
305 case 0x08: case 0x09: case 0x0a: case 0x0b:
306 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
307 if (_tRt_ == reg && _tRs_ == reg) return 1; else
308 if (_tRs_ == reg) return 2; else
309 if (_tRt_ == reg) return 3;
313 if (_tRt_ == reg) return 3;
319 if (_tRt_ == reg) return 3;
322 if (_tRt_ == reg) return 3;
325 if (_tRt_ == reg) return 2;
328 if (_tRt_ == reg) return 2;
339 if (_tRt_ == reg) return 3;
342 if (_tRt_ == reg) return 3;
345 if (_tRt_ == reg) return 2;
348 if (_tRt_ == reg) return 2;
356 case 0x22: case 0x26: // LWL/LWR
357 if (_tRt_ == reg) return 3; else
358 if (_tRs_ == reg) return 2;
361 case 0x20: case 0x21: case 0x23:
362 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
363 if (_tRt_ == reg && _tRs_ == reg) return 1; else
364 if (_tRs_ == reg) return 2; else
365 if (_tRt_ == reg) return 3;
368 case 0x28: case 0x29: case 0x2a:
369 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
370 if (_tRt_ == reg || _tRs_ == reg) return 2;
373 case 0x32: case 0x3a: // LWC2/SWC2
374 if (_tRs_ == reg) return 2;
381 static void psxDelayTest(int reg, u32 bpc) {
382 u32 tmp = intFakeFetch(bpc);
385 switch (psxTestLoadDelay(reg, tmp)) {
387 delayReadWrite(reg, bpc); return;
389 delayRead(reg, bpc); return;
391 delayWrite(reg, bpc); return;
394 psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
402 static u32 psxBranchNoDelay(psxRegisters *regs_) {
405 regs_->code = code = intFakeFetch(regs_->pc);
407 case 0x00: // SPECIAL
413 if (_Rd_) { _SetLink(_Rd_); }
421 return _BranchTarget_;
424 if (_i32(_rRs_) >= 0)
425 return _BranchTarget_;
428 if (_i32(_rRs_) < 0) {
430 return _BranchTarget_;
434 if (_i32(_rRs_) >= 0) {
436 return _BranchTarget_;
447 if (_i32(_rRs_) == _i32(_rRt_))
448 return _BranchTarget_;
451 if (_i32(_rRs_) != _i32(_rRt_))
452 return _BranchTarget_;
455 if (_i32(_rRs_) <= 0)
456 return _BranchTarget_;
460 return _BranchTarget_;
467 static int psxDelayBranchExec(u32 tar) {
477 static int psxDelayBranchTest(u32 tar1) {
478 u32 tar2, tmp1, tmp2;
480 tar2 = psxBranchNoDelay(&psxRegs);
485 * Branch in delay slot:
486 * - execute 1 instruction at tar1
487 * - jump to tar2 (target of branch in delay slot; this branch
488 * has no normal delay slot, instruction at tar1 was fetched instead)
491 tmp1 = psxBranchNoDelay(&psxRegs);
492 if (tmp1 == (u32)-1) {
493 return psxDelayBranchExec(tar2);
498 * Got a branch at tar1:
499 * - execute 1 instruction at tar2
500 * - jump to target of that branch (tmp1)
503 tmp2 = psxBranchNoDelay(&psxRegs);
504 if (tmp2 == (u32)-1) {
505 return psxDelayBranchExec(tmp1);
510 * Got a branch at tar2:
511 * - execute 1 instruction at tmp1
512 * - jump to target of that branch (tmp2)
515 return psxDelayBranchExec(tmp2);
518 static void doBranch(u32 tar) {
521 branch2 = branch = 1;
524 // check for branch in delay slot
525 if (psxDelayBranchTest(tar))
530 psxRegs.code = code = fetch(&psxRegs, psxMemRLUT, pc);
534 // check for load delay
541 psxDelayTest(_Rt_, branchPC);
551 psxDelayTest(_Rt_, branchPC);
558 psxDelayTest(_Rt_, branchPC);
561 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
562 psxDelayTest(_Rt_, branchPC);
568 psxBSC[code >> 26](&psxRegs, code);
571 psxRegs.pc = branchPC;
576 static void doBranchReg(u32 tar) {
577 #ifdef DO_EXCEPTION_ADDR_ERR
578 if (unlikely(tar & 3)) {
579 psxRegs.pc = psxRegs.CP0.n.BadVAddr = tar;
580 psxException(R3000E_AdEL << 2, branch, &psxRegs.CP0);
589 #if __has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ >= 5)
590 #define add_overflow(a, b, r) __builtin_add_overflow(a, b, &(r))
591 #define sub_overflow(a, b, r) __builtin_sub_overflow(a, b, &(r))
593 #define add_overflow(a, b, r) ({r = (u32)a + (u32)b; (a ^ ~b) & (a ^ r) & (1u<<31);})
594 #define sub_overflow(a, b, r) ({r = (u32)a - (u32)b; (a ^ b) & (a ^ r) & (1u<<31);})
597 static void addExc(psxRegisters *regs, u32 rt, s32 a1, s32 a2) {
599 if (add_overflow(a1, a2, r)) {
600 //printf("ov %08x + %08x = %08x\n", a1, a2, r);
602 psxException(R3000E_Ov << 2, branch, ®s->CP0);
609 static void subExc(psxRegisters *regs, u32 rt, s32 a1, s32 a2) {
611 if (sub_overflow(a1, a2, r)) {
613 psxException(R3000E_Ov << 2, branch, ®s->CP0);
620 /*********************************************************
621 * Arithmetic with immediate operand *
622 * Format: OP rt, rs, immediate *
623 *********************************************************/
624 OP(psxADDI) { addExc(regs_, _Rt_, _i32(_rRs_), _Imm_); } // Rt = Rs + Im (Exception on Integer Overflow)
625 OP(psxADDIU) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
626 OP(psxANDI) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
627 OP(psxORI) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
628 OP(psxXORI) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
629 OP(psxSLTI) { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
630 OP(psxSLTIU) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
632 /*********************************************************
633 * Register arithmetic *
634 * Format: OP rd, rs, rt *
635 *********************************************************/
636 OP(psxADD) { addExc(regs_, _Rd_, _i32(_rRs_), _i32(_rRt_)); } // Rd = Rs + Rt (Exception on Integer Overflow)
637 OP(psxSUB) { subExc(regs_, _Rd_, _i32(_rRs_), _i32(_rRt_)); } // Rd = Rs - Rt (Exception on Integer Overflow)
638 OP(psxADDU) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
639 OP(psxSUBU) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
640 OP(psxAND) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
641 OP(psxOR) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
642 OP(psxXOR) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
643 OP(psxNOR) { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
644 OP(psxSLT) { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
645 OP(psxSLTU) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
647 /*********************************************************
648 * Register mult/div & Register trap logic *
649 * Format: OP rs, rt *
650 *********************************************************/
654 if (_rRs_ & 0x80000000) {
660 #if !defined(__arm__) && !defined(__aarch64__)
661 else if (_rRs_ == 0x80000000 && _rRt_ == 0xFFFFFFFF) {
667 _rLo_ = _i32(_rRs_) / _i32(_rRt_);
668 _rHi_ = _i32(_rRs_) % _i32(_rRt_);
673 regs_->muldivBusyCycle = regs_->cycle + 37;
679 _rLo_ = _rRs_ / _rRt_;
680 _rHi_ = _rRs_ % _rRt_;
689 regs_->muldivBusyCycle = regs_->cycle + 37;
690 psxDIVU(regs_, code);
694 u64 res = (s64)_i32(_rRs_) * _i32(_rRt_);
696 regs_->GPR.n.lo = (u32)res;
697 regs_->GPR.n.hi = (u32)(res >> 32);
701 // approximate, but maybe good enough
703 u32 lz = __builtin_clz(((rs ^ ((s32)rs >> 21)) | 1));
704 u32 c = 7 + (2 - (lz / 11)) * 4;
705 regs_->muldivBusyCycle = regs_->cycle + c;
706 psxMULT(regs_, code);
710 u64 res = (u64)_u32(_rRs_) * _u32(_rRt_);
712 regs_->GPR.n.lo = (u32)(res & 0xffffffff);
713 regs_->GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
717 // approximate, but maybe good enough
718 u32 lz = __builtin_clz(_rRs_ | 1);
719 u32 c = 7 + (2 - (lz / 11)) * 4;
720 regs_->muldivBusyCycle = regs_->cycle + c;
721 psxMULTU(regs_, code);
724 /*********************************************************
725 * Register branch logic *
726 * Format: OP rs, offset *
727 *********************************************************/
728 #define RepZBranchi32(op) \
729 if(_i32(_rRs_) op 0) \
730 doBranch(_BranchTarget_);
731 #define RepZBranchLinki32(op) { \
732 s32 temp = _i32(_rRs_); \
735 doBranch(_BranchTarget_); \
738 OP(psxBGEZ) { RepZBranchi32(>=) } // Branch if Rs >= 0
739 OP(psxBGEZAL) { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
740 OP(psxBGTZ) { RepZBranchi32(>) } // Branch if Rs > 0
741 OP(psxBLEZ) { RepZBranchi32(<=) } // Branch if Rs <= 0
742 OP(psxBLTZ) { RepZBranchi32(<) } // Branch if Rs < 0
743 OP(psxBLTZAL) { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
745 /*********************************************************
746 * Shift arithmetic with constant shift *
747 * Format: OP rd, rt, sa *
748 *********************************************************/
749 OP(psxSLL) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
750 OP(psxSRA) { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
751 OP(psxSRL) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
753 /*********************************************************
754 * Shift arithmetic with variant register shift *
755 * Format: OP rd, rt, rs *
756 *********************************************************/
757 OP(psxSLLV) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs
758 OP(psxSRAV) { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic)
759 OP(psxSRLV) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical)
761 /*********************************************************
762 * Load higher 16 bits of the first word in GPR with imm *
763 * Format: OP rt, immediate *
764 *********************************************************/
765 OP(psxLUI) { if (!_Rt_) return; _rRt_ = code << 16; } // Upper halfword of Rt = Im
767 /*********************************************************
768 * Move from HI/LO to GPR *
770 *********************************************************/
771 OP(psxMFHI) { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
772 OP(psxMFLO) { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
774 static void mflohiCheckStall(psxRegisters *regs_)
776 u32 left = regs_->muldivBusyCycle - regs_->cycle;
778 //printf("muldiv stall %u\n", left);
779 regs_->cycle = regs_->muldivBusyCycle;
783 OP(psxMFHI_stall) { mflohiCheckStall(regs_); psxMFHI(regs_, code); }
784 OP(psxMFLO_stall) { mflohiCheckStall(regs_); psxMFLO(regs_, code); }
786 /*********************************************************
787 * Move to GPR to HI/LO & Register jump *
789 *********************************************************/
790 OP(psxMTHI) { _rHi_ = _rRs_; } // Hi = Rs
791 OP(psxMTLO) { _rLo_ = _rRs_; } // Lo = Rs
793 /*********************************************************
794 * Special purpose instructions *
796 *********************************************************/
799 psxException(R3000E_Bp << 2, branch, ®s_->CP0);
804 psxException(R3000E_Syscall << 2, branch, ®s_->CP0);
807 static inline void execI_(u8 **memRLUT, psxRegisters *regs_);
809 static inline void psxTestSWInts(psxRegisters *regs_, int step) {
810 if (regs_->CP0.n.Cause & regs_->CP0.n.Status & 0x0300 &&
811 regs_->CP0.n.Status & 0x1) {
813 execI_(psxMemRLUT, regs_);
814 regs_->CP0.n.Cause &= ~0x7c;
815 psxException(regs_->CP0.n.Cause, branch, ®s_->CP0);
820 // SysPrintf("psxRFE\n");
821 regs_->CP0.n.Status = (regs_->CP0.n.Status & 0xfffffff0) |
822 ((regs_->CP0.n.Status & 0x3c) >> 2);
823 psxTestSWInts(regs_, 0);
826 /*********************************************************
827 * Register branch logic *
828 * Format: OP rs, rt, offset *
829 *********************************************************/
830 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
832 OP(psxBEQ) { RepBranchi32(==) } // Branch if Rs == Rt
833 OP(psxBNE) { RepBranchi32(!=) } // Branch if Rs != Rt
835 /*********************************************************
837 * Format: OP target *
838 *********************************************************/
839 OP(psxJ) { doBranch(_JumpTarget_); }
840 OP(psxJAL) { _SetLink(31); doBranch(_JumpTarget_); }
842 /*********************************************************
844 * Format: OP rs, rd *
845 *********************************************************/
852 u32 temp = _u32(_rRs_);
853 if (_Rd_) { _SetLink(_Rd_); }
857 /*********************************************************
858 * Load and store for GPR *
859 * Format: OP rt, offset(base) *
860 *********************************************************/
862 #define _oB_ (regs_->GPR.r[_Rs_] + _Imm_)
864 OP(psxLB) { u32 v = (s8)psxMemRead8(_oB_); if (_Rt_) _rRt_ = v; }
865 OP(psxLBU) { u32 v = psxMemRead8(_oB_); if (_Rt_) _rRt_ = v; }
866 OP(psxLH) { u32 v = (s16)psxMemRead16(_oB_); if (_Rt_) _rRt_ = v; }
867 OP(psxLHU) { u32 v = psxMemRead16(_oB_); if (_Rt_) _rRt_ = v; }
868 OP(psxLW) { u32 v = psxMemRead32(_oB_); if (_Rt_) _rRt_ = v; }
871 static const u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
872 static const u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
874 u32 shift = addr & 3;
875 u32 mem = psxMemRead32(addr & ~3);
878 _rRt_ = (_u32(_rRt_) & LWL_MASK[shift]) | (mem << LWL_SHIFT[shift]);
881 Mem = 1234. Reg = abcd
883 0 4bcd (mem << 24) | (reg & 0x00ffffff)
884 1 34cd (mem << 16) | (reg & 0x0000ffff)
885 2 234d (mem << 8) | (reg & 0x000000ff)
886 3 1234 (mem ) | (reg & 0x00000000)
891 static const u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
892 static const u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
894 u32 shift = addr & 3;
895 u32 mem = psxMemRead32(addr & ~3);
898 _rRt_ = (_u32(_rRt_) & LWR_MASK[shift]) | (mem >> LWR_SHIFT[shift]);
901 Mem = 1234. Reg = abcd
903 0 1234 (mem ) | (reg & 0x00000000)
904 1 a123 (mem >> 8) | (reg & 0xff000000)
905 2 ab12 (mem >> 16) | (reg & 0xffff0000)
906 3 abc1 (mem >> 24) | (reg & 0xffffff00)
910 OP(psxSB) { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
911 OP(psxSH) { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
912 OP(psxSW) { psxMemWrite32(_oB_, _rRt_); }
915 static const u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
916 static const u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
918 u32 shift = addr & 3;
919 u32 mem = psxMemRead32(addr & ~3);
921 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
922 ( mem & SWL_MASK[shift]) );
924 Mem = 1234. Reg = abcd
926 0 123a (reg >> 24) | (mem & 0xffffff00)
927 1 12ab (reg >> 16) | (mem & 0xffff0000)
928 2 1abc (reg >> 8) | (mem & 0xff000000)
929 3 abcd (reg ) | (mem & 0x00000000)
934 static const u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
935 static const u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
937 u32 shift = addr & 3;
938 u32 mem = psxMemRead32(addr & ~3);
940 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
941 ( mem & SWR_MASK[shift]) );
944 Mem = 1234. Reg = abcd
946 0 abcd (reg ) | (mem & 0x00000000)
947 1 bcd4 (reg << 8) | (mem & 0x000000ff)
948 2 cd34 (reg << 16) | (mem & 0x0000ffff)
949 3 d234 (reg << 24) | (mem & 0x00ffffff)
953 /*********************************************************
954 * Moves between GPR and COPx *
955 * Format: OP rt, fs *
956 *********************************************************/
959 #ifdef DO_EXCEPTION_RESERVEDI
960 if (unlikely(r == 0)) {
962 psxException(R3000E_RI << 2, branch, ®s_->CP0);
966 _rRt_ = regs_->CP0.r[r];
969 OP(psxCFC0) { if (!_Rt_) return; _rRt_ = _rFs_; }
971 static void setupCop(u32 sr);
973 void MTC0(psxRegisters *regs_, int reg, u32 val) {
974 // SysPrintf("MTC0 %d: %x\n", reg, val);
977 if (unlikely((regs_->CP0.n.Status ^ val) & (1 << 16)))
978 psxMemOnIsolate((val >> 16) & 1);
979 if (unlikely((regs_->CP0.n.Status ^ val) & (7 << 29)))
981 regs_->CP0.n.Status = val;
982 psxTestSWInts(regs_, 1);
986 regs_->CP0.n.Cause &= ~0x0300;
987 regs_->CP0.n.Cause |= val & 0x0300;
988 psxTestSWInts(regs_, 0);
992 regs_->CP0.r[reg] = val;
997 OP(psxMTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); }
998 OP(psxCTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); }
1000 /*********************************************************
1001 * Unknown instruction (would generate an exception) *
1003 *********************************************************/
1004 static inline void psxNULL_(void) {
1005 //printf("op %08x @%08x\n", psxRegs.code, psxRegs.pc);
1010 #ifdef DO_EXCEPTION_RESERVEDI
1012 psxException(R3000E_RI << 2, branch, ®s_->CP0);
1016 void gteNULL(struct psxCP2Regs *regs) {
1021 psxSPC[_Funct_](regs_, code);
1026 case 0x00: psxMFC0(regs_, code); break;
1027 case 0x02: psxCFC0(regs_, code); break;
1028 case 0x04: psxMTC0(regs_, code); break;
1029 case 0x06: psxCTC0(regs_, code); break;
1030 case 0x10: psxRFE(regs_, code); break;
1031 default: psxNULL_(); break;
1036 // MTC0(regs_, _Rt_, psxMemRead32(_oB_)); // ?
1037 log_unhandled("LWC0 %08x\n", code);
1041 // ??? what actually happens here?
1045 #ifdef DO_EXCEPTION_RESERVEDI
1047 psxException((1<<28) | (R3000E_RI << 2), branch, ®s_->CP0);
1052 psxCP2[_Funct_](®s_->CP2);
1058 psxCP2[f](®s_->CP2);
1062 #ifdef DO_EXCEPTION_RESERVEDI
1064 psxException((2<<28) | (R3000E_RI << 2), branch, ®s_->CP0);
1070 regs_->GPR.r[_Rt_] = MFC2(®s_->CP2, _Rd_);
1075 regs_->GPR.r[_Rt_] = regs_->CP2C.r[_Rd_];
1079 MTC2(®s_->CP2, regs_->GPR.r[_Rt_], _Rd_);
1083 CTC2(®s_->CP2, regs_->GPR.r[_Rt_], _Rd_);
1087 MTC2(®s_->CP2, psxMemRead32(_oB_), _Rt_);
1091 psxMemWrite32(_oB_, MFC2(®s_->CP2, _Rt_));
1096 gteLWC2(regs_, code);
1101 gteSWC2(regs_, code);
1105 // ??? what actually happens here?
1109 #ifdef DO_EXCEPTION_RESERVEDI
1111 psxException((3<<28) | (R3000E_RI << 2), branch, ®s_->CP0);
1116 // does this read memory?
1117 log_unhandled("LWCx %08x\n", code);
1121 // does this write something to memory?
1122 log_unhandled("SWCx %08x\n", code);
1125 static void psxBASIC(struct psxCP2Regs *cp2regs) {
1126 psxRegisters *regs_ = (void *)((char *)cp2regs - offsetof(psxRegisters, CP2));
1127 u32 code = regs_->code;
1128 assert(regs_ == &psxRegs);
1130 case 0x00: gteMFC2(regs_, code); break;
1131 case 0x02: gteCFC2(regs_, code); break;
1132 case 0x04: gteMTC2(regs_, code); break;
1133 case 0x06: gteCTC2(regs_, code); break;
1134 default: psxNULL_(); break;
1141 case 0x10: psxBLTZAL(regs_, code); break;
1142 case 0x11: psxBGEZAL(regs_, code); break;
1145 psxBGEZ(regs_, code);
1147 psxBLTZ(regs_, code);
1153 if (unlikely(!Config.HLE)) {
1154 psxSWCx(regs_, code);
1157 hleCode = code & 0x03ffffff;
1158 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
1159 psxSWCx(regs_, code);
1165 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code) = {
1166 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
1167 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
1168 psxCOP0 , psxCOP1d , psxCOP2, psxCOP3d, psxNULL, psxCOP1d,psxCOP2d,psxCOP3d,
1169 psxNULL , psxCOP1d , psxCOP2d,psxCOP3d, psxNULL, psxCOP1d,psxCOP2d,psxCOP3d,
1170 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxCOP3d,
1171 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxCOP1d,psxSWR , psxCOP3d,
1172 psxLWC0 , psxLWCx , gteLWC2, psxLWCx , psxNULL, psxCOP1d,psxCOP2d,psxCOP3d,
1173 psxSWCx , psxSWCx , gteSWC2, psxHLE , psxNULL, psxCOP1d,psxCOP2d,psxCOP3d,
1176 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code) = {
1177 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
1178 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
1179 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
1180 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
1181 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
1182 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
1183 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
1184 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
1187 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
1188 psxBASIC, gteRTPS , gteNULL , gteNULL, gteNULL, gteNULL , gteNCLIP, gteNULL, // 00
1189 gteNULL , gteNULL , gteNULL , gteNULL, gteOP , gteNULL , gteNULL , gteNULL, // 08
1190 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , gteNULL , gteNCDT , gteNULL, // 10
1191 gteNULL , gteNULL , gteNULL , gteNCCS, gteCC , gteNULL , gteNCS , gteNULL, // 18
1192 gteNCT , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 20
1193 gteSQR , gteDCPL , gteDPCT , gteNULL, gteNULL, gteAVSZ3, gteAVSZ4, gteNULL, // 28
1194 gteRTPT , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 30
1195 gteNULL , gteNULL , gteNULL , gteNULL, gteNULL, gteGPF , gteGPL , gteNCCT // 38
1198 ///////////////////////////////////////////
1200 static int intInit() {
1204 static void intReset() {
1207 static inline void execI_(u8 **memRLUT, psxRegisters *regs_) {
1210 regs_->code = fetch(regs_, memRLUT, pc);
1214 psxBSC[regs_->code >> 26](regs_, regs_->code);
1217 static void intExecute() {
1218 psxRegisters *regs_ = &psxRegs;
1219 u8 **memRLUT = psxMemRLUT;
1223 execI_(memRLUT, regs_);
1226 void intExecuteBlock(enum blockExecCaller caller) {
1227 psxRegisters *regs_ = &psxRegs;
1228 u8 **memRLUT = psxMemRLUT;
1232 execI_(memRLUT, regs_);
1235 static void intClear(u32 Addr, u32 Size) {
1238 static void intNotify(enum R3000Anote note, void *data) {
1240 case R3000ACPU_NOTIFY_AFTER_LOAD:
1241 setupCop(psxRegs.CP0.n.Status);
1243 case R3000ACPU_NOTIFY_CACHE_ISOLATED: // Armored Core?
1244 memset(&ICache, 0xff, sizeof(ICache));
1246 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
1247 case R3000ACPU_NOTIFY_BEFORE_SAVE:
1252 static void setupCop(u32 sr)
1254 if (sr & (1u << 29))
1255 psxBSC[17] = psxCOP1;
1257 psxBSC[17] = psxCOP1d;
1258 if (sr & (1u << 30))
1259 psxBSC[18] = Config.DisableStalls ? psxCOP2 : psxCOP2_stall;
1261 psxBSC[18] = psxCOP2d;
1262 if (sr & (1u << 31))
1263 psxBSC[19] = psxCOP3;
1265 psxBSC[19] = psxCOP3d;
1268 void intApplyConfig() {
1271 assert(psxBSC[50] == gteLWC2 || psxBSC[50] == gteLWC2_stall);
1272 assert(psxBSC[58] == gteSWC2 || psxBSC[58] == gteSWC2_stall);
1273 assert(psxSPC[16] == psxMFHI || psxSPC[16] == psxMFHI_stall);
1274 assert(psxSPC[18] == psxMFLO || psxSPC[18] == psxMFLO_stall);
1275 assert(psxSPC[24] == psxMULT || psxSPC[24] == psxMULT_stall);
1276 assert(psxSPC[25] == psxMULTU || psxSPC[25] == psxMULTU_stall);
1277 assert(psxSPC[26] == psxDIV || psxSPC[26] == psxDIV_stall);
1278 assert(psxSPC[27] == psxDIVU || psxSPC[27] == psxDIVU_stall);
1280 if (Config.DisableStalls) {
1281 psxBSC[18] = psxCOP2;
1282 psxBSC[50] = gteLWC2;
1283 psxBSC[58] = gteSWC2;
1284 psxSPC[16] = psxMFHI;
1285 psxSPC[18] = psxMFLO;
1286 psxSPC[24] = psxMULT;
1287 psxSPC[25] = psxMULTU;
1288 psxSPC[26] = psxDIV;
1289 psxSPC[27] = psxDIVU;
1291 psxBSC[18] = psxCOP2_stall;
1292 psxBSC[50] = gteLWC2_stall;
1293 psxBSC[58] = gteSWC2_stall;
1294 psxSPC[16] = psxMFHI_stall;
1295 psxSPC[18] = psxMFLO_stall;
1296 psxSPC[24] = psxMULT_stall;
1297 psxSPC[25] = psxMULTU_stall;
1298 psxSPC[26] = psxDIV_stall;
1299 psxSPC[27] = psxDIVU_stall;
1301 setupCop(psxRegs.CP0.n.Status);
1303 // dynarec may occasionally call the interpreter, in such a case the
1304 // cache won't work (cache only works right if all fetches go through it)
1305 if (!Config.icache_emulation || psxCpu != &psxInt)
1306 fetch = fetchNoCache;
1308 fetch = fetchICache;
1310 cycle_mult = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT
1311 ? Config.cycle_multiplier_override : Config.cycle_multiplier;
1312 psxRegs.subCycleStep = 0x10000 * cycle_mult / 100;
1315 static void intShutdown() {
1318 // single step (may do several ops in case of a branch)
1320 execI_(psxMemRLUT, &psxRegs);
1323 R3000Acpu psxInt = {