dsp_base.inc: mail the exception instead of wr3 (no idea why that was there anyways). DSPSpy will report the exception now.
DSPTool: incorporate printresult functionality. delete printresult.cpp DSPSpy: fix dumping of results git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3852 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
d703b01f0c
commit
d09b777de8
|
@ -165,10 +165,6 @@
|
||||||
RelativePath=".\util\dump_roms.ds"
|
RelativePath=".\util\dump_roms.ds"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\util\printresult.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="templates"
|
Name="templates"
|
||||||
|
|
|
@ -327,12 +327,22 @@ void handle_dsp_mail(void)
|
||||||
DCFlushRange(dspbufC, 0x2000);
|
DCFlushRange(dspbufC, 0x2000);
|
||||||
// Then send the code.
|
// Then send the code.
|
||||||
DCFlushRange((void *)dsp_code[curUcode], 0x2000);
|
DCFlushRange((void *)dsp_code[curUcode], 0x2000);
|
||||||
|
// Fill whole iram with code, entry point is just after exception vectors...0x10
|
||||||
real_dsp.SendTask((void *)MEM_VIRTUAL_TO_PHYSICAL(dsp_code[curUcode]), 0, 4000, 0x10);
|
real_dsp.SendTask((void *)MEM_VIRTUAL_TO_PHYSICAL(dsp_code[curUcode]), 0, 4000, 0x10);
|
||||||
|
|
||||||
runningUcode = curUcode + 1;
|
runningUcode = curUcode + 1;
|
||||||
}
|
}
|
||||||
|
else if ((mail & 0xffff0000) == 0x8bad0000)
|
||||||
|
{
|
||||||
|
// dsp_base.inc is reporting an exception happened
|
||||||
|
char temp[100];
|
||||||
|
sprintf(temp, "Exception %x", mail & 0xff);
|
||||||
|
UpdateLastMessage(temp);
|
||||||
|
}
|
||||||
else if (mail == 0x8888dead)
|
else if (mail == 0x8888dead)
|
||||||
{
|
{
|
||||||
|
// Send memory dump (dsp dram from someone's cube?)
|
||||||
|
// not really sure why this is important - I guess just to try to keep tests predictable
|
||||||
u16* tmpBuf = (u16 *)MEM_VIRTUAL_TO_PHYSICAL(mem_dump);
|
u16* tmpBuf = (u16 *)MEM_VIRTUAL_TO_PHYSICAL(mem_dump);
|
||||||
|
|
||||||
while (real_dsp.CheckMailTo());
|
while (real_dsp.CheckMailTo());
|
||||||
|
@ -341,6 +351,7 @@ void handle_dsp_mail(void)
|
||||||
}
|
}
|
||||||
else if (mail == 0x8888beef)
|
else if (mail == 0x8888beef)
|
||||||
{
|
{
|
||||||
|
// Provide register base to dsp (if using dsp_base.inc, it will dma them to the correct place)
|
||||||
while (real_dsp.CheckMailTo());
|
while (real_dsp.CheckMailTo());
|
||||||
real_dsp.SendMailTo((u32)dspbufP);
|
real_dsp.SendMailTo((u32)dspbufP);
|
||||||
while (real_dsp.CheckMailTo());
|
while (real_dsp.CheckMailTo());
|
||||||
|
@ -376,44 +387,47 @@ void handle_dsp_mail(void)
|
||||||
DumpDSP_ROMs(dspbufP, &dspbufP[0x1000]);
|
DumpDSP_ROMs(dspbufP, &dspbufP[0x1000]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CON_Printf(2, 1, "UCode: %d/%d %s, Last mail: %08x", runningUcode, NUM_UCODES, UCODE_NAMES[runningUcode - 1], mail);
|
CON_Printf(2, 1, "UCode: %d/%d %s, Last mail: %08x",
|
||||||
|
curUcode + 1, NUM_UCODES, UCODE_NAMES[curUcode], mail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_all_ucodes(void)
|
void dump_all_ucodes(void)
|
||||||
{
|
{
|
||||||
char filename[260] = {0};
|
char filename[260] = {0};
|
||||||
for (int i = 0; i < NUM_UCODES; i++)
|
for (int UCodeToDump = 0; UCodeToDump < NUM_UCODES; UCodeToDump++)
|
||||||
{
|
{
|
||||||
// First, change the microcode
|
// First, change the microcode
|
||||||
dsp_steps = 0;
|
dsp_steps = 0;
|
||||||
curUcode = i;
|
curUcode = UCodeToDump;
|
||||||
runningUcode = 0;
|
runningUcode = 0;
|
||||||
|
|
||||||
DCInvalidateRange(dspbufC, 0x2000);
|
DCInvalidateRange(dspbufC, 0x2000);
|
||||||
DCFlushRange(dspbufC, 0x2000);
|
DCFlushRange(dspbufC, 0x2000);
|
||||||
|
|
||||||
real_dsp.Reset();
|
real_dsp.Reset();
|
||||||
VIDEO_WaitVSync();
|
|
||||||
|
|
||||||
while (runningUcode != (curUcode + 1))
|
VIDEO_WaitVSync();
|
||||||
{
|
// Loop over handling mail until we've stopped stepping
|
||||||
|
// dsp_steps-3 compensates for mails to setup the ucode
|
||||||
|
for (int steps_cache = dsp_steps-3; steps_cache <= dsp_steps; steps_cache++)
|
||||||
handle_dsp_mail();
|
handle_dsp_mail();
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
}
|
|
||||||
|
|
||||||
// Then write microcode dump to file
|
// Then write microcode dump to file
|
||||||
sprintf(filename, "sd:/dsp_dump%d.bin", i + 1);
|
sprintf(filename, "sd:/dsp_dump%d.bin", UCodeToDump);
|
||||||
FILE *f = fopen(filename, "wb");
|
FILE *f = fopen(filename, "wb");
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
// First write initial regs
|
// First write initial regs
|
||||||
fwrite(dspreg_in, 1, 32 * 2, f);
|
u32 written = fwrite(dspreg_in, 1, 32 * 2, f);
|
||||||
|
|
||||||
// Then write all the dumps.
|
// Then write all the dumps.
|
||||||
fwrite(dspreg_out, 1, dsp_steps * 32 * 2, f);
|
written += fwrite(dspreg_out, 1, dsp_steps * 32 * 2, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
UpdateLastMessage("Dump Successful.");
|
char temp[100];
|
||||||
|
sprintf(temp, "Dump Successful. Wrote %d bytes, steps: %d", written, dsp_steps);
|
||||||
|
UpdateLastMessage(temp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -436,7 +450,7 @@ void InitGeneral()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Obtain the preferred video mode from the system
|
// Obtain the preferred video mode from the system
|
||||||
// This will correspond to the settings in the Wii menu
|
// This will correspond to the settings in the WiUCodeToDump menu
|
||||||
rmode = VIDEO_GetPreferredMode(NULL);
|
rmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
|
||||||
// Allocate memory for the display in the uncached region
|
// Allocate memory for the display in the uncached region
|
||||||
|
|
|
@ -29,8 +29,8 @@ MEM_LO: equ 0x0f7F
|
||||||
|
|
||||||
; Why do we have a main label here?
|
; Why do we have a main label here?
|
||||||
main:
|
main:
|
||||||
clr $ACC1
|
clr $acc1
|
||||||
clr $ACC0
|
clr $acc0
|
||||||
|
|
||||||
; get address of memory dump and copy it to DRAM
|
; get address of memory dump and copy it to DRAM
|
||||||
|
|
||||||
|
@ -40,11 +40,11 @@ main:
|
||||||
si @DIRQ, #0x0001
|
si @DIRQ, #0x0001
|
||||||
|
|
||||||
call wait_for_cpu_mbox
|
call wait_for_cpu_mbox
|
||||||
lrs $AC0.M, @CMBL
|
lrs $ac0.m, @CMBL
|
||||||
andi $ac1.m, #0x7fff
|
andi $ac1.m, #0x7fff
|
||||||
|
|
||||||
sr @MEM_HI, $AC1.M
|
sr @MEM_HI, $ac1.m
|
||||||
sr @MEM_LO, $AC0.M
|
sr @MEM_LO, $ac0.m
|
||||||
|
|
||||||
lri $ax0.l, #0
|
lri $ax0.l, #0
|
||||||
lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
|
lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
|
||||||
|
@ -62,11 +62,11 @@ main:
|
||||||
si @DIRQ, #0x0001
|
si @DIRQ, #0x0001
|
||||||
|
|
||||||
call wait_for_cpu_mbox
|
call wait_for_cpu_mbox
|
||||||
lrs $AC0.M, @CMBL
|
lrs $ac0.m, @CMBL
|
||||||
andi $ac1.m, #0x7fff
|
andi $ac1.m, #0x7fff
|
||||||
|
|
||||||
sr @MEM_HI, $AC1.M
|
sr @MEM_HI, $ac1.m
|
||||||
sr @MEM_LO, $AC0.M
|
sr @MEM_LO, $ac0.m
|
||||||
|
|
||||||
lri $ax0.l, #REGS_BASE
|
lri $ax0.l, #REGS_BASE
|
||||||
lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
|
lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
|
||||||
|
@ -139,21 +139,21 @@ do_dma:
|
||||||
|
|
||||||
; Waits for said DMA to complete by watching a bit in DSCR.
|
; Waits for said DMA to complete by watching a bit in DSCR.
|
||||||
wait_dma:
|
wait_dma:
|
||||||
LRS $AC1.M, @DSCR
|
lrs $ac1.m, @DSCR
|
||||||
andcf $ac1.m, #0x0004
|
andcf $ac1.m, #0x0004
|
||||||
JLZ wait_dma
|
jlz wait_dma
|
||||||
RET
|
ret
|
||||||
|
|
||||||
; This waits for a mail to arrive in the DSP in-mailbox.
|
; This waits for a mail to arrive in the DSP in-mailbox.
|
||||||
wait_for_dsp_mbox:
|
wait_for_dsp_mbox:
|
||||||
lrs $AC1.M, @DMBH
|
lrs $ac1.m, @DMBH
|
||||||
andcf $ac1.m, #0x8000
|
andcf $ac1.m, #0x8000
|
||||||
jlz wait_for_dsp_mbox
|
jlz wait_for_dsp_mbox
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; This waits for the CPU to grab a mail that we just sent from the DSP.
|
; This waits for the CPU to grab a mail that we just sent from the DSP.
|
||||||
wait_for_cpu_mbox:
|
wait_for_cpu_mbox:
|
||||||
lrs $AC1.M, @cmbh
|
lrs $ac1.m, @CMBH
|
||||||
andcf $ac1.m, #0x8000
|
andcf $ac1.m, #0x8000
|
||||||
jlnz wait_for_cpu_mbox
|
jlnz wait_for_cpu_mbox
|
||||||
ret
|
ret
|
||||||
|
@ -200,18 +200,18 @@ irq7:
|
||||||
jmp irq
|
jmp irq
|
||||||
|
|
||||||
irq:
|
irq:
|
||||||
lrs $AC1.M, @DMBH
|
lrs $ac1.m, @DMBH
|
||||||
andcf $ac1.m, #0x8000
|
andcf $ac1.m, #0x8000
|
||||||
jlz irq
|
jlz irq
|
||||||
si @DMBH, #0x8BAD
|
si @DMBH, #0x8bad
|
||||||
sr @DMBL, $wr3 ; ???
|
;sr @DMBL, $wr3 ; ???
|
||||||
;sr @DMBL, $ac0.m
|
sr @DMBL, $ac0.m ; Exception number
|
||||||
si @DIRQ, #0x0001
|
si @DIRQ, #0x0001
|
||||||
halt
|
halt
|
||||||
|
|
||||||
; DMA:s the current state of the registers back to the PowerPC. To do this,
|
; DMA:s the current state of the registers back to the PowerPC. To do this,
|
||||||
; it must write the contents of all regs to DRAM.
|
; it must write the contents of all regs to DRAM.
|
||||||
; Unfortunately, this loop uses AR0 so it's best to use AR1 and friends for testing
|
; Unfortunately, this loop uses ar0 so it's best to use AR1 and friends for testing
|
||||||
; when messing with indexing.
|
; when messing with indexing.
|
||||||
send_back:
|
send_back:
|
||||||
; make state safe.
|
; make state safe.
|
||||||
|
@ -280,7 +280,7 @@ dma_copy:
|
||||||
|
|
||||||
; wait for the CPU to recieve our response before we execute the next op
|
; wait for the CPU to recieve our response before we execute the next op
|
||||||
call wait_for_cpu_mbox
|
call wait_for_cpu_mbox
|
||||||
lrs $AC0.M, @CMBL
|
lrs $ac0.m, @CMBL
|
||||||
andi $ac1.m, #0x7fff
|
andi $ac1.m, #0x7fff
|
||||||
|
|
||||||
; Restore all regs again so we're ready to execute another op.
|
; Restore all regs again so we're ready to execute another op.
|
||||||
|
@ -338,7 +338,7 @@ dump_memory:
|
||||||
bloop $ar1, _fill_loop2
|
bloop $ar1, _fill_loop2
|
||||||
|
|
||||||
mrr $ar3, $ac0.m
|
mrr $ar3, $ac0.m
|
||||||
nx'ld : $AX0.H, $AX1.H, @$AR0
|
nx'ld : $ax0.h, $ax1.h, @$ar0
|
||||||
|
|
||||||
mrr $ac1.m, $ar0
|
mrr $ac1.m, $ar0
|
||||||
mrr $ar0, $ar2
|
mrr $ar0, $ar2
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
typedef unsigned short u16;
|
|
||||||
|
|
||||||
u16 reg_in[32], reg_out[1000][32];
|
|
||||||
|
|
||||||
inline u16 swap16(u16 s) {
|
|
||||||
return (s >> 8) | (s << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printRegs(u16 *lastRegs, u16 *regs) {
|
|
||||||
for (int i = 0; i < 32; i++) {
|
|
||||||
if (! lastRegs || lastRegs[i] != regs[i]) {
|
|
||||||
printf("%02x %04x ", i, swap16(regs[i]));
|
|
||||||
} else {
|
|
||||||
printf(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((i+1) % 8 == 0)
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
|
|
||||||
if (argc != 2) {
|
|
||||||
fprintf(stderr, "Usage %s: <filename>\n", argv[0]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *f = fopen(argv[1], "rb");
|
|
||||||
int steps;
|
|
||||||
if (f) {
|
|
||||||
// read initial regs
|
|
||||||
fread(reg_in, 1, 32 * 2, f);
|
|
||||||
|
|
||||||
// read initial regs (guess number of steps)
|
|
||||||
steps = fread(reg_out, 32 * 2, 1000, f);
|
|
||||||
fclose(f);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error opening file %s\n", argv[1]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Start with:\n");
|
|
||||||
printRegs(NULL, reg_in);
|
|
||||||
|
|
||||||
printf("\nStep 0:\n");
|
|
||||||
printRegs(reg_in, reg_out[0]);
|
|
||||||
|
|
||||||
for (int i=1;i < steps;i++) {
|
|
||||||
printf("\nStep %d:\n", i);
|
|
||||||
printRegs(reg_out[i-1], reg_out[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
|
#include "StringUtil.h"
|
||||||
#include "DSPCodeUtil.h"
|
#include "DSPCodeUtil.h"
|
||||||
|
|
||||||
// Stub out the dsplib host stuff, since this is just a simple cmdline tools.
|
// Stub out the dsplib host stuff, since this is just a simple cmdline tools.
|
||||||
|
@ -202,23 +203,25 @@ void RunAsmTests()
|
||||||
// Disassemble a file, output to standard output:
|
// Disassemble a file, output to standard output:
|
||||||
// dsptool -d asdf.bin
|
// dsptool -d asdf.bin
|
||||||
// Assemble a file:
|
// Assemble a file:
|
||||||
// dsptool -o asdf.bin asdf.txt
|
// dsptool [-f] -o asdf.bin asdf.txt
|
||||||
// Assemble a file, output header:
|
// Assemble a file, output header:
|
||||||
// dsptool -h asdf.h asdf.txt
|
// dsptool [-f] -h asdf.h asdf.txt
|
||||||
// dsptool -f errors are not critical
|
// Print results from DSPSpy register dump
|
||||||
|
// dsptool -p dsp_dump0.bin
|
||||||
// So far, all this binary can do is test partially that itself works correctly.
|
// So far, all this binary can do is test partially that itself works correctly.
|
||||||
int main(int argc, const char *argv[])
|
int main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "--help") || (!strcmp(argv[1], "-?")))))
|
if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "--help") || (!strcmp(argv[1], "-?")))))
|
||||||
{
|
{
|
||||||
printf("USAGE: DSPTool [-?] [--help] [-d] [-m] [-o <FILE>] [-h <FILE>] <DSP ASSEMBLER FILE>\n");
|
printf("USAGE: DSPTool [-?] [--help] [-f] [-d] [-m] [-p <FILE>] [-o <FILE>] [-h <FILE>] <DSP ASSEMBLER FILE>\n");
|
||||||
printf("-? / --help: Prints this message\n");
|
printf("-? / --help: Prints this message\n");
|
||||||
printf("-d: Disassemble\n");
|
printf("-d: Disassemble\n");
|
||||||
printf("-m: Input file contains a list of files (Header assembly only)\n");
|
printf("-m: Input file contains a list of files (Header assembly only)\n");
|
||||||
printf("-s: Print the final size in bytes (only)\n");
|
printf("-s: Print the final size in bytes (only)\n");
|
||||||
|
printf("-f: Force assembly (errors are not critical)\n");
|
||||||
printf("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
|
printf("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
|
||||||
printf("-h <HEADER FILE>: Output assembly results to a header\n");
|
printf("-h <HEADER FILE>: Output assembly results to a header\n");
|
||||||
printf("-f: Errors are not critical\n");
|
printf("-p <DUMP FILE>: Print results of DSPSpy register dump\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +235,7 @@ int main(int argc, const char *argv[])
|
||||||
std::string output_header_name;
|
std::string output_header_name;
|
||||||
std::string output_name;
|
std::string output_name;
|
||||||
|
|
||||||
bool disassemble = false, compare = false, multiple = false, outputSize = false, force = false;
|
bool disassemble = false, compare = false, multiple = false, outputSize = false, force = false, print_results = false;
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if (!strcmp(argv[i], "-d"))
|
if (!strcmp(argv[i], "-d"))
|
||||||
|
@ -249,6 +252,8 @@ int main(int argc, const char *argv[])
|
||||||
multiple = true;
|
multiple = true;
|
||||||
else if (!strcmp(argv[i], "-f"))
|
else if (!strcmp(argv[i], "-f"))
|
||||||
force = true;
|
force = true;
|
||||||
|
else if (!strcmp(argv[i], "-p"))
|
||||||
|
print_results = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!input_name.empty())
|
if (!input_name.empty())
|
||||||
|
@ -285,6 +290,50 @@ int main(int argc, const char *argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (print_results)
|
||||||
|
{
|
||||||
|
std::string dumpfile, results;
|
||||||
|
std::vector<u16> reg_vector;
|
||||||
|
|
||||||
|
File::ReadFileToString(false, input_name.c_str(), dumpfile);
|
||||||
|
BinaryStringBEToCode(dumpfile, reg_vector);
|
||||||
|
|
||||||
|
results.append("Start:\n");
|
||||||
|
for (int initial_reg = 0; initial_reg < 32; initial_reg++)
|
||||||
|
{
|
||||||
|
results.append(StringFromFormat("%02x %04x ", initial_reg, reg_vector.at(initial_reg)));
|
||||||
|
if ((initial_reg + 1) % 8 == 0)
|
||||||
|
results.append("\n");
|
||||||
|
}
|
||||||
|
results.append("\n");
|
||||||
|
results.append("Step [number]:\n[Reg] [last value] [current value]\n\n");
|
||||||
|
for (int step = 1; step < reg_vector.size()/32; step++)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
results.append(StringFromFormat("Step %3d:\n", step));
|
||||||
|
for (int reg = 0; reg < 32; reg++)
|
||||||
|
{
|
||||||
|
u16 last_reg = reg_vector.at((step*32-32)+reg);
|
||||||
|
u16 current_reg = reg_vector.at(step*32+reg);
|
||||||
|
if (last_reg != current_reg)
|
||||||
|
{
|
||||||
|
results.append(StringFromFormat("%02x %04x %04x\n", reg, last_reg, current_reg));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changed)
|
||||||
|
results.append("No Change\n\n");
|
||||||
|
else
|
||||||
|
results.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!output_name.empty())
|
||||||
|
File::WriteStringToFile(true, results, output_name.c_str());
|
||||||
|
else
|
||||||
|
printf(results.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (disassemble)
|
if (disassemble)
|
||||||
{
|
{
|
||||||
if (input_name.empty())
|
if (input_name.empty())
|
||||||
|
|
Loading…
Reference in New Issue