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:
Pokechu22 2022-05-30 18:31:38 -07:00
parent 70bf89fa59
commit f88b7ab6b3
3 changed files with 86 additions and 67 deletions

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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