New DSP debugger: step one. (not ready yet, but try loading zelda WW and look at the dsp debugger..).

Had to shuffle around quite a lot of code to be able to extract the CodeView into a library nicely so it can be used from both the main dolphin and the LLE plugin...  also extracted the symboldb code.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3517 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2009-06-21 08:39:21 +00:00
parent 80217a6ed7
commit aecaf271f1
76 changed files with 1895 additions and 794 deletions

View File

@ -299,7 +299,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\Common\Src"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
PreprocessorDefinitions="LOGGING;WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@ -363,7 +363,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\Common\Src"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
PreprocessorDefinitions="LOGGING;WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@ -426,6 +426,10 @@
>
</File>
</Filter>
<Filter
Name="Debugger"
>
</Filter>
<File
RelativePath=".\Src\assemble.cpp"
>

View File

@ -155,6 +155,8 @@ void DSPCore_CheckExternalInterrupt()
{
// level 7 is the interrupt exception
DSPCore_SetException(7);
// Uh, confusing. Can this really be right?
g_dsp.cr &= ~0x0002;
}
}

View File

@ -24,6 +24,7 @@
// can be stubbed out.
u8 DSPHost_ReadHostMemory(u32 addr);
void DSPHost_WriteHostMemory(u8 value, u32 addr);
bool DSPHost_OnThread();
bool DSPHost_Running();
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);

View File

