From c78b6157cb2b39eb5941dad6806b253886ea08ba Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Thu, 31 Jan 2013 23:02:32 +0000 Subject: [PATCH] VU Interpreter Branch Delays: After some brainstorming amongst the team, we came up with a theory on what should be happening. I'm pleased to say it works in all cases. As a bonus, the Tony Hawk Project 8 game (possibly the others using the same engine too) now have perfect graphics in VU Interpreter :) (software mode still required to get rid of lighting garbage however. Skipdraw 2 "kinda" works, but not overly well) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5541 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/VU.h | 1 - pcsx2/VU0microInterp.cpp | 21 ++++---------- pcsx2/VU1microInterp.cpp | 23 ++++------------ pcsx2/VUops.cpp | 59 +++++++++++++++++++++++++++------------- 4 files changed, 51 insertions(+), 53 deletions(-) diff --git a/pcsx2/VU.h b/pcsx2/VU.h index 9bf094645c..af87cd16b6 100644 --- a/pcsx2/VU.h +++ b/pcsx2/VU.h @@ -140,7 +140,6 @@ struct __aligned16 VURegs { u32 branch; u32 branchpc; u32 delaybranchpc; - u32 firstbranchisjump; bool takedelaybranch; // MAC/Status flags -- these are used by interpreters and superVU, but are kind of hacky diff --git a/pcsx2/VU0microInterp.cpp b/pcsx2/VU0microInterp.cpp index 02350aba4e..c4aca7aa71 100644 --- a/pcsx2/VU0microInterp.cpp +++ b/pcsx2/VU0microInterp.cpp @@ -147,26 +147,15 @@ static void _vu0Exec(VURegs* VU) if (VU->branch > 0) { if (VU->branch-- == 1) { VU->VI[REG_TPC].UL = VU->branchpc; + if(VU->takedelaybranch == true) { - //DevCon.Warning("VU0 - Branch/Jump in Delay Slot"); - if(VU->firstbranchisjump == 1) - { - //DevCon.Warning("Jump first, so reading 1 instruction from first branch, then jumping second"); - - VU->branch = 1; - VU->branchpc = VU->delaybranchpc; - } - else - { - //DevCon.Warning("Branch first, so ignoring second branch"); - } - + VU->branch = 2; + DevCon.Warning("VU0 - Branch/Jump in Delay Slot"); + VU->branchpc = VU->delaybranchpc; VU->delaybranchpc = 0; VU->takedelaybranch = false; - } - - VU->firstbranchisjump = 0; + } } } diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp index a1430de847..85ce8ff550 100644 --- a/pcsx2/VU1microInterp.cpp +++ b/pcsx2/VU1microInterp.cpp @@ -140,30 +140,19 @@ static void _vu1Exec(VURegs* VU) _vuAddLowerStalls(VU, &lregs); _vuTestPipes(VU); - + if (VU->branch > 0) { if (VU->branch-- == 1) { VU->VI[REG_TPC].UL = VU->branchpc; + if(VU->takedelaybranch == true) { - //DevCon.Warning("VU1 - Branch/Jump in Delay Slot"); - if(VU->firstbranchisjump == 1) - { - //DevCon.Warning("Jump first, so reading 1 instruction from first branch, then jumping second"); - - VU->branch = 1; - VU->branchpc = VU->delaybranchpc; - } - else - { - //DevCon.Warning("Branch first, so ignoring second branch"); - } - + VU->branch = 2; + //DevCon.Warning("VU1 - Branch/Jump in Delay Slot"); + VU->branchpc = VU->delaybranchpc; VU->delaybranchpc = 0; VU->takedelaybranch = false; - } - - VU->firstbranchisjump = 0; + } } } diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index 80d22585b5..f619927311 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -1872,7 +1872,7 @@ s32 _branchAddr(VURegs * VU) { return bpc; } -static __fi void _setBranch(VURegs * VU, u32 bpc, bool isjump) { +static __fi void _setBranch(VURegs * VU, u32 bpc) { if(VU->branch == 1) { //DevCon.Warning("Branch in Branch Delay slot!"); @@ -1881,11 +1881,7 @@ static __fi void _setBranch(VURegs * VU, u32 bpc, bool isjump) { } else { - if(isjump) - { - VU->firstbranchisjump = 1; - } - + VU->branch = 2; VU->branchpc = bpc; } @@ -1894,70 +1890,95 @@ static __fi void _setBranch(VURegs * VU, u32 bpc, bool isjump) { static __ri void _vuIBEQ(VURegs * VU) { if (VU->VI[_It_].US[0] == VU->VI[_Is_].US[0]) { s32 bpc = _branchAddr(VU); - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } } static __ri void _vuIBGEZ(VURegs * VU) { if (VU->VI[_Is_].SS[0] >= 0) { s32 bpc = _branchAddr(VU); - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } } static __ri void _vuIBGTZ(VURegs * VU) { if (VU->VI[_Is_].SS[0] > 0) { s32 bpc = _branchAddr(VU); - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } } static __ri void _vuIBLEZ(VURegs * VU) { if (VU->VI[_Is_].SS[0] <= 0) { s32 bpc = _branchAddr(VU); - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } } static __ri void _vuIBLTZ(VURegs * VU) { if (VU->VI[_Is_].SS[0] < 0) { s32 bpc = _branchAddr(VU); - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } } static __ri void _vuIBNE(VURegs * VU) { if (VU->VI[_It_].US[0] != VU->VI[_Is_].US[0]) { s32 bpc = _branchAddr(VU); - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } } static __ri void _vuB(VURegs * VU) { s32 bpc = _branchAddr(VU); - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } -// NOTE!! This might fall in a delay slot, if it does, the BAL won't be taken. Not sure if this is correct static __ri void _vuBAL(VURegs * VU) { s32 bpc = _branchAddr(VU); - if (_It_) VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + + if(_It_) + { + //If we are in the branch delay slot, the instruction after the first + //instruction in the first branches target becomes the linked reg. + if(VU->branch == 1) + { + VU->VI[_It_].US[0] = (VU->branchpc + 8)/8; + } + else + { + VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL+8)/8; + } + } - _setBranch(VU, bpc, false); + _setBranch(VU, bpc); } static __ri void _vuJR(VURegs * VU) { u32 bpc = VU->VI[_Is_].US[0] * 8; - _setBranch(VU, bpc, true); + _setBranch(VU, bpc); } //If this is in a branch delay, the jump isn't taken ( Evil Dead - Fistfull of Boomstick ) static __ri void _vuJALR(VURegs * VU) { u32 bpc = VU->VI[_Is_].US[0] * 8; - if (_It_) VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + + if(_It_) + { + //If we are in the branch delay slot, the instruction after the first + //instruction in the first branches target becomes the linked reg. + if(VU->branch == 1) + { + VU->VI[_It_].US[0] = (VU->branchpc + 8)/8; + } + else + { + VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL+8)/8; + } + } - _setBranch(VU, bpc, true); + _setBranch(VU, bpc); } static __ri void _vuMFP(VURegs * VU) {