X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxinterpreter.c;h=cf3de7985a3df639a4644e02bfdcd2151a31edf0;hb=HEAD;hp=f3bf7b6ca396be0c57ffa3bf62149473378e4ce3;hpb=bc7c5acb6eb1ac9adc6b4381a2c2b2baffd5aebe;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index f3bf7b6c..30608535 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -112,7 +112,8 @@ static void intException(psxRegisters *regs, u32 pc, u32 cause) if (cause != 0x20) { //FILE *f = fopen("/tmp/psx_ram.bin", "wb"); //fwrite(psxM, 1, 0x200000, f); fclose(f); - log_unhandled("exception %08x @%08x\n", cause, pc); + log_unhandled("exception %08x @%08x ra=%08x\n", + cause, pc, regs->GPR.n.ra); } dloadFlush(regs); regs->pc = pc; @@ -127,6 +128,19 @@ static void intExceptionInsn(psxRegisters *regs, u32 cause) intException(regs, regs->pc - 4, cause); } +static noinline void intExceptionReservedInsn(psxRegisters *regs) +{ +#ifdef DO_EXCEPTION_RESERVEDI + static u32 ppc_ = ~0u; + if (regs->pc != ppc_) { + SysPrintf("reserved instruction %08x @%08x ra=%08x\n", + regs->code, regs->pc - 4, regs->GPR.n.ra); + ppc_ = regs->pc; + } + intExceptionInsn(regs, R3000E_RI << 2); +#endif +} + // 29 Enable for 80000000-ffffffff // 30 Enable for 00000000-7fffffff // 31 Enable exception @@ -162,25 +176,21 @@ static int execBreakCheck(psxRegisters *regs, u32 pc) // get an opcode without triggering exceptions or affecting cache u32 intFakeFetch(u32 pc) { - u8 *base = psxMemRLUT[pc >> 16]; - u32 *code; - if (unlikely(base == INVALID_PTR)) + u32 *code = (u32 *)psxm(pc & ~0x3, 0); + if (unlikely(code == INVALID_PTR)) return 0; // nop - code = (u32 *)(base + (pc & 0xfffc)); return SWAP32(*code); } static u32 INT_ATTR fetchNoCache(psxRegisters *regs, u8 **memRLUT, u32 pc) { - u8 *base = memRLUT[pc >> 16]; - u32 *code; - if (unlikely(base == INVALID_PTR)) { + u32 *code = (u32 *)psxm_lut(pc & ~0x3, 0, memRLUT); + if (unlikely(code == INVALID_PTR)) { SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra); intException(regs, pc, R3000E_IBE << 2); return 0; // execute as nop } - code = (u32 *)(base + (pc & 0xfffc)); return SWAP32(*code); } @@ -203,14 +213,12 @@ static u32 INT_ATTR fetchICache(psxRegisters *regs, u8 **memRLUT, u32 pc) if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag) { - const u8 *base = memRLUT[pc >> 16]; - const u32 *code; - if (unlikely(base == INVALID_PTR)) { + const u32 *code = (u32 *)psxm_lut(pc & ~0xf, 0, memRLUT); + if (unlikely(code == INVALID_PTR)) { SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra); intException(regs, pc, R3000E_IBE << 2); return 0; // execute as nop } - code = (u32 *)(base + (pc & 0xfff0)); entry->tag = pc; // treat as 4 words, although other configurations are said to be possible @@ -454,14 +462,6 @@ static void doBranchRegE(psxRegisters *regs, u32 tar) { doBranch(regs, tar, R3000A_BRANCH_TAKEN); } -#if __has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ >= 5) -#define add_overflow(a, b, r) __builtin_add_overflow(a, b, &(r)) -#define sub_overflow(a, b, r) __builtin_sub_overflow(a, b, &(r)) -#else -#define add_overflow(a, b, r) ({r = (u32)a + (u32)b; (a ^ ~b) & (a ^ r) & (1u<<31);}) -#define sub_overflow(a, b, r) ({r = (u32)a - (u32)b; (a ^ b) & (a ^ r) & (1u<<31);}) -#endif - static void addExc(psxRegisters *regs, u32 rt, s32 a1, s32 a2) { s32 val; if (add_overflow(a1, a2, val)) { @@ -869,12 +869,12 @@ OP(psxLWR) { doLWR(regs_, _Rt_, _oB_); } OP(psxLWLe) { if (checkLD(regs_, _oB_ & ~3, 0)) doLWL(regs_, _Rt_, _oB_); } OP(psxLWRe) { if (checkLD(regs_, _oB_ , 0)) doLWR(regs_, _Rt_, _oB_); } -OP(psxSB) { psxMemWrite8 (_oB_, _rRt_ & 0xff); } -OP(psxSH) { psxMemWrite16(_oB_, _rRt_ & 0xffff); } +OP(psxSB) { psxMemWrite8 (_oB_, _rRt_); } +OP(psxSH) { psxMemWrite16(_oB_, _rRt_); } OP(psxSW) { psxMemWrite32(_oB_, _rRt_); } -OP(psxSBe) { if (checkST(regs_, _oB_, 0)) psxMemWrite8 (_oB_, _rRt_ & 0xff); } -OP(psxSHe) { if (checkST(regs_, _oB_, 1)) psxMemWrite16(_oB_, _rRt_ & 0xffff); } +OP(psxSBe) { if (checkST(regs_, _oB_, 0)) psxMemWrite8 (_oB_, _rRt_); } +OP(psxSHe) { if (checkST(regs_, _oB_, 1)) psxMemWrite16(_oB_, _rRt_); } OP(psxSWe) { if (checkST(regs_, _oB_, 3)) psxMemWrite32(_oB_, _rRt_); } static void doSWL(psxRegisters *regs, u32 rt, u32 addr) { @@ -930,17 +930,13 @@ OP(psxSWRe) { if (checkST(regs_, _oB_ , 0)) doSWR(regs_, _Rt_, _oB_); } *********************************************************/ OP(psxMFC0) { u32 r = _Rd_; -#ifdef DO_EXCEPTION_RESERVEDI if (unlikely(0x00000417u & (1u << r))) - intExceptionInsn(regs_, R3000E_RI << 2); -#endif + intExceptionReservedInsn(regs_); doLoad(regs_, _Rt_, regs_->CP0.r[r]); } static void setupCop(u32 sr); -OP(psxCFC0) { doLoad(regs_, _Rt_, regs_->CP0.r[_Rd_]); } - void MTC0(psxRegisters *regs_, int reg, u32 val) { // SysPrintf("MTC0 %d: %x\n", reg, val); switch (reg) { @@ -962,15 +958,20 @@ void MTC0(psxRegisters *regs_, int reg, u32 val) { case 7: if ((regs_->CP0.n.DCIC ^ val) & 0xff800000) log_unhandled("DCIC: %08x->%08x\n", regs_->CP0.n.DCIC, val); - // fallthrough + goto default_; + case 3: + if (regs_->CP0.n.BPC != val) + log_unhandled("BPC: %08x->%08x\n", regs_->CP0.n.BPC, val); + goto default_; + default: + default_: regs_->CP0.r[reg] = val; break; } } OP(psxMTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); } -OP(psxCTC0) { MTC0(regs_, _Rd_, _u32(_rRt_)); } // no exception static inline void psxNULLne(psxRegisters *regs) { @@ -984,9 +985,7 @@ static inline void psxNULLne(psxRegisters *regs) { OP(psxNULL) { psxNULLne(regs_); -#ifdef DO_EXCEPTION_RESERVEDI - intExceptionInsn(regs_, R3000E_RI << 2); -#endif + intExceptionReservedInsn(regs_); } void gteNULL(struct psxCP2Regs *regs) { @@ -999,12 +998,26 @@ OP(psxSPECIAL) { } OP(psxCOP0) { - switch (_Rs_) { + u32 rs = _Rs_; + if (rs & 0x10) { + u32 op2 = code & 0x1f; + switch (op2) { + case 0x01: + case 0x02: + case 0x06: + case 0x08: psxNULL(regs_, code); break; + case 0x10: psxRFE(regs_, code); break; + default: psxNULLne(regs_); break; + } + return; + } + switch (rs) { case 0x00: psxMFC0(regs_, code); break; - case 0x02: psxCFC0(regs_, code); break; case 0x04: psxMTC0(regs_, code); break; - case 0x06: psxCTC0(regs_, code); break; - case 0x10: psxRFE(regs_, code); break; + case 0x02: // CFC + case 0x06: psxNULL(regs_, code); break; // CTC -> exception + case 0x08: + case 0x0c: log_unhandled("BC0 %08x @%08x\n", code, regs_->pc - 4); default: psxNULLne(regs_); break; } } @@ -1014,31 +1027,27 @@ OP(psxCOP1) { log_unhandled("COP1 %08x @%08x\n", code, regs_->pc - 4); } -// TODO: wrong COP2 decoding OP(psxCOP2) { - psxCP2[_Funct_](®s_->CP2); + u32 rt = _Rt_, rd = _Rd_, rs = _Rs_; + if (rs & 0x10) { + psxCP2[_Funct_](®s_->CP2); + return; + } + switch (rs) { + case 0x00: doLoad(regs_, rt, MFC2(®s_->CP2, rd)); break; // MFC2 + case 0x02: doLoad(regs_, rt, regs_->CP2C.r[rd]); break; // CFC2 + case 0x04: MTC2(®s_->CP2, regs_->GPR.r[rt], rd); break; // MTC2 + case 0x06: CTC2(®s_->CP2, regs_->GPR.r[rt], rd); break; // CTC2 + case 0x08: + case 0x0c: log_unhandled("BC2 %08x @%08x\n", code, regs_->pc - 4); + default: psxNULLne(regs_); break; + } } OP(psxCOP2_stall) { u32 f = _Funct_; gteCheckStall(f); - psxCP2[f](®s_->CP2); -} - -OP(gteMFC2) { - doLoad(regs_, _Rt_, MFC2(®s_->CP2, _Rd_)); -} - -OP(gteCFC2) { - doLoad(regs_, _Rt_, regs_->CP2C.r[_Rd_]); -} - -OP(gteMTC2) { - MTC2(®s_->CP2, regs_->GPR.r[_Rt_], _Rd_); -} - -OP(gteCTC2) { - CTC2(®s_->CP2, regs_->GPR.r[_Rt_], _Rd_); + psxCOP2(regs_, code); } OP(gteLWC2) { @@ -1094,21 +1103,6 @@ OP(psxSWCx) { checkST(regs_, _oB_, 3); } -static void psxBASIC(struct psxCP2Regs *cp2regs) { - psxRegisters *regs = (void *)((u8 *)cp2regs - offsetof(psxRegisters, CP2)); - u32 code = regs->code; - assert(regs == &psxRegs); - switch (_Rs_) { - case 0x00: gteMFC2(regs, code); break; - case 0x02: gteCFC2(regs, code); break; - case 0x04: gteMTC2(regs, code); break; - case 0x06: gteCTC2(regs, code); break; - case 0x08: - case 0x0c: log_unhandled("BC2 %08x @%08x\n", code, regs->pc - 4); - default: psxNULLne(regs); break; - } -} - OP(psxREGIMM) { u32 rt = _Rt_; switch (rt) { @@ -1133,7 +1127,9 @@ OP(psxHLE) { psxSWCx(regs_, code); return; } + dloadFlush(regs_); psxHLEt[hleCode](); + branchSeen = 1; } static void (INT_ATTR *psxBSC[64])(psxRegisters *regs_, u32 code) = { @@ -1159,7 +1155,7 @@ static void (INT_ATTR *psxSPC[64])(psxRegisters *regs_, u32 code) = { }; void (*psxCP2[64])(struct psxCP2Regs *regs) = { - psxBASIC, gteRTPS , gteNULL , gteNULL, gteNULL, gteNULL , gteNCLIP, gteNULL, // 00 + gteNULL , gteRTPS , gteNULL , gteNULL, gteNULL, gteNULL , gteNCLIP, gteNULL, // 00 gteNULL , gteNULL , gteNULL , gteNULL, gteOP , gteNULL , gteNULL , gteNULL, // 08 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , gteNULL , gteNCDT , gteNULL, // 10 gteNULL , gteNULL , gteNULL , gteNCCS, gteCC , gteNULL , gteNCS , gteNULL, // 18 @@ -1177,6 +1173,7 @@ static int intInit() { static void intReset() { dloadClear(&psxRegs); + psxRegs.subCycle = 0; } static inline void execI_(u8 **memRLUT, psxRegisters *regs) { @@ -1241,6 +1238,7 @@ static void intNotify(enum R3000Anote note, void *data) { break; case R3000ACPU_NOTIFY_AFTER_LOAD: dloadClear(&psxRegs); + psxRegs.subCycle = 0; setupCop(psxRegs.CP0.n.SR); // fallthrough case R3000ACPU_NOTIFY_CACHE_ISOLATED: // Armored Core? @@ -1350,12 +1348,15 @@ void intApplyConfig() { } static void intShutdown() { + dloadClear(&psxRegs); } -// single step (may do several ops in case of a branch) +// single step (may do several ops in case of a branch or load delay) +// called by asm/dynarec void execI(psxRegisters *regs) { - execI_(psxMemRLUT, regs); - dloadFlush(regs); + do { + execIbp(psxMemRLUT, regs); + } while (regs->dloadReg[0] || regs->dloadReg[1]); } R3000Acpu psxInt = {