VU Interpreter: It seems doing JALR in a delay slot is not taken ( Evil Dead - Fistfull of Boomstick) So the game now works in VU1 interpreter only. Tried fixing up MicroVU but its too confusing. Got close but lots of missing textures :(

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5538 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction@gmail.com 2013-01-27 16:56:58 +00:00
parent 82e4b1166a
commit 26cac4d837
4 changed files with 38 additions and 17 deletions

View File

@ -140,6 +140,7 @@ struct __aligned16 VURegs {
u32 branch; u32 branch;
u32 branchpc; u32 branchpc;
u32 delaybranchpc; u32 delaybranchpc;
u32 linkreg;
bool takedelaybranch; bool takedelaybranch;
// MAC/Status flags -- these are used by interpreters and superVU, but are kind of hacky // MAC/Status flags -- these are used by interpreters and superVU, but are kind of hacky

View File

@ -148,14 +148,21 @@ static void _vu0Exec(VURegs* VU)
VU->branch--; VU->branch--;
if (VU->branch == 0) { if (VU->branch == 0) {
VU->VI[REG_TPC].UL = VU->branchpc; VU->VI[REG_TPC].UL = VU->branchpc;
if(VU->takedelaybranch == true) if(VU->takedelaybranch == true && VU->linkreg == 0)
{ {
//DevCon.Warning("Setting VU0 Delay branch to next branch, treating first as delay slot"); //DevCon.Warning("Setting VU0 Delay branch to next branch, treating first as delay slot");
VU->branch = 2;
VU->branchpc = VU->delaybranchpc; VU->branchpc = VU->delaybranchpc;
VU->delaybranchpc = 0; VU->delaybranchpc = 0;
VU->branch = 2;
VU->takedelaybranch = false; VU->takedelaybranch = false;
} }
else
{
VU->takedelaybranch = false;
VU->linkreg = 0;
}
} }
} }

View File

@ -144,14 +144,21 @@ static void _vu1Exec(VURegs* VU)
if (VU->branch > 0) { if (VU->branch > 0) {
if (VU->branch-- == 1) { if (VU->branch-- == 1) {
VU->VI[REG_TPC].UL = VU->branchpc; VU->VI[REG_TPC].UL = VU->branchpc;
if(VU->takedelaybranch == true) if(VU->takedelaybranch == true && VU->linkreg == 0)
{ {
//DevCon.Warning("Setting VU1 Delay branch to next branch, treating first as delay slot"); //DevCon.Warning("Setting VU1 Delay branch to next branch, treating first as delay slot");
VU->branch = 2;
VU->branchpc = VU->delaybranchpc; VU->branchpc = VU->delaybranchpc;
VU->delaybranchpc = 0; VU->delaybranchpc = 0;
VU->branch = 2;
VU->takedelaybranch = false; VU->takedelaybranch = false;
} }
else
{
VU->takedelaybranch = false;
VU->linkreg = 0;
}
} }
} }

View File

@ -1872,9 +1872,13 @@ s32 _branchAddr(VURegs * VU) {
return bpc; return bpc;
} }
static __fi void _setBranch(VURegs * VU, u32 bpc) { static __fi void _setBranch(VURegs * VU, u32 bpc, bool islink) {
if(VU->branch == 1) if(VU->branch == 1)
{ {
if(islink)
{
VU->linkreg = _It_;
}
//DevCon.Warning("Branch in Branch Delay slot!"); //DevCon.Warning("Branch in Branch Delay slot!");
VU->delaybranchpc = bpc; VU->delaybranchpc = bpc;
VU->takedelaybranch = true; VU->takedelaybranch = true;
@ -1889,68 +1893,70 @@ static __fi void _setBranch(VURegs * VU, u32 bpc) {
static __ri void _vuIBEQ(VURegs * VU) { static __ri void _vuIBEQ(VURegs * VU) {
if (VU->VI[_It_].US[0] == VU->VI[_Is_].US[0]) { if (VU->VI[_It_].US[0] == VU->VI[_Is_].US[0]) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
} }
static __ri void _vuIBGEZ(VURegs * VU) { static __ri void _vuIBGEZ(VURegs * VU) {
if (VU->VI[_Is_].SS[0] >= 0) { if (VU->VI[_Is_].SS[0] >= 0) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
} }
static __ri void _vuIBGTZ(VURegs * VU) { static __ri void _vuIBGTZ(VURegs * VU) {
if (VU->VI[_Is_].SS[0] > 0) { if (VU->VI[_Is_].SS[0] > 0) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
} }
static __ri void _vuIBLEZ(VURegs * VU) { static __ri void _vuIBLEZ(VURegs * VU) {
if (VU->VI[_Is_].SS[0] <= 0) { if (VU->VI[_Is_].SS[0] <= 0) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
} }
static __ri void _vuIBLTZ(VURegs * VU) { static __ri void _vuIBLTZ(VURegs * VU) {
if (VU->VI[_Is_].SS[0] < 0) { if (VU->VI[_Is_].SS[0] < 0) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
} }
static __ri void _vuIBNE(VURegs * VU) { static __ri void _vuIBNE(VURegs * VU) {
if (VU->VI[_It_].US[0] != VU->VI[_Is_].US[0]) { if (VU->VI[_It_].US[0] != VU->VI[_Is_].US[0]) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
} }
static __ri void _vuB(VURegs * VU) { static __ri void _vuB(VURegs * VU) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
// 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) { static __ri void _vuBAL(VURegs * VU) {
s32 bpc = _branchAddr(VU); s32 bpc = _branchAddr(VU);
if (_It_) VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; if (_It_) VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL + 8)/8;
_setBranch(VU, bpc); _setBranch(VU, bpc, true);
} }
static __ri void _vuJR(VURegs * VU) { static __ri void _vuJR(VURegs * VU) {
u32 bpc = VU->VI[_Is_].US[0] * 8; u32 bpc = VU->VI[_Is_].US[0] * 8;
_setBranch(VU, bpc); _setBranch(VU, bpc, false);
} }
//If this is in a branch delay, the jump isn't taken ( Evil Dead - Fistfull of Boomstick )
static __ri void _vuJALR(VURegs * VU) { static __ri void _vuJALR(VURegs * VU) {
u32 bpc = VU->VI[_Is_].US[0] * 8; u32 bpc = VU->VI[_Is_].US[0] * 8;
if (_It_) VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; if (_It_) VU->VI[_It_].US[0] = (VU->VI[REG_TPC].UL + 8)/8;
_setBranch(VU, bpc); _setBranch(VU, bpc, true);
} }
static __ri void _vuMFP(VURegs * VU) { static __ri void _vuMFP(VURegs * VU) {