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));
49 void (*psxCP2[64])(struct psxCP2Regs *regs);
50 void (*psxCP2BSC[32])();
52 #ifdef ICACHE_EMULATION
55 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
57 static u8* ICache_Addr;
58 static u8* ICache_Code;
59 uint32_t *Read_ICache(uint32_t pc)
61 uint32_t pc_bank, pc_offset, pc_cache;
62 uint8_t *IAddr, *ICode;
65 pc_offset = pc & 0xffffff;
66 pc_cache = pc & 0xfff;
72 if (pc_bank == 0x80 || pc_bank == 0x00)
74 if (SWAP32(*(uint32_t *)(IAddr + pc_cache)) == pc_offset)
76 // Cache hit - return last opcode used
77 return (uint32_t *)(ICode + pc_cache);
81 // Cache miss - addresses don't match
82 // - default: 0xffffffff (not init)
84 // cache line is 4 bytes wide
89 *(uint32_t *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
90 *(uint32_t *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
91 *(uint32_t *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
92 *(uint32_t *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
95 pc_offset = pc & ~0xf;
96 *(uint32_t *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
97 *(uint32_t *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
98 *(uint32_t *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
99 *(uint32_t *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
104 TODO: Probably should add cached BIOS
107 return (uint32_t *)PSXM(pc);
111 static void delayRead(int reg, u32 bpc) {
114 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
116 rold = psxRegs.GPR.r[reg];
117 psxBSC[psxRegs.code >> 26](); // branch delay load
118 rnew = psxRegs.GPR.r[reg];
124 psxRegs.GPR.r[reg] = rold;
125 execI(); // first branch opcode
126 psxRegs.GPR.r[reg] = rnew;
131 static void delayWrite(int reg, u32 bpc) {
133 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
135 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
136 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
138 // no changes from normal behavior
140 psxBSC[psxRegs.code >> 26]();
148 static void delayReadWrite(int reg, u32 bpc) {
150 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
152 // the branch delay load is skipped
160 // this defines shall be used with the tmp
161 // of the next func (instead of _Funct_...)
162 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
163 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
164 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
165 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
166 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
168 int psxTestLoadDelay(int reg, u32 tmp) {
169 if (tmp == 0) return 0; // NOP
171 case 0x00: // SPECIAL
174 case 0x02: case 0x03: // SRL/SRA
175 if (_tRd_ == reg && _tRt_ == reg) return 1; else
176 if (_tRt_ == reg) return 2; else
177 if (_tRd_ == reg) return 3;
181 if (_tRs_ == reg) return 2;
184 if (_tRd_ == reg && _tRs_ == reg) return 1; else
185 if (_tRs_ == reg) return 2; else
186 if (_tRd_ == reg) return 3;
189 // SYSCALL/BREAK just a break;
191 case 0x20: case 0x21: case 0x22: case 0x23:
192 case 0x24: case 0x25: case 0x26: case 0x27:
193 case 0x2a: case 0x2b: // ADD/ADDU...
194 case 0x04: case 0x06: case 0x07: // SLLV...
195 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
196 if (_tRt_ == reg || _tRs_ == reg) return 2; else
197 if (_tRd_ == reg) return 3;
200 case 0x10: case 0x12: // MFHI/MFLO
201 if (_tRd_ == reg) return 3;
203 case 0x11: case 0x13: // MTHI/MTLO
204 if (_tRs_ == reg) return 2;
207 case 0x18: case 0x19:
208 case 0x1a: case 0x1b: // MULT/DIV...
209 if (_tRt_ == reg || _tRs_ == reg) return 2;
216 case 0x00: case 0x01:
217 case 0x10: case 0x11: // BLTZ/BGEZ...
218 // Xenogears - lbu v0 / beq v0
219 // - no load delay (fixes battle loading)
222 if (_tRs_ == reg) return 2;
227 // J would be just a break;
229 if (31 == reg) return 3;
232 case 0x04: case 0x05: // BEQ/BNE
233 // Xenogears - lbu v0 / beq v0
234 // - no load delay (fixes battle loading)
237 if (_tRs_ == reg || _tRt_ == reg) return 2;
240 case 0x06: case 0x07: // BLEZ/BGTZ
241 // Xenogears - lbu v0 / beq v0
242 // - no load delay (fixes battle loading)
245 if (_tRs_ == reg) return 2;
248 case 0x08: case 0x09: case 0x0a: case 0x0b:
249 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
250 if (_tRt_ == reg && _tRs_ == reg) return 1; else
251 if (_tRs_ == reg) return 2; else
252 if (_tRt_ == reg) return 3;
256 if (_tRt_ == reg) return 3;
262 if (_tRt_ == reg) return 3;
265 if (_tRt_ == reg) return 3;
268 if (_tRt_ == reg) return 2;
271 if (_tRt_ == reg) return 2;
282 if (_tRt_ == reg) return 3;
285 if (_tRt_ == reg) return 3;
288 if (_tRt_ == reg) return 2;
291 if (_tRt_ == reg) return 2;
299 case 0x22: case 0x26: // LWL/LWR
300 if (_tRt_ == reg) return 3; else
301 if (_tRs_ == reg) return 2;
304 case 0x20: case 0x21: case 0x23:
305 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
306 if (_tRt_ == reg && _tRs_ == reg) return 1; else
307 if (_tRs_ == reg) return 2; else
308 if (_tRt_ == reg) return 3;
311 case 0x28: case 0x29: case 0x2a:
312 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
313 if (_tRt_ == reg || _tRs_ == reg) return 2;
316 case 0x32: case 0x3a: // LWC2/SWC2
317 if (_tRs_ == reg) return 2;
324 void psxDelayTest(int reg, u32 bpc) {
328 #ifdef ICACHE_EMULATION
329 if (Config.icache_emulation)
331 code = Read_ICache(psxRegs.pc);
336 code = (u32 *)PSXM(psxRegs.pc);
339 tmp = ((code == NULL) ? 0 : SWAP32(*code));
342 switch (psxTestLoadDelay(reg, tmp)) {
344 delayReadWrite(reg, bpc); return;
346 delayRead(reg, bpc); return;
348 delayWrite(reg, bpc); return;
350 psxBSC[psxRegs.code >> 26]();
358 static u32 psxBranchNoDelay(void) {
362 #ifdef ICACHE_EMULATION
363 if (Config.icache_emulation)
365 code = Read_ICache(psxRegs.pc);
370 code = (u32 *)PSXM(psxRegs.pc);
372 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
374 case 0x00: // SPECIAL
380 if (_Rd_) { _SetLink(_Rd_); }
388 return _BranchTarget_;
391 if (_i32(_rRs_) >= 0)
392 return _BranchTarget_;
395 if (_i32(_rRs_) < 0) {
397 return _BranchTarget_;
401 if (_i32(_rRs_) >= 0) {
403 return _BranchTarget_;
414 if (_i32(_rRs_) == _i32(_rRt_))
415 return _BranchTarget_;
418 if (_i32(_rRs_) != _i32(_rRt_))
419 return _BranchTarget_;
422 if (_i32(_rRs_) <= 0)
423 return _BranchTarget_;
427 return _BranchTarget_;
434 static int psxDelayBranchExec(u32 tar) {
439 psxRegs.cycle += BIAS;
444 static int psxDelayBranchTest(u32 tar1) {
445 u32 tar2, tmp1, tmp2;
447 tar2 = psxBranchNoDelay();
454 * Branch in delay slot:
455 * - execute 1 instruction at tar1
456 * - jump to tar2 (target of branch in delay slot; this branch
457 * has no normal delay slot, instruction at tar1 was fetched instead)
460 tmp1 = psxBranchNoDelay();
461 if (tmp1 == (u32)-1) {
462 return psxDelayBranchExec(tar2);
465 psxRegs.cycle += BIAS;
468 * Got a branch at tar1:
469 * - execute 1 instruction at tar2
470 * - jump to target of that branch (tmp1)
473 tmp2 = psxBranchNoDelay();
474 if (tmp2 == (u32)-1) {
475 return psxDelayBranchExec(tmp1);
478 psxRegs.cycle += BIAS;
481 * Got a branch at tar2:
482 * - execute 1 instruction at tmp1
483 * - jump to target of that branch (tmp2)
486 return psxDelayBranchExec(tmp2);
489 static void doBranch(u32 tar) {
493 branch2 = branch = 1;
496 // check for branch in delay slot
497 if (psxDelayBranchTest(tar))
500 #ifdef ICACHE_EMULATION
501 if (Config.icache_emulation)
503 code = Read_ICache(psxRegs.pc);
508 code = (u32 *)PSXM(psxRegs.pc);
510 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
515 psxRegs.cycle += BIAS;
517 // check for load delay
518 tmp = psxRegs.code >> 26;
524 psxDelayTest(_Rt_, branchPC);
534 psxDelayTest(_Rt_, branchPC);
541 psxDelayTest(_Rt_, branchPC);
544 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
545 psxDelayTest(_Rt_, branchPC);
551 psxBSC[psxRegs.code >> 26]();
554 psxRegs.pc = branchPC;
559 /*********************************************************
560 * Arithmetic with immediate operand *
561 * Format: OP rt, rs, immediate *
562 *********************************************************/
563 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
564 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
565 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
566 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
567 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
568 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
569 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
571 /*********************************************************
572 * Register arithmetic *
573 * Format: OP rd, rs, rt *
574 *********************************************************/
575 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
576 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
577 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
578 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
579 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
580 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
581 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
582 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
583 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
584 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
586 /*********************************************************
587 * Register mult/div & Register trap logic *
588 * Format: OP rs, rt *
589 *********************************************************/
592 _i32(_rHi_) = _i32(_rRs_);
593 if (_i32(_rRs_) & 0x80000000) {
596 _i32(_rLo_) = 0xFFFFFFFF;
599 * Notaz said that this was "not needed" for ARM platforms and could slow it down so let's disable for ARM.
600 * This fixes a crash issue that can happen when running Amidog's CPU test.
601 * (It still stays stuck to a black screen but at least it doesn't crash anymore)
603 #if !defined(__arm__) && !defined(__aarch64__)
604 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
605 _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);
710 /*********************************************************
711 * Register branch logic *
712 * Format: OP rs, rt, offset *
713 *********************************************************/
714 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
716 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
717 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
719 /*********************************************************
721 * Format: OP target *
722 *********************************************************/
723 void psxJ() { doBranch(_JumpTarget_); }
724 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
726 /*********************************************************
728 * Format: OP rs, rd *
729 *********************************************************/
731 doBranch(_rRs_ & ~3);
736 u32 temp = _u32(_rRs_);
737 if (_Rd_) { _SetLink(_Rd_); }
741 /*********************************************************
742 * Load and store for GPR *
743 * Format: OP rt, offset(base) *
744 *********************************************************/
746 #define _oB_ (_u32(_rRs_) + _Imm_)
750 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
758 _u32(_rRt_) = psxMemRead8(_oB_);
766 _i32(_rRt_) = (short)psxMemRead16(_oB_);
774 _u32(_rRt_) = psxMemRead16(_oB_);
782 _u32(_rRt_) = psxMemRead32(_oB_);
788 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
789 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
793 u32 shift = addr & 3;
794 u32 mem = psxMemRead32(addr & ~3);
797 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
798 ( mem << LWL_SHIFT[shift]);
801 Mem = 1234. Reg = abcd
803 0 4bcd (mem << 24) | (reg & 0x00ffffff)
804 1 34cd (mem << 16) | (reg & 0x0000ffff)
805 2 234d (mem << 8) | (reg & 0x000000ff)
806 3 1234 (mem ) | (reg & 0x00000000)
810 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
811 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
815 u32 shift = addr & 3;
816 u32 mem = psxMemRead32(addr & ~3);
819 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
820 ( mem >> LWR_SHIFT[shift]);
823 Mem = 1234. Reg = abcd
825 0 1234 (mem ) | (reg & 0x00000000)
826 1 a123 (mem >> 8) | (reg & 0xff000000)
827 2 ab12 (mem >> 16) | (reg & 0xffff0000)
828 3 abc1 (mem >> 24) | (reg & 0xffffff00)
832 void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
833 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
834 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
836 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
837 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
841 u32 shift = addr & 3;
842 u32 mem = psxMemRead32(addr & ~3);
844 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
845 ( mem & SWL_MASK[shift]) );
847 Mem = 1234. Reg = abcd
849 0 123a (reg >> 24) | (mem & 0xffffff00)
850 1 12ab (reg >> 16) | (mem & 0xffff0000)
851 2 1abc (reg >> 8) | (mem & 0xff000000)
852 3 abcd (reg ) | (mem & 0x00000000)
856 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
857 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
861 u32 shift = addr & 3;
862 u32 mem = psxMemRead32(addr & ~3);
864 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
865 ( mem & SWR_MASK[shift]) );
868 Mem = 1234. Reg = abcd
870 0 abcd (reg ) | (mem & 0x00000000)
871 1 bcd4 (reg << 8) | (mem & 0x000000ff)
872 2 cd34 (reg << 16) | (mem & 0x0000ffff)
873 3 d234 (reg << 24) | (mem & 0x00ffffff)
877 /*********************************************************
878 * Moves between GPR and COPx *
879 * Format: OP rt, fs *
880 *********************************************************/
881 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
882 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
884 void psxTestSWInts() {
885 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
886 psxRegs.CP0.n.Status & 0x1) {
887 psxRegs.CP0.n.Cause &= ~0x7c;
888 psxException(psxRegs.CP0.n.Cause, branch);
892 void MTC0(int reg, u32 val) {
893 // SysPrintf("MTC0 %d: %x\n", reg, val);
896 psxRegs.CP0.r[12] = val;
901 psxRegs.CP0.n.Cause &= ~0x0300;
902 psxRegs.CP0.n.Cause |= val & 0x0300;
907 psxRegs.CP0.r[reg] = val;
912 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
913 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
915 /*********************************************************
916 * Unknow instruction (would generate an exception) *
918 *********************************************************/
921 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
938 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
941 void psxBASIC(struct psxCP2Regs *regs) {
946 // psxHLEt[psxRegs.code & 0xffff]();
947 // psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
948 uint32_t hleCode = psxRegs.code & 0x03ffffff;
949 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
956 void (*psxBSC[64])() = {
957 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
958 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
959 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
960 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
961 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
962 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
963 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
964 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
968 void (*psxSPC[64])() = {
969 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
970 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
971 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
972 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
973 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
974 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
975 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
976 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
979 void (*psxREG[32])() = {
980 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
981 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
982 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
983 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
986 void (*psxCP0[32])() = {
987 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
988 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
989 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
990 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
993 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
994 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
995 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
996 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
997 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
998 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
999 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
1000 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
1001 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
1004 void (*psxCP2BSC[32])() = {
1005 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
1006 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1007 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1008 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1012 ///////////////////////////////////////////
1014 static int intInit() {
1015 #ifdef ICACHE_EMULATION
1016 /* We have to allocate the icache memory even if
1017 * the user has not enabled it as otherwise it can cause issues.
1021 ICache_Addr = malloc(0x1000);
1030 ICache_Code = malloc(0x1000);
1036 memset(ICache_Addr, 0xff, 0x1000);
1037 memset(ICache_Code, 0xff, 0x1000);
1042 static void intReset() {
1043 #ifdef ICACHE_EMULATION
1044 memset(ICache_Addr, 0xff, 0x1000);
1045 memset(ICache_Code, 0xff, 0x1000);
1055 void intExecuteBlock() {
1057 while (!branch2) execI();
1060 static void intClear(u32 Addr, u32 Size) {
1063 void intNotify (int note, void *data) {
1064 #ifdef ICACHE_EMULATION
1065 /* Gameblabla - Only clear the icache if it's isolated */
1066 if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED)
1068 memset(ICache_Addr, 0xff, 0x1000);
1069 memset(ICache_Code, 0xff, 0x1000);
1074 static void intShutdown() {
1075 #ifdef ICACHE_EMULATION
1090 // interpreter execution
1093 #ifdef ICACHE_EMULATION
1094 if (Config.icache_emulation)
1096 code = Read_ICache(psxRegs.pc);
1101 code = (u32 *)PSXM(psxRegs.pc);
1103 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
1107 if (Config.Debug) ProcessDebug();
1110 psxRegs.cycle += BIAS;
1112 psxBSC[psxRegs.code >> 26]();
1115 R3000Acpu psxInt = {
1121 #ifdef ICACHE_EMULATION