From 99e29c82fd2c258cfa44d569aa18a5afc40a5ef5 Mon Sep 17 00:00:00 2001 From: nakeee Date: Wed, 15 Apr 2009 22:04:44 +0000 Subject: [PATCH] DSP: make all logical operations set the logical SR_LOGIC_ZERO flag instead of the arithmetic flags assumed 0x20 is a mistake and suppose to be the logical zero flag Couldn't see any change whatsoever. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2975 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DSPCore/Src/DSPInterpreter.cpp | 104 +++++++++--------- Source/Core/DSPCore/Src/DSPInterpreter.h | 2 +- Source/Core/DSPCore/Src/DSPTables.cpp | 4 +- .../Core/DSPCore/Src/gdsp_condition_codes.cpp | 23 +++- .../Core/DSPCore/Src/gdsp_condition_codes.h | 1 + 5 files changed, 72 insertions(+), 62 deletions(-) diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp index 9e94051474..7bf073234d 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.cpp +++ b/Source/Core/DSPCore/Src/DSPInterpreter.cpp @@ -35,14 +35,6 @@ void unknown(const UDSPInstruction& opc) ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc); } -// test register and updates SR accordingly -void tsta(int reg) -{ - s64 acc = dsp_get_long_acc(reg); - - Update_SR_Register64(acc); -} - // Generic call implementation // CALLcc addressA // 0000 0010 1011 cccc @@ -669,7 +661,10 @@ void cmp(const UDSPInstruction& opc) // Test accumulator %acR. void tst(const UDSPInstruction& opc) { - tsta((opc.hex >> 11) & 0x1); + s8 reg = (opc.hex >> 11) & 0x1; + s64 acc = dsp_get_long_acc(reg); + + Update_SR_Register64(acc); } // ADDAXL $acD, $axS.l @@ -767,7 +762,10 @@ void xorr(const UDSPInstruction& opc) g_dsp.r[0x1e + dreg] ^= g_dsp.r[0x1a + sreg]; - tsta(dreg); + s64 acc = dsp_get_long_acc(dreg); + + Update_SR_LZ(acc); + // tsta(dreg); } // ANDR $acD.m, $axS.h @@ -781,7 +779,10 @@ void andr(const UDSPInstruction& opc) g_dsp.r[0x1e + dreg] &= g_dsp.r[0x1a + sreg]; - tsta(dreg); + s64 acc = dsp_get_long_acc(dreg); + + Update_SR_LZ(acc); + // tsta(dreg); } // ORR $acD.m, $axS.h @@ -796,7 +797,11 @@ void orr(const UDSPInstruction& opc) g_dsp.r[0x1e + dreg] |= g_dsp.r[0x1a + sreg]; - tsta(dreg); + s64 acc = dsp_get_long_acc(dreg); + + Update_SR_LZ(acc); + + // tsta(dreg); } // ANDC $acD.m, $ac(1-D).m @@ -812,21 +817,25 @@ void andc(const UDSPInstruction& opc) dsp_set_long_acc(D, ac1 & ac2); - if ((ac1 & ac2) == 0) - { - g_dsp.r[DSP_REG_SR] |= 0x20; // 0x40? - } - else - { - g_dsp.r[DSP_REG_SR] &= ~0x20; // 0x40? - } - - Update_SR_Register64(dsp_get_long_acc(D)); + Update_SR_LZ(dsp_get_long_acc(D)); + // Update_SR_Register64(dsp_get_long_acc(D)); } +// ORC $acD.m, $ac(1-D).m +// 0011 111d xxxx xxxx +// Logic OR middle part of accumulator $acD.m with middle part of +// accumulator $ax(1-D).m. void orc(const UDSPInstruction& opc) { - ERROR_LOG(DSPLLE, "orc not implemented"); + u8 D = (opc.hex >> 8) & 0x1; + + u16 ac1 = dsp_get_acc_m(D); + u16 ac2 = dsp_get_acc_m(1 - D); + + dsp_set_long_acc(D, ac1 | ac2); + + Update_SR_LZ(dsp_get_long_acc(D)); + // Update_SR_Register64(dsp_get_long_acc(D)); } void orf(const UDSPInstruction& opc) @@ -849,21 +858,14 @@ void nx(const UDSPInstruction& opc) // 0000 001r 1100 0000 // iiii iiii iiii iiii // Set logic zero (LZ) flag in status register $sr if result of logic AND of -// accumulator mid part $acD.m with immediate value I is equal zero. -void andfc(const UDSPInstruction& opc) +// accumulator mid part $acD.m with immediate value I is equal I. +void andcf(const UDSPInstruction& opc) { u8 reg = (opc.hex >> 8) & 0x1; u16 imm = dsp_fetch_code(); u16 val = dsp_get_acc_m(reg); - if ((val & imm) == imm) - { - g_dsp.r[DSP_REG_SR] |= 0x40; - } - else - { - g_dsp.r[DSP_REG_SR] &= ~0x40; - } + Update_SR_LZ(((val & imm) == imm)?0:1); } // Hermes switched andf and andcf, so check to make sure they are still correct @@ -873,7 +875,7 @@ void andfc(const UDSPInstruction& opc) // iiii iiii iiii iiii // Set logic zero (LZ) flag in status register $sr if result of logical AND // operation of accumulator mid part $acD.m with immediate value I is equal -// immediate value I. +// immediate value 0. void andf(const UDSPInstruction& opc) { u8 reg; @@ -884,14 +886,7 @@ void andf(const UDSPInstruction& opc) imm = dsp_fetch_code(); val = g_dsp.r[reg]; - if ((val & imm) == 0) - { - g_dsp.r[DSP_REG_SR] |= 0x40; - } - else - { - g_dsp.r[DSP_REG_SR] &= ~0x40; - } + Update_SR_LZ(((val & imm) == 0)?0:1); } // CMPI $amD, #I @@ -922,7 +917,8 @@ void xori(const UDSPInstruction& opc) u16 imm = dsp_fetch_code(); g_dsp.r[reg] ^= imm; - Update_SR_Register16((s16)g_dsp.r[reg]); + Update_SR_LZ(g_dsp.r[reg]); + // Update_SR_Register16((s16)g_dsp.r[reg]); } // ANDI $acD.m, #I @@ -935,7 +931,8 @@ void andi(const UDSPInstruction& opc) u16 imm = dsp_fetch_code(); g_dsp.r[reg] &= imm; - Update_SR_Register16((s16)g_dsp.r[reg]); + Update_SR_LZ(g_dsp.r[reg]); + // Update_SR_Register16((s16)g_dsp.r[reg]); } @@ -950,7 +947,8 @@ void ori(const UDSPInstruction& opc) u16 imm = dsp_fetch_code(); g_dsp.r[reg] |= imm; - Update_SR_Register16((s16)g_dsp.r[reg]); + Update_SR_LZ(g_dsp.r[reg]); + // Update_SR_Register16((s16)g_dsp.r[reg]); } //------------------------------------------------------------- @@ -1258,8 +1256,8 @@ void lsl16(const UDSPInstruction& opc) s64 acc = dsp_get_long_acc(areg); acc <<= 16; dsp_set_long_acc(areg, acc); - - Update_SR_Register64(acc); + Update_SR_LZ(acc); + // Update_SR_Register64(acc); } // MADD $axS.l, $axS.h @@ -1306,8 +1304,8 @@ void lsr16(const UDSPInstruction& opc) acc >>= 16; dsp_set_long_acc(areg, acc); - - Update_SR_Register64(acc); + Update_SR_LZ(acc); + // Update_SR_Register64(acc); } // ASR16 $acR @@ -1335,8 +1333,8 @@ void lsl(const UDSPInstruction& opc) acc <<= shift; dsp_set_long_acc(opc.areg, acc); - - Update_SR_Register64(acc); + Update_SR_LZ(acc); + // Update_SR_Register64(acc); } // LSR $acR, #I @@ -1351,8 +1349,8 @@ void lsr(const UDSPInstruction& opc) acc &= 0x000000FFFFFFFFFFULL; acc >>= shift; dsp_set_long_acc(opc.areg, (s64)acc); - - Update_SR_Register64(acc); + Update_SR_LZ(acc); + // Update_SR_Register64(acc); } // ASL $acR, #I diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.h b/Source/Core/DSPCore/Src/DSPInterpreter.h index dec7f9e187..4e3ba86f50 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.h +++ b/Source/Core/DSPCore/Src/DSPInterpreter.h @@ -129,7 +129,7 @@ void ilrr(const UDSPInstruction& opc); void ilrrd(const UDSPInstruction& opc); void ilrri(const UDSPInstruction& opc); void ilrrn(const UDSPInstruction& opc); -void andfc(const UDSPInstruction& opc); +void andcf(const UDSPInstruction& opc); void andf(const UDSPInstruction& opc); void xori(const UDSPInstruction& opc); void andi(const UDSPInstruction& opc); diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp index a1d3222906..5437ae9edc 100644 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -176,7 +176,7 @@ const DSPOPCTemplate opcodes[] = {"ADDIS", 0x0400, 0xfe00, DSPInterpreter::addis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,}, - {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andfc, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,}, + {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andcf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,}, {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, @@ -225,8 +225,6 @@ const DSPOPCTemplate opcodes[] = // calculations or something? Or clamp? // SET15/CLR15 is commonly used around MULXAC in Zeldas. // SET16 is done around complicated loops with many madds etc. - // It seems SET16 come in all cases found with either CR or IR (almost always with AR3) - // Set40 also comes with CR and AR3, but it's not common enough to see the connection. {"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 ba3c74eaf7..c88962f6e6 100644 --- a/Source/Core/DSPCore/Src/gdsp_condition_codes.cpp +++ b/Source/Core/DSPCore/Src/gdsp_condition_codes.cpp @@ -42,8 +42,8 @@ void Update_SR_Register64(s64 _Value) // weird if ((_Value >> 62) == 0) - { - g_dsp.r[DSP_REG_SR] |= 0x20; + { + Update_SR_LZ(0); } } @@ -64,10 +64,23 @@ void Update_SR_Register16(s16 _Value) // weird if ((_Value >> 14) == 0) { - g_dsp.r[DSP_REG_SR] |= 0x20; + Update_SR_LZ(0); } } +void Update_SR_LZ(s64 value) { + + if (value == 0) + { + g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO; + } + else + { + g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO; + } + +} + // If this always returns 1, Hermes' demo sounds better. // However, most AX games are negatively affected. int GetMultiplyModifier() @@ -133,13 +146,13 @@ bool CheckCondition(u8 _Condition) case 0xc: // LNZ - LOGIC NOT ZERO - if (!(g_dsp.r[DSP_REG_SR] & 0x40)) + if (!(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO)) taken = true; break; case 0xd: // LZ - LOGIC ZERO - if (g_dsp.r[DSP_REG_SR] & 0x40) + if (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) taken = true; break; diff --git a/Source/Core/DSPCore/Src/gdsp_condition_codes.h b/Source/Core/DSPCore/Src/gdsp_condition_codes.h index df28775210..5e95d00c4e 100644 --- a/Source/Core/DSPCore/Src/gdsp_condition_codes.h +++ b/Source/Core/DSPCore/Src/gdsp_condition_codes.h @@ -46,6 +46,7 @@ int GetMultiplyModifier(); void Update_SR_Register16(s16 _Value); void Update_SR_Register64(s64 _Value); +void Update_SR_LZ(s64 value); } // namespace