stable: Apply JIT/Int fixes from stable.

Fixes shadows in Animal Crossing and Matter Splatter Galaxy in SMG.
(fixes by godisgovernment and possibly others)


git-svn-id: https://dolphin-emu.googlecode.com/svn/branches/stable@5276 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
NeoBrainX 2010-04-04 18:14:37 +00:00
commit cfd83be9a1
2 changed files with 114 additions and 34 deletions

View file

@ -477,9 +477,13 @@ void divwx(UGeckoInstruction _inst)
s32 b = m_GPR[_inst.RB]; s32 b = m_GPR[_inst.RB];
if (b == 0 || ((u32)a == 0x80000000 && b == -1)) if (b == 0 || ((u32)a == 0x80000000 && b == -1))
{ {
if (_inst.OE) if (_inst.OE)
// should set OV
PanicAlert("OE: divwx"); PanicAlert("OE: divwx");
//else PanicAlert("Div by zero", "divwux"); if (((u32)a & 0x80000000) && b == 0)
m_GPR[_inst.RD] = -1;
else
m_GPR[_inst.RD] = 0;
} }
else else
m_GPR[_inst.RD] = (u32)(a / b); m_GPR[_inst.RD] = (u32)(a / b);
@ -493,17 +497,17 @@ void divwux(UGeckoInstruction _inst)
u32 a = m_GPR[_inst.RA]; u32 a = m_GPR[_inst.RA];
u32 b = m_GPR[_inst.RB]; u32 b = m_GPR[_inst.RB];
if (b == 0) // || (a == 0x80000000 && b == 0xFFFFFFFF)) if (b == 0)
{ {
if (_inst.OE) if (_inst.OE)
// should set OV
PanicAlert("OE: divwux"); PanicAlert("OE: divwux");
//else PanicAlert("Div by zero", "divwux"); m_GPR[_inst.RD] = 0;
} }
else else
{
m_GPR[_inst.RD] = a / b; m_GPR[_inst.RD] = a / b;
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
} if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
} }
void mulhwx(UGeckoInstruction _inst) void mulhwx(UGeckoInstruction _inst)
@ -572,7 +576,7 @@ void subfex(UGeckoInstruction _inst)
m_GPR[_inst.RD] = (~a) + b + carry; m_GPR[_inst.RD] = (~a) + b + carry;
SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry)); SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry));
if (_inst.OE) PanicAlert("OE: subfcx"); if (_inst.OE) PanicAlert("OE: subfex");
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]); if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
} }

View file

