mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
DSP LLE JIT: Fix Update_SR_Register16_OverS32
There were 3 bugs here: - The input register for the full register wasn't actually being used; it was read into RCX but RCX wasn't used by Update_SR_Register16_OverS32 (except as a scratch register). The way the DSP LLE recompiler uses registers is in general confusing, so this commit changes a few uses to have a variable for the register being used, to make code a bit more readable. (Default parameter values were also removed so that they needed to be explicitly specified). - Update_SR_Register16 was doing a 64-bit test, when it should have been doing a 16-bit test. For the most part this doesn't matter due to sign-extension, but it does come up with e.g. `ORI` or `ANDI`. - Update_SR_Register16_OverS32 did the over s32 check, and then called Update_SR_Register16. Update_SR_Register16 masks $sr with ~SR_CMP_MASK, clearing the over s32 bit. Now the over s32 check is performed after calling Update_SR_Register16 (without masking a second time). No official uCode cares about the over s32 bit.
This commit is contained in:
parent
70bf89fa59
commit
f88b7ab6b3
@ -257,8 +257,8 @@ private:
|
||||
{
|
||||
UpdateSR64AddSub(val1, val2, result, scratch, true);
|
||||
}
|
||||
void Update_SR_Register16(Gen::X64Reg val = Gen::EAX);
|
||||
void Update_SR_Register16_OverS32(Gen::X64Reg val = Gen::EAX);
|
||||
void Update_SR_Register16(Gen::X64Reg val);
|
||||
void Update_SR_Register16_OverS32(Gen::X64Reg val, Gen::X64Reg full_val, Gen::X64Reg scratch);
|
||||
|
||||
// Register helpers
|
||||
void setCompileSR(u16 bit);
|
||||
|
@ -152,9 +152,9 @@ void DSPEmitter::tstaxh(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = (opc >> 8) & 0x1;
|
||||
// s16 val = dsp_get_ax_h(reg);
|
||||
get_ax_h(reg);
|
||||
get_ax_h(reg, EAX);
|
||||
// Update_SR_Register16(val);
|
||||
Update_SR_Register16();
|
||||
Update_SR_Register16(EAX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,16 +301,18 @@ void DSPEmitter::xorr(const UDSPInstruction opc)
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
// u16 accm = g_dsp.r.acm[dreg] ^ g_dsp.r.axh[sreg];
|
||||
get_acc_m(dreg, RAX);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(dreg, accm);
|
||||
get_ax_h(sreg, RDX);
|
||||
XOR(64, R(RAX), R(RDX));
|
||||
XOR(64, R(accm), R(RDX));
|
||||
// g_dsp.r.acm[dreg] = accm;
|
||||
set_acc_m(dreg);
|
||||
set_acc_m(dreg, R(accm));
|
||||
// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(dreg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(dreg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,16 +328,18 @@ void DSPEmitter::andr(const UDSPInstruction opc)
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
// u16 accm = g_dsp.r.acm[dreg] & g_dsp.r.axh[sreg];
|
||||
get_acc_m(dreg, RAX);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(dreg, accm);
|
||||
get_ax_h(sreg, RDX);
|
||||
AND(64, R(RAX), R(RDX));
|
||||
AND(64, R(accm), R(RDX));
|
||||
// g_dsp.r.acm[dreg] = accm;
|
||||
set_acc_m(dreg);
|
||||
set_acc_m(dreg, R(accm));
|
||||
// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(dreg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(dreg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,16 +355,18 @@ void DSPEmitter::orr(const UDSPInstruction opc)
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
// u16 accm = g_dsp.r.acm[dreg] | g_dsp.r.axh[sreg];
|
||||
get_acc_m(dreg, RAX);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(dreg, accm);
|
||||
get_ax_h(sreg, RDX);
|
||||
OR(64, R(RAX), R(RDX));
|
||||
OR(64, R(accm), R(RDX));
|
||||
// g_dsp.r.acm[dreg] = accm;
|
||||
set_acc_m(dreg);
|
||||
set_acc_m(dreg, R(accm));
|
||||
// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(dreg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(dreg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,16 +381,18 @@ void DSPEmitter::andc(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
// u16 accm = g_dsp.r.acm[dreg] & g_dsp.r.acm[1 - dreg];
|
||||
get_acc_m(dreg, RAX);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(dreg, accm);
|
||||
get_acc_m(1 - dreg, RDX);
|
||||
AND(64, R(RAX), R(RDX));
|
||||
AND(64, R(accm), R(RDX));
|
||||
// g_dsp.r.acm[dreg] = accm;
|
||||
set_acc_m(dreg);
|
||||
set_acc_m(dreg, R(accm));
|
||||
// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(dreg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(dreg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,16 +407,18 @@ void DSPEmitter::orc(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
// u16 accm = g_dsp.r.acm[dreg] | g_dsp.r.acm[1 - dreg];
|
||||
get_acc_m(dreg, RAX);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(dreg, accm);
|
||||
get_acc_m(1 - dreg, RDX);
|
||||
OR(64, R(RAX), R(RDX));
|
||||
OR(64, R(accm), R(RDX));
|
||||
// g_dsp.r.acm[dreg] = accm;
|
||||
set_acc_m(dreg);
|
||||
set_acc_m(dreg, R(accm));
|
||||
// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(dreg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(dreg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,16 +432,18 @@ void DSPEmitter::xorc(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
// u16 accm = g_dsp.r.acm[dreg] ^ g_dsp.r.acm[1 - dreg];
|
||||
get_acc_m(dreg, RAX);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(dreg, accm);
|
||||
get_acc_m(1 - dreg, RDX);
|
||||
XOR(64, R(RAX), R(RDX));
|
||||
XOR(64, R(accm), R(RDX));
|
||||
// g_dsp.r.acm[dreg] = accm;
|
||||
set_acc_m(dreg);
|
||||
set_acc_m(dreg, R(accm));
|
||||
// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(dreg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(dreg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,15 +457,17 @@ void DSPEmitter::notc(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
// u16 accm = g_dsp.r.acm[dreg] ^ 0xffff;
|
||||
get_acc_m(dreg, RAX);
|
||||
NOT(16, R(AX));
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(dreg, accm);
|
||||
NOT(16, R(accm));
|
||||
// g_dsp.r.acm[dreg] = accm;
|
||||
set_acc_m(dreg);
|
||||
set_acc_m(dreg, R(accm));
|
||||
// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(dreg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(dreg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,14 +484,16 @@ void DSPEmitter::xori(const UDSPInstruction opc)
|
||||
// u16 imm = dsp_fetch_code();
|
||||
const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
|
||||
// g_dsp.r.acm[reg] ^= imm;
|
||||
get_acc_m(reg, RAX);
|
||||
XOR(16, R(RAX), Imm16(imm));
|
||||
set_acc_m(reg);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(reg, accm);
|
||||
XOR(16, R(accm), Imm16(imm));
|
||||
set_acc_m(reg, R(accm));
|
||||
// Update_SR_Register16((s16)g_dsp.r.acm[reg], false, false, isOverS32(dsp_get_long_acc(reg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(reg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(reg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,14 +509,16 @@ void DSPEmitter::andi(const UDSPInstruction opc)
|
||||
// u16 imm = dsp_fetch_code();
|
||||
const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
|
||||
// g_dsp.r.acm[reg] &= imm;
|
||||
get_acc_m(reg, RAX);
|
||||
AND(16, R(RAX), Imm16(imm));
|
||||
set_acc_m(reg);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(reg, accm);
|
||||
AND(16, R(accm), Imm16(imm));
|
||||
set_acc_m(reg, R(accm));
|
||||
// Update_SR_Register16((s16)g_dsp.r.acm[reg], false, false, isOverS32(dsp_get_long_acc(reg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(reg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(reg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,14 +534,16 @@ void DSPEmitter::ori(const UDSPInstruction opc)
|
||||
// u16 imm = dsp_fetch_code();
|
||||
const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
|
||||
// g_dsp.r.acm[reg] |= imm;
|
||||
get_acc_m(reg, RAX);
|
||||
OR(16, R(RAX), Imm16(imm));
|
||||
set_acc_m(reg);
|
||||
X64Reg accm = RAX;
|
||||
get_acc_m(reg, accm);
|
||||
OR(16, R(accm), Imm16(imm));
|
||||
set_acc_m(reg, R(accm));
|
||||
// Update_SR_Register16((s16)g_dsp.r.acm[reg], false, false, isOverS32(dsp_get_long_acc(reg)));
|
||||
if (FlagsNeeded())
|
||||
{
|
||||
get_long_acc(reg, RCX);
|
||||
Update_SR_Register16_OverS32();
|
||||
X64Reg acc_full = RCX;
|
||||
get_long_acc(reg, acc_full);
|
||||
Update_SR_Register16_OverS32(accm, acc_full, RDX);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ void DSPEmitter::UpdateSR64AddSub(Gen::X64Reg val1, Gen::X64Reg val2, Gen::X64Re
|
||||
Update_SR_Register(result, scratch);
|
||||
}
|
||||
|
||||
// In: RAX: s64 _Value
|
||||
// In: RAX: s16 _Value (middle)
|
||||
void DSPEmitter::Update_SR_Register16(X64Reg val)
|
||||
{
|
||||
const OpArg sr_reg = m_gpr.GetReg(DSP_REG_SR);
|
||||
@ -122,7 +122,7 @@ void DSPEmitter::Update_SR_Register16(X64Reg val)
|
||||
|
||||
// // 0x04
|
||||
// if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
TEST(64, R(val), R(val));
|
||||
TEST(16, R(val), R(val));
|
||||
FixupBranch notZero = J_CC(CC_NZ);
|
||||
OR(16, sr_reg, Imm16(SR_ARITH_ZERO | SR_TOP2BITS));
|
||||
FixupBranch end = J();
|
||||
@ -149,26 +149,25 @@ void DSPEmitter::Update_SR_Register16(X64Reg val)
|
||||
m_gpr.PutReg(DSP_REG_SR);
|
||||
}
|
||||
|
||||
// In: RAX: s64 _Value
|
||||
// Clobbers RCX
|
||||
void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val)
|
||||
// In: RAX: s16 _Value (middle)
|
||||
// In: RDX: s64 _FullValue
|
||||
// Clobbers scratch
|
||||
void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val, Gen::X64Reg full_val,
|
||||
Gen::X64Reg scratch)
|
||||
{
|
||||
Update_SR_Register16(val);
|
||||
|
||||
const OpArg sr_reg = m_gpr.GetReg(DSP_REG_SR);
|
||||
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
|
||||
|
||||
// // 0x10
|
||||
// if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||
MOVSX(64, 32, RCX, R(val));
|
||||
CMP(64, R(RCX), R(val));
|
||||
// if (_FullValue != (s32)_FullValue) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||
MOVSX(64, 32, scratch, R(full_val));
|
||||
CMP(64, R(scratch), R(full_val));
|
||||
FixupBranch noOverS32 = J_CC(CC_E);
|
||||
OR(16, sr_reg, Imm16(SR_OVER_S32));
|
||||
SetJumpTarget(noOverS32);
|
||||
|
||||
m_gpr.PutReg(DSP_REG_SR);
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
// if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
||||
// AND(32, R(val), Imm32(0xc0000000));
|
||||
Update_SR_Register16(val);
|
||||
}
|
||||
|
||||
} // namespace DSP::JIT::x64
|
||||
|
Loading…
Reference in New Issue
Block a user