DSPLLE: Wrapping behaviour for single increments/decrements of address registers implemented. It made little/no difference as far as I can tell :P

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3129 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-05-01 22:17:22 +00:00
parent 2352cf0fed
commit 474f1343f7
6 changed files with 90 additions and 73 deletions

View File

@ -166,6 +166,8 @@ void halt(const UDSPInstruction& opc)
// from register $R reaches zero. Each execution decrement counter. Register // 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 // $R remains unchanged. If register $R is set to zero at the beginning of loop
// then looped instruction will not get executed. // 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) void loop(const UDSPInstruction& opc)
{ {
u16 reg = opc.hex & 0x1f; 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 reaches zero. Each execution decrement counter. If
// immediate value I is set to zero at the beginning of loop then looped // immediate value I is set to zero at the beginning of loop then looped
// instruction will not get executed. // 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) void loopi(const UDSPInstruction& opc)
{ {
u16 cnt = opc.hex & 0xff; u16 cnt = opc.hex & 0xff;
@ -295,7 +299,7 @@ void lrrd(const UDSPInstruction& opc)
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val); dsp_op_write_reg(dreg, val);
g_dsp.r[sreg]--; dsp_decrement_addr_reg(sreg);
} }
// LRRI $D, @$S // LRRI $D, @$S
@ -310,8 +314,7 @@ void lrri(const UDSPInstruction& opc)
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val); dsp_op_write_reg(dreg, val);
g_dsp.r[sreg]++; dsp_increment_addr_reg(sreg);
} }
// LRRN $D, @$S // LRRN $D, @$S
@ -326,7 +329,7 @@ void lrrn(const UDSPInstruction& opc)
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val); 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 // SRR @$D, $S
@ -355,7 +358,7 @@ void srrd(const UDSPInstruction& opc)
u16 val = dsp_op_read_reg(sreg); u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val); dsp_dmem_write(g_dsp.r[dreg], val);
g_dsp.r[dreg]--; dsp_decrement_addr_reg(dreg);
} }
// SRRI @$D, $S // SRRI @$D, $S
@ -370,7 +373,7 @@ void srri(const UDSPInstruction& opc)
u16 val = dsp_op_read_reg(sreg); u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val); dsp_dmem_write(g_dsp.r[dreg], val);
g_dsp.r[dreg]++; dsp_increment_addr_reg(dreg);
} }
// SRRN @$D, $S // 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[dreg] = dsp_imem_read(g_dsp.r[reg]);
g_dsp.r[reg]--; dsp_decrement_addr_reg(reg);
} }
// ILRRI $acD.m, @$S // 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[dreg] = dsp_imem_read(g_dsp.r[reg]);
g_dsp.r[reg]++; dsp_increment_addr_reg(reg);
} }
// ILRRN $acD.m, @$arS // ILRRN $acD.m, @$arS
@ -1385,30 +1388,20 @@ void asr(const UDSPInstruction& opc)
} }
//------------------------------------------------------------- //-------------------------------------------------------------
// DAR $arD ?
// hcs give me this code!!
// DAR $arD
// 0000 0000 0000 01dd // 0000 0000 0000 01dd
// Decrement address register $arD. // Decrement address register $arD.
// More docs needed - the operation is really odd!
void dar(const UDSPInstruction& opc) void dar(const UDSPInstruction& opc)
{ {
int reg = opc.hex & 0x3; dsp_decrement_addr_reg(opc.hex & 0x3);
g_dsp.r[reg]--; // TODO: Wrap properly.
} }
// IAR $arD ?
// hcs give me this code!!
// IAR $arD
// 0000 0000 0000 10dd // 0000 0000 0000 10dd
// Increment address register $arD. // Increment address register $arD.
// More docs needed - the operation is really odd!
void iar(const UDSPInstruction& opc) void iar(const UDSPInstruction& opc)
{ {
int reg = opc.hex & 0x3; dsp_increment_addr_reg(opc.hex & 0x3);
g_dsp.r[reg]++; // TODO: Wrap properly according to the corresponding WR register.
} }
//------------------------------------------------------------- //-------------------------------------------------------------

View File

