From 6073600084a1e5d4a180f502626bc44d4b7022f0 Mon Sep 17 00:00:00 2001 From: Marko Pusljar Date: Tue, 1 Mar 2011 20:20:04 +0000 Subject: [PATCH] DSP: implemented saturation in dsplle-int git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7270 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/DSP/DSPCore.h | 4 +- Source/Core/Core/Src/DSP/DSPIntExtOps.cpp | 22 ++++----- Source/Core/Core/Src/DSP/DSPIntUtil.h | 21 ++++++++ Source/Core/Core/Src/DSP/DspIntLoadStore.cpp | 50 ++++++++++++-------- Source/Core/Core/Src/DSP/DspIntMisc.cpp | 8 ++-- 5 files changed, 68 insertions(+), 37 deletions(-) diff --git a/Source/Core/Core/Src/DSP/DSPCore.h b/Source/Core/Core/Src/DSP/DSPCore.h index feb82bce9f..ed3d33e583 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.h +++ b/Source/Core/Core/Src/DSP/DSPCore.h @@ -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 diff --git a/Source/Core/Core/Src/DSP/DSPIntExtOps.cpp b/Source/Core/Core/Src/DSP/DSPIntExtOps.cpp index 11eca9abac..4eff38b240 100644 --- a/Source/Core/Core/Src/DSP/DSPIntExtOps.cpp +++ b/Source/Core/Core/Src/DSP/DSPIntExtOps.cpp @@ -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])); diff --git a/Source/Core/Core/Src/DSP/DSPIntUtil.h b/Source/Core/Core/Src/DSP/DSPIntUtil.h index f2fed5c348..4474b5408c 100644 --- a/Source/Core/Core/Src/DSP/DSPIntUtil.h +++ b/Source/Core/Core/Src/DSP/DSPIntUtil.h @@ -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) // --------------------------------------------------------------------------------------- diff --git a/Source/Core/Core/Src/DSP/DspIntLoadStore.cpp b/Source/Core/Core/Src/DSP/DspIntLoadStore.cpp index b43d6707b3..3b301277ae 100644 --- a/Source/Core/Core/Src/DSP/DspIntLoadStore.cpp +++ b/Source/Core/Core/Src/DSP/DspIntLoadStore.cpp @@ -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]); } diff --git a/Source/Core/Core/Src/DSP/DspIntMisc.cpp b/Source/Core/Core/Src/DSP/DspIntMisc.cpp index f2c1f921af..611cbb8266 100644 --- a/Source/Core/Core/Src/DSP/DspIntMisc.cpp +++ b/Source/Core/Core/Src/DSP/DspIntMisc.cpp @@ -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); }