@ -364,15 +364,42 @@ const pdlabel_t pdlabels[] =
{0xffad, "COEF_A2_6", "COEF_A2_6",},
{0xffae, "COEF_A1_7", "COEF_A1_7",},
{0xffaf, "COEF_A2_7", "COEF_A2_7",},
{0xffb0, 0, 0,},
{0xffb1, 0, 0,},
{0xffb2, 0, 0,},
{0xffb3, 0, 0,},
{0xffb4, 0, 0,},
{0xffb5, 0, 0,},
{0xffb6, 0, 0,},
{0xffb7, 0, 0,},
{0xffb8, 0, 0,},
{0xffb9, 0, 0,},
{0xffba, 0, 0,},
{0xffbb, 0, 0,},
{0xffbc, 0, 0,},
{0xffbd, 0, 0,},
{0xffbe, 0, 0,},
{0xffbf, 0, 0,},
{0xffc0, 0, 0,},
{0xffc1, 0, 0,},
{0xffc2, 0, 0,},
{0xffc3, 0, 0,},
{0xffc4, 0, 0,},
{0xffc5, 0, 0,},
{0xffc6, 0, 0,},
{0xffc7, 0, 0,},
{0xffc8, 0, 0,},
{0xffc9, "DSCR", "DSP DMA Control Reg",},
{0xffca, 0, 0,},
{0xffcb, "DSBL", "DSP DMA Block Length",},
{0xffcc, 0, 0,},
{0xffcd, "DSPA", "DSP DMA DMEM Address",},
{0xffce, "DSMAH", "DSP DMA Mem Address H",},
{0xffcf, "DSMAL", "DSP DMA Mem Address L",},
{0xffd0, 0,0,},
{0xffd1, "SampleFormat", "SampleFormat",},
{0xffd3, "Unk Zelda", "Unk Zelda writes to it",},
{0xffd2, 0,0,},
{0xffd3, "UnkZelda", "Unk Zelda reads/writes from/to it",},
{0xffd4, "ACSAH", "Accelerator start address H",},
{0xffd5, "ACSAL", "Accelerator start address L",},
{0xffd6, "ACEAH", "Accelerator end address H",},
@ -384,7 +411,34 @@ const pdlabel_t pdlabels[] =
{0xffdc, "yn2", "yn2",},
{0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",},
{0xffde, "GAIN", "Gain",},
{0xffdf, 0,0,},
{0xffe0, 0,0,},
{0xffe1, 0,0,},
{0xffe2, 0,0,},
{0xffe3, 0,0,},
{0xffe4, 0,0,},
{0xffe5, 0,0,},
{0xffe6, 0,0,},
{0xffe7, 0,0,},
{0xffe8, 0,0,},
{0xffe9, 0,0,},
{0xffea, 0,0,},
{0xffeb, 0,0,},
{0xffec, 0,0,},
{0xffed, 0,0,},
{0xffee, 0,0,},
{0xffef, "AMDM", "ARAM DMA Request Mask",},
{0xfff0, 0,0,},
{0xfff1, 0,0,},
{0xfff2, 0,0,},
{0xfff3, 0,0,},
{0xfff4, 0,0,},
{0xfff5, 0,0,},
{0xfff6, 0,0,},
{0xfff7, 0,0,},
{0xfff8, 0,0,},
{0xfff9, 0,0,},
{0xfffa, 0,0,},
{0xfffb, "DIRQ", "DSP IRQ Request",},
{0xfffc, "DMBH", "DSP Mailbox H",},
{0xfffd, "DMBL", "DSP Mailbox L",},

View File

@ -82,7 +82,7 @@ bool DSPDisassembler::Disassemble(int start_pc, const std::vector<u16> &code, in
fclose(f);
// Run the two passes.
return DisFile(tmp1, 1, text) && DisFile(tmp1, 2, text);
return DisFile(tmp1, base_addr, 1, text) && DisFile(tmp1, base_addr, 2, text);
}
char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char *strbuf)
@ -186,7 +186,7 @@ static void MakeLowerCase(char *ptr)
}
}
void DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest)
bool DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest)
{
char buffer[256];
char *buf = buffer;
@ -200,11 +200,10 @@ void DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16
{
*pc++;
dest.append("; outside memory");
return;
return false;
}
*pc &= 0x0fff;
const u32 op1 = binbuf[*pc];
const u32 op1 = binbuf[*pc & 0x0fff];
const DSPOPCTemplate *opc = NULL;
const DSPOPCTemplate *opc_ext = NULL;
@ -259,7 +258,7 @@ void DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16
// Size 2 - the op has a large immediate.
if ((opc->size & ~P_EXT) == 2)
{
op2 = binbuf[*pc + 1];
op2 = binbuf[(*pc + 1) & 0x0fff];
if (settings_.show_hex)
buf += sprintf(buf, "%04x %04x ", op1, op2);
}
@ -318,9 +317,10 @@ void DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16
if (pass == 2)
dest.append(buffer);
return true;
}
bool DSPDisassembler::DisFile(const char* name, int pass, std::string &output)
bool DSPDisassembler::DisFile(const char* name, int base_addr, int pass, std::string &output)
{
FILE* in = fopen(name, "rb");
if (in == NULL)
@ -339,7 +339,7 @@ bool DSPDisassembler::DisFile(const char* name, int pass, std::string &output)
// Actually do the disassembly.
for (u16 pc = 0; pc < (size / 2);)
{
DisOpcode(binbuf, 0x0000, pass, &pc, output);
DisOpcode(binbuf, base_addr, pass, &pc, output);
if (pass == 2)
output.append("\n");
}

View File

@ -67,11 +67,11 @@ public:
// Warning - this one is trickier to use right.
// Use pass == 2 if you're just using it by itself.
void DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest);
bool DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest);
private:
// Moves PC forward and writes the result to dest.
bool DisFile(const char* name, int pass, std::string &output);
bool DisFile(const char* name, int base_addr, int pass, std::string &output);
char* DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char* strbuf);
std::map<u16, int> unk_opcodes;

View File

@ -64,6 +64,18 @@ s16 ADPCM_Step(u32& _rSamplePos)
return val;
}
void dsp_write_aram_d3(u16 value)
{
// Not sure about this one but it sure looks like Zelda is writing to ARAM
// through 0xFFd3...
const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
DSPHost_WriteHostMemory(value >> 8, Address);
DSPHost_WriteHostMemory(value & 0xFF, Address + 1);
}
u16 dsp_read_aram()
{
const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];

View File

@ -19,5 +19,6 @@
#define _GDSP_ARAM_H
u16 dsp_read_aram();
void dsp_write_aram_d3(u16 value);
#endif

View File

