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:
parent
874a31e8ba
commit
cf5b6efba0
|
@ -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;
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue