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"
32 #define ProcessDebug()
34 static int branch = 0;
35 static int branch2 = 0;
38 // These macros are used to assemble the repassembler functions
41 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
47 #define INT_ATTR __attribute__((regparm(2)))
52 #define INVALID_PTR NULL
56 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code);
57 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code);
59 static u32 INT_ATTR fetchNoCache(u8 **memRLUT, u32 pc)
61 u8 *base = memRLUT[pc >> 16];
62 if (base == INVALID_PTR)
64 u32 *code = (u32 *)(base + (pc & 0xfffc));
70 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
72 static struct cache_entry {
77 static u32 INT_ATTR fetchICache(u8 **memRLUT, u32 pc)
82 // this is not how the hardware works but whatever
83 struct cache_entry *entry = &ICache[(pc & 0xff0) >> 4];
85 if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag)
87 const u8 *base = memRLUT[pc >> 16];
89 if (base == INVALID_PTR)
91 code = (u32 *)(base + (pc & 0xfff0));
94 // treat as 4 words, although other configurations are said to be possible
97 case 0x00: entry->data[0] = SWAP32(code[0]);
98 case 0x04: entry->data[1] = SWAP32(code[1]);
99 case 0x08: entry->data[2] = SWAP32(code[2]);
100 case 0x0c: entry->data[3] = SWAP32(code[3]);
103 return entry->data[(pc & 0x0f) >> 2];
106 return fetchNoCache(memRLUT, pc);
109 static u32 (INT_ATTR *fetch)(u8 **memRLUT, u32 pc) = fetchNoCache;
111 // Make the timing events trigger faster as we are currently assuming everything
112 // takes one cycle, which is not the case on real hardware.
113 // FIXME: count cache misses, memory latencies, stalls to get rid of this
114 static inline void addCycle(void)
116 assert(psxRegs.subCycleStep >= 0x10000);
117 psxRegs.subCycle += psxRegs.subCycleStep;
118 psxRegs.cycle += psxRegs.subCycle >> 16;
119 psxRegs.subCycle &= 0xffff;
122 static void delayRead(int reg, u32 bpc) {
125 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
127 rold = psxRegs.GPR.r[reg];
128 psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code); // branch delay load
129 rnew = psxRegs.GPR.r[reg];
135 psxRegs.GPR.r[reg] = rold;
136 execI(); // first branch opcode
137 psxRegs.GPR.r[reg] = rnew;
142 static void delayWrite(int reg, u32 bpc) {
144 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
146 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
147 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
149 // no changes from normal behavior
151 psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
159 static void delayReadWrite(int reg, u32 bpc) {
161 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
163 // the branch delay load is skipped
171 /**** R3000A Instruction Macros ****/
172 #define _PC_ regs_->pc // The next PC to be executed
174 #define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register
175 #define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register
176 #define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register
177 #define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register
178 #define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register
179 #define _fSa_(code) ((code >> 6) & 0x1F) // The sa part of the instruction register
180 #define _fIm_(code) ((u16)code) // The immediate part of the instruction register
181 #define _fTarget_(code) (code & 0x03ffffff) // The target part of the instruction register
183 #define _fImm_(code) ((s16)code) // sign-extended immediate
184 #define _fImmU_(code) (code&0xffff) // zero-extended immediate
186 #define _Op_ _fOp_(code)
187 #define _Funct_ _fFunct_(code)
188 #define _Rd_ _fRd_(code)
189 #define _Rt_ _fRt_(code)
190 #define _Rs_ _fRs_(code)
191 #define _Sa_ _fSa_(code)
192 #define _Im_ _fIm_(code)
193 #define _Target_ _fTarget_(code)
195 #define _Imm_ _fImm_(code)
196 #define _ImmU_ _fImmU_(code)
198 #define _rRs_ regs_->GPR.r[_Rs_] // Rs register
199 #define _rRt_ regs_->GPR.r[_Rt_] // Rt register
200 #define _rRd_ regs_->GPR.r[_Rd_] // Rd register
201 #define _rSa_ regs_->GPR.r[_Sa_] // Sa register
202 #define _rFs_ regs_->CP0.r[_Rd_] // Fs register
204 #define _rHi_ regs_->GPR.n.hi // The HI register
205 #define _rLo_ regs_->GPR.n.lo // The LO register
207 #define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction
208 #define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction
210 #define _SetLink(x) regs_->GPR.r[x] = _PC_ + 4; // Sets the return address in the link register
213 static inline INT_ATTR void name(psxRegisters *regs_, u32 code)
215 // this defines shall be used with the tmp
216 // of the next func (instead of _Funct_...)
217 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
218 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
219 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
220 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
221 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
223 #define _i32(x) (s32)(x)
224 #define _u32(x) (u32)(x)
226 static int psxTestLoadDelay(int reg, u32 tmp) {
227 if (tmp == 0) return 0; // NOP
229 case 0x00: // SPECIAL
232 case 0x02: case 0x03: // SRL/SRA
233 if (_tRd_ == reg && _tRt_ == reg) return 1; else
234 if (_tRt_ == reg) return 2; else
235 if (_tRd_ == reg) return 3;
239 if (_tRs_ == reg) return 2;
242 if (_tRd_ == reg && _tRs_ == reg) return 1; else
243 if (_tRs_ == reg) return 2; else
244 if (_tRd_ == reg) return 3;
247 // SYSCALL/BREAK just a break;
249 case 0x20: case 0x21: case 0x22: case 0x23:
250 case 0x24: case 0x25: case 0x26: case 0x27:
251 case 0x2a: case 0x2b: // ADD/ADDU...
252 case 0x04: case 0x06: case 0x07: // SLLV...
253 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
254 if (_tRt_ == reg || _tRs_ == reg) return 2; else
255 if (_tRd_ == reg) return 3;
258 case 0x10: case 0x12: // MFHI/MFLO
259 if (_tRd_ == reg) return 3;
261 case 0x11: case 0x13: // MTHI/MTLO
262 if (_tRs_ == reg) return 2;
265 case 0x18: case 0x19:
266 case 0x1a: case 0x1b: // MULT/DIV...
267 if (_tRt_ == reg || _tRs_ == reg) return 2;
274 case 0x00: case 0x01:
275 case 0x10: case 0x11: // BLTZ/BGEZ...
276 // Xenogears - lbu v0 / beq v0
277 // - no load delay (fixes battle loading)
280 if (_tRs_ == reg) return 2;
285 // J would be just a break;
287 if (31 == reg) return 3;
290 case 0x04: case 0x05: // BEQ/BNE
291 // Xenogears - lbu v0 / beq v0
292 // - no load delay (fixes battle loading)
295 if (_tRs_ == reg || _tRt_ == reg) return 2;
298 case 0x06: case 0x07: // BLEZ/BGTZ
299 // Xenogears - lbu v0 / beq v0
300 // - no load delay (fixes battle loading)
303 if (_tRs_ == reg) return 2;
306 case 0x08: case 0x09: case 0x0a: case 0x0b:
307 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
308 if (_tRt_ == reg && _tRs_ == reg) return 1; else
309 if (_tRs_ == reg) return 2; else
310 if (_tRt_ == reg) return 3;
314 if (_tRt_ == reg) return 3;
320 if (_tRt_ == reg) return 3;
323 if (_tRt_ == reg) return 3;
326 if (_tRt_ == reg) return 2;
329 if (_tRt_ == reg) return 2;
340 if (_tRt_ == reg) return 3;
343 if (_tRt_ == reg) return 3;
346 if (_tRt_ == reg) return 2;
349 if (_tRt_ == reg) return 2;
357 case 0x22: case 0x26: // LWL/LWR
358 if (_tRt_ == reg) return 3; else
359 if (_tRs_ == reg) return 2;
362 case 0x20: case 0x21: case 0x23:
363 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
364 if (_tRt_ == reg && _tRs_ == reg) return 1; else
365 if (_tRs_ == reg) return 2; else
366 if (_tRt_ == reg) return 3;
369 case 0x28: case 0x29: case 0x2a:
370 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
371 if (_tRt_ == reg || _tRs_ == reg) return 2;
374 case 0x32: case 0x3a: // LWC2/SWC2
375 if (_tRs_ == reg) return 2;
382 static void psxDelayTest(int reg, u32 bpc) {
383 u32 tmp = fetch(psxMemRLUT, bpc);
386 switch (psxTestLoadDelay(reg, tmp)) {
388 delayReadWrite(reg, bpc); return;
390 delayRead(reg, bpc); return;
392 delayWrite(reg, bpc); return;
394 psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
402 static u32 psxBranchNoDelay(psxRegisters *regs_) {
405 regs_->code = code = fetch(psxMemRLUT, 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);
487 * Branch in delay slot:
488 * - execute 1 instruction at tar1
489 * - jump to tar2 (target of branch in delay slot; this branch
490 * has no normal delay slot, instruction at tar1 was fetched instead)
493 tmp1 = psxBranchNoDelay(&psxRegs);
494 if (tmp1 == (u32)-1) {
495 return psxDelayBranchExec(tar2);
501 * Got a branch at tar1:
502 * - execute 1 instruction at tar2
503 * - jump to target of that branch (tmp1)
506 tmp2 = psxBranchNoDelay(&psxRegs);
507 if (tmp2 == (u32)-1) {
508 return psxDelayBranchExec(tmp1);
514 * Got a branch at tar2:
515 * - execute 1 instruction at tmp1
516 * - jump to target of that branch (tmp2)
519 return psxDelayBranchExec(tmp2);
522 static void doBranch(u32 tar) {
525 branch2 = branch = 1;
528 // check for branch in delay slot
529 if (psxDelayBranchTest(tar))
532 psxRegs.code = code = fetch(psxMemRLUT, psxRegs.pc);
539 // check for load delay
540 tmp = psxRegs.code >> 26;
546 psxDelayTest(_Rt_, branchPC);
556 psxDelayTest(_Rt_, branchPC);
563 psxDelayTest(_Rt_, branchPC);
566 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
567 psxDelayTest(_Rt_, branchPC);
573 psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
576 psxRegs.pc = branchPC;
581 /*********************************************************
582 * Arithmetic with immediate operand *
583 * Format: OP rt, rs, immediate *
584 *********************************************************/
585 OP(psxADDI) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
586 OP(psxADDIU) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
587 OP(psxANDI) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
588 OP(psxORI) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
589 OP(psxXORI) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
590 OP(psxSLTI) { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
591 OP(psxSLTIU) { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
593 /*********************************************************
594 * Register arithmetic *
595 * Format: OP rd, rs, rt *
596 *********************************************************/
597 OP(psxADD) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
598 OP(psxADDU) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
599 OP(psxSUB) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
600 OP(psxSUBU) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
601 OP(psxAND) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
602 OP(psxOR) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
603 OP(psxXOR) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
604 OP(psxNOR) { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
605 OP(psxSLT) { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
606 OP(psxSLTU) { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
608 /*********************************************************
609 * Register mult/div & Register trap logic *
610 * Format: OP rs, rt *
611 *********************************************************/
615 if (_rRs_ & 0x80000000) {
621 #if !defined(__arm__) && !defined(__aarch64__)
622 else if (_rRs_ == 0x80000000 && _rRt_ == 0xFFFFFFFF) {
628 _rLo_ = _i32(_rRs_) / _i32(_rRt_);
629 _rHi_ = _i32(_rRs_) % _i32(_rRt_);
634 regs_->muldivBusyCycle = regs_->cycle + 37;
640 _rLo_ = _rRs_ / _rRt_;
641 _rHi_ = _rRs_ % _rRt_;
650 regs_->muldivBusyCycle = regs_->cycle + 37;
651 psxDIVU(regs_, code);
655 u64 res = (s64)_i32(_rRs_) * _i32(_rRt_);
657 regs_->GPR.n.lo = (u32)res;
658 regs_->GPR.n.hi = (u32)(res >> 32);
662 // approximate, but maybe good enough
664 u32 lz = __builtin_clz(((rs ^ ((s32)rs >> 21)) | 1));
665 u32 c = 7 + (2 - (lz / 11)) * 4;
666 regs_->muldivBusyCycle = regs_->cycle + c;
667 psxMULT(regs_, code);
671 u64 res = (u64)_u32(_rRs_) * _u32(_rRt_);
673 regs_->GPR.n.lo = (u32)(res & 0xffffffff);
674 regs_->GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
678 // approximate, but maybe good enough
679 u32 lz = __builtin_clz(_rRs_ | 1);
680 u32 c = 7 + (2 - (lz / 11)) * 4;
681 regs_->muldivBusyCycle = regs_->cycle + c;
682 psxMULTU(regs_, code);
685 /*********************************************************
686 * Register branch logic *
687 * Format: OP rs, offset *
688 *********************************************************/
689 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
690 #define RepZBranchLinki32(op) { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } }
692 OP(psxBGEZ) { RepZBranchi32(>=) } // Branch if Rs >= 0
693 OP(psxBGEZAL) { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
694 OP(psxBGTZ) { RepZBranchi32(>) } // Branch if Rs > 0
695 OP(psxBLEZ) { RepZBranchi32(<=) } // Branch if Rs <= 0
696 OP(psxBLTZ) { RepZBranchi32(<) } // Branch if Rs < 0
697 OP(psxBLTZAL) { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
699 /*********************************************************
700 * Shift arithmetic with constant shift *
701 * Format: OP rd, rt, sa *
702 *********************************************************/
703 OP(psxSLL) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
704 OP(psxSRA) { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
705 OP(psxSRL) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
707 /*********************************************************
708 * Shift arithmetic with variant register shift *
709 * Format: OP rd, rt, rs *
710 *********************************************************/
711 OP(psxSLLV) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs
712 OP(psxSRAV) { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic)
713 OP(psxSRLV) { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical)
715 /*********************************************************
716 * Load higher 16 bits of the first word in GPR with imm *
717 * Format: OP rt, immediate *
718 *********************************************************/
719 OP(psxLUI) { if (!_Rt_) return; _rRt_ = code << 16; } // Upper halfword of Rt = Im
721 /*********************************************************
722 * Move from HI/LO to GPR *
724 *********************************************************/
725 OP(psxMFHI) { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
726 OP(psxMFLO) { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
728 static void mflohiCheckStall(psxRegisters *regs_)
730 u32 left = regs_->muldivBusyCycle - regs_->cycle;
732 //printf("muldiv stall %u\n", left);
733 regs_->cycle = regs_->muldivBusyCycle;
737 OP(psxMFHI_stall) { mflohiCheckStall(regs_); psxMFHI(regs_, code); }
738 OP(psxMFLO_stall) { mflohiCheckStall(regs_); psxMFLO(regs_, code); }
740 /*********************************************************
741 * Move to GPR to HI/LO & Register jump *
743 *********************************************************/
744 OP(psxMTHI) { _rHi_ = _rRs_; } // Hi = Rs
745 OP(psxMTLO) { _rLo_ = _rRs_; } // Lo = Rs
747 /*********************************************************
748 * Special purpose instructions *
750 *********************************************************/
753 psxException(0x24, branch, ®s_->CP0);
758 psxException(0x20, branch, ®s_->CP0);
761 static inline void psxTestSWInts(psxRegisters *regs_) {
762 if (regs_->CP0.n.Cause & regs_->CP0.n.Status & 0x0300 &&
763 regs_->CP0.n.Status & 0x1) {
764 regs_->CP0.n.Cause &= ~0x7c;
765 psxException(regs_->CP0.n.Cause, branch, ®s_->CP0);
770 // SysPrintf("psxRFE\n");
771 regs_->CP0.n.Status = (regs_->CP0.n.Status & 0xfffffff0) |
772 ((regs_->CP0.n.Status & 0x3c) >> 2);
773 psxTestSWInts(regs_);
776 /*********************************************************
777 * Register branch logic *
778 * Format: OP rs, rt, offset *
779 *********************************************************/
780 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
782 OP(psxBEQ) { RepBranchi32(==) } // Branch if Rs == Rt
783 OP(psxBNE) { RepBranchi32(!=) } // Branch if Rs != Rt
785 /*********************************************************
787 * Format: OP target *
788 *********************************************************/
789 OP(psxJ) { doBranch(_JumpTarget_); }
790 OP(psxJAL) { _SetLink(31); doBranch(_JumpTarget_); }
792 /*********************************************************
794 * Format: OP rs, rd *
795 *********************************************************/
797 doBranch(_rRs_ & ~3);
802 u32 temp = _u32(_rRs_);
803 if (_Rd_) { _SetLink(_Rd_); }
807 /*********************************************************
808 * Load and store for GPR *
809 * Format: OP rt, offset(base) *
810 *********************************************************/
812 #define _oB_ (regs_->GPR.r[_Rs_] + _Imm_)
814 OP(psxLB) { u32 v = (s8)psxMemRead8(_oB_); if (_Rt_) _rRt_ = v; }
815 OP(psxLBU) { u32 v = psxMemRead8(_oB_); if (_Rt_) _rRt_ = v; }
816 OP(psxLH) { u32 v = (s16)psxMemRead16(_oB_); if (_Rt_) _rRt_ = v; }
817 OP(psxLHU) { u32 v = psxMemRead16(_oB_); if (_Rt_) _rRt_ = v; }
818 OP(psxLW) { u32 v = psxMemRead32(_oB_); if (_Rt_) _rRt_ = v; }
821 static const u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
822 static const u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
824 u32 shift = addr & 3;
825 u32 mem = psxMemRead32(addr & ~3);
828 _rRt_ = (_u32(_rRt_) & LWL_MASK[shift]) | (mem << LWL_SHIFT[shift]);
831 Mem = 1234. Reg = abcd
833 0 4bcd (mem << 24) | (reg & 0x00ffffff)
834 1 34cd (mem << 16) | (reg & 0x0000ffff)
835 2 234d (mem << 8) | (reg & 0x000000ff)
836 3 1234 (mem ) | (reg & 0x00000000)
841 static const u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
842 static const u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
844 u32 shift = addr & 3;
845 u32 mem = psxMemRead32(addr & ~3);
848 _rRt_ = (_u32(_rRt_) & LWR_MASK[shift]) | (mem >> LWR_SHIFT[shift]);
851 Mem = 1234. Reg = abcd
853 0 1234 (mem ) | (reg & 0x00000000)
854 1 a123 (mem >> 8) | (reg & 0xff000000)
855 2 ab12 (mem >> 16) | (reg & 0xffff0000)
856 3 abc1 (mem >> 24) | (reg & 0xffffff00)
860 OP(psxSB) { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
861 OP(psxSH) { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
862 OP(psxSW) { psxMemWrite32(_oB_, _rRt_); }
865 static const u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
866 static const u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
868 u32 shift = addr & 3;
869 u32 mem = psxMemRead32(addr & ~3);
871 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
872 ( mem & SWL_MASK[shift]) );
874 Mem = 1234. Reg = abcd
876 0 123a (reg >> 24) | (mem & 0xffffff00)
877 1 12ab (reg >> 16) | (mem & 0xffff0000)
878 2 1abc (reg >> 8) | (mem & 0xff000000)
879 3 abcd (reg ) | (mem & 0x00000000)
884 static const u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
885 static const u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
887 u32 shift = addr & 3;
888 u32 mem = psxMemRead32(addr & ~3);
890 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
891 ( mem & SWR_MASK[shift]) );
894 Mem = 1234. Reg = abcd
896 0 abcd (reg ) | (mem & 0x00000000)
897 1 bcd4 (reg << 8) | (mem & 0x000000ff)
898 2 cd34 (reg << 16) | (mem & 0x0000ffff)
899 3 d234 (reg << 24) | (mem & 0x00ffffff)
903 /*********************************************************
904 * Moves between GPR and COPx *
905 * Format: OP rt, fs *
906 *********************************************************/
907 OP(psxMFC0) { if (!_Rt_) return; _rRt_ = _rFs_; }
908 OP(psxCFC0) { if (!_Rt_) return; _rRt_ = _rFs_; }
910 void MTC0(psxRegisters *regs_, int reg, u32 val) {
911 // SysPrintf("MTC0 %d: %x\n", reg, val);
914 if ((regs_->CP0.n.Status ^ val) & (1 << 16))
915 psxMemOnIsolate((val >> 16) & 1);
916 regs_->CP0.n.Status = val;
917 psxTestSWInts(regs_);
921 regs_->CP0.n.Cause &= ~0x0300;
922 regs_->CP0.n.Cause |= val & 0x0300;
923 psxTestSWInts(regs_);
927 regs_->CP0.r[reg] = val;
932 OP(psxMTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); }
933 OP(psxCTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); }
935 /*********************************************************
936 * Unknow instruction (would generate an exception) *
938 *********************************************************/
939 static inline void psxNULL_(void) {
941 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
945 OP(psxNULL) { psxNULL_(); }
946 void gteNULL(struct psxCP2Regs *regs) { psxNULL_(); }
949 psxSPC[_Funct_](regs_, code);
954 case 0x00: psxMFC0(regs_, code); break;
955 case 0x02: psxCFC0(regs_, code); break;
956 case 0x04: psxMTC0(regs_, code); break;
957 case 0x06: psxCTC0(regs_, code); break;
958 case 0x10: psxRFE(regs_, code); break;
959 default: psxNULL_(); break;
964 psxCP2[_Funct_](®s_->CP2);
970 psxCP2[f](®s_->CP2);
975 regs_->GPR.r[_Rt_] = MFC2(®s_->CP2, _Rd_);
980 regs_->GPR.r[_Rt_] = regs_->CP2C.r[_Rd_];
984 MTC2(®s_->CP2, regs_->GPR.r[_Rt_], _Rd_);
988 CTC2(®s_->CP2, regs_->GPR.r[_Rt_], _Rd_);
992 MTC2(®s_->CP2, psxMemRead32(_oB_), _Rt_);
996 psxMemWrite32(_oB_, MFC2(®s_->CP2, _Rt_));
1001 gteLWC2(regs_, code);
1006 gteSWC2(regs_, code);
1009 static void psxBASIC(struct psxCP2Regs *cp2regs) {
1010 psxRegisters *regs_ = (void *)((char *)cp2regs - offsetof(psxRegisters, CP2));
1011 u32 code = regs_->code;
1012 assert(regs_ == &psxRegs);
1014 case 0x00: gteMFC2(regs_, code); break;
1015 case 0x02: gteCFC2(regs_, code); break;
1016 case 0x04: gteMTC2(regs_, code); break;
1017 case 0x06: gteCTC2(regs_, code); break;
1018 default: psxNULL_(); break;
1024 case 0x00: psxBLTZ(regs_, code); break;
1025 case 0x01: psxBGEZ(regs_, code); break;
1026 case 0x10: psxBLTZAL(regs_, code); break;
1027 case 0x11: psxBGEZAL(regs_, code); break;
1028 default: psxNULL_(); break;
1033 uint32_t hleCode = code & 0x03ffffff;
1034 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
1041 static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code) = {
1042 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
1043 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
1044 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1045 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1046 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
1047 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
1048 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1049 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
1052 static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code) = {
1053 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
1054 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
1055 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
1056 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
1057 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
1058 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
1059 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
1060 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
1063 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
1064 psxBASIC, gteRTPS , gteNULL , gteNULL, gteNULL, gteNULL , gteNCLIP, gteNULL, // 00
1065 gteNULL , gteNULL , gteNULL , gteNULL, gteOP , gteNULL , gteNULL , gteNULL, // 08
1066 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , gteNULL , gteNCDT , gteNULL, // 10
1067 gteNULL , gteNULL , gteNULL , gteNCCS, gteCC , gteNULL , gteNCS , gteNULL, // 18
1068 gteNCT , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 20
1069 gteSQR , gteDCPL , gteDPCT , gteNULL, gteNULL, gteAVSZ3, gteAVSZ4, gteNULL, // 28
1070 gteRTPT , gteNULL , gteNULL , gteNULL, gteNULL, gteNULL , gteNULL , gteNULL, // 30
1071 gteNULL , gteNULL , gteNULL , gteNULL, gteNULL, gteGPF , gteGPL , gteNCCT // 38
1074 ///////////////////////////////////////////
1076 static int intInit() {
1080 static void intReset() {
1083 static inline void execI_(u8 **memRLUT, psxRegisters *regs_) {
1084 regs_->code = fetch(memRLUT, regs_->pc);
1088 if (Config.Debug) ProcessDebug();
1093 psxBSC[regs_->code >> 26](regs_, regs_->code);
1096 static void intExecute() {
1097 psxRegisters *regs_ = &psxRegs;
1098 u8 **memRLUT = psxMemRLUT;
1102 execI_(memRLUT, regs_);
1105 void intExecuteBlock() {
1106 psxRegisters *regs_ = &psxRegs;
1107 u8 **memRLUT = psxMemRLUT;
1111 execI_(memRLUT, regs_);
1114 static void intClear(u32 Addr, u32 Size) {
1117 static void intNotify(enum R3000Anote note, void *data) {
1119 case R3000ACPU_NOTIFY_CACHE_ISOLATED: // Armored Core?
1120 case R3000ACPU_NOTIFY_AFTER_LOAD:
1121 memset(&ICache, 0xff, sizeof(ICache));
1123 case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
1124 case R3000ACPU_NOTIFY_BEFORE_SAVE:
1129 void intApplyConfig() {
1132 assert(psxBSC[18] == psxCOP2 || psxBSC[18] == psxCOP2_stall);
1133 assert(psxBSC[50] == gteLWC2 || psxBSC[50] == gteLWC2_stall);
1134 assert(psxBSC[58] == gteSWC2 || psxBSC[58] == gteSWC2_stall);
1135 assert(psxSPC[16] == psxMFHI || psxSPC[16] == psxMFHI_stall);
1136 assert(psxSPC[18] == psxMFLO || psxSPC[18] == psxMFLO_stall);
1137 assert(psxSPC[24] == psxMULT || psxSPC[24] == psxMULT_stall);
1138 assert(psxSPC[25] == psxMULTU || psxSPC[25] == psxMULTU_stall);
1139 assert(psxSPC[26] == psxDIV || psxSPC[26] == psxDIV_stall);
1140 assert(psxSPC[27] == psxDIVU || psxSPC[27] == psxDIVU_stall);
1142 if (Config.DisableStalls) {
1143 psxBSC[18] = psxCOP2;
1144 psxBSC[50] = gteLWC2;
1145 psxBSC[58] = gteSWC2;
1146 psxSPC[16] = psxMFHI;
1147 psxSPC[18] = psxMFLO;
1148 psxSPC[24] = psxMULT;
1149 psxSPC[25] = psxMULTU;
1150 psxSPC[26] = psxDIV;
1151 psxSPC[27] = psxDIVU;
1153 psxBSC[18] = psxCOP2_stall;
1154 psxBSC[50] = gteLWC2_stall;
1155 psxBSC[58] = gteSWC2_stall;
1156 psxSPC[16] = psxMFHI_stall;
1157 psxSPC[18] = psxMFLO_stall;
1158 psxSPC[24] = psxMULT_stall;
1159 psxSPC[25] = psxMULTU_stall;
1160 psxSPC[26] = psxDIV_stall;
1161 psxSPC[27] = psxDIVU_stall;
1164 // dynarec may occasionally call the interpreter, in such a case the
1165 // cache won't work (cache only works right if all fetches go through it)
1166 if (!Config.icache_emulation || psxCpu != &psxInt)
1167 fetch = fetchNoCache;
1169 fetch = fetchICache;
1171 cycle_mult = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT
1172 ? Config.cycle_multiplier_override : Config.cycle_multiplier;
1173 psxRegs.subCycleStep = 0x10000 * cycle_mult / 100;
1176 static void intShutdown() {
1179 // single step (may do several ops in case of a branch)
1181 execI_(psxMemRLUT, &psxRegs);
1184 R3000Acpu psxInt = {