From 858d0675b9d940fbd2062c31aabac34dadd853e8 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sat, 14 Aug 2021 17:26:40 -0700 Subject: DSPLLE: Handle cr, sr, and prod.h masking --- Source/Core/Core/DSP/DSPCore.h | 2 +- .../Core/Core/DSP/Interpreter/DSPInterpreter.cpp | 9 ++-- Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp | 53 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) (limited to 'Source/Core') diff --git a/Source/Core/Core/DSP/DSPCore.h b/Source/Core/Core/DSP/DSPCore.h index 8162dde619..506e3995d4 100644 --- a/Source/Core/Core/DSP/DSPCore.h +++ b/Source/Core/Core/DSP/DSPCore.h @@ -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 diff --git a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp index 5d8fd7e32b..3d1e7216ce 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp @@ -687,7 +687,7 @@ 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. @@ -720,10 +720,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 +732,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; diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp index d6ffde8d00..1d3b2768de 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp @@ -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; } -- cgit v1.2.3 From 3b4bc9852fa19a66188ce2015ba8b1ab008dd9b3 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 15 Aug 2021 18:18:43 -0700 Subject: DSPInterpreter: Fix sign extension of accumulators The extension needs to happen in SetLongAcc, not GetLongAcc, as the extension needs to always be reflected in acS.h. There is no functional difference with the write handler for acS.h, but it is more readable than 4 casts in a row. --- Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Source/Core') diff --git a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp index 3d1e7216ce..1fd3aa3ff3 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp @@ -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(state.r.ac[reg].val << 24) >> 24; + return static_cast(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(value); + // 40-bit sign extension + state.r.ac[reg].val = static_cast((value << (64 - 40)) >> (64 - 40)); } s16 Interpreter::GetAccLow(s32 reg) const @@ -690,8 +691,8 @@ void Interpreter::OpWriteRegister(int reg_, u16 val) // 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(val); break; // Stack registers. -- cgit v1.2.3 From 439bf1597b0c3c067c9aef40a65118550ff7a7bd Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 16 Aug 2021 13:46:37 -0700 Subject: DSPJitUtil: Remove redundant handling of ac0.h and ac1.h m_gpr.WriteReg calls PutReg which already handles the sign extension. --- Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'Source/Core') diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp index 896fd30d40..4957947b40 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp @@ -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: -- cgit v1.2.3