@ -50,18 +50,14 @@ namespace Ext
// xxxx xxxx 0000 01rr // xxxx xxxx 0000 01rr
// Decrement addressing register $arR. // Decrement addressing register $arR.
void dr(const UDSPInstruction& opc) { void dr(const UDSPInstruction& opc) {
u8 reg = opc.hex & 0x3; dsp_decrement_addr_reg(opc.hex & 0x3);
g_dsp.r[reg]--;
} }
// IR $arR // IR $arR
// xxxx xxxx 0000 10rr // xxxx xxxx 0000 10rr
// Increment addressing register $arR. // Increment addressing register $arR.
void ir(const UDSPInstruction& opc) { void ir(const UDSPInstruction& opc) {
u8 reg = opc.hex & 0x3; dsp_increment_addr_reg(opc.hex & 0x3);
g_dsp.r[reg]++;
} }
// NR $arR // NR $arR
@ -95,7 +91,7 @@ void s(const UDSPInstruction& opc)
dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]);
g_dsp.r[dreg]++; dsp_increment_addr_reg(dreg);
} }
// SN @$D, $acD.l // SN @$D, $acD.l
@ -124,7 +120,7 @@ void l(const UDSPInstruction& opc)
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg] = val; g_dsp.r[dreg] = val;
g_dsp.r[sreg]++; dsp_increment_addr_reg(sreg);
} }
// LN axD.l, @$S // 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[dreg] = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); 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]++; dsp_increment_addr_reg(DSP_REG_AR3);
} }
// Not in duddie's doc // 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[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]);
g_dsp.r[sreg] += g_dsp.r[sreg + DSP_REG_IX0]; 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 // 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[dreg] = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); 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]; 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; break;
case 0x01: // DR case 0x01: // DR
g_dsp.r[reg]--; dsp_decrement_addr_reg(reg);
break; break;
case 0x02: // IR case 0x02: // IR
g_dsp.r[reg]++; dsp_increment_addr_reg(reg);
break; break;
case 0x03: // NR case 0x03: // NR
@ -251,7 +247,7 @@ void dsp_op_ext_s(const UDSPInstruction& opc)
} }
else 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 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 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 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 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 else // SL
{ {
g_dsp.r[0x03]++; dsp_increment_addr_reg(0x03);
} }
} }
@ -355,7 +351,7 @@ void dsp_op_ext_ld(const UDSPInstruction& opc)
} }
else else
{ {
g_dsp.r[sreg]++; dsp_increment_addr_reg(sreg);
} }
if (opc.hex & 0x08) // M if (opc.hex & 0x08) // M
@ -364,9 +360,8 @@ void dsp_op_ext_ld(const UDSPInstruction& opc)
} }
else else
{ {
g_dsp.r[0x03]++; dsp_increment_addr_reg(0x03);
} }
} }

View File

