mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
DSPLLE - small idleskip improvment for zelda
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5248 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -30,7 +30,7 @@ u8 code_flags[ISPACE];
|
|||||||
// as well give up its time slice immediately, after executing once.
|
// as well give up its time slice immediately, after executing once.
|
||||||
|
|
||||||
// Max signature length is 6. A 0 in a signature is ignored.
|
// Max signature length is 6. A 0 in a signature is ignored.
|
||||||
#define NUM_IDLE_SIGS 7
|
#define NUM_IDLE_SIGS 8
|
||||||
#define MAX_IDLE_SIG_SIZE 6
|
#define MAX_IDLE_SIG_SIZE 6
|
||||||
|
|
||||||
// 0xFFFF means ignore.
|
// 0xFFFF means ignore.
|
||||||
@ -65,7 +65,12 @@ const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
|||||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||||
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
||||||
0x029c, 0xFFFF, // JLNZ 0x05cf
|
0x029c, 0xFFFF, // JLNZ 0x05cf
|
||||||
0 }
|
0 },
|
||||||
|
// From Zelda - experimental
|
||||||
|
{ 0x00da, 0x0352, // lr $AX0.H, @0x0352
|
||||||
|
0x8600, // tstaxh $AX0.H
|
||||||
|
0x0295, 0xFFFF, // jz 0x????
|
||||||
|
0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
@ -121,7 +126,7 @@ void AnalyzeRange(int start_addr, int end_addr)
|
|||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x (sigNum:%d)", addr, s+1);
|
||||||
code_flags[addr] |= CODE_IDLE_SKIP;
|
code_flags[addr] |= CODE_IDLE_SKIP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ void Update_SR_Register64(s64 _Value, bool carry, bool overflow)
|
|||||||
g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x20 - Checks if top bits of m are equal, what is it good for?
|
// 0x20 - Checks if top bits of m are equal
|
||||||
if (((_Value & 0xc0000000) == 0) || ((_Value & 0xc0000000) == 0xc0000000))
|
if (((_Value & 0xc0000000) == 0) || ((_Value & 0xc0000000) == 0xc0000000))
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
||||||
@ -104,7 +104,7 @@ void Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32)
|
|||||||
g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x20 - Checks if top bits of m are equal, what is it good for?
|
// 0x20 - Checks if top bits of m are equal
|
||||||
if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
||||||
@ -152,7 +152,7 @@ inline bool isConditionA() {
|
|||||||
return (((g_dsp.r[DSP_REG_SR] & SR_OVER_S32) || (g_dsp.r[DSP_REG_SR] & SR_TOP2BITS)) && !(g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO)) ? true : false;
|
return (((g_dsp.r[DSP_REG_SR] & SR_OVER_S32) || (g_dsp.r[DSP_REG_SR] & SR_TOP2BITS)) && !(g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO)) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//see gdsp_registers.h for flags
|
//see DSPCore.h for flags
|
||||||
bool CheckCondition(u8 _Condition)
|
bool CheckCondition(u8 _Condition)
|
||||||
{
|
{
|
||||||
switch (_Condition & 0xf)
|
switch (_Condition & 0xf)
|
||||||
@ -190,8 +190,7 @@ bool CheckCondition(u8 _Condition)
|
|||||||
case 0xf: // Empty - always true.
|
case 0xf: // Empty - always true.
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x", _Condition & 0xf);
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ inline s64 dsp_get_long_prod()
|
|||||||
|
|
||||||
inline s64 dsp_get_long_prod_round_prodl()
|
inline s64 dsp_get_long_prod_round_prodl()
|
||||||
{
|
{
|
||||||
return (dsp_get_long_prod() + 0x8000) & ~0xffff;
|
return (dsp_get_long_prod() + 0x7fff) & ~0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For accurate emulation, this is wrong - but the real prod registers behave
|
// For accurate emulation, this is wrong - but the real prod registers behave
|
||||||
|
@ -108,7 +108,7 @@ const DSPOPCTemplate opcodes[] =
|
|||||||
{"JMPxB", 0x029b, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
{"JMPxB", 0x029b, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
||||||
{"JLNZ", 0x029c, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
{"JLNZ", 0x029c, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
||||||
{"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
{"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
||||||
{"JMPO", 0x029e, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
{"JO", 0x029e, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
||||||
{"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
{"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true},
|
||||||
|
|
||||||
{"JRGE", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
{"JRGE", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||||
@ -125,7 +125,7 @@ const DSPOPCTemplate opcodes[] =
|
|||||||
{"JMPRxB", 0x170b, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
{"JMPRxB", 0x170b, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||||
{"JRLNZ", 0x170c, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
{"JRLNZ", 0x170c, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||||
{"JRLZ", 0x170d, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
{"JRLZ", 0x170d, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||||
{"JMPRO", 0x170e, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
{"JRO", 0x170e, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||||
{"JMPR", 0x170f, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
{"JMPR", 0x170f, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||||
|
|
||||||
{"CALLRGE", 0x1710, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
{"CALLRGE", 0x1710, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||||
|
@ -46,25 +46,25 @@ inline s64 dsp_get_multiply_prod(u16 a, u16 b, u8 sign)
|
|||||||
return prod;
|
return prod;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 dsp_multiply(u16 a, u16 b, u8 sign = 0)
|
inline s64 dsp_multiply(u16 a, u16 b, u8 sign = 0)
|
||||||
{
|
{
|
||||||
s64 prod = dsp_get_multiply_prod(a, b, sign);
|
s64 prod = dsp_get_multiply_prod(a, b, sign);
|
||||||
return prod;
|
return prod;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 dsp_multiply_add(u16 a, u16 b, u8 sign = 0)
|
inline s64 dsp_multiply_add(u16 a, u16 b, u8 sign = 0)
|
||||||
{
|
{
|
||||||
s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign);
|
s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign);
|
||||||
return prod;
|
return prod;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 dsp_multiply_sub(u16 a, u16 b, u8 sign = 0)
|
inline s64 dsp_multiply_sub(u16 a, u16 b, u8 sign = 0)
|
||||||
{
|
{
|
||||||
s64 prod = dsp_get_long_prod() - dsp_get_multiply_prod(a, b, sign);
|
s64 prod = dsp_get_long_prod() - dsp_get_multiply_prod(a, b, sign);
|
||||||
return prod;
|
return prod;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 dsp_multiply_mulx(u8 axh0, u8 axh1, u16 val1, u16 val2)
|
inline s64 dsp_multiply_mulx(u8 axh0, u8 axh1, u16 val1, u16 val2)
|
||||||
{
|
{
|
||||||
s64 result;
|
s64 result;
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ void clrp(const UDSPInstruction opc)
|
|||||||
// 1000 0101 xxxx xxxx
|
// 1000 0101 xxxx xxxx
|
||||||
// Test prod regs value.
|
// Test prod regs value.
|
||||||
//
|
//
|
||||||
// flags out: xx xx0x <- CF??
|
// flags out: --xx xx0x
|
||||||
void tstprod(const UDSPInstruction opc)
|
void tstprod(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
s64 prod = dsp_get_long_prod();
|
s64 prod = dsp_get_long_prod();
|
||||||
@ -136,7 +136,7 @@ void tstprod(const UDSPInstruction opc)
|
|||||||
// 0110 111d xxxx xxxx
|
// 0110 111d xxxx xxxx
|
||||||
// Moves multiply product from $prod register to accumulator $acD register.
|
// Moves multiply product from $prod register to accumulator $acD register.
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void movp(const UDSPInstruction opc)
|
void movp(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 8) & 0x1;
|
u8 dreg = (opc >> 8) & 0x1;
|
||||||
@ -154,7 +154,7 @@ void movp(const UDSPInstruction opc)
|
|||||||
// Moves negative of multiply product from $prod register to accumulator
|
// Moves negative of multiply product from $prod register to accumulator
|
||||||
// $acD register.
|
// $acD register.
|
||||||
//
|
//
|
||||||
// flags out: xx xx0x <- CF??
|
// flags out: --xx xx0x
|
||||||
void movnp(const UDSPInstruction opc)
|
void movnp(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 8) & 0x1;
|
u8 dreg = (opc >> 8) & 0x1;
|
||||||
@ -172,7 +172,7 @@ void movnp(const UDSPInstruction opc)
|
|||||||
// Moves multiply product from $prod register to accumulator $acD
|
// Moves multiply product from $prod register to accumulator $acD
|
||||||
// register and sets $acD.l to 0
|
// register and sets $acD.l to 0
|
||||||
//
|
//
|
||||||
// flags out: xx xx0x <- CF??
|
// flags out: --xx xx0x
|
||||||
void movpz(const UDSPInstruction opc)
|
void movpz(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 8) & 0x01;
|
u8 dreg = (opc >> 8) & 0x01;
|
||||||
@ -190,12 +190,13 @@ void movpz(const UDSPInstruction opc)
|
|||||||
// Adds secondary accumulator $axS to product register and stores result
|
// Adds secondary accumulator $axS to product register and stores result
|
||||||
// in accumulator register. Low 16-bits of $acD ($acD.l) are set to 0.
|
// in accumulator register. Low 16-bits of $acD ($acD.l) are set to 0.
|
||||||
//
|
//
|
||||||
// flags out: ?-xx xx??
|
// flags out: --xx xx0x
|
||||||
void addpaxz(const UDSPInstruction opc)
|
void addpaxz(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 8) & 0x1;
|
u8 dreg = (opc >> 8) & 0x1;
|
||||||
u8 sreg = (opc >> 9) & 0x1;
|
u8 sreg = (opc >> 9) & 0x1;
|
||||||
|
|
||||||
|
s64 oldprod = dsp_get_long_prod();
|
||||||
s64 prod = dsp_get_long_prod_round_prodl();
|
s64 prod = dsp_get_long_prod_round_prodl();
|
||||||
s64 ax = dsp_get_long_acx(sreg);
|
s64 ax = dsp_get_long_acx(sreg);
|
||||||
s64 res = prod + (ax & ~0xffff);
|
s64 res = prod + (ax & ~0xffff);
|
||||||
@ -204,7 +205,7 @@ void addpaxz(const UDSPInstruction opc)
|
|||||||
|
|
||||||
dsp_set_long_acc(dreg, res);
|
dsp_set_long_acc(dreg, res);
|
||||||
res = dsp_get_long_acc(dreg);
|
res = dsp_get_long_acc(dreg);
|
||||||
Update_SR_Register64(res);
|
Update_SR_Register64(res, isCarry(oldprod, res), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----
|
//----
|
||||||
@ -246,7 +247,7 @@ void mul(const UDSPInstruction opc)
|
|||||||
// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
|
// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
|
||||||
// accumulator $axS (treat them both as signed).
|
// accumulator $axS (treat them both as signed).
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulac(const UDSPInstruction opc)
|
void mulac(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
@ -270,7 +271,7 @@ void mulac(const UDSPInstruction opc)
|
|||||||
// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
|
// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
|
||||||
// accumulator $axS (treat them both as signed).
|
// accumulator $axS (treat them both as signed).
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulmv(const UDSPInstruction opc)
|
void mulmv(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
@ -295,7 +296,7 @@ void mulmv(const UDSPInstruction opc)
|
|||||||
// accumulator $axS by high part $axS.h of secondary accumulator $axS (treat
|
// accumulator $axS by high part $axS.h of secondary accumulator $axS (treat
|
||||||
// them both as signed).
|
// them both as signed).
|
||||||
//
|
//
|
||||||
// flags out: xx xx0x
|
// flags out: --xx xx0x
|
||||||
void mulmvz(const UDSPInstruction opc)
|
void mulmvz(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
@ -339,7 +340,7 @@ void mulx(const UDSPInstruction opc)
|
|||||||
// $ax0 by one part $ax1. Part is selected by S and
|
// $ax0 by one part $ax1. Part is selected by S and
|
||||||
// T bits. Zero selects low part, one selects high part.
|
// T bits. Zero selects low part, one selects high part.
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulxac(const UDSPInstruction opc)
|
void mulxac(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
@ -364,7 +365,7 @@ void mulxac(const UDSPInstruction opc)
|
|||||||
// $ax0 by one part $ax1. Part is selected by S and
|
// $ax0 by one part $ax1. Part is selected by S and
|
||||||
// T bits. Zero selects low part, one selects high part.
|
// T bits. Zero selects low part, one selects high part.
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulxmv(const UDSPInstruction opc)
|
void mulxmv(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = ((opc >> 8) & 0x1);
|
u8 rreg = ((opc >> 8) & 0x1);
|
||||||
@ -390,7 +391,7 @@ void mulxmv(const UDSPInstruction opc)
|
|||||||
// Part is selected by S and T bits. Zero selects low part,
|
// Part is selected by S and T bits. Zero selects low part,
|
||||||
// one selects high part.
|
// one selects high part.
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulxmvz(const UDSPInstruction opc)
|
void mulxmvz(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
@ -435,7 +436,7 @@ void mulc(const UDSPInstruction opc)
|
|||||||
// secondary accumulator $axS (treat them both as signed). Add product
|
// secondary accumulator $axS (treat them both as signed). Add product
|
||||||
// register before multiplication to accumulator $acR.
|
// register before multiplication to accumulator $acR.
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulcac(const UDSPInstruction opc)
|
void mulcac(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
@ -461,7 +462,7 @@ void mulcac(const UDSPInstruction opc)
|
|||||||
// register before multiplication to accumulator $acR.
|
// register before multiplication to accumulator $acR.
|
||||||
// possible mistake in duddie's doc axT.h rather than axS.h
|
// possible mistake in duddie's doc axT.h rather than axS.h
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulcmv(const UDSPInstruction opc)
|
void mulcmv(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
@ -488,7 +489,7 @@ void mulcmv(const UDSPInstruction opc)
|
|||||||
// register before multiplication to accumulator $acR, set low part of
|
// register before multiplication to accumulator $acR, set low part of
|
||||||
// accumulator $acR.l to zero.
|
// accumulator $acR.l to zero.
|
||||||
//
|
//
|
||||||
// flags out: xx xx00
|
// flags out: --xx xx0x
|
||||||
void mulcmvz(const UDSPInstruction opc)
|
void mulcmvz(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 rreg = (opc >> 8) & 0x1;
|
u8 rreg = (opc >> 8) & 0x1;
|
||||||
|
Reference in New Issue
Block a user