mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
DSPLLE - tons of bugs fixed... try Zelda ucode games under LLE now (like Luigi Mansion :)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5211 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
02edaf3db8
commit
d9714c3c9d
@ -79,10 +79,15 @@ void nr(const UDSPInstruction& opc) {
|
||||
// Move value of $acS.l to the $axD.l.
|
||||
void mv(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = opc.hex & 0x3;
|
||||
u8 sreg = (opc.hex & 0x3) + DSP_REG_ACL0;
|
||||
u8 dreg = ((opc.hex >> 2) & 0x3);
|
||||
|
||||
writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r[sreg + DSP_REG_ACL0]);
|
||||
|
||||
#if 0 //more tests
|
||||
if ((sreg >= DSP_REG_ACM0) && (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT))
|
||||
writeToBackLog(0, dreg + DSP_REG_AXL0, ((u16)dsp_get_acc_h(sreg-DSP_REG_ACM0) & 0x0080) ? 0x8000 : 0x7fff);
|
||||
else
|
||||
#endif
|
||||
writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r[sreg]);
|
||||
}
|
||||
|
||||
// S @$D, $acD.l
|
||||
@ -331,12 +336,12 @@ void ld(const UDSPInstruction& opc)
|
||||
|
||||
writeToBackLog(2, sreg, dsp_increment_addr_reg(sreg));
|
||||
} else {
|
||||
writeToBackLog(0, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
|
||||
if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3]))
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
else
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
|
||||
writeToBackLog(2, dreg, dsp_increment_addr_reg(dreg));
|
||||
}
|
||||
@ -363,12 +368,12 @@ void ldn(const UDSPInstruction& opc)
|
||||
|
||||
writeToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]));
|
||||
} else {
|
||||
writeToBackLog(0, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
|
||||
if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3]))
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
else
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
|
||||
writeToBackLog(2, dreg, dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]));
|
||||
}
|
||||
@ -396,12 +401,12 @@ void ldm(const UDSPInstruction& opc)
|
||||
|
||||
writeToBackLog(2, sreg, dsp_increment_addr_reg(sreg));
|
||||
} else {
|
||||
writeToBackLog(0, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
|
||||
if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3]))
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
else
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
|
||||
writeToBackLog(2, dreg, dsp_increment_addr_reg(dreg));
|
||||
}
|
||||
@ -429,12 +434,12 @@ void ldnm(const UDSPInstruction& opc)
|
||||
|
||||
writeToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]));
|
||||
} else {
|
||||
writeToBackLog(0, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
|
||||
if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3]))
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[dreg]));
|
||||
else
|
||||
writeToBackLog(1, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r[DSP_REG_AR3]));
|
||||
|
||||
writeToBackLog(2, dreg, dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]));
|
||||
}
|
||||
|
@ -218,6 +218,13 @@ inline s64 dsp_get_long_prod()
|
||||
return val;
|
||||
}
|
||||
|
||||
inline s64 dsp_get_long_prod_prodl_zero()
|
||||
{
|
||||
s64 tempprod = dsp_get_long_prod();
|
||||
tempprod = (tempprod & ~0xffff)+(((tempprod & 0xffff) >= 0x8000) ? 0x10000 : 0);
|
||||
return tempprod;
|
||||
}
|
||||
|
||||
// For accurate emulation, this is wrong - but the real prod registers behave
|
||||
// in completely bizarre ways. Probably not meaningful to emulate them accurately.
|
||||
inline void dsp_set_long_prod(s64 val)
|
||||
|
@ -48,9 +48,13 @@ void clrl(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = (opc.hex >> 8) & 0x1;
|
||||
|
||||
g_dsp.r[DSP_REG_ACL0 + reg] = 0;
|
||||
Update_SR_Register64(dsp_get_long_acc(reg));
|
||||
s64 acc = dsp_get_long_acc(reg);
|
||||
acc = (acc & ~0xffff) + (((acc & 0xffff) >= 0x8000) ? 0x10000 : 0);
|
||||
|
||||
zeroWriteBackLogPreserveAcc(reg);
|
||||
|
||||
dsp_set_long_acc(reg, acc);
|
||||
Update_SR_Register64(acc);
|
||||
}
|
||||
|
||||
//----
|
||||
|
@ -28,16 +28,16 @@
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// Only MULX family instructions have unsigned support.
|
||||
inline s64 dsp_get_multiply_prod(u16 a, u16 b, bool sign)
|
||||
inline s64 dsp_get_multiply_prod(u16 a, u16 b, u8 sign)
|
||||
{
|
||||
s64 prod;
|
||||
|
||||
#if 0 //causing probs with all games atm
|
||||
if (sign && g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)
|
||||
prod = (u64)a * (u64)b; // won't overflow 32-bits
|
||||
if ((sign == 1) && (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)) //unsigned
|
||||
prod = (u64)a * (u64)b;
|
||||
else if ((sign == 2) && (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)) //mixed
|
||||
prod = (u64)a * (s64)(s16)b;
|
||||
else
|
||||
#endif
|
||||
prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
|
||||
prod = (s64)(s16)a * (s64)(s16)b;
|
||||
|
||||
// Conditionally multiply by 2.
|
||||
if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
|
||||
@ -46,19 +46,19 @@ inline s64 dsp_get_multiply_prod(u16 a, u16 b, bool sign)
|
||||
return prod;
|
||||
}
|
||||
|
||||
s64 dsp_multiply(u16 a, u16 b, bool sign = false)
|
||||
s64 dsp_multiply(u16 a, u16 b, u8 sign = 0)
|
||||
{
|
||||
s64 prod = dsp_get_multiply_prod(a, b, sign);
|
||||
return prod;
|
||||
}
|
||||
|
||||
s64 dsp_multiply_add(u16 a, u16 b, bool sign = false)
|
||||
s64 dsp_multiply_add(u16 a, u16 b, u8 sign = 0)
|
||||
{
|
||||
s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign);
|
||||
return prod;
|
||||
}
|
||||
|
||||
s64 dsp_multiply_sub(u16 a, u16 b, bool sign = false)
|
||||
s64 dsp_multiply_sub(u16 a, u16 b, u8 sign = 0)
|
||||
{
|
||||
s64 prod = dsp_get_long_prod() - dsp_get_multiply_prod(a, b, sign);
|
||||
return prod;
|
||||
@ -140,7 +140,7 @@ void movpz(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 8) & 0x01;
|
||||
|
||||
s64 acc = dsp_get_long_prod() & ~0xffff;
|
||||
s64 acc = dsp_get_long_prod_prodl_zero();
|
||||
|
||||
zeroWriteBackLog();
|
||||
|
||||
@ -153,23 +153,21 @@ void movpz(const UDSPInstruction& opc)
|
||||
// Adds secondary accumulator $axS to product register and stores result
|
||||
// in accumulator register. Low 16-bits of $acD ($acD.l) are set to 0.
|
||||
//
|
||||
// flags out: x-xx xxxx
|
||||
//
|
||||
// TEST THIS!!
|
||||
// flags out: ?-xx xx??
|
||||
void addpaxz(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 8) & 0x1;
|
||||
u8 sreg = (opc.hex >> 9) & 0x1;
|
||||
|
||||
s64 prod = dsp_get_long_prod() & ~0xffff; // hm, should we really mask here?
|
||||
s64 prod = dsp_get_long_prod_prodl_zero();
|
||||
s64 ax = dsp_get_long_acx(sreg);
|
||||
s64 acc = (prod + ax) & ~0xffff;
|
||||
s64 res = prod + (ax & ~0xffff);
|
||||
|
||||
zeroWriteBackLog();
|
||||
|
||||
dsp_set_long_acc(dreg, acc);
|
||||
acc = dsp_get_long_acc(dreg);
|
||||
Update_SR_Register64(acc, isCarry2(prod, acc), isOverflow(prod, ax, acc));
|
||||
dsp_set_long_acc(dreg, res);
|
||||
res = dsp_get_long_acc(dreg);
|
||||
Update_SR_Register64(res);
|
||||
}
|
||||
|
||||
//----
|
||||
@ -260,13 +258,13 @@ void mulmv(const UDSPInstruction& opc)
|
||||
// accumulator $axS by high part $axS.h of secondary accumulator $axS (treat
|
||||
// them both as signed).
|
||||
//
|
||||
// flags out: xx xx00
|
||||
// flags out: xx xx0x
|
||||
void mulmvz(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 rreg = (opc.hex >> 8) & 0x1;
|
||||
u8 sreg = (opc.hex >> 11) & 0x1;
|
||||
|
||||
s64 acc = dsp_get_long_prod() & ~0xffff;
|
||||
s64 acc = dsp_get_long_prod_prodl_zero();
|
||||
u16 axl = dsp_get_ax_l(sreg);
|
||||
u16 axh = dsp_get_ax_h(sreg);
|
||||
s64 prod = dsp_multiply(axl, axh);
|
||||
@ -282,7 +280,7 @@ void mulmvz(const UDSPInstruction& opc)
|
||||
|
||||
// MULX $ax0.S, $ax1.T
|
||||
// 101s t000 xxxx xxxx
|
||||
// Multiply one part $ax0 by one part $ax1 (treat them both as signed).
|
||||
// Multiply one part $ax0 by one part $ax1.
|
||||
// Part is selected by S and T bits. Zero selects low part, one selects high part.
|
||||
void mulx(const UDSPInstruction& opc)
|
||||
{
|
||||
@ -291,8 +289,40 @@ void mulx(const UDSPInstruction& opc)
|
||||
|
||||
u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
s64 prod = dsp_multiply(val1, val2, true);
|
||||
|
||||
s64 prod;
|
||||
|
||||
if (!treg && !sreg)
|
||||
{
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
else if (treg && !sreg)
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 2);
|
||||
else if ((val1 >= 0x8000) && (val2 < 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
}
|
||||
else if (!treg && sreg)
|
||||
{
|
||||
if ((val2 >= 0x8000) && (val1 >= 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 2);
|
||||
else if ((val2 >= 0x8000) && (val1 < 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 1);
|
||||
else
|
||||
prod = dsp_multiply(val2, val1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else if ((val1 >= 0x8000) || (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
|
||||
zeroWriteBackLog();
|
||||
|
||||
dsp_set_long_prod(prod);
|
||||
@ -301,7 +331,7 @@ void mulx(const UDSPInstruction& opc)
|
||||
// MULXAC $ax0.S, $ax1.T, $acR
|
||||
// 101s t01r xxxx xxxx
|
||||
// Add product register to accumulator register $acR. Multiply one part
|
||||
// $ax0 by one part $ax1 (treat them both as signed). 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.
|
||||
//
|
||||
// flags out: xx xx00
|
||||
@ -314,7 +344,39 @@ void mulxac(const UDSPInstruction& opc)
|
||||
s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod();
|
||||
u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
s64 prod = dsp_multiply(val1, val2, true);
|
||||
s64 prod;
|
||||
|
||||
if (!treg && !sreg)
|
||||
{
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
else if (treg && !sreg)
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 2);
|
||||
else if ((val1 >= 0x8000) && (val2 < 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
}
|
||||
else if (!treg && sreg)
|
||||
{
|
||||
if ((val2 >= 0x8000) && (val1 >= 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 2);
|
||||
else if ((val2 >= 0x8000) && (val1 < 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 1);
|
||||
else
|
||||
prod = dsp_multiply(val2, val1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else if ((val1 >= 0x8000) || (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
|
||||
zeroWriteBackLog();
|
||||
|
||||
@ -326,7 +388,7 @@ void mulxac(const UDSPInstruction& opc)
|
||||
// MULXMV $ax0.S, $ax1.T, $acR
|
||||
// 101s t11r xxxx xxxx
|
||||
// Move product register to accumulator register $acR. Multiply one part
|
||||
// $ax0 by one part $ax1 (treat them both as signed). 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.
|
||||
//
|
||||
// flags out: xx xx00
|
||||
@ -337,9 +399,41 @@ void mulxmv(const UDSPInstruction& opc)
|
||||
u8 sreg = (opc.hex >> 12) & 0x1;
|
||||
|
||||
s64 acc = dsp_get_long_prod();
|
||||
s16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
s16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
s64 prod = dsp_multiply(val1, val2, true);
|
||||
u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
s64 prod;
|
||||
|
||||
if (!treg && !sreg)
|
||||
{
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
else if (treg && !sreg)
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 2);
|
||||
else if ((val1 >= 0x8000) && (val2 < 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
}
|
||||
else if (!treg && sreg)
|
||||
{
|
||||
if ((val2 >= 0x8000) && (val1 >= 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 2);
|
||||
else if ((val2 >= 0x8000) && (val1 < 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 1);
|
||||
else
|
||||
prod = dsp_multiply(val2, val1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else if ((val1 >= 0x8000) || (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
|
||||
zeroWriteBackLog();
|
||||
|
||||
@ -351,8 +445,8 @@ void mulxmv(const UDSPInstruction& opc)
|
||||
// MULXMV $ax0.S, $ax1.T, $acR
|
||||
// 101s t01r xxxx xxxx
|
||||
// Move product register to accumulator register $acR and clear low part
|
||||
// of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1 (treat
|
||||
// them both as signed). Part is selected by S and T bits. Zero selects low part,
|
||||
// of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1
|
||||
// Part is selected by S and T bits. Zero selects low part,
|
||||
// one selects high part.
|
||||
//
|
||||
// flags out: xx xx00
|
||||
@ -362,10 +456,42 @@ void mulxmvz(const UDSPInstruction& opc)
|
||||
u8 treg = (opc.hex >> 11) & 0x1;
|
||||
u8 sreg = (opc.hex >> 12) & 0x1;
|
||||
|
||||
s64 acc = dsp_get_long_prod() & ~0xffff;
|
||||
s64 acc = dsp_get_long_prod_prodl_zero();
|
||||
u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
s64 prod = dsp_multiply(val1, val2, true);
|
||||
s64 prod;
|
||||
|
||||
if (!treg && !sreg)
|
||||
{
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
else if (treg && !sreg)
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 2);
|
||||
else if ((val1 >= 0x8000) && (val2 < 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
}
|
||||
else if (!treg && sreg)
|
||||
{
|
||||
if ((val2 >= 0x8000) && (val1 >= 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 2);
|
||||
else if ((val2 >= 0x8000) && (val1 < 0x8000))
|
||||
prod = dsp_multiply(val2, val1, 1);
|
||||
else
|
||||
prod = dsp_multiply(val2, val1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((val1 >= 0x8000) && (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
else if ((val1 >= 0x8000) || (val2 >= 0x8000))
|
||||
prod = dsp_multiply(val1, val2, 0);
|
||||
else
|
||||
prod = dsp_multiply(val1, val2, 1);
|
||||
}
|
||||
|
||||
zeroWriteBackLog();
|
||||
|
||||
@ -460,7 +586,7 @@ void mulcmvz(const UDSPInstruction& opc)
|
||||
u8 treg = (opc.hex >> 11) & 0x1;
|
||||
u8 sreg = (opc.hex >> 12) & 0x1;
|
||||
|
||||
s64 acc = dsp_get_long_prod() & ~0xffff;
|
||||
s64 acc = dsp_get_long_prod_prodl_zero();
|
||||
u16 accm = dsp_get_acc_m(sreg);
|
||||
u16 axh = dsp_get_ax_h(treg);
|
||||
s64 prod = dsp_multiply(accm, axh);
|
||||
|
@ -223,6 +223,10 @@ int main(int argc, const char *argv[])
|
||||
printf("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
|
||||
printf("-h <HEADER FILE>: Output assembly results to a header\n");
|
||||
printf("-p <DUMP FILE>: Print results of DSPSpy register dump\n");
|
||||
printf("-ps <DUMP FILE>: Print results of DSPSpy register dump (disable SR output)\n");
|
||||
printf("-pm <DUMP FILE>: Print results of DSPSpy register dump (convert PROD values)\n");
|
||||
printf("-psm <DUMP FILE>: Print results of DSPSpy register dump (convert PROD values/disable SR output)\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -236,7 +240,8 @@ int main(int argc, const char *argv[])
|
||||
std::string output_header_name;
|
||||
std::string output_name;
|
||||
|
||||
bool disassemble = false, compare = false, multiple = false, outputSize = false, force = false, print_results = false;
|
||||
bool disassemble = false, compare = false, multiple = false, outputSize = false,
|
||||
force = false, print_results = false, print_results_prodhack = false, print_results_srhack = false;
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "-d"))
|
||||
@ -255,6 +260,19 @@ int main(int argc, const char *argv[])
|
||||
force = true;
|
||||
else if (!strcmp(argv[i], "-p"))
|
||||
print_results = true;
|
||||
else if (!strcmp(argv[i], "-ps")) {
|
||||
print_results = true;
|
||||
print_results_srhack = true;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-pm")) {
|
||||
print_results = true;
|
||||
print_results_prodhack = true;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-psm")) {
|
||||
print_results = true;
|
||||
print_results_srhack = true;
|
||||
print_results_prodhack = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!input_name.empty())
|
||||
@ -311,12 +329,40 @@ int main(int argc, const char *argv[])
|
||||
for (unsigned int step = 1; step < reg_vector.size()/32; step++)
|
||||
{
|
||||
bool changed = false;
|
||||
u16 current_reg;
|
||||
u16 last_reg;
|
||||
u32 htemp;
|
||||
//results.append(StringFromFormat("Step %3d: (CW 0x%04x) UC:%03d\n", step, 0x8fff+step, (step-1)/32));
|
||||
results.append(StringFromFormat("Step %3d:\n", step));
|
||||
for (int reg = 0; reg < 32; reg++)
|
||||
{
|
||||
if ((reg >= 0x0c) && (reg <= 0x0f)) continue;
|
||||
u16 last_reg = reg_vector.at((step*32-32)+reg);
|
||||
u16 current_reg = reg_vector.at(step*32+reg);
|
||||
if (print_results_srhack && (reg == 0x13)) continue;
|
||||
|
||||
if ((print_results_prodhack) && (reg >= 0x15) && (reg <= 0x17)) {
|
||||
switch (reg) {
|
||||
case 0x15: //DSP_REG_PRODM
|
||||
last_reg = reg_vector.at((step*32-32)+reg) + reg_vector.at((step*32-32)+reg+2);
|
||||
current_reg = reg_vector.at(step*32+reg) + reg_vector.at(step*32+reg+2);
|
||||
break;
|
||||
case 0x16: //DSP_REG_PRODH
|
||||
htemp = ((reg_vector.at(step*32+reg-1) + reg_vector.at(step*32+reg+1))&~0xffff)>>16;
|
||||
current_reg = (u8)(reg_vector.at(step*32+reg) + htemp);
|
||||
htemp = ((reg_vector.at(step*32-32+reg-1) + reg_vector.at(step*32-32+reg+1))&~0xffff)>>16;
|
||||
last_reg = (u8)(reg_vector.at(step*32-32+reg) + htemp);
|
||||
break;
|
||||
case 0x17: //DSP_REG_PRODM2
|
||||
current_reg = 0;
|
||||
last_reg = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
current_reg = reg_vector.at(step*32+reg);
|
||||
last_reg = reg_vector.at((step*32-32)+reg);
|
||||
}
|
||||
if (last_reg != current_reg)
|
||||
{
|
||||
results.append(StringFromFormat("%02x %-7s: %04x %04x\n", reg, pdregname(reg), last_reg, current_reg));
|
||||
|
Loading…
Reference in New Issue
Block a user