From cf5b6efba007cf3fc576d6fd540aa918b02213d0 Mon Sep 17 00:00:00 2001 From: nakeee Date: Tue, 21 Apr 2009 08:53:36 +0000 Subject: [PATCH] DSP change condition code in accordance to latest finding git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3027 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DSPCore/Src/DSPInterpreter.cpp | 1 - Source/Core/DSPCore/Src/DSPTables.cpp | 5 +- .../Core/DSPCore/Src/gdsp_condition_codes.cpp | 31 +++---- Source/Core/DSPCore/Src/gdsp_opcodes_helper.h | 81 ++++++++++++++----- Source/Core/DSPCore/Src/gdsp_registers.h | 8 +- 5 files changed, 80 insertions(+), 46 deletions(-) diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp index b23e636593..b7e0162cbb 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.cpp +++ b/Source/Core/DSPCore/Src/DSPInterpreter.cpp @@ -793,7 +793,6 @@ void andr(const UDSPInstruction& opc) // 0011 10sd xxxx xxxx // Logic OR middle part of accumulator $acD.m with high part of // secondary accumulator $axS.h. - void orr(const UDSPInstruction& opc) { u8 sreg = (opc.hex >> 9) & 0x1; diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp index 73d78ee658..321b253718 100644 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -111,7 +111,7 @@ const DSPOPCTemplate opcodes[] = {"IFGE", 0x0277, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, {"IFLNZ", 0x027c, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, {"IFLZ", 0x027d, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF", 0x027f, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, // Hermes doesn't list this + {"IF", 0x027f, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, // This is just nop {"JNS", 0x0290, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL}, {"JS", 0x0291, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL}, @@ -219,11 +219,8 @@ const DSPOPCTemplate opcodes[] = {"M0", 0x8b00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // These guys probably change the precision or range of some operations. - // The question is which. 16-bit mode vs 40-bit mode sounds plausible for - // SET40/SET16. Maybe Set15 makes the dsp drop the top bit from all // calculations or something? Or clamp? // SET15/CLR15 is commonly used around MULXAC in Zeldas. - // SET16 is done around complicated loops with many madds etc. {"CLR15", 0x8c00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, {"SET15", 0x8d00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, {"SET40", 0x8e00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, diff --git a/Source/Core/DSPCore/Src/gdsp_condition_codes.cpp b/Source/Core/DSPCore/Src/gdsp_condition_codes.cpp index 40eadebfac..ab886a330d 100644 --- a/Source/Core/DSPCore/Src/gdsp_condition_codes.cpp +++ b/Source/Core/DSPCore/Src/gdsp_condition_codes.cpp @@ -81,12 +81,6 @@ void Update_SR_LZ(s64 value) { } -// If this always returns 1, Hermes' demo sounds better. -// However, most AX games are negatively affected. -// nakee: It seems to be enough to start the bit with 1 to fix Hermes' demo without breaking -// anything. I also can't seem to find what sets that bit, sbset is called with 0/2/3/5/6 -// and sbclr with 0/2-6 (14 requires 8). Also trying to print when the register is set to 1 -// didn't seem to give any result. int GetMultiplyModifier() { if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) @@ -96,6 +90,14 @@ int GetMultiplyModifier() } +inline bool isSign() { + return ((g_dsp.r[DSP_REG_SR] & 0x02) || (g_dsp.r[DSP_REG_SR] & 0x08)); +} + +inline bool isZero() { + return g_dsp.r[DSP_REG_SR] & 0x04; +} + //see gdsp_registers.h for flags bool CheckCondition(u8 _Condition) { @@ -103,45 +105,44 @@ bool CheckCondition(u8 _Condition) switch (_Condition & 0xf) { case 0x0: //NS - NOT SIGN - if ((!(g_dsp.r[DSP_REG_SR] & 0x02)) && (!(g_dsp.r[DSP_REG_SR] & 0x08))) + if (! isSign()) taken = true; break; case 0x1: // S - SIGN - if ((!(g_dsp.r[DSP_REG_SR] & 0x02)) && (g_dsp.r[DSP_REG_SR] & 0x08)) + if (isSign()) taken = true; break; case 0x2: // G - GREATER - - if ((!(g_dsp.r[DSP_REG_SR] & 0x02)) && (!(g_dsp.r[DSP_REG_SR] & 0x08)) && !((g_dsp.r[DSP_REG_SR] & 0x04))) // gets zelda stuck + if (! isSign() && ! isZero()) taken = true; break; case 0x3: // LE - LESS EQUAL - if ((!(g_dsp.r[DSP_REG_SR] & 0x02)) && ((g_dsp.r[DSP_REG_SR] & 0x08) || (g_dsp.r[DSP_REG_SR] & 0x04))) + if (isSign() || isZero()) taken = true; break; case 0x4: // NZ - NOT ZERO - if (!(g_dsp.r[DSP_REG_SR] & 0x04)) + if (!isZero()) taken = true; break; case 0x5: // Z - ZERO - if (g_dsp.r[DSP_REG_SR] & 0x04) + if (isZero()) taken = true; break; case 0x6: // L - LESS - if (!(g_dsp.r[DSP_REG_SR] & 0x02) && (g_dsp.r[DSP_REG_SR] & 0x08)) + if (isSign()) taken = true; break; case 0x7: // GE - GREATER EQUAL - if ((!(g_dsp.r[DSP_REG_SR] & 0x02)) && (!(g_dsp.r[DSP_REG_SR] & 0x08) || (g_dsp.r[DSP_REG_SR] & 0x04))) + if (! isSign() || isZero()) taken = true; break; diff --git a/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h index 36b0e9a4d5..02eae01d85 100644 --- a/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h +++ b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h @@ -61,19 +61,19 @@ inline bool dsp_SR_is_flag_set(int flag) inline u16 dsp_op_read_reg(u8 reg) { u16 val; + + switch (reg & 0x1f) { + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: - switch (reg & 0x1f) - { - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - val = dsp_reg_load_stack(reg - 0x0c); - break; + val = dsp_reg_load_stack(reg - 0x0c); + break; - default: - val = g_dsp.r[reg]; - break; + default: + val = g_dsp.r[reg]; + break; } return val; @@ -82,18 +82,55 @@ inline u16 dsp_op_read_reg(u8 reg) inline void dsp_op_write_reg(u8 reg, u16 val) { - switch (reg & 0x1f) - { - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - dsp_reg_store_stack(reg - 0x0c, val); - break; + switch (reg & 0x1f) { - default: - g_dsp.r[reg] = val; - break; + + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dsp_reg_store_stack(reg - 0x0c, val); + break; +#if 0 // FIXME + case 0x1e: // AC0.M + case 0x1f: // AC1.M + // in "s16 mode", LRI $AC0.M, xxx will set AC0.L and AC0.H to 0, + // while it won't in "s40 mode". + if (g_dsp.r[DSP_REG_SR] & SR_16_BIT) { + g_dsp.r[reg - 0x2] = 0; // L + g_dsp.r[reg - 0xe] = 0; // H + } + + g_dsp.r[reg] = val; + break; + + + case 0x1c: // AC0.L + case 0x1d: // AC1.L + + if (g_dsp.r[DSP_REG_SR] & SR_16_BIT) { + g_dsp.r[reg + 0x2] = 0; // M + g_dsp.r[reg - 0xc] = 0; // H + } + + g_dsp.r[reg] = val; + break; + + case 0x10: // AC0.H + case 0x11: // AC1.H + if (g_dsp.r[DSP_REG_SR] & SR_16_BIT) { + g_dsp.r[reg + 0xc] = 0; // L + g_dsp.r[reg + 0xe] = 0; // M + } + + g_dsp.r[reg] = val; + break; +#endif + + + default: + g_dsp.r[reg] = val; + break; } } diff --git a/Source/Core/DSPCore/Src/gdsp_registers.h b/Source/Core/DSPCore/Src/gdsp_registers.h index 2d7b5d0946..9e04a77705 100644 --- a/Source/Core/DSPCore/Src/gdsp_registers.h +++ b/Source/Core/DSPCore/Src/gdsp_registers.h @@ -92,12 +92,12 @@ #define DSP_STACK_C 0 #define DSP_STACK_D 1 -// These are probably not accurate. Do not use yet. + #define SR_UNKNOWN 0x0002 // ???????? -#define SR_ARITH_ZERO 0x0004 -#define SR_SIGN 0x0008 +#define SR_ARITH_ZERO 0x0004 +#define SR_SIGN 0x0008 // tested #define SR_TOP2BITS 0x0020 // this is an odd one. -#define SR_LOGIC_ZERO 0x0040 // ?? duddie's doc sometimes say & 1<<6 (0x40), sometimes 1<<14 (0x4000), while we have 0x20 .. eh +#define SR_LOGIC_ZERO 0x0040 #define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so. #define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2) #define SR_TOP_BIT_UNK 0x8000 // 1 = normal. 0 = x2 (CLR15, SET15)