@ -388,34 +388,77 @@ void Jit64::subfic(UGeckoInstruction inst)
void Jit64::subfcx(UGeckoInstruction inst) void Jit64::subfcx(UGeckoInstruction inst)
{ {
INSTRUCTION_START; INSTRUCTION_START;
Default(inst); JITDISABLE(Integer)
return; int a = inst.RA, b = inst.RB, d = inst.RD;
/* gpr.Lock(a, b, d);
u32 a = m_GPR[_inst.RA]; if(d != a && d != b)
u32 b = m_GPR[_inst.RB]; gpr.LoadToX64(d, false, true);
m_GPR[_inst.RD] = b - a; else
SetCarry(a == 0 || Helper_Carry(b, 0-a)); gpr.LoadToX64(d, true, true);
if (_inst.OE) PanicAlert("OE: subfcx"); // For some reason, I could not get the jit versions of sub*
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]); // working with x86 sub...so we use the ~a + b + 1 method
*/ JitClearCA();
MOV(32, R(EAX), gpr.R(a));
NOT(32, R(EAX));
ADD(32, R(EAX), gpr.R(b));
FixupBranch carry1 = J_CC(CC_NC);
JitSetCA();
SetJumpTarget(carry1);
ADD(32, R(EAX), Imm32(1));
FixupBranch carry2 = J_CC(CC_NC);
JitSetCA();
SetJumpTarget(carry2);
MOV(32, gpr.R(d), R(EAX));
gpr.UnlockAll();
if (inst.OE) PanicAlert("OE: subfcx");
if (inst.Rc) {
CALL((u8*)asm_routines.computeRc);
}
} }
void Jit64::subfex(UGeckoInstruction inst) void Jit64::subfex(UGeckoInstruction inst)
{ {
INSTRUCTION_START; INSTRUCTION_START;
Default(inst); JITDISABLE(Integer)
return; int a = inst.RA, b = inst.RB, d = inst.RD;
/* gpr.FlushLockX(ECX);
u32 a = m_GPR[_inst.RA]; gpr.Lock(a, b, d);
u32 b = m_GPR[_inst.RB]; if(d != a && d != b)
int carry = GetCarry(); gpr.LoadToX64(d, false, true);
m_GPR[_inst.RD] = (~a) + b + carry; else
SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry)); gpr.LoadToX64(d, true, true);
if (_inst.OE) PanicAlert("OE: subfcx"); // Get CA
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]); MOV(32, R(ECX), M(&PowerPC::ppcState.spr[SPR_XER]));
*/ SHR(32, R(ECX), Imm8(29));
AND(32, R(ECX), Imm32(1));
// Don't need it anymore
JitClearCA();
// ~a + b
MOV(32, R(EAX), gpr.R(a));
NOT(32, R(EAX));
ADD(32, R(EAX), gpr.R(b));
FixupBranch carry1 = J_CC(CC_NC);
JitSetCA();
SetJumpTarget(carry1);
// + CA
ADD(32, R(EAX), R(ECX));
FixupBranch carry2 = J_CC(CC_NC);
JitSetCA();
SetJumpTarget(carry2);
MOV(32, gpr.R(d), R(EAX));
gpr.UnlockAll();
gpr.UnlockAllX();
if (inst.OE) PanicAlert("OE: subfex");
if (inst.Rc) {
CALL((u8*)asm_routines.computeRc);
}
} }
void Jit64::subfx(UGeckoInstruction inst) void Jit64::subfx(UGeckoInstruction inst)
@ -503,10 +546,10 @@ void Jit64::mulhwux(UGeckoInstruction inst)
} }
} }
// skipped some of the special handling in here - if we get crashes, let the interpreter handle this op void Jit64::divwux(UGeckoInstruction inst)
void Jit64::divwux(UGeckoInstruction inst) { {
Default(inst); return; INSTRUCTION_START
JITDISABLE(Integer)
int a = inst.RA, b = inst.RB, d = inst.RD; int a = inst.RA, b = inst.RB, d = inst.RD;
gpr.FlushLockX(EDX); gpr.FlushLockX(EDX);
gpr.Lock(a, b, d); gpr.Lock(a, b, d);
@ -518,8 +561,16 @@ void Jit64::divwux(UGeckoInstruction inst) {
MOV(32, R(EAX), gpr.R(a)); MOV(32, R(EAX), gpr.R(a));
XOR(32, R(EDX), R(EDX)); XOR(32, R(EDX), R(EDX));
gpr.KillImmediate(b); gpr.KillImmediate(b);
CMP(32, gpr.R(b), Imm32(0));
// doesn't handle if OE is set, but int doesn't either...
FixupBranch not_div_by_zero = J_CC(CC_NZ);
MOV(32, gpr.R(d), R(EDX));
MOV(32, R(EAX), gpr.R(d));
FixupBranch end = J();
SetJumpTarget(not_div_by_zero);
DIV(32, gpr.R(b)); DIV(32, gpr.R(b));
MOV(32, gpr.R(d), R(EAX)); MOV(32, gpr.R(d), R(EAX));
SetJumpTarget(end);
gpr.UnlockAll(); gpr.UnlockAll();
gpr.UnlockAllX(); gpr.UnlockAllX();
if (inst.Rc) { if (inst.Rc) {
@ -575,6 +626,31 @@ void Jit64::addx(UGeckoInstruction inst)
} }
gpr.UnlockAll(); gpr.UnlockAll();
} }
else if( a == b && b == d && a == d)
{
gpr.Lock(d);
gpr.LoadToX64(d, true);
ADD(32, gpr.R(d), gpr.R(d));
if (inst.Rc)
{
MOV(32, R(EAX), gpr.R(d));
CALL((u8*)asm_routines.computeRc);
}
gpr.UnlockAll();
}
else if( a == b && b != d)
{
gpr.Lock(a, d);
gpr.LoadToX64(d, false);
MOV(32, gpr.R(d), gpr.R(a));
ADD(32, gpr.R(d), gpr.R(d));
if (inst.Rc)
{
MOV(32, R(EAX), gpr.R(d));
CALL((u8*)asm_routines.computeRc);
}
gpr.UnlockAll();
}
else else
{ {
Default(inst); return; Default(inst); return;