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
This commit is contained in:
nakeee 2009-04-21 08:53:36 +00:00
parent 874a31e8ba
commit cf5b6efba0
5 changed files with 80 additions and 46 deletions

View File

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

View File

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

View File

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

View File

@ -62,18 +62,18 @@ inline u16 dsp_op_read_reg(u8 reg)
{
u16 val;
switch (reg & 0x1f)
{
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
val = dsp_reg_load_stack(reg - 0x0c);
break;
switch (reg & 0x1f) {
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
default:
val = g_dsp.r[reg];
break;
val = dsp_reg_load_stack(reg - 0x0c);
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;
}
}

View File

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