DSP LLE: Just some renaming and cleanup. Prepared for proper base address support in disassembly. Added a "DebugInterface" for the DSP which would allow us to hook up a CodeView .. although CoreView currently doesn't have any support for variable-length instructions.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3351 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2009-06-07 11:06:40 +00:00
parent 89cd1a4a76
commit bb06a53e28
15 changed files with 309 additions and 123 deletions

View File

@ -59,7 +59,7 @@ bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &t
settings.decode_registers = true;
DSPDisassembler disasm(settings);
bool success = disasm.Disassemble(0, code, text);
bool success = disasm.Disassemble(0, code, 0x0000, text);
return success;
}
@ -80,9 +80,9 @@ bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
{
std::string line1, line2;
u16 pc = i;
disassembler.DisOpcode(&code1[0], 2, &pc, line1);
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
pc = i;
disassembler.DisOpcode(&code2[0], 2, &pc, line2);
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
}
}
@ -94,7 +94,7 @@ bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
{
u16 pc = i;
std::string line;
disassembler.DisOpcode(&longest[0], 2, &pc, line);
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
printf("!! %s\n", line.c_str());
}
}

View File

@ -32,16 +32,38 @@
#include "gdsp_registers.h"
#include "gdsp_opcodes_helper.h"
//namespace DSPCore
//{
SDSP g_dsp;
//-------------------------------------------------------------------------------
void gdsp_init()
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
{
FILE *pFile = fopen(fname, "rb");
const size_t size_in_bytes = size_in_words * sizeof(u16);
if (pFile)
{
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
if (read_bytes != size_in_bytes)
{
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
fclose(pFile);
return false;
}
fclose(pFile);
// Byteswap the rom.
for (int i = 0; i < DSP_IROM_SIZE; i++)
rom[i] = Common::swap16(rom[i]);
return true;
}
// Always keep ROMs write protected.
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
return false;
}
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
{
g_dsp.step_counter = 0;
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
@ -51,6 +73,10 @@ void gdsp_init()
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
for (int i = 0; i < 32; i++)
{
g_dsp.r[i] = 0;
@ -74,14 +100,15 @@ void gdsp_init()
// Just zero out DRAM.
for (int i = 0; i < DSP_DRAM_SIZE; i++)
{
g_dsp.dram[i] = 0x2100;
g_dsp.dram[i] = 0;
}
// copied from a real console after the custom UCode has been loaded
g_dsp.r[0x08] = 0xffff;
g_dsp.r[0x09] = 0xffff;
g_dsp.r[0x0a] = 0xffff;
g_dsp.r[0x0b] = 0xffff;
// Copied from a real console after the custom UCode has been loaded.
// These are the indexing wrapping registers.
g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff;
g_dsp.cr = 0x804;
gdsp_ifx_init();
@ -90,9 +117,11 @@ void gdsp_init()
// in new ucodes.
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
DSPAnalyzer::Analyze();
return true;
}
void gdsp_shutdown()
void DSPCore_Shutdown()
{
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
@ -100,71 +129,24 @@ void gdsp_shutdown()
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
}
void gdsp_reset()
void DSPCore_Reset()
{
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false;
g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff;
}
void gdsp_generate_exception(u8 level)
void DSPCore_SetException(u8 level)
{
g_dsp.exceptions |= 1 << level;
}
bool gdsp_load_irom(const char *fname)
{
FILE *pFile = fopen(fname, "rb");
if (pFile)
{
size_t size_in_bytes = DSP_IROM_SIZE * sizeof(u16);
size_t read_bytes = fread(g_dsp.irom, 1, size_in_bytes, pFile);
if (read_bytes != size_in_bytes)
{
PanicAlert("IROM too short : %i/%i", (int)read_bytes, (int)size_in_bytes);
fclose(pFile);
return false;
}
fclose(pFile);
// Byteswap the rom.
for (int i = 0; i < DSP_IROM_SIZE; i++)
g_dsp.irom[i] = Common::swap16(g_dsp.irom[i]);
return true;
}
// Always keep IROM write protected.
WriteProtectMemory(g_dsp.irom, DSP_IROM_BYTE_SIZE, false);
return false;
}
bool gdsp_load_coef(const char *fname)
{
FILE *pFile = fopen(fname, "rb");
if (pFile)
{
size_t size_in_bytes = DSP_COEF_SIZE * sizeof(u16);
size_t read_bytes = fread(g_dsp.coef, 1, size_in_bytes, pFile);
if (read_bytes != size_in_bytes)
{
PanicAlert("COEF too short : %i/%i", (int)read_bytes, (int)size_in_bytes);
fclose(pFile);
return false;
}
fclose(pFile);
// Byteswap the rom.
for (int i = 0; i < DSP_IROM_SIZE; i++)
g_dsp.coef[i] = Common::swap16(g_dsp.coef[i]);
return true;
}
// Always keep COEF write protected. We unprotect only when DMA-ing
WriteProtectMemory(g_dsp.coef, DSP_COEF_BYTE_SIZE, false);
return false;
}
void gdsp_check_external_int()
void DSPCore_CheckExternalInterrupt()
{
// check if there is an external interrupt
if (g_dsp.cr & CR_EXTERNAL_INT)
@ -172,13 +154,13 @@ void gdsp_check_external_int()
if (dsp_SR_is_flag_set(FLAG_ENABLE_INTERUPT) && (g_dsp.exception_in_progress_hack == false))
{
// level 7 is the interrupt exception
gdsp_generate_exception(7);
DSPCore_SetException(7);
g_dsp.cr &= ~0x0002;
}
}
}
void gdsp_check_exceptions()
void DSPCore_CheckExceptions()
{
// check exceptions
if ((g_dsp.exceptions != 0) && (!g_dsp.exception_in_progress_hack))
@ -201,5 +183,3 @@ void gdsp_check_exceptions()
}
}
}
//} // namespace

