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
// $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);
}
//-------------------------------------------------------------

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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

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;
}
// 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
// ---------------------------------------------------------------------------------------

View File

@ -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);
}
}