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:
parent
f9903f2054
commit
d973a9e001
|
@ -626,7 +626,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string *str)
|
|||
fseek(f, 0, SEEK_SET);
|
||||
char *buf = new char[len + 1];
|
||||
buf[fread(buf, 1, len, f)] = 0;
|
||||
*str = std::string(buf);
|
||||
*str = std::string(buf, len);
|
||||
fclose(f);
|
||||
delete [] buf;
|
||||
return true;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
bool Assemble(const char *text, std::vector<u16> *code)
|
||||
{
|
||||
const char *fname = "tmp.asm";
|
||||
AssemblerSettings settings;
|
||||
settings.pc = 0;
|
||||
// settings.decode_registers = false;
|
||||
|
@ -34,22 +33,11 @@ bool Assemble(const char *text, std::vector<u16> *code)
|
|||
settings.print_tabs = false;
|
||||
settings.ext_separator = '\'';
|
||||
|
||||
if (!File::WriteStringToFile(true, text, fname))
|
||||
return false;
|
||||
|
||||
// TODO: fix the terrible api of the assembler.
|
||||
DSPAssembler assembler(settings);
|
||||
assembler.gd_ass_init_pass(1);
|
||||
if (!assembler.gd_ass_file(fname, 1))
|
||||
return false;
|
||||
assembler.gd_ass_init_pass(2);
|
||||
if (!assembler.gd_ass_file(fname, 2))
|
||||
return false;
|
||||
if (!assembler.Assemble(text, code))
|
||||
printf("%s", assembler.GetErrorString().c_str());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -57,34 +45,19 @@ bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string *t
|
|||
{
|
||||
if (code.empty())
|
||||
return false;
|
||||
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);
|
||||
AssemblerSettings settings;
|
||||
|
||||
FILE* t = fopen(tmp2, "w");
|
||||
if (t != NULL)
|
||||
{
|
||||
AssemblerSettings settings;
|
||||
// These two prevent roundtripping.
|
||||
settings.show_hex = false;
|
||||
settings.show_pc = line_numbers;
|
||||
settings.ext_separator = '\'';
|
||||
settings.decode_names = false;
|
||||
settings.decode_registers = true;
|
||||
|
||||
// These two prevent roundtripping.
|
||||
settings.show_hex = false;
|
||||
settings.show_pc = line_numbers;
|
||||
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;
|
||||
DSPDisassembler disasm(settings);
|
||||
bool success = disasm.Disassemble(0, code, text);
|
||||
return success;
|
||||
}
|
||||
|
||||
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())
|
||||
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
||||
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++)
|
||||
{
|
||||
if (code1[i] == code2[i])
|
||||
|
@ -150,7 +123,7 @@ void BinaryStringBEToCode(const std::string &str, std::vector<u16> *code)
|
|||
code->resize(str.size() / 2);
|
||||
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;
|
||||
if (!File::ReadFileToString(false, filename, &buffer))
|
||||
return false;
|
||||
|
||||
BinaryStringBEToCode(buffer, code);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -352,8 +352,8 @@ const DSPOPCTemplate opcodes_ext[] =
|
|||
{"XXX", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, NULL, NULL,},
|
||||
};
|
||||
|
||||
const u32 opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
|
||||
const u32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate);
|
||||
const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
|
||||
const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate);
|
||||
|
||||
const pdlabel_t pdlabels[] =
|
||||
{
|
||||
|
|
|
@ -120,9 +120,9 @@ typedef DSPOPCTemplate opc_t;
|
|||
|
||||
// Opcodes
|
||||
extern const DSPOPCTemplate opcodes[];
|
||||
extern const u32 opcodes_size;
|
||||
extern const int opcodes_size;
|
||||
extern const DSPOPCTemplate opcodes_ext[];
|
||||
extern const u32 opcodes_ext_size;
|
||||
extern const int opcodes_ext_size;
|
||||
extern u8 opSize[OPTABLE_SIZE];
|
||||
extern const DSPOPCTemplate cw;
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ Initial import
|
|||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPTables.h"
|
||||
#include "disassemble.h"
|
||||
|
@ -80,38 +81,60 @@ DSPAssembler::DSPAssembler(const AssemblerSettings &settings)
|
|||
: current_param(0),
|
||||
cur_addr(0),
|
||||
cur_pass(0),
|
||||
settings_(settings)
|
||||
settings_(settings)
|
||||
{
|
||||
gdg_buffer = NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
fprintf(stderr, "%i : %s\n", code_line, cur_line);
|
||||
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)
|
||||
extra_info = "-";
|
||||
if (fsrc)
|
||||
fclose(fsrc);
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: %s : %s\n", err_string[err_code], extra_info);
|
||||
}
|
||||
|
||||
// modified by Hermes
|
||||
buf_ptr += sprintf(buf_ptr, "ERROR: %s : %s\n", err_string[err_code], extra_info);
|
||||
|
||||
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
|
||||
fprintf(stderr, "ERROR: %s Line: %d Param: %d : %s\n",
|
||||
err_string[err_code], code_line, current_param, extra_info);
|
||||
buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d Param: %d : %s\n",
|
||||
err_string[err_code], code_line, current_param, extra_info);
|
||||
last_error_str = error_buffer;
|
||||
last_error = err_code;
|
||||
}
|
||||
|
||||
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;
|
||||
if (pass == 1)
|
||||
|
@ -719,7 +742,7 @@ void DSPAssembler::gd_ass_init_pass(int pass)
|
|||
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
|
||||
|
||||
|
@ -892,7 +915,7 @@ bool DSPAssembler::gd_ass_file(const char *fname, int pass)
|
|||
tmpstr = (char *)malloc(strlen(params[0].str) + 1);
|
||||
strcpy(tmpstr, params[0].str);
|
||||
}
|
||||
gd_ass_file(tmpstr, pass);
|
||||
AssembleFile(tmpstr, pass);
|
||||
free(tmpstr);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -67,8 +67,16 @@ public:
|
|||
DSPAssembler(const AssemblerSettings &settings);
|
||||
~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
|
||||
{
|
||||
label_t(const char *lbl, s32 address) : label(lbl), addr(address) {}
|
||||
|
@ -90,13 +98,13 @@ public:
|
|||
SEGMENT_OVERLAY,
|
||||
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;
|
||||
int gdg_buffer_size;
|
||||
|
||||
private:
|
||||
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_clear_labels();
|
||||
|
@ -119,6 +127,8 @@ private:
|
|||
FILE *fsrc;
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
std::string last_error_str;
|
||||
err_t last_error;
|
||||
|
||||
typedef std::map<std::string, std::string> AliasMap;
|
||||
AliasMap aliases;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "disassemble.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
|
@ -39,31 +40,81 @@ extern void nop(const UDSPInstruction& opc);
|
|||
DSPDisassembler::DSPDisassembler(const AssemblerSettings &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;
|
||||
for (int j = 0; j < opc->param_count; j++)
|
||||
for (int j = 0; j < opc.param_count; j++)
|
||||
{
|
||||
if (j > 0)
|
||||
buf += sprintf(buf, ", ");
|
||||
|
||||
u32 val;
|
||||
if (opc->params[j].loc >= 1)
|
||||
if (opc.params[j].loc >= 1)
|
||||
val = op2;
|
||||
else
|
||||
val = op1;
|
||||
|
||||
val &= opc->params[j].mask;
|
||||
val &= opc.params[j].mask;
|
||||
|
||||
if (opc->params[j].lshift < 0)
|
||||
val = val << (-opc->params[j].lshift);
|
||||
if (opc.params[j].lshift < 0)
|
||||
val = val << (-opc.params[j].lshift);
|
||||
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)
|
||||
type &= 0xff00;
|
||||
|
@ -102,9 +153,9 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
|
|||
break;
|
||||
|
||||
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);
|
||||
else
|
||||
sprintf(buf, "#0x%02x", val);
|
||||
|
@ -114,7 +165,7 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
|
|||
break;
|
||||
|
||||
case P_MEM:
|
||||
if (opc->params[j].size != 2)
|
||||
if (opc.params[j].size != 2)
|
||||
val = (u16)(s8)val;
|
||||
|
||||
if (settings_.decode_names)
|
||||
|
@ -124,7 +175,7 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
|
|||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(DSPLLE, "Unknown parameter type: %x", opc->params[j].type);
|
||||
ERROR_LOG(DSPLLE, "Unknown parameter type: %x", opc.params[j].type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -134,70 +185,7 @@ char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2
|
|||
return strbuf;
|
||||
}
|
||||
|
||||
#if 0
|
||||
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)
|
||||
void DSPDisassembler::DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest)
|
||||
{
|
||||
u32 op2;
|
||||
char buffer[256];
|
||||
|
@ -297,22 +285,19 @@ void DSPDisassembler::gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *des
|
|||
buf += strlen(buf);
|
||||
|
||||
if (opc->param_count > 0)
|
||||
gd_dis_params(opc, op1, op2, buf);
|
||||
DisParams(*opc, op1, op2, buf);
|
||||
|
||||
buf += strlen(buf);
|
||||
|
||||
if (extended)
|
||||
{
|
||||
if (opc->param_count > 0)
|
||||
sprintf(buf, " ");
|
||||
buf += sprintf(buf, " ");
|
||||
|
||||
buf += strlen(buf);
|
||||
|
||||
sprintf(buf, ": ");
|
||||
buf += strlen(buf);
|
||||
buf += sprintf(buf, ": ");
|
||||
|
||||
if (opc_ext->param_count > 0)
|
||||
gd_dis_params(opc_ext, op1, op2, buf);
|
||||
DisParams(*opc_ext, op1, op2, buf);
|
||||
|
||||
buf += strlen(buf);
|
||||
}
|
||||
|
@ -332,10 +317,8 @@ void DSPDisassembler::gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *des
|
|||
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;
|
||||
u32 size;
|
||||
|
||||
|
@ -346,95 +329,24 @@ bool DSPDisassembler::gd_dis_file(const char* name, FILE* output)
|
|||
}
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
size = (int)ftell(in);
|
||||
size = (int)ftell(in) & ~1;
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
u16 *binbuf = (u16*)malloc(size);
|
||||
u16 *binbuf = new u16[size / 2];
|
||||
fread(binbuf, 1, size, in);
|
||||
|
||||
for (u16 pc = 0; pc < (size / 2);)
|
||||
{
|
||||
std::string str;
|
||||
gd_dis_opcode(binbuf, &pc, &str);
|
||||
DisOpcode(binbuf, &pc, &str);
|
||||
fprintf(output, "%s\n", str.c_str());
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
|
||||
free(binbuf);
|
||||
|
||||
gd_dis_close_unkop();
|
||||
|
||||
delete [] binbuf;
|
||||
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)
|
||||
{
|
||||
return regnames[reg].name;
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#ifndef _DSP_DISASSEMBLE_H
|
||||
#define _DSP_DISASSEMBLE_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
|
@ -55,25 +58,24 @@ class DSPDisassembler
|
|||
{
|
||||
public:
|
||||
DSPDisassembler(const AssemblerSettings &settings);
|
||||
~DSPDisassembler() {}
|
||||
~DSPDisassembler();
|
||||
|
||||
// Moves PC forward and writes the result to dest.
|
||||
void gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *dest);
|
||||
bool gd_dis_file(const char* name, FILE *output);
|
||||
bool Disassemble(int start_pc, const std::vector<u16> &code, std::string *text);
|
||||
|
||||
void gd_dis_close_unkop();
|
||||
void gd_dis_open_unkop();
|
||||
const char* gd_dis_get_reg_name(u16 reg);
|
||||
// Warning - this one is trickier to use right.
|
||||
void DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest);
|
||||
|
||||
private:
|
||||
char* gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2, char* strbuf);
|
||||
u32 unk_opcodes[0x10000];
|
||||
// Moves PC forward and writes the result to dest.
|
||||
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 char *gd_get_reg_name(u16 reg);
|
||||
//u16 gd_dis_get_opcode_size(gd_globals_t* gdg);
|
||||
|
||||
#endif // _DSP_DISASSEMBLE_H
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ volatile u32 gdsp_running;
|
|||
static bool cr_halt = true;
|
||||
static bool cr_external_int = false;
|
||||
|
||||
|
||||
void UpdateCachedCR()
|
||||
{
|
||||
cr_halt = (g_dsp.cr & 0x4) != 0;
|
||||
|
|
|
@ -116,12 +116,7 @@ void gdsp_run_cycles(int cycles);
|
|||
void gdsp_stop();
|
||||
|
||||
void gdsp_write_cr(u16 val);
|
||||
u16 gdsp_read_cr(void);
|
||||
|
||||
u16* gdsp_get_iram(void);
|
||||
u16* gdsp_get_irom(void);
|
||||
u16* gdsp_get_dram(void);
|
||||
u16* gdsp_get_drom(void);
|
||||
u16 gdsp_read_cr();
|
||||
|
||||
// sets a flag in the pending exception register.
|
||||
void gdsp_generate_exception(u8 level);
|
||||
|
|
|
@ -120,15 +120,15 @@ void RunAsmTests()
|
|||
// 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
|
||||
// interesting test cases.
|
||||
/*
|
||||
|
||||
puts("Insane Random Code Test\n");
|
||||
std::vector<u16> rand_code;
|
||||
GenRandomCode(31, &rand_code);
|
||||
GenRandomCode(30, &rand_code);
|
||||
std::string rand_code_text;
|
||||
Disassemble(rand_code, true, &rand_code_text);
|
||||
printf("%s", rand_code_text.c_str());
|
||||
RoundTrip(rand_code);
|
||||
*/
|
||||
|
||||
std::string dsp_test;
|
||||
|
||||
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
|
||||
|
|
|
@ -45,7 +45,6 @@ bool DSPHost_Running()
|
|||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
|
||||
{
|
||||
u32 crc = GenerateCRC(ptr, size);
|
||||
|
||||
DumpDSPCode(ptr, size, crc);
|
||||
return crc;
|
||||
}
|
|
@ -221,7 +221,7 @@ void DSPDebuggerLLE::RebuildDisAsmListView()
|
|||
AssemblerSettings settings;
|
||||
DSPDisassembler disasm(settings);
|
||||
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* pExtension = NULL;
|
||||
|
||||
|
|
|
@ -21,58 +21,48 @@
|
|||
#include "Common.h"
|
||||
#include "Globals.h"
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "DSPCodeUtil.h"
|
||||
#include "Tools.h"
|
||||
#include "disassemble.h"
|
||||
#include "gdsp_interpreter.h"
|
||||
|
||||
bool DumpDSPCode(const u8 *data, u32 _Length, 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)
|
||||
bool DumpDSPCode(const u8 *code_be, int size_in_bytes, u32 crc)
|
||||
{
|
||||
char binFile[MAX_PATH];
|
||||
char txtFile[MAX_PATH];
|
||||
sprintf(binFile, "%sDSP_UC_%08X.bin", 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;
|
||||
settings.show_hex = true;
|
||||
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;
|
||||
fwrite(code_be, size_in_bytes, 1, pFile);
|
||||
fclose(pFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("Cant open file (%s) to dump UCode!!", binFile);
|
||||
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)
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
#ifndef _DSPLLE_TOOLS_H
|
||||
#define _DSPLLE_TOOLS_H
|
||||
|
||||
bool DumpDSPCode(const u8 *data, u32 _Length, u32 crc);
|
||||
bool DisasmUCodeDump(u32 crc);
|
||||
bool DumpDSPCode(const u8 *code_be, int size_in_bytes, u32 crc);
|
||||
u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength);
|
||||
bool DumpCWCode(u32 _Address, u32 _Length);
|
||||
|
||||
|
|
Loading…
Reference in New Issue