@ -38,10 +38,9 @@ namespace DSPInterpreter {
volatile u32 gdsp_running; volatile u32 gdsp_running;
// Hm, should instructions that change CR use this? Probably not (but they // Hm, should instructions that change CR use this? Probably not (but they
// should call UpdateCachedCR()) // should call UpdateCachedCR())
void gdsp_write_cr(u16 val) void WriteCR(u16 val)
{ {
// reset // reset
if (val & 0x0001) if (val & 0x0001)
@ -55,9 +54,8 @@ void gdsp_write_cr(u16 val)
g_dsp.cr = val; g_dsp.cr = val;
} }
// Hm, should instructions that read CR use this? (Probably not). // Hm, should instructions that read CR use this? (Probably not).
u16 gdsp_read_cr() u16 ReadCR()
{ {
if (g_dsp.pc & 0x8000) if (g_dsp.pc & 0x8000)
{ {
@ -71,8 +69,7 @@ u16 gdsp_read_cr()
return g_dsp.cr; return g_dsp.cr;
} }
void HandleLoop()
void gdsp_handle_loop()
{ {
// Handle looping hardware. // Handle looping hardware.
u16& rLoopCounter = g_dsp.r[DSP_REG_ST3]; u16& rLoopCounter = g_dsp.r[DSP_REG_ST3];
@ -100,7 +97,7 @@ void gdsp_handle_loop()
} }
} }
void gdsp_step() void Step()
{ {
gdsp_check_exceptions(); gdsp_check_exceptions();
@ -123,11 +120,11 @@ void gdsp_step()
u16 opc = dsp_fetch_code(); u16 opc = dsp_fetch_code();
ExecuteInstruction(UDSPInstruction(opc)); ExecuteInstruction(UDSPInstruction(opc));
gdsp_handle_loop(); HandleLoop();
} }
// Used by thread mode. // Used by thread mode.
void gdsp_run() void Run()
{ {
gdsp_running = true; gdsp_running = true;
while (!(g_dsp.cr & CR_HALT)) while (!(g_dsp.cr & CR_HALT))
@ -139,7 +136,7 @@ void gdsp_run()
gdsp_check_external_int(); gdsp_check_external_int();
// This number (500) is completely arbitrary. TODO: tweak. // This number (500) is completely arbitrary. TODO: tweak.
for (int i = 0; i < 500 && !(g_dsp.cr & CR_HALT); i++) for (int i = 0; i < 500 && !(g_dsp.cr & CR_HALT); i++)
gdsp_step(); Step();
if (!gdsp_running) if (!gdsp_running)
break; break;
@ -148,7 +145,7 @@ void gdsp_run()
} }
// Used by non-thread mode. // Used by non-thread mode.
void gdsp_run_cycles(int cycles) void RunCycles(int cycles)
{ {
gdsp_check_external_int(); gdsp_check_external_int();
@ -157,7 +154,7 @@ void gdsp_run_cycles(int cycles)
{ {
if (g_dsp.cr & CR_HALT) if (g_dsp.cr & CR_HALT)
return; return;
gdsp_step(); Step();
cycles--; cycles--;
} }
@ -168,7 +165,7 @@ void gdsp_run_cycles(int cycles)
return; return;
if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP)
return; return;
gdsp_step(); Step();
cycles--; 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. // idle loop and if so we waste some time here. Might be beneficial to slice even further.
while (cycles > 0) while (cycles > 0)
{ {
gdsp_step(); Step();
cycles--; cycles--;
// We don't bother directly supporting pause - if the main emu pauses, // We don't bother directly supporting pause - if the main emu pauses,
// it just won't call this function anymore. // it just won't call this function anymore.
} }
} }
void gdsp_stop() void Stop()
{ {
gdsp_running = false; gdsp_running = false;
} }

View File

@ -48,14 +48,13 @@
namespace DSPInterpreter { namespace DSPInterpreter {
// steps through DSP code, returns false if error occured // steps through DSP code, returns false if error occured
void gdsp_step(); void Step();
void gdsp_loop_step(); void Run();
void gdsp_run(); void RunCycles(int cycles);
void gdsp_run_cycles(int cycles); void Stop();
void gdsp_stop();
void gdsp_write_cr(u16 val); void WriteCR(u16 val);
u16 gdsp_read_cr(); u16 ReadCR();
} // namespace } // namespace

View File

@ -50,6 +50,39 @@ inline bool dsp_SR_is_flag_set(int flag)
return (g_dsp.r[DSP_REG_SR] & (1 << flag)) != 0; 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 // --- reg
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------

View File

@ -179,7 +179,7 @@ THREAD_RETURN dsp_thread(void* lpParameter)
{ {
while (bIsRunning) while (bIsRunning)
{ {
DSPInterpreter::gdsp_run(); DSPInterpreter::Run();
} }
return 0; return 0;
} }
@ -249,7 +249,7 @@ void Initialize(void *init)
void DSP_StopSoundStream() void DSP_StopSoundStream()
{ {
DSPInterpreter::gdsp_stop(); DSPInterpreter::Stop();
bIsRunning = false; bIsRunning = false;
if (g_dspInitialize.bOnThread) if (g_dspInitialize.bOnThread)
{ {
@ -266,13 +266,13 @@ void Shutdown()
u16 DSP_WriteControlRegister(u16 _uFlag) u16 DSP_WriteControlRegister(u16 _uFlag)
{ {
DSPInterpreter::gdsp_write_cr(_uFlag); DSPInterpreter::WriteCR(_uFlag);
return DSPInterpreter::gdsp_read_cr(); return DSPInterpreter::ReadCR();
} }
u16 DSP_ReadControlRegister() u16 DSP_ReadControlRegister()
{ {
return DSPInterpreter::gdsp_read_cr(); return DSPInterpreter::ReadCR();
} }
u16 DSP_ReadMailboxHigh(bool _CPUMailbox) 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 we're not on a thread, run cycles here.
if (!g_dspInitialize.bOnThread) if (!g_dspInitialize.bOnThread)
{ {
DSPInterpreter::gdsp_run_cycles(cycles); DSPInterpreter::RunCycles(cycles);
} }
} }