X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fpsxinterpreter.c;h=ff4949133ff5aaa91ea53165d67681a80966ee98;hp=1f4b46cd6883ea98eca53d6c1e6d0d3a9bad2cc5;hb=8ad120c9c4dca424feac32098cb4af6a2c8f641f;hpb=ef79bbde537d6b9c745a7d86cb9df1d04c35590d diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 1f4b46cd..ff494913 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -25,6 +25,7 @@ #include "r3000a.h" #include "gte.h" #include "psxhle.h" +#include "debug.h" static int branch = 0; static int branch2 = 0; @@ -38,14 +39,14 @@ static u32 branchPC; #define debugI() #endif -inline void execI(); +void execI(); // Subsets void (*psxBSC[64])(); void (*psxSPC[64])(); void (*psxREG[32])(); void (*psxCP0[32])(); -void (*psxCP2[64])(); +void (*psxCP2[64])(struct psxCP2Regs *regs); void (*psxCP2BSC[32])(); static void delayRead(int reg, u32 bpc) { @@ -59,13 +60,13 @@ static void delayRead(int reg, u32 bpc) { psxRegs.pc = bpc; - psxBranchTest(); + branch = 0; psxRegs.GPR.r[reg] = rold; execI(); // first branch opcode psxRegs.GPR.r[reg] = rnew; - branch = 0; + psxBranchTest(); } static void delayWrite(int reg, u32 bpc) { @@ -153,8 +154,12 @@ int psxTestLoadDelay(int reg, u32 tmp) { case 0x01: // REGIMM switch (_tRt_) { - case 0x00: case 0x02: - case 0x10: case 0x12: // BLTZ/BGEZ... + case 0x00: case 0x01: + case 0x10: case 0x11: // BLTZ/BGEZ... + // Xenogears - lbu v0 / beq v0 + // - no load delay (fixes battle loading) + break; + if (_tRs_ == reg) return 2; break; } @@ -166,10 +171,18 @@ int psxTestLoadDelay(int reg, u32 tmp) { break; case 0x04: case 0x05: // BEQ/BNE + // Xenogears - lbu v0 / beq v0 + // - no load delay (fixes battle loading) + break; + if (_tRs_ == reg || _tRt_ == reg) return 2; break; case 0x06: case 0x07: // BLEZ/BGTZ + // Xenogears - lbu v0 / beq v0 + // - no load delay (fixes battle loading) + break; + if (_tRs_ == reg) return 2; break; @@ -273,13 +286,139 @@ void psxDelayTest(int reg, u32 bpc) { psxBranchTest(); } -__inline void doBranch(u32 tar) { +static u32 psxBranchNoDelay(void) { + u32 *code; + u32 temp; + + code = (u32 *)PSXM(psxRegs.pc); + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + switch (_Op_) { + case 0x00: // SPECIAL + switch (_Funct_) { + case 0x08: // JR + return _u32(_rRs_); + case 0x09: // JALR + temp = _u32(_rRs_); + if (_Rd_) { _SetLink(_Rd_); } + return temp; + } + break; + case 0x01: // REGIMM + switch (_Rt_) { + case 0x00: // BLTZ + if (_i32(_rRs_) < 0) + return _BranchTarget_; + break; + case 0x01: // BGEZ + if (_i32(_rRs_) >= 0) + return _BranchTarget_; + break; + case 0x08: // BLTZAL + if (_i32(_rRs_) < 0) { + _SetLink(31); + return _BranchTarget_; + } + break; + case 0x09: // BGEZAL + if (_i32(_rRs_) >= 0) { + _SetLink(31); + return _BranchTarget_; + } + break; + } + break; + case 0x02: // J + return _JumpTarget_; + case 0x03: // JAL + _SetLink(31); + return _JumpTarget_; + case 0x04: // BEQ + if (_i32(_rRs_) == _i32(_rRt_)) + return _BranchTarget_; + break; + case 0x05: // BNE + if (_i32(_rRs_) != _i32(_rRt_)) + return _BranchTarget_; + break; + case 0x06: // BLEZ + if (_i32(_rRs_) <= 0) + return _BranchTarget_; + break; + case 0x07: // BGTZ + if (_i32(_rRs_) > 0) + return _BranchTarget_; + break; + } + + return (u32)-1; +} + +static int psxDelayBranchExec(u32 tar) { + execI(); + + branch = 0; + psxRegs.pc = tar; + psxRegs.cycle += BIAS; + psxBranchTest(); + return 1; +} + +static int psxDelayBranchTest(u32 tar1) { + u32 tar2, tmp1, tmp2; + + tar2 = psxBranchNoDelay(); + if (tar2 == (u32)-1) + return 0; + + debugI(); + + /* + * Branch in delay slot: + * - execute 1 instruction at tar1 + * - jump to tar2 (target of branch in delay slot; this branch + * has no normal delay slot, instruction at tar1 was fetched instead) + */ + psxRegs.pc = tar1; + tmp1 = psxBranchNoDelay(); + if (tmp1 == (u32)-1) { + return psxDelayBranchExec(tar2); + } + debugI(); + psxRegs.cycle += BIAS; + + /* + * Got a branch at tar1: + * - execute 1 instruction at tar2 + * - jump to target of that branch (tmp1) + */ + psxRegs.pc = tar2; + tmp2 = psxBranchNoDelay(); + if (tmp2 == (u32)-1) { + return psxDelayBranchExec(tmp1); + } + debugI(); + psxRegs.cycle += BIAS; + + /* + * Got a branch at tar2: + * - execute 1 instruction at tmp1 + * - jump to target of that branch (tmp2) + */ + psxRegs.pc = tmp1; + return psxDelayBranchExec(tmp2); +} + +static void doBranch(u32 tar) { u32 *code; u32 tmp; branch2 = branch = 1; branchPC = tar; + // check for branch in delay slot + if (psxDelayBranchTest(tar)) + return; + code = (u32 *)PSXM(psxRegs.pc); psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); @@ -366,6 +505,10 @@ void psxDIV() { _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_); _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_); } + else { + _i32(_rLo_) = _i32(_rRs_) >= 0 ? 0xffffffff : 1; + _i32(_rHi_) = _i32(_rRs_); + } } void psxDIVU() { @@ -373,6 +516,10 @@ void psxDIVU() { _rLo_ = _rRs_ / _rRt_; _rHi_ = _rRs_ % _rRt_; } + else { + _i32(_rLo_) = 0xffffffff; + _i32(_rHi_) = _i32(_rRs_); + } } void psxMULT() { @@ -633,15 +780,14 @@ void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; } void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; } void psxTestSWInts() { - // the next code is untested, if u know please - // tell me if it works ok or not (linuzappz) if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 && - psxRegs.CP0.n.Status & 0x1) { + psxRegs.CP0.n.Status & 0x1) { + psxRegs.CP0.n.Cause &= ~0x7c; psxException(psxRegs.CP0.n.Cause, branch); } } -__inline void MTC0(int reg, u32 val) { +void MTC0(int reg, u32 val) { // SysPrintf("MTC0 %d: %x\n", reg, val); switch (reg) { case 12: // Status @@ -650,7 +796,8 @@ __inline void MTC0(int reg, u32 val) { break; case 13: // Cause - psxRegs.CP0.n.Cause = val & ~(0xfc00); + psxRegs.CP0.n.Cause &= ~0x0300; + psxRegs.CP0.n.Cause |= val & 0x0300; psxTestSWInts(); break; @@ -686,10 +833,10 @@ void psxCOP0() { } void psxCOP2() { - psxCP2[_Funct_](); + psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D); } -void psxBASIC() { +void psxBASIC(struct psxCP2Regs *regs) { psxCP2BSC[_Rs_](); } @@ -735,7 +882,7 @@ void (*psxCP0[32])() = { psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL }; -void (*psxCP2[64])() = { +void (*psxCP2[64])(struct psxCP2Regs *regs) = { psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10 @@ -763,12 +910,13 @@ static int intInit() { static void intReset() { } -static void intExecute() { - for (;;) +void intExecute() { + extern int stop; + for (;!stop;) execI(); } -static void intExecuteBlock() { +void intExecuteBlock() { branch2 = 0; while (!branch2) execI(); } @@ -780,7 +928,7 @@ static void intShutdown() { } // interpreter execution -inline void execI() { +void execI() { u32 *code = (u32 *)PSXM(psxRegs.pc); psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));