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"
30 static int branch = 0;
31 static int branch2 = 0;
34 // These macros are used to assemble the repassembler functions
37 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
45 void StartDebugger() {}
46 void ProcessDebug() {}
47 void StopDebugger() {}
57 void (*psxCP2[64])(struct psxCP2Regs *regs);
58 void (*psxCP2BSC[32])();
60 #ifdef ICACHE_EMULATION
63 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
65 static u8* ICache_Addr;
66 static u8* ICache_Code;
67 uint32_t *Read_ICache(uint32_t pc)
69 uint32_t pc_bank, pc_offset, pc_cache;
70 uint8_t *IAddr, *ICode;
73 pc_offset = pc & 0xffffff;
74 pc_cache = pc & 0xfff;
80 if (pc_bank == 0x80 || pc_bank == 0x00)
82 if (SWAP32(*(uint32_t *)(IAddr + pc_cache)) == pc_offset)
84 // Cache hit - return last opcode used
85 return (uint32_t *)(ICode + pc_cache);
89 // Cache miss - addresses don't match
90 // - default: 0xffffffff (not init)
92 // cache line is 4 bytes wide
97 *(uint32_t *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
98 *(uint32_t *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
99 *(uint32_t *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
100 *(uint32_t *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
103 pc_offset = pc & ~0xf;
104 *(uint32_t *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
105 *(uint32_t *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
106 *(uint32_t *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
107 *(uint32_t *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
112 TODO: Probably should add cached BIOS
115 return (uint32_t *)PSXM(pc);
119 static void delayRead(int reg, u32 bpc) {
122 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
124 rold = psxRegs.GPR.r[reg];
125 psxBSC[psxRegs.code >> 26](); // branch delay load
126 rnew = psxRegs.GPR.r[reg];
132 psxRegs.GPR.r[reg] = rold;
133 execI(); // first branch opcode
134 psxRegs.GPR.r[reg] = rnew;
139 static void delayWrite(int reg, u32 bpc) {
141 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
143 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
144 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
146 // no changes from normal behavior
148 psxBSC[psxRegs.code >> 26]();
156 static void delayReadWrite(int reg, u32 bpc) {
158 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
160 // the branch delay load is skipped
168 // this defines shall be used with the tmp
169 // of the next func (instead of _Funct_...)
170 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
171 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
172 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
173 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
174 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
176 int psxTestLoadDelay(int reg, u32 tmp) {
177 if (tmp == 0) return 0; // NOP
179 case 0x00: // SPECIAL
182 case 0x02: case 0x03: // SRL/SRA
183 if (_tRd_ == reg && _tRt_ == reg) return 1; else
184 if (_tRt_ == reg) return 2; else
185 if (_tRd_ == reg) return 3;
189 if (_tRs_ == reg) return 2;
192 if (_tRd_ == reg && _tRs_ == reg) return 1; else
193 if (_tRs_ == reg) return 2; else
194 if (_tRd_ == reg) return 3;
197 // SYSCALL/BREAK just a break;
199 case 0x20: case 0x21: case 0x22: case 0x23:
200 case 0x24: case 0x25: case 0x26: case 0x27:
201 case 0x2a: case 0x2b: // ADD/ADDU...
202 case 0x04: case 0x06: case 0x07: // SLLV...
203 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
204 if (_tRt_ == reg || _tRs_ == reg) return 2; else
205 if (_tRd_ == reg) return 3;
208 case 0x10: case 0x12: // MFHI/MFLO
209 if (_tRd_ == reg) return 3;
211 case 0x11: case 0x13: // MTHI/MTLO
212 if (_tRs_ == reg) return 2;
215 case 0x18: case 0x19:
216 case 0x1a: case 0x1b: // MULT/DIV...
217 if (_tRt_ == reg || _tRs_ == reg) return 2;
224 case 0x00: case 0x01:
225 case 0x10: case 0x11: // BLTZ/BGEZ...
226 // Xenogears - lbu v0 / beq v0
227 // - no load delay (fixes battle loading)
230 if (_tRs_ == reg) return 2;
235 // J would be just a break;
237 if (31 == reg) return 3;
240 case 0x04: case 0x05: // BEQ/BNE
241 // Xenogears - lbu v0 / beq v0
242 // - no load delay (fixes battle loading)
245 if (_tRs_ == reg || _tRt_ == reg) return 2;
248 case 0x06: case 0x07: // BLEZ/BGTZ
249 // Xenogears - lbu v0 / beq v0
250 // - no load delay (fixes battle loading)
253 if (_tRs_ == reg) return 2;
256 case 0x08: case 0x09: case 0x0a: case 0x0b:
257 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
258 if (_tRt_ == reg && _tRs_ == reg) return 1; else
259 if (_tRs_ == reg) return 2; else
260 if (_tRt_ == reg) return 3;
264 if (_tRt_ == reg) return 3;
270 if (_tRt_ == reg) return 3;
273 if (_tRt_ == reg) return 3;
276 if (_tRt_ == reg) return 2;
279 if (_tRt_ == reg) return 2;
290 if (_tRt_ == reg) return 3;
293 if (_tRt_ == reg) return 3;
296 if (_tRt_ == reg) return 2;
299 if (_tRt_ == reg) return 2;
307 case 0x22: case 0x26: // LWL/LWR
308 if (_tRt_ == reg) return 3; else
309 if (_tRs_ == reg) return 2;
312 case 0x20: case 0x21: case 0x23:
313 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
314 if (_tRt_ == reg && _tRs_ == reg) return 1; else
315 if (_tRs_ == reg) return 2; else
316 if (_tRt_ == reg) return 3;
319 case 0x28: case 0x29: case 0x2a:
320 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
321 if (_tRt_ == reg || _tRs_ == reg) return 2;
324 case 0x32: case 0x3a: // LWC2/SWC2
325 if (_tRs_ == reg) return 2;
332 void psxDelayTest(int reg, u32 bpc) {
336 #ifdef ICACHE_EMULATION
337 if (Config.icache_emulation)
339 code = Read_ICache(psxRegs.pc);
344 code = (u32 *)PSXM(psxRegs.pc);
346 tmp = ((code == NULL) ? 0 : SWAP32(*code));
349 switch (psxTestLoadDelay(reg, tmp)) {
351 delayReadWrite(reg, bpc); return;
353 delayRead(reg, bpc); return;
355 delayWrite(reg, bpc); return;
357 psxBSC[psxRegs.code >> 26]();
365 static u32 psxBranchNoDelay(void) {
369 #ifdef ICACHE_EMULATION
370 if (Config.icache_emulation)
372 code = Read_ICache(psxRegs.pc);
377 code = (u32 *)PSXM(psxRegs.pc);
379 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
381 case 0x00: // SPECIAL
387 if (_Rd_) { _SetLink(_Rd_); }
395 return _BranchTarget_;
398 if (_i32(_rRs_) >= 0)
399 return _BranchTarget_;
402 if (_i32(_rRs_) < 0) {
404 return _BranchTarget_;
408 if (_i32(_rRs_) >= 0) {
410 return _BranchTarget_;
421 if (_i32(_rRs_) == _i32(_rRt_))
422 return _BranchTarget_;
425 if (_i32(_rRs_) != _i32(_rRt_))
426 return _BranchTarget_;
429 if (_i32(_rRs_) <= 0)
430 return _BranchTarget_;
434 return _BranchTarget_;
441 static int psxDelayBranchExec(u32 tar) {
446 psxRegs.cycle += BIAS;
451 static int psxDelayBranchTest(u32 tar1) {
452 u32 tar2, tmp1, tmp2;
454 tar2 = psxBranchNoDelay();
461 * Branch in delay slot:
462 * - execute 1 instruction at tar1
463 * - jump to tar2 (target of branch in delay slot; this branch
464 * has no normal delay slot, instruction at tar1 was fetched instead)
467 tmp1 = psxBranchNoDelay();
468 if (tmp1 == (u32)-1) {
469 return psxDelayBranchExec(tar2);
472 psxRegs.cycle += BIAS;
475 * Got a branch at tar1:
476 * - execute 1 instruction at tar2
477 * - jump to target of that branch (tmp1)
480 tmp2 = psxBranchNoDelay();
481 if (tmp2 == (u32)-1) {
482 return psxDelayBranchExec(tmp1);
485 psxRegs.cycle += BIAS;
488 * Got a branch at tar2:
489 * - execute 1 instruction at tmp1
490 * - jump to target of that branch (tmp2)
493 return psxDelayBranchExec(tmp2);
496 static void doBranch(u32 tar) {
500 branch2 = branch = 1;
503 // check for branch in delay slot
504 if (psxDelayBranchTest(tar))
507 #ifdef ICACHE_EMULATION
508 if (Config.icache_emulation)
510 code = Read_ICache(psxRegs.pc);
515 code = (u32 *)PSXM(psxRegs.pc);
517 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
522 psxRegs.cycle += BIAS;
524 // check for load delay
525 tmp = psxRegs.code >> 26;
531 psxDelayTest(_Rt_, branchPC);
541 psxDelayTest(_Rt_, branchPC);
548 psxDelayTest(_Rt_, branchPC);
551 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
552 psxDelayTest(_Rt_, branchPC);
558 psxBSC[psxRegs.code >> 26]();
561 psxRegs.pc = branchPC;
566 /*********************************************************
567 * Arithmetic with immediate operand *
568 * Format: OP rt, rs, immediate *
569 *********************************************************/
570 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
571 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
572 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
573 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
574 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
575 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
576 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
578 /*********************************************************
579 * Register arithmetic *
580 * Format: OP rd, rs, rt *
581 *********************************************************/
582 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
583 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
584 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
585 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
586 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
587 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
588 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
589 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
590 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
591 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
593 /*********************************************************
594 * Register mult/div & Register trap logic *
595 * Format: OP rs, rt *
596 *********************************************************/
599 _i32(_rHi_) = _i32(_rRs_);
600 if (_i32(_rRs_) & 0x80000000) {
603 _i32(_rLo_) = 0xFFFFFFFF;
605 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
606 _i32(_rLo_) = 0x80000000;
609 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
610 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
616 _rLo_ = _rRs_ / _rRt_;
617 _rHi_ = _rRs_ % _rRt_;
620 _i32(_rLo_) = 0xffffffff;
621 _i32(_rHi_) = _i32(_rRs_);
626 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
628 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
629 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
633 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
635 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
636 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
639 /*********************************************************
640 * Register branch logic *
641 * Format: OP rs, offset *
642 *********************************************************/
643 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
644 #define RepZBranchLinki32(op) { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } }
646 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
647 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
648 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
649 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
650 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
651 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
653 /*********************************************************
654 * Shift arithmetic with constant shift *
655 * Format: OP rd, rt, sa *
656 *********************************************************/
657 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
658 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
659 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
661 /*********************************************************
662 * Shift arithmetic with variant register shift *
663 * Format: OP rd, rt, rs *
664 *********************************************************/
665 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs
666 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic)
667 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical)
669 /*********************************************************
670 * Load higher 16 bits of the first word in GPR with imm *
671 * Format: OP rt, immediate *
672 *********************************************************/
673 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
675 /*********************************************************
676 * Move from HI/LO to GPR *
678 *********************************************************/
679 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
680 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
682 /*********************************************************
683 * Move to GPR to HI/LO & Register jump *
685 *********************************************************/
686 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
687 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
689 /*********************************************************
690 * Special purpose instructions *
692 *********************************************************/
695 psxException(0x24, branch);
700 psxException(0x20, branch);
704 // SysPrintf("psxRFE\n");
705 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
706 ((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(_u32(_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);
938 PSXCPU_LOG("Attempted to use an invalid floating point instruction. Ignored.\n");
943 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
948 PSXCPU_LOG("Attempted to access COP3. Ignored\n");
952 void psxBASIC(struct psxCP2Regs *regs) {
957 // psxHLEt[psxRegs.code & 0xffff]();
958 // psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
959 uint32_t hleCode = psxRegs.code & 0x03ffffff;
960 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
967 void (*psxBSC[64])() = {
968 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
969 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
970 psxCOP0 , psxCOP1 , psxCOP2, psxCOP3 , psxNULL, psxNULL, psxNULL, psxNULL,
971 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
972 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
973 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
974 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
975 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
979 void (*psxSPC[64])() = {
980 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
981 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
982 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
983 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
984 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
985 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
986 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
987 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
990 void (*psxREG[32])() = {
991 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
992 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
993 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
994 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
997 void (*psxCP0[32])() = {
998 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
999 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1000 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1001 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1004 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
1005 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
1006 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
1007 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
1008 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
1009 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
1010 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
1011 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
1012 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
1015 void (*psxCP2BSC[32])() = {
1016 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
1017 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1018 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1019 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1023 ///////////////////////////////////////////
1025 static int intInit() {
1026 #ifdef ICACHE_EMULATION
1029 ICache_Addr = malloc(0x1000);
1038 ICache_Code = malloc(0x1000);
1044 memset(ICache_Addr, 0xff, 0x1000);
1045 memset(ICache_Code, 0xff, 0x1000);
1050 static void intReset() {
1051 #ifdef ICACHE_EMULATION
1052 memset(ICache_Addr, 0xff, 0x1000);
1053 memset(ICache_Code, 0xff, 0x1000);
1063 void intExecuteBlock() {
1065 while (!branch2) execI();
1068 static void intClear(u32 Addr, u32 Size) {
1071 void intNotify (int note, void *data) {
1072 #ifdef ICACHE_EMULATION
1073 /* Gameblabla - Only clear the icache if it's isolated */
1074 if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED)
1076 memset(ICache_Addr, 0xff, 0x1000);
1077 memset(ICache_Code, 0xff, 0x1000);
1082 static void intShutdown() {
1083 #ifdef ICACHE_EMULATION
1098 // interpreter execution
1100 #ifndef ICACHE_EMULATION
1101 u32 *code = (u32 *)PSXM(psxRegs.pc);
1103 u32 *code = Read_ICache(psxRegs.pc);
1106 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
1110 if (Config.Debug) ProcessDebug();
1113 psxRegs.cycle += BIAS;
1115 psxBSC[psxRegs.code >> 26]();
1118 R3000Acpu psxInt = {
1124 #ifdef ICACHE_EMULATION