X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxinterpreter.c;h=f9e13bf280c47ed623ef897cfaead88a5594ee6d;hb=c018117d41a845b3f4341d32e1d1b59b5598701a;hp=6c19f061debfc1a7dbe81da99c345785cde6c23c;hpb=606e46a1ec09c89ecfb7261b5f58860dfe6973f8;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 6c19f061..f9e13bf2 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -57,6 +57,65 @@ void (*psxCP0[32])(); void (*psxCP2[64])(struct psxCP2Regs *regs); void (*psxCP2BSC[32])(); +#ifdef ICACHE_EMULATION +/* +Formula One 2001 : +Use old CPU cache code when the RAM location is updated with new code (affects in-game racing) +*/ +static u8* ICache_Addr; +static u8* ICache_Code; +uint32_t *Read_ICache(uint32_t pc) +{ + uint32_t pc_bank, pc_offset, pc_cache; + uint8_t *IAddr, *ICode; + + pc_bank = pc >> 24; + pc_offset = pc & 0xffffff; + pc_cache = pc & 0xfff; + + IAddr = ICache_Addr; + ICode = ICache_Code; + + // cached - RAM + if (pc_bank == 0x80 || pc_bank == 0x00) + { + if (SWAP32(*(uint32_t *)(IAddr + pc_cache)) == pc_offset) + { + // Cache hit - return last opcode used + return (uint32_t *)(ICode + pc_cache); + } + else + { + // Cache miss - addresses don't match + // - default: 0xffffffff (not init) + + // cache line is 4 bytes wide + pc_offset &= ~0xf; + pc_cache &= ~0xf; + + // address line + *(uint32_t *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0); + *(uint32_t *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4); + *(uint32_t *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8); + *(uint32_t *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc); + + // opcode line + pc_offset = pc & ~0xf; + *(uint32_t *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0); + *(uint32_t *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4); + *(uint32_t *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8); + *(uint32_t *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc); + } + } + + /* + TODO: Probably should add cached BIOS + */ + // default + return (uint32_t *)PSXM(pc); +} +#endif + static void delayRead(int reg, u32 bpc) { u32 rold, rnew; @@ -274,7 +333,16 @@ void psxDelayTest(int reg, u32 bpc) { u32 *code; u32 tmp; - code = (u32 *)PSXM(bpc); + #ifdef ICACHE_EMULATION + if (Config.icache_emulation) + { + code = Read_ICache(psxRegs.pc); + } + else + #endif + { + code = (u32 *)PSXM(psxRegs.pc); + } tmp = ((code == NULL) ? 0 : SWAP32(*code)); branch = 1; @@ -298,7 +366,16 @@ static u32 psxBranchNoDelay(void) { u32 *code; u32 temp; - code = (u32 *)PSXM(psxRegs.pc); + #ifdef ICACHE_EMULATION + if (Config.icache_emulation) + { + code = Read_ICache(psxRegs.pc); + } + else + #endif + { + code = (u32 *)PSXM(psxRegs.pc); + } psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); switch (_Op_) { case 0x00: // SPECIAL @@ -427,7 +504,16 @@ static void doBranch(u32 tar) { if (psxDelayBranchTest(tar)) return; - code = (u32 *)PSXM(psxRegs.pc); + #ifdef ICACHE_EMULATION + if (Config.icache_emulation) + { + code = Read_ICache(psxRegs.pc); + } + else + #endif + { + code = (u32 *)PSXM(psxRegs.pc); + } psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); debugI(); @@ -555,7 +641,7 @@ void psxMULTU() { * Format: OP rs, offset * *********************************************************/ #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_); -#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); } +#define RepZBranchLinki32(op) { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } } void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link @@ -576,9 +662,9 @@ void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = * Shift arithmetic with variant register shift * * Format: OP rd, rt, rs * *********************************************************/ -void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs -void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic) -void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical) +void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs +void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic) +void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical) /********************************************************* * Load higher 16 bits of the first word in GPR with imm * @@ -605,7 +691,8 @@ void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs * Format: OP * *********************************************************/ void psxBREAK() { - // Break exception - psx rom doens't handles this + psxRegs.pc -= 4; + psxException(0x24, branch); } void psxSYSCALL() { @@ -640,14 +727,14 @@ void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); } * Format: OP rs, rd * *********************************************************/ void psxJR() { - doBranch(_u32(_rRs_)); + doBranch(_u32(_rRs_) & ~3); psxJumpTest(); } void psxJALR() { u32 temp = _u32(_rRs_); if (_Rd_) { _SetLink(_Rd_); } - doBranch(temp); + doBranch(temp & ~3); } /********************************************************* @@ -846,10 +933,22 @@ void psxCOP0() { psxCP0[_Rs_](); } +void psxCOP1() { +#ifdef PSXCPU_LOG + PSXCPU_LOG("Attempted to use an invalid floating point instruction. Ignored.\n"); +#endif +} + void psxCOP2() { psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D); } +void psxCOP3() { +#ifdef PSXCPU_LOG + PSXCPU_LOG("Attempted to access COP3. Ignored\n"); +#endif +} + void psxBASIC(struct psxCP2Regs *regs) { psxCP2BSC[_Rs_](); } @@ -868,7 +967,7 @@ void psxHLE() { void (*psxBSC[64])() = { psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ, psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI , - psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxCOP0 , psxCOP1 , psxCOP2, psxCOP3 , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL, psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, @@ -924,10 +1023,35 @@ void (*psxCP2BSC[32])() = { /////////////////////////////////////////// static int intInit() { +#ifdef ICACHE_EMULATION + if (!ICache_Addr) + { + ICache_Addr = malloc(0x1000); + if (!ICache_Addr) + { + return -1; + } + } + + if (!ICache_Code) + { + ICache_Code = malloc(0x1000); + if (!ICache_Code) + { + return -1; + } + } + memset(ICache_Addr, 0xff, 0x1000); + memset(ICache_Code, 0xff, 0x1000); +#endif return 0; } static void intReset() { +#ifdef ICACHE_EMULATION + memset(ICache_Addr, 0xff, 0x1000); + memset(ICache_Code, 0xff, 0x1000); +#endif } void intExecute() { @@ -944,12 +1068,41 @@ void intExecuteBlock() { static void intClear(u32 Addr, u32 Size) { } +void intNotify (int note, void *data) { +#ifdef ICACHE_EMULATION + /* Gameblabla - Only clear the icache if it's isolated */ + if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED) + { + memset(ICache_Addr, 0xff, 0x1000); + memset(ICache_Code, 0xff, 0x1000); + } +#endif +} + static void intShutdown() { +#ifdef ICACHE_EMULATION + if (ICache_Addr) + { + free(ICache_Addr); + ICache_Addr = NULL; + } + + if (ICache_Code) + { + free(ICache_Code); + ICache_Code = NULL; + } +#endif } // interpreter execution void execI() { +#ifndef ICACHE_EMULATION u32 *code = (u32 *)PSXM(psxRegs.pc); +#else + u32 *code = Read_ICache(psxRegs.pc); +#endif + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); debugI(); @@ -968,5 +1121,8 @@ R3000Acpu psxInt = { intExecute, intExecuteBlock, intClear, +#ifdef ICACHE_EMULATION + intNotify, +#endif intShutdown };