diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-02-01 02:15:55 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-02-01 02:15:55 +0000 |
| commit | f1da161879cfb46abd5680203cdc2ffad7870283 (patch) | |
| tree | 6a7087f35c8ce2e4e9d38b2844be3cbea927e13b /libpcsxcore | |
| parent | ad7c7d019ce039b9e9893ec94260f83edb581e6f (diff) | |
| download | pcsxr-f1da161879cfb46abd5680203cdc2ffad7870283.tar.gz | |
notaz:
- libpcsxcore: add handling for a branch in delay slot. This fixes explosion effect in Shadow Master. Interpreter only. (Patch #8233).
- dfsound: don't stop a channel by adsr if we have potential irq. otherwise we miss irqs, causing lockups in Misadventures of Tron Bonne (Patch #8234).
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@62781 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'libpcsxcore')
| -rw-r--r-- | libpcsxcore/psxinterpreter.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 77791897..398142cd 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -287,6 +287,128 @@ void psxDelayTest(int reg, u32 bpc) { psxBranchTest(); } +static u32 psxBranchNoDelay(void) { + u32 *code; + u32 temp; + + code = Read_ICache(psxRegs.pc, TRUE); + 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); +} + __inline void doBranch(u32 tar) { u32 *code; u32 tmp; @@ -294,6 +416,10 @@ __inline void doBranch(u32 tar) { branch2 = branch = 1; branchPC = tar; + // notaz: check for branch in delay slot + if (psxDelayBranchTest(tar)) + return; + // branch delay slot
code = Read_ICache(psxRegs.pc, TRUE);
|