@ -30,6 +30,7 @@
#include "DSPCore.h"
#include "DSPHost.h"
#include "DSPTables.h"
#include "DSPAnalyzer.h"
#include "gdsp_aram.h"
#include "gdsp_interpreter.h"
@ -89,6 +90,8 @@ void gdsp_mbox_write_l(u8 mbx, u16 val)
if (mbx == GDSP_MBOX_DSP)
{
DEBUG_LOG(DSPLLE, " - DSP writes mail to mbx %i: 0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc);
} else {
// Trigger exception?
}
}
@ -138,6 +141,11 @@ void gdsp_ifx_write(u16 addr, u16 val)
gdsp_ifx_regs[DSP_DSCR] &= ~0x0004;
break;
case 0xd3: // ZeldaUnk (accelerator WRITE)
ERROR_LOG(DSPLLE, "Write To ZeldaUnk pc=%04x (%04x)\n", g_dsp.pc, val);
dsp_write_aram_d3(val);
break;
case 0xde:
//if (val)
// PanicAlert("Gain written: %04x", val); // BMX XXX does, and sounds HORRIBLE.
@ -149,10 +157,17 @@ void gdsp_ifx_write(u16 addr, u16 val)
break;
default:
/* if ((addr & 0xff) >= 0xa0 && reg_names[addr - 0xa0])
DEBUG_LOG(DSPLLE, "%04x MW %s (%04x)\n", g_dsp.pc, reg_names[addr - 0xa0], val);
else
DEBUG_LOG(DSPLLE, "%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);*/
if ((addr & 0xff) >= 0xa0) {
if (pdlabels[(addr & 0xFF) - 0xa0].name) {
INFO_LOG(DSPLLE, "%04x MW %s (%04x)\n", g_dsp.pc, pdlabels[(addr & 0xFF) - 0xa0].name, val);
}
else {
ERROR_LOG(DSPLLE, "%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);
}
}
else {
ERROR_LOG(DSPLLE, "%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);
}
gdsp_ifx_regs[addr & 0xFF] = val;
break;
}
@ -176,14 +191,22 @@ u16 gdsp_ifx_read(u16 addr)
return gdsp_ifx_regs[addr & 0xFF];
case 0xdd:
// ERROR_LOG(DSPLLE, "Accelerator");
return dsp_read_aram();
default:
if ((addr & 0xff) >= 0xa0) {
if (pdlabels[(addr & 0xFF) - 0xa0].name) {
INFO_LOG(DSPLLE, "%04x MR %s (%04x)\n", g_dsp.pc, pdlabels[(addr & 0xFF) - 0xa0].name, gdsp_ifx_regs[addr & 0xFF]);
}
else {
ERROR_LOG(DSPLLE, "%04x MR %04x (%04x)\n", g_dsp.pc, addr, gdsp_ifx_regs[addr & 0xFF]);
}
}
else {
ERROR_LOG(DSPLLE, "%04x MR %04x (%04x)\n", g_dsp.pc, addr, gdsp_ifx_regs[addr & 0xFF]);
}
return gdsp_ifx_regs[addr & 0xFF];
/* if ((addr & 0xff) >= 0xc0 && reg_names[addr & 0x3f])
printf("%04x MR %s (%04x)\n", g_dsp.pc, reg_names[addr & 0x3f], val);
else
printf("%04x MR %04x (%04x)\n", g_dsp.pc, addr, val);*/
}
}

View File

@ -78,10 +78,12 @@ void HandleLoop()
const u16 rCallAddress = g_dsp.r[DSP_REG_ST0];
const u16 rLoopAddress = g_dsp.r[DSP_REG_ST2];
// This does not always work correctly!
// The loop end tends to point to the second part of
// two-byte instructions!
if (g_dsp.pc == (rLoopAddress + 1))
{
rLoopCounter--;
if (rLoopCounter > 0)
{
g_dsp.pc = rCallAddress;
@ -147,6 +149,21 @@ void Run()
// Used by non-thread mode.
void RunCycles(int cycles)
{
if (cycles < 18)
{
for (int i = 0; i < cycles; i++)
{
if (g_dsp.cr & CR_HALT)
return;
if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP)
return;
Step();
cycles--;
}
return;
}
DSPCore_CheckExternalInterrupt();
// First, let's run a few cycles with no idle skipping so that things can progress a bit.
@ -158,7 +175,7 @@ void RunCycles(int cycles)
cycles--;
}
// Next, let's run a few cycles with idle skipping, so that we can skip loops.
// Next, let's run a few cycles with idle skipping, so that we can skip idle loops.
for (int i = 0; i < 8; i++)
{
if (g_dsp.cr & CR_HALT)