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"
29 #include "psxinterpreter.h"
31 static int branch = 0;
32 static int branch2 = 0;
35 // These macros are used to assemble the repassembler functions
38 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
48 void (*psxCP2[64])(struct psxCP2Regs *regs);
49 void (*psxCP2BSC[32])();
51 #ifdef ICACHE_EMULATION
54 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
56 static u8* ICache_Addr;
57 static u8* ICache_Code;
58 uint32_t *Read_ICache(uint32_t pc)
60 uint32_t pc_bank, pc_offset, pc_cache;
61 uint8_t *IAddr, *ICode;
64 pc_offset = pc & 0xffffff;
65 pc_cache = pc & 0xfff;
71 if (pc_bank == 0x80 || pc_bank == 0x00)
73 if (SWAP32(*(uint32_t *)(IAddr + pc_cache)) == pc_offset)
75 // Cache hit - return last opcode used
76 return (uint32_t *)(ICode + pc_cache);
80 // Cache miss - addresses don't match
81 // - default: 0xffffffff (not init)
83 // cache line is 4 bytes wide
88 *(uint32_t *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
89 *(uint32_t *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
90 *(uint32_t *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
91 *(uint32_t *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
94 pc_offset = pc & ~0xf;
95 *(uint32_t *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
96 *(uint32_t *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
97 *(uint32_t *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
98 *(uint32_t *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
103 TODO: Probably should add cached BIOS
106 return (uint32_t *)PSXM(pc);
110 static void delayRead(int reg, u32 bpc) {
113 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
115 rold = psxRegs.GPR.r[reg];
116 psxBSC[psxRegs.code >> 26](); // branch delay load
117 rnew = psxRegs.GPR.r[reg];
123 psxRegs.GPR.r[reg] = rold;
124 execI(); // first branch opcode
125 psxRegs.GPR.r[reg] = rnew;
130 static void delayWrite(int reg, u32 bpc) {
132 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
134 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
135 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
137 // no changes from normal behavior
139 psxBSC[psxRegs.code >> 26]();
147 static void delayReadWrite(int reg, u32 bpc) {
149 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
151 // the branch delay load is skipped
159 // this defines shall be used with the tmp
160 // of the next func (instead of _Funct_...)
161 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
162 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
163 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
164 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
165 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
167 int psxTestLoadDelay(int reg, u32 tmp) {
168 if (tmp == 0) return 0; // NOP
170 case 0x00: // SPECIAL
173 case 0x02: case 0x03: // SRL/SRA
174 if (_tRd_ == reg && _tRt_ == reg) return 1; else
175 if (_tRt_ == reg) return 2; else
176 if (_tRd_ == reg) return 3;
180 if (_tRs_ == reg) return 2;
183 if (_tRd_ == reg && _tRs_ == reg) return 1; else
184 if (_tRs_ == reg) return 2; else
185 if (_tRd_ == reg) return 3;
188 // SYSCALL/BREAK just a break;
190 case 0x20: case 0x21: case 0x22: case 0x23:
191 case 0x24: case 0x25: case 0x26: case 0x27:
192 case 0x2a: case 0x2b: // ADD/ADDU...
193 case 0x04: case 0x06: case 0x07: // SLLV...
194 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
195 if (_tRt_ == reg || _tRs_ == reg) return 2; else
196 if (_tRd_ == reg) return 3;
199 case 0x10: case 0x12: // MFHI/MFLO
200 if (_tRd_ == reg) return 3;
202 case 0x11: case 0x13: // MTHI/MTLO
203 if (_tRs_ == reg) return 2;
206 case 0x18: case 0x19:
207 case 0x1a: case 0x1b: // MULT/DIV...
208 if (_tRt_ == reg || _tRs_ == reg) return 2;
215 case 0x00: case 0x01:
216 case 0x10: case 0x11: // BLTZ/BGEZ...
217 // Xenogears - lbu v0 / beq v0
218 // - no load delay (fixes battle loading)
221 if (_tRs_ == reg) return 2;
226 // J would be just a break;
228 if (31 == reg) return 3;
231 case 0x04: case 0x05: // BEQ/BNE
232 // Xenogears - lbu v0 / beq v0
233 // - no load delay (fixes battle loading)
236 if (_tRs_ == reg || _tRt_ == reg) return 2;
239 case 0x06: case 0x07: // BLEZ/BGTZ
240 // Xenogears - lbu v0 / beq v0
241 // - no load delay (fixes battle loading)
244 if (_tRs_ == reg) return 2;
247 case 0x08: case 0x09: case 0x0a: case 0x0b:
248 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
249 if (_tRt_ == reg && _tRs_ == reg) return 1; else
250 if (_tRs_ == reg) return 2; else
251 if (_tRt_ == reg) return 3;
255 if (_tRt_ == reg) return 3;
261 if (_tRt_ == reg) return 3;
264 if (_tRt_ == reg) return 3;
267 if (_tRt_ == reg) return 2;
270 if (_tRt_ == reg) return 2;
281 if (_tRt_ == reg) return 3;
284 if (_tRt_ == reg) return 3;
287 if (_tRt_ == reg) return 2;
290 if (_tRt_ == reg) return 2;
298 case 0x22: case 0x26: // LWL/LWR
299 if (_tRt_ == reg) return 3; else
300 if (_tRs_ == reg) return 2;
303 case 0x20: case 0x21: case 0x23:
304 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
305 if (_tRt_ == reg && _tRs_ == reg) return 1; else
306 if (_tRs_ == reg) return 2; else
307 if (_tRt_ == reg) return 3;
310 case 0x28: case 0x29: case 0x2a:
311 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
312 if (_tRt_ == reg || _tRs_ == reg) return 2;
315 case 0x32: case 0x3a: // LWC2/SWC2
316 if (_tRs_ == reg) return 2;
323 void psxDelayTest(int reg, u32 bpc) {
327 #ifdef ICACHE_EMULATION
328 if (Config.icache_emulation)
330 code = Read_ICache(psxRegs.pc);
335 code = (u32 *)PSXM(psxRegs.pc);
338 tmp = ((code == NULL) ? 0 : SWAP32(*code));
341 switch (psxTestLoadDelay(reg, tmp)) {
343 delayReadWrite(reg, bpc); return;
345 delayRead(reg, bpc); return;
347 delayWrite(reg, bpc); return;
349 psxBSC[psxRegs.code >> 26]();
357 static u32 psxBranchNoDelay(void) {
361 #ifdef ICACHE_EMULATION
362 if (Config.icache_emulation)
364 code = Read_ICache(psxRegs.pc);
369 code = (u32 *)PSXM(psxRegs.pc);
371 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
373 case 0x00: // SPECIAL
379 if (_Rd_) { _SetLink(_Rd_); }
387 return _BranchTarget_;
390 if (_i32(_rRs_) >= 0)
391 return _BranchTarget_;
394 if (_i32(_rRs_) < 0) {
396 return _BranchTarget_;
400 if (_i32(_rRs_) >= 0) {
402 return _BranchTarget_;
413 if (_i32(_rRs_) == _i32(_rRt_))
414 return _BranchTarget_;
417 if (_i32(_rRs_) != _i32(_rRt_))
418 return _BranchTarget_;
421 if (_i32(_rRs_) <= 0)
422 return _BranchTarget_;
426 return _BranchTarget_;
433 static int psxDelayBranchExec(u32 tar) {
438 psxRegs.cycle += BIAS;
443 static int psxDelayBranchTest(u32 tar1) {
444 u32 tar2, tmp1, tmp2;
446 tar2 = psxBranchNoDelay();
453 * Branch in delay slot:
454 * - execute 1 instruction at tar1
455 * - jump to tar2 (target of branch in delay slot; this branch
456 * has no normal delay slot, instruction at tar1 was fetched instead)
459 tmp1 = psxBranchNoDelay();
460 if (tmp1 == (u32)-1) {
461 return psxDelayBranchExec(tar2);
464 psxRegs.cycle += BIAS;
467 * Got a branch at tar1:
468 * - execute 1 instruction at tar2
469 * - jump to target of that branch (tmp1)
472 tmp2 = psxBranchNoDelay();
473 if (tmp2 == (u32)-1) {
474 return psxDelayBranchExec(tmp1);
477 psxRegs.cycle += BIAS;
480 * Got a branch at tar2:
481 * - execute 1 instruction at tmp1
482 * - jump to target of that branch (tmp2)
485 return psxDelayBranchExec(tmp2);
488 static void doBranch(u32 tar) {
492 branch2 = branch = 1;
495 // check for branch in delay slot
496 if (psxDelayBranchTest(tar))
499 #ifdef ICACHE_EMULATION
500 if (Config.icache_emulation)
502 code = Read_ICache(psxRegs.pc);
507 code = (u32 *)PSXM(psxRegs.pc);
509 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
514 psxRegs.cycle += BIAS;
516 // check for load delay
517 tmp = psxRegs.code >> 26;
523 psxDelayTest(_Rt_, branchPC);
533 psxDelayTest(_Rt_, branchPC);
540 psxDelayTest(_Rt_, branchPC);
543 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
544 psxDelayTest(_Rt_, branchPC);
550 psxBSC[psxRegs.code >> 26]();
553 psxRegs.pc = branchPC;
558 /*********************************************************
559 * Arithmetic with immediate operand *
560 * Format: OP rt, rs, immediate *
561 *********************************************************/
562 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
563 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
564 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
565 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
566 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
567 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
568 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
570 /*********************************************************
571 * Register arithmetic *
572 * Format: OP rd, rs, rt *
573 *********************************************************/
574 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
575 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
576 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
577 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
578 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
579 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
580 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
581 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
582 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
583 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
585 /*********************************************************
586 * Register mult/div & Register trap logic *
587 * Format: OP rs, rt *
588 *********************************************************/
591 _i32(_rHi_) = _i32(_rRs_);
592 if (_i32(_rRs_) & 0x80000000) {
595 _i32(_rLo_) = 0xFFFFFFFF;
598 * Notaz said that this was "not needed" for ARM platforms and could slow it down so let's disable for ARM.
599 * This fixes a crash issue that can happen when running Amidog's CPU test.
600 * (It still stays stuck to a black screen but at least it doesn't crash anymore)
602 #if !defined(__arm__) && !defined(__aarch64__)
603 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
604 _i32(_rLo_) = 0x80000000;
608 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
609 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
615 _rLo_ = _rRs_ / _rRt_;
616 _rHi_ = _rRs_ % _rRt_;
619 _i32(_rLo_) = 0xffffffff;
620 _i32(_rHi_) = _i32(_rRs_);
625 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
627 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
628 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
632 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
634 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
635 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
638 /*********************************************************
639 * Register branch logic *
640 * Format: OP rs, offset *
641 *********************************************************/
642 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
643 #define RepZBranchLinki32(op) { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } }
645 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
646 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
647 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
648 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
649 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
650 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
652 /*********************************************************
653 * Shift arithmetic with constant shift *
654 * Format: OP rd, rt, sa *
655 *********************************************************/
656 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
657 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
658 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
660 /*********************************************************
661 * Shift arithmetic with variant register shift *
662 * Format: OP rd, rt, rs *
663 *********************************************************/
664 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs
665 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic)
666 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical)
668 /*********************************************************
669 * Load higher 16 bits of the first word in GPR with imm *
670 * Format: OP rt, immediate *
671 *********************************************************/
672 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
674 /*********************************************************
675 * Move from HI/LO to GPR *
677 *********************************************************/
678 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
679 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
681 /*********************************************************
682 * Move to GPR to HI/LO & Register jump *
684 *********************************************************/
685 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
686 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
688 /*********************************************************
689 * Special purpose instructions *
691 *********************************************************/
694 psxException(0x24, branch);
699 psxException(0x20, branch);
703 // SysPrintf("psxRFE\n");
704 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
705 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
709 /*********************************************************
710 * Register branch logic *
711 * Format: OP rs, rt, offset *
712 *********************************************************/
713 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
715 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
716 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
718 /*********************************************************
720 * Format: OP target *
721 *********************************************************/
722 void psxJ() { doBranch(_JumpTarget_); }
723 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
725 /*********************************************************
727 * Format: OP rs, rd *
728 *********************************************************/
730 doBranch(_rRs_ & ~3);
735 u32 temp = _u32(_rRs_);
736 if (_Rd_) { _SetLink(_Rd_); }
740 /*********************************************************
741 * Load and store for GPR *
742 * Format: OP rt, offset(base) *
743 *********************************************************/
745 #define _oB_ (_u32(_rRs_) + _Imm_)
749 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
757 _u32(_rRt_) = psxMemRead8(_oB_);
765 _i32(_rRt_) = (short)psxMemRead16(_oB_);
773 _u32(_rRt_) = psxMemRead16(_oB_);
781 _u32(_rRt_) = psxMemRead32(_oB_);
787 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
788 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
792 u32 shift = addr & 3;
793 u32 mem = psxMemRead32(addr & ~3);
796 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
797 ( mem << LWL_SHIFT[shift]);
800 Mem = 1234. Reg = abcd
802 0 4bcd (mem << 24) | (reg & 0x00ffffff)
803 1 34cd (mem << 16) | (reg & 0x0000ffff)
804 2 234d (mem << 8) | (reg & 0x000000ff)
805 3 1234 (mem ) | (reg & 0x00000000)
809 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
810 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
814 u32 shift = addr & 3;
815 u32 mem = psxMemRead32(addr & ~3);
818 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
819 ( mem >> LWR_SHIFT[shift]);
822 Mem = 1234. Reg = abcd
824 0 1234 (mem ) | (reg & 0x00000000)
825 1 a123 (mem >> 8) | (reg & 0xff000000)
826 2 ab12 (mem >> 16) | (reg & 0xffff0000)
827 3 abc1 (mem >> 24) | (reg & 0xffffff00)
831 void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
832 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
833 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
835 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
836 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
840 u32 shift = addr & 3;
841 u32 mem = psxMemRead32(addr & ~3);
843 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
844 ( mem & SWL_MASK[shift]) );
846 Mem = 1234. Reg = abcd
848 0 123a (reg >> 24) | (mem & 0xffffff00)
849 1 12ab (reg >> 16) | (mem & 0xffff0000)
850 2 1abc (reg >> 8) | (mem & 0xff000000)
851 3 abcd (reg ) | (mem & 0x00000000)
855 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
856 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
860 u32 shift = addr & 3;
861 u32 mem = psxMemRead32(addr & ~3);
863 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
864 ( mem & SWR_MASK[shift]) );
867 Mem = 1234. Reg = abcd
869 0 abcd (reg ) | (mem & 0x00000000)
870 1 bcd4 (reg << 8) | (mem & 0x000000ff)
871 2 cd34 (reg << 16) | (mem & 0x0000ffff)
872 3 d234 (reg << 24) | (mem & 0x00ffffff)
876 /*********************************************************
877 * Moves between GPR and COPx *
878 * Format: OP rt, fs *
879 *********************************************************/
880 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
881 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
883 void psxTestSWInts() {
884 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
885 psxRegs.CP0.n.Status & 0x1) {
886 psxRegs.CP0.n.Cause &= ~0x7c;
887 psxException(psxRegs.CP0.n.Cause, branch);
891 void MTC0(int reg, u32 val) {
892 // SysPrintf("MTC0 %d: %x\n", reg, val);
895 psxRegs.CP0.r[12] = val;
900 psxRegs.CP0.n.Cause &= ~0x0300;
901 psxRegs.CP0.n.Cause |= val & 0x0300;
906 psxRegs.CP0.r[reg] = val;
911 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
912 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
914 /*********************************************************
915 * Unknow instruction (would generate an exception) *
917 *********************************************************/
920 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
937 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
940 void psxBASIC(struct psxCP2Regs *regs) {
945 // psxHLEt[psxRegs.code & 0xffff]();
946 // psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
947 uint32_t hleCode = psxRegs.code & 0x03ffffff;
948 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
955 void (*psxBSC[64])() = {
956 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
957 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
958 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
959 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
960 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
961 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
962 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
963 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
967 void (*psxSPC[64])() = {
968 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
969 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
970 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
971 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
972 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
973 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
974 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
975 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
978 void (*psxREG[32])() = {
979 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
980 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
981 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
982 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
985 void (*psxCP0[32])() = {
986 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
987 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
988 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
989 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
992 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
993 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
994 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
995 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
996 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
997 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
998 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
999 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
1000 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
1003 void (*psxCP2BSC[32])() = {
1004 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
1005 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1006 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1007 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1011 ///////////////////////////////////////////
1013 static int intInit() {
1014 #ifdef ICACHE_EMULATION
1015 /* We have to allocate the icache memory even if
1016 * the user has not enabled it as otherwise it can cause issues.
1020 ICache_Addr = malloc(0x1000);
1029 ICache_Code = malloc(0x1000);
1035 memset(ICache_Addr, 0xff, 0x1000);
1036 memset(ICache_Code, 0xff, 0x1000);
1041 static void intReset() {
1042 #ifdef ICACHE_EMULATION
1043 memset(ICache_Addr, 0xff, 0x1000);
1044 memset(ICache_Code, 0xff, 0x1000);
1054 void intExecuteBlock() {
1056 while (!branch2) execI();
1059 static void intClear(u32 Addr, u32 Size) {
1062 void intNotify (int note, void *data) {
1063 #ifdef ICACHE_EMULATION
1064 /* Gameblabla - Only clear the icache if it's isolated */
1065 if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED)
1067 memset(ICache_Addr, 0xff, 0x1000);
1068 memset(ICache_Code, 0xff, 0x1000);
1073 static void intShutdown() {
1074 #ifdef ICACHE_EMULATION
1089 // interpreter execution
1092 #ifdef ICACHE_EMULATION
1093 if (Config.icache_emulation)
1095 code = Read_ICache(psxRegs.pc);
1100 code = (u32 *)PSXM(psxRegs.pc);
1102 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
1106 if (Config.Debug) ProcessDebug();
1109 psxRegs.cycle += BIAS;
1111 psxBSC[psxRegs.code >> 26]();
1114 R3000Acpu psxInt = {
1120 #ifdef ICACHE_EMULATION