Merge pull request #10032 from Pokechu22/dsp-lle-masks

DSP masking and sign extension fixes
This commit is contained in:
Tilka
2021-08-18 20:20:31 +01:00
committed by GitHub
6 changed files with 140 additions and 22 deletions

View File

@ -200,7 +200,7 @@ enum : u16
SR_LOGIC_ZERO = 0x0040,
SR_OVERFLOW_STICKY =
0x0080, // Set at the same time as 0x2 (under same conditions) - but not cleared the same
SR_100 = 0x0100, // Unknown
SR_100 = 0x0100, // Unknown, always reads back as 0
SR_INT_ENABLE = 0x0200, // Not 100% sure but duddie says so. This should replace the hack, if so.
SR_400 = 0x0400, // Unknown
SR_EXT_INT_ENABLE = 0x0800, // Appears in zelda - seems to disable external interrupts

View File

@ -394,13 +394,14 @@ s16 Interpreter::GetAXHigh(s32 reg) const
s64 Interpreter::GetLongAcc(s32 reg) const
{
const auto& state = m_dsp_core.DSPState();
return static_cast<s64>(state.r.ac[reg].val << 24) >> 24;
return static_cast<s64>(state.r.ac[reg].val);
}
void Interpreter::SetLongAcc(s32 reg, s64 value)
{
auto& state = m_dsp_core.DSPState();
state.r.ac[reg].val = static_cast<u64>(value);
// 40-bit sign extension
state.r.ac[reg].val = static_cast<u64>((value << (64 - 40)) >> (64 - 40));
}
s16 Interpreter::GetAccLow(s32 reg) const
@ -687,11 +688,11 @@ void Interpreter::OpWriteRegister(int reg_, u16 val)
switch (reg)
{
// 8-bit sign extended registers. Should look at prod.h too...
// 8-bit sign extended registers.
case DSP_REG_ACH0:
case DSP_REG_ACH1:
// sign extend from the bottom 8 bits.
state.r.ac[reg - DSP_REG_ACH0].h = (u16)(s16)(s8)(u8)val;
// Sign extend from the bottom 8 bits.
state.r.ac[reg - DSP_REG_ACH0].h = static_cast<s8>(val);
break;
// Stack registers.
@ -720,10 +721,10 @@ void Interpreter::OpWriteRegister(int reg_, u16 val)
state.r.wr[reg - DSP_REG_WR0] = val;
break;
case DSP_REG_CR:
state.r.cr = val;
state.r.cr = val & 0x00ff;
break;
case DSP_REG_SR:
state.r.sr = val;
state.r.sr = val & ~SR_100;
break;
case DSP_REG_PRODL:
state.r.prod.l = val;
@ -732,7 +733,8 @@ void Interpreter::OpWriteRegister(int reg_, u16 val)
state.r.prod.m = val;
break;
case DSP_REG_PRODH:
state.r.prod.h = val;
// Unlike ac0.h and ac1.h, prod.h is not sign-extended
state.r.prod.h = val & 0x00ff;
break;
case DSP_REG_PRODM2:
state.r.prod.m2 = val;

View File

@ -751,6 +751,7 @@ void DSPJitRegCache::PutReg(int reg, bool dirty)
else if (oparg.IsImm())
{
// TODO: Immediates?
ASSERT(false);
}
else
{
@ -772,6 +773,58 @@ void DSPJitRegCache::PutReg(int reg, bool dirty)
m_emitter.SAR(64, oparg, Imm8(64 - 40));
}
break;
case DSP_REG_CR:
case DSP_REG_PRODH:
if (dirty)
{
if (oparg.IsSimpleReg())
{
// register is already shifted correctly
// (if at all)
// Zero extend from the bottom 8 bits.
m_emitter.MOVZX(16, 8, oparg.GetSimpleReg(), oparg);
}
else if (oparg.IsImm())
{
// TODO: Immediates?
ASSERT(false);
}
else
{
// This works on the memory, so use reg instead
// of real_reg, since it has the right loc
X64Reg tmp = GetFreeXReg();
// Zero extend from the bottom 8 bits.
m_emitter.MOVZX(16, 8, tmp, m_regs[reg].loc);
m_emitter.MOV(16, m_regs[reg].loc, R(tmp));
PutXReg(tmp);
}
}
break;
case DSP_REG_SR:
if (dirty)
{
if (oparg.IsSimpleReg())
{
// register is already shifted correctly
// (if at all)
// Clear SR_100, which always reads back as 0
m_emitter.AND(16, R(oparg.GetSimpleReg()), Gen::Imm16(~SR_100));
}
else if (oparg.IsImm())
{
// TODO: Immediates?
ASSERT(false);
}
else
{
// Clear SR_100, which always reads back as 0
m_emitter.AND(16, m_regs[reg].loc, Gen::Imm16(~SR_100));
}
}
break;
default:
break;
}

View File

@ -109,12 +109,6 @@ void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg)
{
switch (reg & 0x1f)
{
// 8-bit sign extended registers.
case DSP_REG_ACH0:
case DSP_REG_ACH1:
m_gpr.WriteReg(reg, R(host_sreg));
break;
// Stack registers.
case DSP_REG_ST0:
case DSP_REG_ST1:
@ -133,11 +127,6 @@ void DSPEmitter::dsp_op_write_reg_imm(int reg, u16 val)
{
switch (reg & 0x1f)
{
// 8-bit sign extended registers. Should look at prod.h too...
case DSP_REG_ACH0:
case DSP_REG_ACH1:
m_gpr.WriteReg(reg, Imm16((u16)(s16)(s8)(u8)val));
break;
// Stack registers.
case DSP_REG_ST0:
case DSP_REG_ST1: