DSP: Give the assembler and disassembler saner public APIs. Fix bug in fileutil ReadFileToString. More cleanup.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2970 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-04-14 22:30:31 +00:00
parent f9903f2054
commit d973a9e001
15 changed files with 193 additions and 288 deletions

View File

@ -626,7 +626,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string *str)
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
char *buf = new char[len + 1]; char *buf = new char[len + 1];
buf[fread(buf, 1, len, f)] = 0; buf[fread(buf, 1, len, f)] = 0;
*str = std::string(buf); *str = std::string(buf, len);
fclose(f); fclose(f);
delete [] buf; delete [] buf;
return true; return true;

View File

@ -26,7 +26,6 @@
bool Assemble(const char *text, std::vector<u16> *code) bool Assemble(const char *text, std::vector<u16> *code)
{ {
const char *fname = "tmp.asm";
AssemblerSettings settings; AssemblerSettings settings;
settings.pc = 0; settings.pc = 0;
// settings.decode_registers = false; // settings.decode_registers = false;
@ -34,22 +33,11 @@ bool Assemble(const char *text, std::vector<u16> *code)
settings.print_tabs = false; settings.print_tabs = false;
settings.ext_separator = '\''; settings.ext_separator = '\'';
if (!File::WriteStringToFile(true, text, fname))
return false;
// TODO: fix the terrible api of the assembler. // TODO: fix the terrible api of the assembler.
DSPAssembler assembler(settings); DSPAssembler assembler(settings);
assembler.gd_ass_init_pass(1); if (!assembler.Assemble(text, code))
if (!assembler.gd_ass_file(fname, 1)) printf("%s", assembler.GetErrorString().c_str());
return false;
assembler.gd_ass_init_pass(2);
if (!assembler.gd_ass_file(fname, 2))
return false;
code->resize(assembler.gdg_buffer_size);
for (int i = 0; i < assembler.gdg_buffer_size; i++) {
(*code)[i] = *(u16 *)(assembler.gdg_buffer + i * 2);
}
return true; return true;
} }
@ -57,34 +45,19 @@ bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string *t
{ {
if (code.empty()) if (code.empty())
return false; return false;
const char *tmp1 = "tmp1.bin";
const char *tmp2 = "tmp.txt";
// First we have to dump the code to a bin file. AssemblerSettings settings;
FILE *f = fopen(tmp1, "wb");
fwrite(&code[0], 1, code.size() * 2, f);
fclose(f);
FILE* t = fopen(tmp2, "w"); // These two prevent roundtripping.
if (t != NULL) settings.show_hex = false;
{ settings.show_pc = line_numbers;
AssemblerSettings settings; settings.ext_separator = '\'';
settings.decode_names = false;
settings.decode_registers = true;
// These two prevent roundtripping. DSPDisassembler disasm(settings);
settings.show_hex = false; bool success = disasm.Disassemble(0, code, text);
settings.show_pc = line_numbers; return success;
settings.ext_separator = '\'';
settings.decode_names = false;
settings.decode_registers = true;
DSPDisassembler disasm(settings);
bool success = disasm.gd_dis_file(tmp1, t);
fclose(t);
File::ReadFileToString(true, tmp2, text);
return success;
}
return false;
} }
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2) bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
@ -92,7 +65,7 @@ bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
if (code1.size() != code2.size()) if (code1.size() != code2.size())
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size()); printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
int count_equal = 0; int count_equal = 0;
const int min_size = std::min(code1.size(), code2.size()); const int min_size = (int)std::min(code1.size(), code2.size());
for (int i = 0; i < min_size; i++) for (int i = 0; i < min_size; i++)
{ {
if (code1[i] == code2[i]) if (code1[i] == code2[i])
@ -150,7 +123,7 @@ void BinaryStringBEToCode(const std::string &str, std::vector<u16> *code)
code->resize(str.size() / 2); code->resize(str.size() / 2);
for (int i = 0; i < code->size(); i++) for (int i = 0; i < code->size(); i++)
{ {
(*code)[i] = (str[i * 2 + 0] << 8) | (str[i * 2 + 1]); (*code)[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
} }
} }
@ -159,6 +132,7 @@ bool LoadBinary(const char *filename, std::vector<u16> *code)
std::string buffer; std::string buffer;
if (!File::ReadFileToString(false, filename, &buffer)) if (!File::ReadFileToString(false, filename, &buffer))
return false; return false;
BinaryStringBEToCode(buffer, code); BinaryStringBEToCode(buffer, code);
return true; return true;
} }

View File

@ -352,8 +352,8 @@ const DSPOPCTemplate opcodes_ext[] =
{"XXX", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, NULL, NULL,}, {"XXX", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, NULL, NULL,},
}; };
const u32 opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate); const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
const u32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate); const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate);
const pdlabel_t pdlabels[] = const pdlabel_t pdlabels[] =
{ {

View File

@ -120,9 +120,9 @@ typedef DSPOPCTemplate opc_t;
// Opcodes // Opcodes
extern const DSPOPCTemplate opcodes[]; extern const DSPOPCTemplate opcodes[];
extern const u32 opcodes_size; extern const int opcodes_size;
extern const DSPOPCTemplate opcodes_ext[]; extern const DSPOPCTemplate opcodes_ext[];
extern const u32 opcodes_ext_size; extern const int opcodes_ext_size;
extern u8 opSize[OPTABLE_SIZE]; extern u8 opSize[OPTABLE_SIZE];
extern const DSPOPCTemplate cw; extern const DSPOPCTemplate cw;

View File

@ -44,6 +44,7 @@ Initial import
#include <map> #include <map>
#include "Common.h" #include "Common.h"
#include "FileUtil.h"
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
#include "DSPTables.h" #include "DSPTables.h"
#include "disassemble.h" #include "disassemble.h"
@ -80,38 +81,60 @@ DSPAssembler::DSPAssembler(const AssemblerSettings &settings)
: current_param(0), : current_param(0),
cur_addr(0), cur_addr(0),
cur_pass(0), cur_pass(0),
settings_(settings) settings_(settings)
{ {
gdg_buffer = NULL; gdg_buffer = NULL;
} }
DSPAssembler::~DSPAssembler() DSPAssembler::~DSPAssembler()
{ {
}
bool DSPAssembler::Assemble(const char *text, std::vector<u16> *code, std::vector<int> *line_numbers)
{
if (line_numbers)
line_numbers->clear();
const char *fname = "tmp.asm";
if (!File::WriteStringToFile(true, text, fname))
return false;
InitPass(1);
if (!AssembleFile(fname, 1))
return false;
InitPass(2);
if (!AssembleFile(fname, 2))
return false;
code->resize(gdg_buffer_size);
for (int i = 0; i < gdg_buffer_size; i++) {
(*code)[i] = *(u16 *)(gdg_buffer + i * 2);
}
last_error_str = "(no errors)";
last_error = ERR_OK;
return true;
} }
void DSPAssembler::parse_error(err_t err_code, const char *extra_info) void DSPAssembler::parse_error(err_t err_code, const char *extra_info)
{ {
fprintf(stderr, "%i : %s\n", code_line, cur_line);
failed = true; failed = true;
char error_buffer[1024];
char *buf_ptr = error_buffer;
buf_ptr += sprintf(buf_ptr, "%i : %s\n", code_line, cur_line);
if (!extra_info) if (!extra_info)
extra_info = "-"; extra_info = "-";
if (fsrc) if (fsrc)
fclose(fsrc); fclose(fsrc);
else else
{ buf_ptr += sprintf(buf_ptr, "ERROR: %s : %s\n", err_string[err_code], extra_info);
fprintf(stderr, "ERROR: %s : %s\n", err_string[err_code], extra_info);
}
// modified by Hermes
if (current_param == 0) if (current_param == 0)
fprintf(stderr, "ERROR: %s Line: %d : %s\n", err_string[err_code], code_line, extra_info); buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d : %s\n", err_string[err_code], code_line, extra_info);
else else
fprintf(stderr, "ERROR: %s Line: %d Param: %d : %s\n", buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d Param: %d : %s\n",
err_string[err_code], code_line, current_param, extra_info); err_string[err_code], code_line, current_param, extra_info);
last_error_str = error_buffer;
last_error = err_code;
} }
char *skip_spaces(char *ptr) char *skip_spaces(char *ptr)
@ -692,7 +715,7 @@ void DSPAssembler::build_code(const opc_t *opc, param_t *par, u32 par_count, u16
} }
} }
void DSPAssembler::gd_ass_init_pass(int pass) void DSPAssembler::InitPass(int pass)
{ {
failed = false; failed = false;
if (pass == 1) if (pass == 1)
@ -719,7 +742,7 @@ void DSPAssembler::gd_ass_init_pass(int pass)
segment_addr[SEGMENT_OVERLAY] = 0; segment_addr[SEGMENT_OVERLAY] = 0;
} }
bool DSPAssembler::gd_ass_file(const char *fname, int pass) bool DSPAssembler::AssembleFile(const char *fname, int pass)
{ {
int disable_text = 0; // modified by Hermes int disable_text = 0; // modified by Hermes
@ -892,7 +915,7 @@ bool DSPAssembler::gd_ass_file(const char *fname, int pass)
tmpstr = (char *)malloc(strlen(params[0].str) + 1); tmpstr = (char *)malloc(strlen(params[0].str) + 1);
strcpy(tmpstr, params[0].str); strcpy(tmpstr, params[0].str);
} }
gd_ass_file(tmpstr, pass); AssembleFile(tmpstr, pass);
free(tmpstr); free(tmpstr);
} }
else else

View File

@ -67,8 +67,16 @@ public:
DSPAssembler(const AssemblerSettings &settings); DSPAssembler(const AssemblerSettings &settings);
~DSPAssembler(); ~DSPAssembler();
void Assemble(const char *text, std::vector<u16> *code); // line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
// one for each word of code, indicating the source assembler code line number it came from.
// If returns false, call GetErrorString to get some text to present to the user.
bool Assemble(const char *text, std::vector<u16> *code, std::vector<int> *line_numbers = NULL);
std::string GetErrorString() const { return last_error_str; }
err_t GetError() const { return last_error; }
private:
struct label_t struct label_t
{ {
label_t(const char *lbl, s32 address) : label(lbl), addr(address) {} label_t(const char *lbl, s32 address) : label(lbl), addr(address) {}
@ -90,13 +98,13 @@ public:
SEGMENT_OVERLAY, SEGMENT_OVERLAY,
SEGMENT_MAX SEGMENT_MAX
}; };
void gd_ass_init_pass(int pass);
bool gd_ass_file(const char *fname, int pass); void InitPass(int pass);
bool AssembleFile(const char *fname, int pass);
char *gdg_buffer; char *gdg_buffer;
int gdg_buffer_size; int gdg_buffer_size;
private:
void parse_error(err_t err_code, const char *extra_info = NULL); void parse_error(err_t err_code, const char *extra_info = NULL);
void gd_ass_register_label(const char *label, u16 lval); void gd_ass_register_label(const char *label, u16 lval);
void gd_ass_clear_labels(); void gd_ass_clear_labels();
@ -119,6 +127,8 @@ private:
FILE *fsrc; FILE *fsrc;
u32 code_line; u32 code_line;
bool failed; bool failed;
std::string last_error_str;
err_t last_error;
typedef std::map<std::string, std::string> AliasMap; typedef std::map<std::string, std::string> AliasMap;
AliasMap aliases; AliasMap aliases;

View File

@ -27,6 +27,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "FileUtil.h"
#include "disassemble.h" #include "disassemble.h"
#include "DSPTables.h" #include "DSPTables.h"
@ -39,31 +40,81 @@ extern void nop(const UDSPInstruction& opc);
DSPDisassembler::DSPDisassembler(const AssemblerSettings &settings) DSPDisassembler::DSPDisassembler(const AssemblerSettings &settings)
: settings_(settings) : settings_(settings)
{ {
memset(unk_opcodes, 0, sizeof(unk_opcodes));
} }
char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2, char *strbuf) DSPDisassembler::~DSPDisassembler()
{
// Some old code for logging unknown ops.
char filename[MAX_PATH];
sprintf(filename, "%sUnkOps.txt", FULL_DSP_DUMP_DIR);
FILE *uo = fopen(filename, "w");
if (!uo)
return;
int count = 0;
for (std::map<u16, int>::const_iterator iter = unk_opcodes.begin();
iter != unk_opcodes.end(); ++iter)
{
if (iter->second > 0)
{
count++;
fprintf(uo, "OP%04x\t%d", iter->first, iter->second);
for (int j = 15; j >= 0; j--) // print op bits
{
if ((j & 0x3) == 3)
fprintf(uo, "\tb");
fprintf(uo, "%d", (iter->first >> j) & 0x1);
}
fprintf(uo, "\n");
}
}
fprintf(uo, "Unknown opcodes count: %d\n", count);
fclose(uo);
}
bool DSPDisassembler::Disassemble(int start_pc, const std::vector<u16> &code, std::string *text)
{
const char *tmp1 = "tmp1.bin";
const char *tmp2 = "tmp.txt";
// First we have to dump the code to a bin file.
FILE *f = fopen(tmp1, "wb");
fwrite(&code[0], 1, code.size() * 2, f);
fclose(f);
FILE* t = fopen(tmp2, "w");
if (!t)
return false;
bool success = DisFile(tmp1, t);
fclose(t);
File::ReadFileToString(true, tmp2, text);
return success;
}
char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char *strbuf)
{ {
char *buf = strbuf; char *buf = strbuf;
for (int j = 0; j < opc->param_count; j++) for (int j = 0; j < opc.param_count; j++)
{ {
if (j > 0) if (j > 0)
buf += sprintf(buf, ", "); buf += sprintf(buf, ", ");
u32 val; u32 val;
if (opc->params[j].loc >= 1) if (opc.params[j].loc >= 1)
val = op2; val = op2;
else else
val = op1; val = op1;
val &= opc->params[j].mask; val &= opc.params[j].mask;
if (opc->params[j].lshift < 0) if (opc.params[j].lshift < 0)
val = val << (-opc->params[j].lshift); val = val << (-opc.params[j].lshift);
else else
val = val >> opc->params[j].lshift; val = val >> opc.params[j].lshift;
u32 type = opc->params[j].type; u32 type = opc.params[j].type;
if ((type & 0xff) == 0x10) if ((type & 0xff) == 0x10)
type &= 0xff00; type &= 0xff00;
@ -102,9 +153,9 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
break; break;
case P_IMM: case P_IMM:
if (opc->params[j].size != 2) if (opc.params[j].size != 2)
{ {
if (opc->params[j].mask == 0x003f) // LSL, LSR, ASL, ASR if (opc.params[j].mask == 0x003f) // LSL, LSR, ASL, ASR
sprintf(buf, "#%d", (val & 0x20) ? (val | 0xFFFFFFC0) : val); sprintf(buf, "#%d", (val & 0x20) ? (val | 0xFFFFFFC0) : val);
else else
sprintf(buf, "#0x%02x", val); sprintf(buf, "#0x%02x", val);
@ -114,7 +165,7 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
break; break;
case P_MEM: case P_MEM:
if (opc->params[j].size != 2) if (opc.params[j].size != 2)
val = (u16)(s8)val; val = (u16)(s8)val;
if (settings_.decode_names) if (settings_.decode_names)
@ -124,7 +175,7 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
break; break;
default: default:
ERROR_LOG(DSPLLE, "Unknown parameter type: %x", opc->params[j].type); ERROR_LOG(DSPLLE, "Unknown parameter type: %x", opc.params[j].type);
break; break;
} }
@ -134,70 +185,7 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
return strbuf; return strbuf;
} }
#if 0 void DSPDisassembler::DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest)
u16 gd_dis_get_opcode_size(gd_globals_t* gdg)
{
const DSPOPCTemplate* opc = 0;
const DSPOPCTemplate* opc_ext = 0;
bool extended;
// Undefined memory.
if ((gdg->pc & 0x7fff) >= 0x1000)
return 1;
u32 op1 = gdg->binbuf[gdg->pc & 0x0fff];
for (u32 j = 0; j < opcodes_size; j++)
{
u16 mask;
if (opcodes[j].size & P_EXT)
mask = opcodes[j].opcode_mask & 0xff00;
else
mask = opcodes[j].opcode_mask;
if ((op1 & mask) == opcodes[j].opcode)
{
opc = &opcodes[j];
break;
}
}
if (!opc)
{
ERROR_LOG(DSPLLE, "get_opcode_size ARGH");
}
if (opc->size & P_EXT && op1 & 0x00ff)
extended = true;
else
extended = false;
if (extended)
{
// opcode has an extension
// find opcode
for (u32 j = 0; j < opcodes_ext_size; j++)
{
if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode)
{
opc_ext = &opcodes_ext[j];
break;
}
}
if (!opc_ext)
{
ERROR_LOG(DSPLLE, "get_opcode_size ext ARGH");
}
return opc_ext->size;
}
return opc->size & ~P_EXT;
}
#endif
void DSPDisassembler::gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *dest)
{ {
u32 op2; u32 op2;
char buffer[256]; char buffer[256];
@ -297,22 +285,19 @@ void DSPDisassembler::gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *des
buf += strlen(buf); buf += strlen(buf);
if (opc->param_count > 0) if (opc->param_count > 0)
gd_dis_params(opc, op1, op2, buf); DisParams(*opc, op1, op2, buf);
buf += strlen(buf); buf += strlen(buf);
if (extended) if (extended)
{ {
if (opc->param_count > 0) if (opc->param_count > 0)
sprintf(buf, " "); buf += sprintf(buf, " ");
buf += strlen(buf); buf += sprintf(buf, ": ");
sprintf(buf, ": ");
buf += strlen(buf);
if (opc_ext->param_count > 0) if (opc_ext->param_count > 0)
gd_dis_params(opc_ext, op1, op2, buf); DisParams(*opc_ext, op1, op2, buf);
buf += strlen(buf); buf += strlen(buf);
} }
@ -332,10 +317,8 @@ void DSPDisassembler::gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *des
dest->append(buffer); dest->append(buffer);
} }
bool DSPDisassembler::gd_dis_file(const char* name, FILE* output) bool DSPDisassembler::DisFile(const char* name, FILE* output)
{ {
gd_dis_open_unkop();
FILE* in; FILE* in;
u32 size; u32 size;
@ -346,95 +329,24 @@ bool DSPDisassembler::gd_dis_file(const char* name, FILE* output)
} }
fseek(in, 0, SEEK_END); fseek(in, 0, SEEK_END);
size = (int)ftell(in); size = (int)ftell(in) & ~1;
fseek(in, 0, SEEK_SET); fseek(in, 0, SEEK_SET);
u16 *binbuf = (u16*)malloc(size); u16 *binbuf = new u16[size / 2];
fread(binbuf, 1, size, in); fread(binbuf, 1, size, in);
for (u16 pc = 0; pc < (size / 2);) for (u16 pc = 0; pc < (size / 2);)
{ {
std::string str; std::string str;
gd_dis_opcode(binbuf, &pc, &str); DisOpcode(binbuf, &pc, &str);
fprintf(output, "%s\n", str.c_str()); fprintf(output, "%s\n", str.c_str());
} }
fclose(in); fclose(in);
delete [] binbuf;
free(binbuf);
gd_dis_close_unkop();
return true; return true;
} }
void DSPDisassembler::gd_dis_close_unkop()
{
FILE* uo;
int i, j;
u32 count = 0;
char filename[MAX_PATH];
sprintf(filename, "%sUnkOps.bin", FULL_DSP_DUMP_DIR);
uo = fopen(filename, "wb");
if (uo)
{
fwrite(unk_opcodes, 1, sizeof(unk_opcodes), uo);
fclose(uo);
}
sprintf(filename, "%sUnkOps.txt", FULL_DSP_DUMP_DIR);
uo = fopen(filename, "w");
if (uo)
{
for (i = 0; i < 0x10000; i++)
{
if (unk_opcodes[i])
{
count++;
fprintf(uo, "OP%04x\t%d", i, unk_opcodes[i]);
for (j = 15; j >= 0; j--)
{
if ((j & 0x3) == 3)
fprintf(uo, "\tb");
fprintf(uo, "%d", (i >> j) & 0x1);
}
fprintf(uo, "\n");
}
}
fprintf(uo, "Unknown opcodes count: %d\n", count);
fclose(uo);
}
}
void DSPDisassembler::gd_dis_open_unkop()
{
FILE* uo;
char filename[MAX_PATH];
sprintf(filename, "%sUnkOps.bin", FULL_DSP_DUMP_DIR);
uo = fopen(filename, "rb");
if (uo)
{
fread(unk_opcodes, 1, sizeof(unk_opcodes), uo);
fclose(uo);
}
else
{
for (int i = 0; i < 0x10000; i++)
{
unk_opcodes[i] = 0;
}
}
}
const char *gd_get_reg_name(u16 reg) const char *gd_get_reg_name(u16 reg)
{ {
return regnames[reg].name; return regnames[reg].name;

View File

@ -25,6 +25,9 @@
#ifndef _DSP_DISASSEMBLE_H #ifndef _DSP_DISASSEMBLE_H
#define _DSP_DISASSEMBLE_H #define _DSP_DISASSEMBLE_H
#include <map>
#include <vector>
#include "Common.h" #include "Common.h"
#include "DSPTables.h" #include "DSPTables.h"
@ -55,25 +58,24 @@ class DSPDisassembler
{ {
public: public:
DSPDisassembler(const AssemblerSettings &settings); DSPDisassembler(const AssemblerSettings &settings);
~DSPDisassembler() {} ~DSPDisassembler();
// Moves PC forward and writes the result to dest. bool Disassemble(int start_pc, const std::vector<u16> &code, std::string *text);
void gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *dest);
bool gd_dis_file(const char* name, FILE *output);
void gd_dis_close_unkop(); // Warning - this one is trickier to use right.
void gd_dis_open_unkop(); void DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest);
const char* gd_dis_get_reg_name(u16 reg);
private: private:
char* gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2, char* strbuf); // Moves PC forward and writes the result to dest.
u32 unk_opcodes[0x10000]; bool DisFile(const char* name, FILE *output);
char* DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char* strbuf);
std::map<u16, int> unk_opcodes;
const AssemblerSettings settings_; const AssemblerSettings settings_;
}; };
const char *gd_get_reg_name(u16 reg); const char *gd_get_reg_name(u16 reg);
//u16 gd_dis_get_opcode_size(gd_globals_t* gdg);
#endif // _DSP_DISASSEMBLE_H #endif // _DSP_DISASSEMBLE_H

View File

@ -44,6 +44,7 @@ volatile u32 gdsp_running;
static bool cr_halt = true; static bool cr_halt = true;
static bool cr_external_int = false; static bool cr_external_int = false;
void UpdateCachedCR() void UpdateCachedCR()
{ {
cr_halt = (g_dsp.cr & 0x4) != 0; cr_halt = (g_dsp.cr & 0x4) != 0;

View File

@ -116,12 +116,7 @@ void gdsp_run_cycles(int cycles);
void gdsp_stop(); void gdsp_stop();
void gdsp_write_cr(u16 val); void gdsp_write_cr(u16 val);
u16 gdsp_read_cr(void); u16 gdsp_read_cr();
u16* gdsp_get_iram(void);
u16* gdsp_get_irom(void);
u16* gdsp_get_dram(void);
u16* gdsp_get_drom(void);
// sets a flag in the pending exception register. // sets a flag in the pending exception register.
void gdsp_generate_exception(u8 level); void gdsp_generate_exception(u8 level);

View File

@ -120,15 +120,15 @@ void RunAsmTests()
// Let's get brutal. We generate random code bytes and make sure that they can // Let's get brutal. We generate random code bytes and make sure that they can
// be roundtripped. We don't expect it to always succeed but it'll be sure to generate // be roundtripped. We don't expect it to always succeed but it'll be sure to generate
// interesting test cases. // interesting test cases.
/*
puts("Insane Random Code Test\n"); puts("Insane Random Code Test\n");
std::vector<u16> rand_code; std::vector<u16> rand_code;
GenRandomCode(31, &rand_code); GenRandomCode(30, &rand_code);
std::string rand_code_text; std::string rand_code_text;
Disassemble(rand_code, true, &rand_code_text); Disassemble(rand_code, true, &rand_code_text);
printf("%s", rand_code_text.c_str()); printf("%s", rand_code_text.c_str());
RoundTrip(rand_code); RoundTrip(rand_code);
*/
std::string dsp_test; std::string dsp_test;
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test)) if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))

View File

@ -45,7 +45,6 @@ bool DSPHost_Running()
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
{ {
u32 crc = GenerateCRC(ptr, size); u32 crc = GenerateCRC(ptr, size);
DumpDSPCode(ptr, size, crc); DumpDSPCode(ptr, size, crc);
return crc; return crc;
} }

View File

@ -221,7 +221,7 @@ void DSPDebuggerLLE::RebuildDisAsmListView()
AssemblerSettings settings; AssemblerSettings settings;
DSPDisassembler disasm(settings); DSPDisassembler disasm(settings);
std::string op_str; std::string op_str;
disasm.gd_dis_opcode(binbuf,&settings.pc, &op_str); disasm.DisOpcode(binbuf, &settings.pc, &op_str);
const char* pParameter = NULL; const char* pParameter = NULL;
const char* pExtension = NULL; const char* pExtension = NULL;

View File

@ -21,58 +21,48 @@
#include "Common.h" #include "Common.h"
#include "Globals.h" #include "Globals.h"
#include "FileUtil.h"
#include "DSPCodeUtil.h"
#include "Tools.h" #include "Tools.h"
#include "disassemble.h" #include "disassemble.h"
#include "gdsp_interpreter.h" #include "gdsp_interpreter.h"
bool DumpDSPCode(const u8 *data, u32 _Length, u32 crc) bool DumpDSPCode(const u8 *code_be, int size_in_bytes, u32 crc)
{
char szFilename[MAX_PATH];
sprintf(szFilename, "%sDSP_UC_%08X.bin", FULL_DSP_DUMP_DIR, crc);
FILE* pFile = fopen(szFilename, "wb");
if (pFile)
{
fwrite(data, _Length, 1, pFile);
fclose(pFile);
}
else
{
PanicAlert("Cant open file (%s) to dump UCode!!", szFilename);
return false;
}
if (!DisasmUCodeDump(crc))
{
PanicAlert("Failed to disasm UCode!!", szFilename);
return false;
}
return true;
}
bool DisasmUCodeDump(u32 crc)
{ {
char binFile[MAX_PATH]; char binFile[MAX_PATH];
char txtFile[MAX_PATH]; char txtFile[MAX_PATH];
sprintf(binFile, "%sDSP_UC_%08X.bin", FULL_DSP_DUMP_DIR, crc); sprintf(binFile, "%sDSP_UC_%08X.bin", FULL_DSP_DUMP_DIR, crc);
sprintf(txtFile, "%sDSP_UC_%08X.txt", FULL_DSP_DUMP_DIR, crc); sprintf(txtFile, "%sDSP_UC_%08X.txt", FULL_DSP_DUMP_DIR, crc);
FILE* t = fopen(txtFile, "wb");
if (t != NULL) FILE* pFile = fopen(binFile, "wb");
if (pFile)
{ {
AssemblerSettings settings; fwrite(code_be, size_in_bytes, 1, pFile);
settings.show_hex = true; fclose(pFile);
settings.show_pc = true;
settings.ext_separator = '\t';
settings.decode_names = true;
settings.decode_registers = true;
DSPDisassembler disasm(settings);
disasm.gd_dis_file(binFile, t);
fclose(t);
return true;
} }
else else
{
PanicAlert("Cant open file (%s) to dump UCode!!", binFile);
return false; return false;
}
// Load the binary back in.
std::vector<u16> code;
LoadBinary(binFile, &code);
AssemblerSettings settings;
settings.show_hex = true;
settings.show_pc = true;
settings.ext_separator = '\t';
settings.decode_names = true;
settings.decode_registers = true;
std::string text;
DSPDisassembler disasm(settings);
if (!disasm.Disassemble(0, code, &text))
return false;
return File::WriteStringToFile(true, text, txtFile);
} }
u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength) u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength)

View File

@ -18,8 +18,7 @@
#ifndef _DSPLLE_TOOLS_H #ifndef _DSPLLE_TOOLS_H
#define _DSPLLE_TOOLS_H #define _DSPLLE_TOOLS_H
bool DumpDSPCode(const u8 *data, u32 _Length, u32 crc); bool DumpDSPCode(const u8 *code_be, int size_in_bytes, u32 crc);
bool DisasmUCodeDump(u32 crc);
u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength); u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength);
bool DumpCWCode(u32 _Address, u32 _Length); bool DumpCWCode(u32 _Address, u32 _Length);