mirror of https://github.com/PCSX2/pcsx2.git
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
This commit is contained in:
parent
73a08536d1
commit
c78b6157cb
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue