mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
DSP: implemented saturation in dsplle-int
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7270 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
74f22a57d1
commit
6073600084
@ -165,8 +165,8 @@
|
||||
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
|
||||
#define SR_1000 0x1000 // unknown
|
||||
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
|
||||
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
|
||||
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
|
||||
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums and data saturation for stores from mid accums.
|
||||
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats ax?.l as unsigned.
|
||||
|
||||
// This should be the bits affected by CMP. Does not include logic zero.
|
||||
#define SR_CMP_MASK 0x3f
|
||||
|
@ -88,7 +88,7 @@ void mv(const UDSPInstruction opc)
|
||||
break;
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r.ac[sreg-DSP_REG_ACM0].m);
|
||||
writeToBackLog(0, dreg + DSP_REG_AXL0, dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -109,7 +109,7 @@ void s(const UDSPInstruction opc)
|
||||
break;
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg-DSP_REG_ACM0].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
break;
|
||||
}
|
||||
writeToBackLog(0, dreg, dsp_increment_addr_reg(dreg));
|
||||
@ -131,7 +131,7 @@ void sn(const UDSPInstruction opc)
|
||||
break;
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg-DSP_REG_ACM0].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
break;
|
||||
}
|
||||
writeToBackLog(0, dreg, dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg]));
|
||||
@ -195,7 +195,7 @@ void ls(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
|
||||
@ -214,7 +214,7 @@ void lsn(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
|
||||
@ -232,7 +232,7 @@ void lsm(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
|
||||
@ -251,7 +251,7 @@ void lsnm(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
|
||||
@ -268,7 +268,7 @@ void sl(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
|
||||
@ -286,7 +286,7 @@ void sln(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
|
||||
@ -304,7 +304,7 @@ void slm(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
|
||||
@ -322,7 +322,7 @@ void slnm(const UDSPInstruction opc)
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
|
||||
dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m);
|
||||
dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
|
||||
|
||||
writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
|
||||
writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
|
||||
|
@ -362,6 +362,27 @@ inline s16 dsp_get_acc_h(int _reg)
|
||||
return g_dsp.r.ac[_reg].h;
|
||||
}
|
||||
|
||||
inline u16 dsp_op_read_reg_and_saturate(u8 _reg)
|
||||
{
|
||||
if (g_dsp.r.sr & SR_40_MODE_BIT)
|
||||
{
|
||||
s64 acc = dsp_get_long_acc(_reg);
|
||||
|
||||
if (acc != (s32)acc)
|
||||
{
|
||||
//NOTICE_LOG(DSPLLE,"LIMIT: 0x%x", g_dsp.pc);
|
||||
if (acc > 0)
|
||||
return 0x7fff;
|
||||
else
|
||||
return 0x8000;
|
||||
}
|
||||
else
|
||||
return g_dsp.r.ac[_reg].m;
|
||||
}
|
||||
else
|
||||
return g_dsp.r.ac[_reg].m;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// --- AX - extra accumulators (32-bit)
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
@ -34,7 +34,11 @@ void srs(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
|
||||
dsp_dmem_write(addr, dsp_op_read_reg(reg));
|
||||
|
||||
if (reg >= DSP_REG_ACM0)
|
||||
dsp_dmem_write(addr, dsp_op_read_reg_and_saturate(reg-DSP_REG_ACM0));
|
||||
else
|
||||
dsp_dmem_write(addr, dsp_op_read_reg(reg));
|
||||
}
|
||||
|
||||
// LRS $(0x18+D), @M
|
||||
@ -54,7 +58,6 @@ void lrs(const UDSPInstruction opc)
|
||||
// 0000 0000 110d dddd
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Move value from data memory pointed by address M to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = opc & DSP_REG_MASK;
|
||||
@ -68,13 +71,15 @@ void lr(const UDSPInstruction opc)
|
||||
// 0000 0000 111s ssss
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Store value from register $S to a memory pointed by address M.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void sr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = opc & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_op_read_reg(reg);
|
||||
dsp_dmem_write(addr, val);
|
||||
|
||||
if (reg >= DSP_REG_ACM0)
|
||||
dsp_dmem_write(addr, dsp_op_read_reg_and_saturate(reg-DSP_REG_ACM0));
|
||||
else
|
||||
dsp_dmem_write(addr, dsp_op_read_reg(reg));
|
||||
}
|
||||
|
||||
// SI @M, #I
|
||||
@ -92,7 +97,6 @@ void si(const UDSPInstruction opc)
|
||||
// LRR $D, @$S
|
||||
// 0001 1000 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
@ -107,7 +111,6 @@ void lrr(const UDSPInstruction opc)
|
||||
// 0001 1000 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||
// Decrement register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrd(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
@ -123,7 +126,6 @@ void lrrd(const UDSPInstruction opc)
|
||||
// 0001 1001 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Increment register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrri(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
@ -139,7 +141,6 @@ void lrri(const UDSPInstruction opc)
|
||||
// 0001 1001 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Add indexing register $(0x4+S) to register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrn(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
@ -155,28 +156,31 @@ void lrrn(const UDSPInstruction opc)
|
||||
// 0001 1010 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], val);
|
||||
if (sreg >= DSP_REG_ACM0)
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
else
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
|
||||
}
|
||||
|
||||
// SRRD @$D, $S
|
||||
// 0001 1010 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Decrement register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrd(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], val);
|
||||
if (sreg >= DSP_REG_ACM0)
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
else
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
|
||||
|
||||
g_dsp.r.ar[dreg] = dsp_decrement_addr_reg(dreg);
|
||||
}
|
||||
|
||||
@ -184,14 +188,16 @@ void srrd(const UDSPInstruction opc)
|
||||
// 0001 1011 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Increment register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srri(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], val);
|
||||
if (sreg >= DSP_REG_ACM0)
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
else
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
|
||||
|
||||
g_dsp.r.ar[dreg] = dsp_increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
@ -199,14 +205,16 @@ void srri(const UDSPInstruction opc)
|
||||
// 0001 1011 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrn(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], val);
|
||||
if (sreg >= DSP_REG_ACM0)
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
else
|
||||
dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
|
||||
|
||||
g_dsp.r.ar[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg]);
|
||||
}
|
||||
|
||||
|
@ -28,14 +28,16 @@ namespace DSPInterpreter {
|
||||
// MRR $D, $S
|
||||
// 0001 11dd ddds ssss
|
||||
// Move value from register $S to register $D.
|
||||
// todo: Perform additional operation depending on destination register.
|
||||
void mrr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = opc & 0x1f;
|
||||
u8 dreg = (opc >> 5) & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
if (sreg >= DSP_REG_ACM0)
|
||||
dsp_op_write_reg(dreg, dsp_op_read_reg_and_saturate(sreg-DSP_REG_ACM0));
|
||||
else
|
||||
dsp_op_write_reg(dreg, dsp_op_read_reg(sreg));
|
||||
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user