View File

@ -26,9 +26,6 @@
#ifndef _DSPCORE_H
#define _DSPCORE_H
//namespace DSPCore
//{
#define DSP_IRAM_BYTE_SIZE 0x2000
#define DSP_IRAM_SIZE 0x1000
#define DSP_IRAM_MASK 0x0fff
@ -83,19 +80,14 @@ struct SDSP
extern SDSP g_dsp;
void gdsp_init();
void gdsp_reset();
void gdsp_shutdown();
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
void DSPCore_Reset();
void DSPCore_Shutdown(); // Frees all allocated memory.
bool gdsp_load_irom(const char *filename);
bool gdsp_load_coef(const char *filename);
void gdsp_check_external_int();
void gdsp_check_exceptions();
void DSPCore_CheckExternalInterrupt();
void DSPCore_CheckExceptions();
// sets a flag in the pending exception register.
void gdsp_generate_exception(u8 level);
//} // namespace
void DSPCore_SetException(u8 level);
#endif // _DSPCORE_H

View File

@ -71,7 +71,7 @@ DSPDisassembler::~DSPDisassembler()
fclose(uo);
}
bool DSPDisassembler::Disassemble(int start_pc, const std::vector<u16> &code, std::string &text)
bool DSPDisassembler::Disassemble(int start_pc, const std::vector<u16> &code, int base_addr, std::string &text)
{
const char *tmp1 = "tmp1.bin";
const char *tmp2 = "tmp.txt";
@ -186,7 +186,7 @@ static void MakeLowerCase(char *ptr)
}
}
void DSPDisassembler::DisOpcode(const u16 *binbuf, int pass, u16 *pc, std::string &dest)
void DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest)
{
char buffer[256];
char *buf = buffer;
@ -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, pass, &pc, output);
DisOpcode(binbuf, 0x0000, pass, &pc, output);
if (pass == 2)
output.append("\n");
}

View File

@ -63,11 +63,11 @@ public:
DSPDisassembler(const AssemblerSettings &settings);
~DSPDisassembler();
bool Disassemble(int start_pc, const std::vector<u16> &code, std::string &text);
bool Disassemble(int start_pc, const std::vector<u16> &code, int base_addr, std::string &text);
// 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 pass, u16 *pc, std::string &dest);
void DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest);
private:
// Moves PC forward and writes the result to dest.

View File

@ -103,8 +103,8 @@ u16 dsp_read_aram()
Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
// Do we really need both?
gdsp_generate_exception(3);
gdsp_generate_exception(5);
DSPCore_SetException(3);
DSPCore_SetException(5);
// Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah,
// it seems likely that we should raise an exception to let the DSP program do that,

View File

@ -35,10 +35,11 @@
// "index" register (the second four, IXx). The addressing registers will wrap
// in odd ways, dictated by the corresponding wrapping register, WP0-3.
// The following should be applied as a decrement:
// The following should be applied as a decrement (and is applied by dsp_decrement_addr_reg):
// ar[i] = (ar[i] & wp[i]) == 0 ? ar[i] | wp[i] : ar[i] - 1;
// I have not found the corresponding algorithms for increments yet.
// It's gotta be fairly simple though. See R3123, R3125 in Google Code.
// (May have something to do with (ar[i] ^ wp[i]) == 0)
namespace DSPInterpreter
{

View File

@ -45,7 +45,7 @@ void WriteCR(u16 val)
// reset
if (val & 0x0001)
{
gdsp_reset();
DSPCore_Reset();
}
val &= ~0x0001;
@ -99,7 +99,7 @@ void HandleLoop()
void Step()
{
gdsp_check_exceptions();
DSPCore_CheckExceptions();
g_dsp.step_counter++;
@ -133,7 +133,7 @@ void Run()
if (DSPHost_Running())
break;
gdsp_check_external_int();
DSPCore_CheckExternalInterrupt();
// This number (500) is completely arbitrary. TODO: tweak.
for (int i = 0; i < 500 && !(g_dsp.cr & CR_HALT); i++)
Step();
@ -147,7 +147,7 @@ void Run()
// Used by non-thread mode.
void RunCycles(int cycles)
{
gdsp_check_external_int();
DSPCore_CheckExternalInterrupt();
// First, let's run a few cycles with no idle skipping so that things can progress a bit.
for (int i = 0; i < 8; i++)