diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp index 9c1c2640c1..a5ec0505c4 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.cpp +++ b/Source/Core/DSPCore/Src/DSPInterpreter.cpp @@ -166,6 +166,8 @@ void halt(const UDSPInstruction& opc) // from register $R reaches zero. Each execution decrement counter. Register // $R remains unchanged. If register $R is set to zero at the beginning of loop // then looped instruction will not get executed. +// Actually, this instruction simply prepares the loop stacks for the above. +// The looping hardware takes care of the rest. void loop(const UDSPInstruction& opc) { u16 reg = opc.hex & 0x1f; @@ -186,6 +188,8 @@ void loop(const UDSPInstruction& opc) // immediate value I reaches zero. Each execution decrement counter. If // immediate value I is set to zero at the beginning of loop then looped // instruction will not get executed. +// Actually, this instruction simply prepares the loop stacks for the above. +// The looping hardware takes care of the rest. void loopi(const UDSPInstruction& opc) { u16 cnt = opc.hex & 0xff; @@ -295,7 +299,7 @@ void lrrd(const UDSPInstruction& opc) u16 val = dsp_dmem_read(g_dsp.r[sreg]); dsp_op_write_reg(dreg, val); - g_dsp.r[sreg]--; + dsp_decrement_addr_reg(sreg); } // LRRI $D, @$S @@ -310,8 +314,7 @@ void lrri(const UDSPInstruction& opc) u16 val = dsp_dmem_read(g_dsp.r[sreg]); dsp_op_write_reg(dreg, val); - g_dsp.r[sreg]++; - + dsp_increment_addr_reg(sreg); } // LRRN $D, @$S @@ -326,7 +329,7 @@ void lrrn(const UDSPInstruction& opc) u16 val = dsp_dmem_read(g_dsp.r[sreg]); dsp_op_write_reg(dreg, val); - g_dsp.r[sreg] += g_dsp.r[sreg + 4]; + g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg]; } // SRR @$D, $S @@ -355,7 +358,7 @@ void srrd(const UDSPInstruction& opc) u16 val = dsp_op_read_reg(sreg); dsp_dmem_write(g_dsp.r[dreg], val); - g_dsp.r[dreg]--; + dsp_decrement_addr_reg(dreg); } // SRRI @$D, $S @@ -370,7 +373,7 @@ void srri(const UDSPInstruction& opc) u16 val = dsp_op_read_reg(sreg); dsp_dmem_write(g_dsp.r[dreg], val); - g_dsp.r[dreg]++; + dsp_increment_addr_reg(dreg); } // SRRN @$D, $S @@ -411,7 +414,7 @@ void ilrrd(const UDSPInstruction& opc) g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); - g_dsp.r[reg]--; + dsp_decrement_addr_reg(reg); } // ILRRI $acD.m, @$S @@ -425,7 +428,7 @@ void ilrri(const UDSPInstruction& opc) g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); - g_dsp.r[reg]++; + dsp_increment_addr_reg(reg); } // ILRRN $acD.m, @$arS @@ -1385,30 +1388,20 @@ void asr(const UDSPInstruction& opc) } //------------------------------------------------------------- - -// hcs give me this code!! -// DAR $arD +// DAR $arD ? // 0000 0000 0000 01dd // Decrement address register $arD. -// More docs needed - the operation is really odd! void dar(const UDSPInstruction& opc) { - int reg = opc.hex & 0x3; - - g_dsp.r[reg]--; // TODO: Wrap properly. + dsp_decrement_addr_reg(opc.hex & 0x3); } - -// hcs give me this code!! -// IAR $arD +// IAR $arD ? // 0000 0000 0000 10dd // Increment address register $arD. -// More docs needed - the operation is really odd! void iar(const UDSPInstruction& opc) { - int reg = opc.hex & 0x3; - - g_dsp.r[reg]++; // TODO: Wrap properly according to the corresponding WR register. + dsp_increment_addr_reg(opc.hex & 0x3); } //------------------------------------------------------------- diff --git a/Source/Core/DSPCore/Src/gdsp_ext_op.cpp b/Source/Core/DSPCore/Src/gdsp_ext_op.cpp index 4d0bde0ed2..e352899839 100644 --- a/Source/Core/DSPCore/Src/gdsp_ext_op.cpp +++ b/Source/Core/DSPCore/Src/gdsp_ext_op.cpp @@ -50,18 +50,14 @@ namespace Ext // xxxx xxxx 0000 01rr // Decrement addressing register $arR. void dr(const UDSPInstruction& opc) { - u8 reg = opc.hex & 0x3; - - g_dsp.r[reg]--; + dsp_decrement_addr_reg(opc.hex & 0x3); } // IR $arR // xxxx xxxx 0000 10rr // Increment addressing register $arR. void ir(const UDSPInstruction& opc) { - u8 reg = opc.hex & 0x3; - - g_dsp.r[reg]++; + dsp_increment_addr_reg(opc.hex & 0x3); } // NR $arR @@ -95,7 +91,7 @@ void s(const UDSPInstruction& opc) dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); - g_dsp.r[dreg]++; + dsp_increment_addr_reg(dreg); } // SN @$D, $acD.l @@ -124,7 +120,7 @@ void l(const UDSPInstruction& opc) u16 val = dsp_dmem_read(g_dsp.r[sreg]); g_dsp.r[dreg] = val; - g_dsp.r[sreg]++; + dsp_increment_addr_reg(sreg); } // LN axD.l, @$S @@ -153,8 +149,8 @@ void ld(const UDSPInstruction& opc) g_dsp.r[dreg] = dsp_dmem_read(g_dsp.r[sreg]); g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); - g_dsp.r[sreg]++; - g_dsp.r[DSP_REG_AR3]++; + dsp_increment_addr_reg(sreg); + dsp_increment_addr_reg(DSP_REG_AR3); } // Not in duddie's doc @@ -169,7 +165,7 @@ void ldn(const UDSPInstruction& opc) g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); g_dsp.r[sreg] += g_dsp.r[sreg + DSP_REG_IX0]; - g_dsp.r[DSP_REG_AR3]++; + dsp_increment_addr_reg(DSP_REG_AR3); } // Not in duddie's doc @@ -183,7 +179,7 @@ void ldm(const UDSPInstruction& opc) g_dsp.r[dreg] = dsp_dmem_read(g_dsp.r[sreg]); g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); - g_dsp.r[sreg]++; + dsp_increment_addr_reg(sreg); g_dsp.r[DSP_REG_AR3] += g_dsp.r[DSP_REG_IX3]; } @@ -215,11 +211,11 @@ void dsp_op_ext_r_epi(const UDSPInstruction& opc) break; case 0x01: // DR - g_dsp.r[reg]--; + dsp_decrement_addr_reg(reg); break; case 0x02: // IR - g_dsp.r[reg]++; + dsp_increment_addr_reg(reg); break; case 0x03: // NR @@ -251,7 +247,7 @@ void dsp_op_ext_s(const UDSPInstruction& opc) } else { - g_dsp.r[dreg]++; // S + dsp_increment_addr_reg(dreg); // S } } @@ -270,7 +266,7 @@ void dsp_op_ext_l(const UDSPInstruction& opc) } else { - g_dsp.r[sreg]++; // LS + dsp_increment_addr_reg(sreg); // LS } } @@ -286,7 +282,7 @@ void dsp_op_ext_ls_pro(const UDSPInstruction& opc) } else // LS { - g_dsp.r[0x03]++; + dsp_increment_addr_reg(0x03); } } @@ -303,7 +299,7 @@ void dsp_op_ext_ls_epi(const UDSPInstruction& opc) } else // LS { - g_dsp.r[0x00]++; + dsp_increment_addr_reg(0x00); } } @@ -319,7 +315,7 @@ void dsp_op_ext_sl_pro(const UDSPInstruction& opc) } else // SL { - g_dsp.r[0x00]++; + dsp_increment_addr_reg(0x00); } } @@ -336,7 +332,7 @@ void dsp_op_ext_sl_epi(const UDSPInstruction& opc) } else // SL { - g_dsp.r[0x03]++; + dsp_increment_addr_reg(0x03); } } @@ -355,7 +351,7 @@ void dsp_op_ext_ld(const UDSPInstruction& opc) } else { - g_dsp.r[sreg]++; + dsp_increment_addr_reg(sreg); } if (opc.hex & 0x08) // M @@ -364,9 +360,8 @@ void dsp_op_ext_ld(const UDSPInstruction& opc) } else { - g_dsp.r[0x03]++; + dsp_increment_addr_reg(0x03); } - } diff --git a/Source/Core/DSPCore/Src/gdsp_interpreter.cpp b/Source/Core/DSPCore/Src/gdsp_interpreter.cpp index ea816486dc..883e6e8881 100644 --- a/Source/Core/DSPCore/Src/gdsp_interpreter.cpp +++ b/Source/Core/DSPCore/Src/gdsp_interpreter.cpp @@ -38,10 +38,9 @@ namespace DSPInterpreter { volatile u32 gdsp_running; - // Hm, should instructions that change CR use this? Probably not (but they // should call UpdateCachedCR()) -void gdsp_write_cr(u16 val) +void WriteCR(u16 val) { // reset if (val & 0x0001) @@ -55,9 +54,8 @@ void gdsp_write_cr(u16 val) g_dsp.cr = val; } - // Hm, should instructions that read CR use this? (Probably not). -u16 gdsp_read_cr() +u16 ReadCR() { if (g_dsp.pc & 0x8000) { @@ -71,8 +69,7 @@ u16 gdsp_read_cr() return g_dsp.cr; } - -void gdsp_handle_loop() +void HandleLoop() { // Handle looping hardware. u16& rLoopCounter = g_dsp.r[DSP_REG_ST3]; @@ -100,7 +97,7 @@ void gdsp_handle_loop() } } -void gdsp_step() +void Step() { gdsp_check_exceptions(); @@ -123,11 +120,11 @@ void gdsp_step() u16 opc = dsp_fetch_code(); ExecuteInstruction(UDSPInstruction(opc)); - gdsp_handle_loop(); + HandleLoop(); } // Used by thread mode. -void gdsp_run() +void Run() { gdsp_running = true; while (!(g_dsp.cr & CR_HALT)) @@ -139,7 +136,7 @@ void gdsp_run() gdsp_check_external_int(); // This number (500) is completely arbitrary. TODO: tweak. for (int i = 0; i < 500 && !(g_dsp.cr & CR_HALT); i++) - gdsp_step(); + Step(); if (!gdsp_running) break; @@ -148,7 +145,7 @@ void gdsp_run() } // Used by non-thread mode. -void gdsp_run_cycles(int cycles) +void RunCycles(int cycles) { gdsp_check_external_int(); @@ -157,7 +154,7 @@ void gdsp_run_cycles(int cycles) { if (g_dsp.cr & CR_HALT) return; - gdsp_step(); + Step(); cycles--; } @@ -168,7 +165,7 @@ void gdsp_run_cycles(int cycles) return; if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) return; - gdsp_step(); + Step(); cycles--; } @@ -176,14 +173,14 @@ void gdsp_run_cycles(int cycles) // idle loop and if so we waste some time here. Might be beneficial to slice even further. while (cycles > 0) { - gdsp_step(); + Step(); cycles--; // We don't bother directly supporting pause - if the main emu pauses, // it just won't call this function anymore. } } -void gdsp_stop() +void Stop() { gdsp_running = false; } diff --git a/Source/Core/DSPCore/Src/gdsp_interpreter.h b/Source/Core/DSPCore/Src/gdsp_interpreter.h index 06869b4004..f8504f72ce 100644 --- a/Source/Core/DSPCore/Src/gdsp_interpreter.h +++ b/Source/Core/DSPCore/Src/gdsp_interpreter.h @@ -48,14 +48,13 @@ namespace DSPInterpreter { // steps through DSP code, returns false if error occured -void gdsp_step(); -void gdsp_loop_step(); -void gdsp_run(); -void gdsp_run_cycles(int cycles); -void gdsp_stop(); +void Step(); +void Run(); +void RunCycles(int cycles); +void Stop(); -void gdsp_write_cr(u16 val); -u16 gdsp_read_cr(); +void WriteCR(u16 val); +u16 ReadCR(); } // namespace diff --git a/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h index a53902be17..2a071bb563 100644 --- a/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h +++ b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h @@ -50,6 +50,39 @@ inline bool dsp_SR_is_flag_set(int flag) return (g_dsp.r[DSP_REG_SR] & (1 << flag)) != 0; } + +// See http://code.google.com/p/dolphin-emu/source/detail?r=3125 +inline void dsp_decrement_addr_reg(int reg) +{ + // This one was easy. increment is worse... + if ((g_dsp.r[reg] & g_dsp.r[DSP_REG_WR0 + reg]) == 0) + g_dsp.r[reg] |= g_dsp.r[DSP_REG_WR0 + reg]; + else + g_dsp.r[reg]--; +} + + +// HORRIBLE UGLINESS, someone please fix. +// See http://code.google.com/p/dolphin-emu/source/detail?r=3125 + +inline u16 ToMask(u16 a) +{ + a = a | (a >> 8); + a = a | (a >> 4); + a = a | (a >> 2); + return a | (a >> 1); +} + +inline void dsp_increment_addr_reg(int reg) +{ + u16 tmb = ToMask(g_dsp.r[DSP_REG_WR0 + reg]); + if ((g_dsp.r[reg] & tmb) == tmb) + g_dsp.r[reg] ^= g_dsp.r[DSP_REG_WR0 + reg]; + else + g_dsp.r[reg]++; +} + + // --------------------------------------------------------------------------------------- // --- reg // --------------------------------------------------------------------------------------- diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index e7de70632e..51427f3158 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -179,7 +179,7 @@ THREAD_RETURN dsp_thread(void* lpParameter) { while (bIsRunning) { - DSPInterpreter::gdsp_run(); + DSPInterpreter::Run(); } return 0; } @@ -249,7 +249,7 @@ void Initialize(void *init) void DSP_StopSoundStream() { - DSPInterpreter::gdsp_stop(); + DSPInterpreter::Stop(); bIsRunning = false; if (g_dspInitialize.bOnThread) { @@ -266,13 +266,13 @@ void Shutdown() u16 DSP_WriteControlRegister(u16 _uFlag) { - DSPInterpreter::gdsp_write_cr(_uFlag); - return DSPInterpreter::gdsp_read_cr(); + DSPInterpreter::WriteCR(_uFlag); + return DSPInterpreter::ReadCR(); } u16 DSP_ReadControlRegister() { - return DSPInterpreter::gdsp_read_cr(); + return DSPInterpreter::ReadCR(); } u16 DSP_ReadMailboxHigh(bool _CPUMailbox) @@ -343,7 +343,7 @@ void DSP_Update(int cycles) // If we're not on a thread, run cycles here. if (!g_dspInitialize.bOnThread) { - DSPInterpreter::gdsp_run_cycles(cycles); + DSPInterpreter::RunCycles(cycles); } }