DSP asm/disasm: Lots of cleanup, mostly. I may have broken the DSP debugger a bit. will fix it properly later..
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2968 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
0c65e2fe11
commit
d25d6b5f98
|
@ -23,50 +23,34 @@
|
|||
#include "assemble.h"
|
||||
#include "disassemble.h"
|
||||
|
||||
DSPAssembler::DSPAssembler()
|
||||
: include_dir(0),
|
||||
current_param(0),
|
||||
cur_addr(0),
|
||||
labels_count(0),
|
||||
cur_pass(0)
|
||||
{
|
||||
include_dir = 0;
|
||||
current_param = 0;
|
||||
}
|
||||
|
||||
DSPAssembler::~DSPAssembler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> *code)
|
||||
{
|
||||
const char *fname = "tmp.asm";
|
||||
gd_globals_t gdg;
|
||||
memset(&gdg, 0, sizeof(gdg));
|
||||
gdg.pc = 0;
|
||||
// gdg.decode_registers = false;
|
||||
// gdg.decode_names = false;
|
||||
gdg.print_tabs = false;
|
||||
gdg.ext_separator = '\'';
|
||||
gdg.buffer = 0;
|
||||
AssemblerSettings settings;
|
||||
memset(&settings, 0, sizeof(settings));
|
||||
settings.pc = 0;
|
||||
// settings.decode_registers = false;
|
||||
// settings.decode_names = false;
|
||||
settings.print_tabs = false;
|
||||
settings.ext_separator = '\'';
|
||||
settings.buffer = 0;
|
||||
|
||||
if (!File::WriteStringToFile(true, text, fname))
|
||||
return false;
|
||||
|
||||
// TODO: fix the terrible api of the assembler.
|
||||
DSPAssembler assembler;
|
||||
DSPAssembler assembler(settings);
|
||||
assembler.gd_ass_init_pass(1);
|
||||
if (!assembler.gd_ass_file(&gdg, fname, 1))
|
||||
if (!assembler.gd_ass_file(fname, 1))
|
||||
return false;
|
||||
assembler.gd_ass_init_pass(2);
|
||||
if (!assembler.gd_ass_file(&gdg, fname, 2))
|
||||
if (!assembler.gd_ass_file(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);
|
||||
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;
|
||||
}
|
||||
|
@ -86,18 +70,17 @@ bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string *t
|
|||
FILE* t = fopen(tmp2, "w");
|
||||
if (t != NULL)
|
||||
{
|
||||
gd_globals_t gdg;
|
||||
memset(&gdg, 0, sizeof(gdg));
|
||||
AssemblerSettings settings;
|
||||
|
||||
// These two prevent roundtripping.
|
||||
gdg.show_hex = false;
|
||||
gdg.show_pc = line_numbers;
|
||||
gdg.ext_separator = '\'';
|
||||
gdg.decode_names = false;
|
||||
gdg.decode_registers = true;
|
||||
settings.show_hex = false;
|
||||
settings.show_pc = line_numbers;
|
||||
settings.ext_separator = '\'';
|
||||
settings.decode_names = false;
|
||||
settings.decode_registers = true;
|
||||
|
||||
DSPDisassembler disasm;
|
||||
bool success = disasm.gd_dis_file(&gdg, tmp1, t);
|
||||
DSPDisassembler disasm(settings);
|
||||
bool success = disasm.gd_dis_file(tmp1, t);
|
||||
fclose(t);
|
||||
|
||||
File::ReadFileToString(true, tmp2, text);
|
||||
|
|
|
@ -234,11 +234,11 @@ const DSPOPCTemplate opcodes[] =
|
|||
|
||||
|
||||
{"INCM", 0x7400, 0xfeff, DSPInterpreter::incm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"INC", 0x7600, 0xfeff, DSPInterpreter::inc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"INC", 0x7600, 0xfeff, DSPInterpreter::inc, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"DECM", 0x7800, 0xfeff, DSPInterpreter::decm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"DEC", 0x7a00, 0xfeff, DSPInterpreter::dec, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"NEG", 0x7c00, 0xfeff, DSPInterpreter::neg, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MOVNP", 0x7e00, 0xfeff, DSPInterpreter::movnp, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"DEC", 0x7a00, 0xfeff, DSPInterpreter::dec, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"NEG", 0x7c00, 0xfeff, DSPInterpreter::neg, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MOVNP", 0x7e00, 0xfeff, DSPInterpreter::movnp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
||||
|
||||
{"TST", 0xb100, 0xf7ff, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
@ -278,19 +278,19 @@ const DSPOPCTemplate opcodes[] =
|
|||
{"ORC", 0x3E00, 0xfeff, DSPInterpreter::orc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this
|
||||
|
||||
{"MULX", 0xa000, 0xe7ff, DSPInterpreter::mulx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULXMVZ", 0xa200, 0xe6ff, DSPInterpreter::mulxmvz, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULXAC", 0xa400, 0xe6ff, DSPInterpreter::mulxac, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULXMV", 0xa600, 0xe6ff, DSPInterpreter::mulxmv, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULXMVZ", 0xa200, 0xe6ff, DSPInterpreter::mulxmvz, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULXAC", 0xa400, 0xe6ff, DSPInterpreter::mulxac, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULXMV", 0xa600, 0xe6ff, DSPInterpreter::mulxmv, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
||||
{"MUL", 0x9000, 0xf7ff, DSPInterpreter::mul, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULMVZ", 0x9200, 0xf6ff, DSPInterpreter::mulmvz, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULAC", 0x9400, 0xf6ff, DSPInterpreter::mulac, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULMV", 0x9600, 0xf6ff, DSPInterpreter::mulmv, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULMVZ", 0x9200, 0xf6ff, DSPInterpreter::mulmvz, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULAC", 0x9400, 0xf6ff, DSPInterpreter::mulac, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULMV", 0x9600, 0xf6ff, DSPInterpreter::mulmv, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
||||
{"MULC", 0xc000, 0xe7ff, DSPInterpreter::mulc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULCMVZ", 0xc200, 0xe6ff, DSPInterpreter::mulcmvz, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULCAC", 0xc400, 0xe6ff, DSPInterpreter::mulcac, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULCMV", 0xc600, 0xe6ff, DSPInterpreter::mulcmv, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULCMVZ", 0xc200, 0xe6ff, DSPInterpreter::mulcmvz, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULCAC", 0xc400, 0xe6ff, DSPInterpreter::mulcac, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"MULCMV", 0xc600, 0xe6ff, DSPInterpreter::mulcmv, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
||||
{"ADDR", 0x4000, 0xf8ff, DSPInterpreter::addr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"ADDAX", 0x4800, 0xfcff, DSPInterpreter::addax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
@ -316,7 +316,6 @@ const DSPOPCTemplate cw =
|
|||
|
||||
const DSPOPCTemplate opcodes_ext[] =
|
||||
{
|
||||
|
||||
// FIXME: guessing this is cr need checking
|
||||
{"CR", 0x0000, 0x00fc, DSPInterpreter::Ext::cr, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
|
||||
{"DR", 0x0004, 0x00fc, DSPInterpreter::Ext::dr, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
|
||||
|
@ -410,10 +409,10 @@ const pdlabel_t regnames[] =
|
|||
{0x01, "AR1", "Addr Reg 01",},
|
||||
{0x02, "AR2", "Addr Reg 02",},
|
||||
{0x03, "AR3", "Addr Reg 03",},
|
||||
{0x04, "IX0", "Index Reg 1(04)",},
|
||||
{0x05, "IX1", "Index Reg 2(05)",},
|
||||
{0x06, "IX2", "Index Reg 3(06)",},
|
||||
{0x07, "IX3", "Indec Reg 4(07)",},
|
||||
{0x04, "IX0", "Index Reg 0(04)",},
|
||||
{0x05, "IX1", "Index Reg 1(05)",},
|
||||
{0x06, "IX2", "Index Reg 2(06)",},
|
||||
{0x07, "IX3", "Indec Reg 3(07)",},
|
||||
{0x08, "R08", "Register 08",},
|
||||
{0x09, "R09", "Register 09",},
|
||||
{0x0a, "R10", "Register 10",},
|
||||
|
@ -422,7 +421,7 @@ const pdlabel_t regnames[] =
|
|||
{0x0d, "ST1", "Data stack",},
|
||||
{0x0e, "ST2", "Loop addr stack",},
|
||||
{0x0f, "ST3", "Loop counter",},
|
||||
{0x00, "AC0.H", "Accu High 0",},
|
||||
{0x10, "AC0.H", "Accu High 0",},
|
||||
{0x11, "AC1.H", "Accu High 1",},
|
||||
{0x12, "CR", "Config Register",},
|
||||
{0x13, "SR", "Special Register",},
|
||||
|
@ -439,7 +438,7 @@ const pdlabel_t regnames[] =
|
|||
{0x1e, "AC0.M", "Accu Mid 0",},
|
||||
{0x1f, "AC1.M", "Accu Mid 1",},
|
||||
|
||||
// To resolve special names.
|
||||
// To resolve combined register names.
|
||||
{0x20, "ACC0", "Accu Full 0",},
|
||||
{0x21, "ACC1", "Accu Full 1",},
|
||||
{0x22, "AX0", "Extra Accu 0",},
|
||||
|
@ -451,7 +450,6 @@ dspInstFunc opTable[OPTABLE_SIZE];
|
|||
dspInstFunc prologueTable[OPTABLE_SIZE];
|
||||
dspInstFunc epilogueTable[OPTABLE_SIZE];
|
||||
|
||||
|
||||
const char* pdname(u16 val)
|
||||
{
|
||||
static char tmpstr[12]; // nasty
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
|
||||
// The ones that end with _D are the opposite one - if the bit specify
|
||||
// ACC0, then ACC_D will be ACC1.
|
||||
|
||||
// The values of these are very important.
|
||||
// For the reg ones, the value >> 8 is the base register.
|
||||
// & 0x80 means it's a "D".
|
||||
|
||||
enum partype_t
|
||||
{
|
||||
P_NONE = 0x0000,
|
||||
|
@ -37,15 +42,15 @@ enum partype_t
|
|||
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
|
||||
P_REG19 = P_REG | 0x1900,
|
||||
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
|
||||
P_REG1A = P_REG | 0x1a00,
|
||||
P_REG1A = P_REG | 0x1a80,
|
||||
P_REG1C = P_REG | 0x1c00,
|
||||
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
|
||||
P_ACC_D = P_REG | 0x1c80,
|
||||
P_ACCL = P_REG | 0x1c00, // used for mid accum
|
||||
P_ACCM = P_REG | 0x1e00, // used for mid accum
|
||||
P_ACCL = P_REG | 0x1c00, // used for low part of accum
|
||||
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
|
||||
// The following are not in gcdsptool
|
||||
P_ACCM_D = P_REG | 0x1e80,
|
||||
P_ACC = P_REG | 0x2000, // used for global accum.
|
||||
P_ACC = P_REG | 0x2000, // used for full accum.
|
||||
P_AX = P_REG | 0x2200,
|
||||
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
|
||||
P_REF = P_REG | 0x4000,
|
||||
|
|
|
@ -76,14 +76,30 @@ static const char *err_string[] =
|
|||
"Number out of range"
|
||||
};
|
||||
|
||||
void DSPAssembler::parse_error(err_t err_code, fass_t *fa, const char *extra_info)
|
||||
DSPAssembler::DSPAssembler(const AssemblerSettings &settings)
|
||||
: current_param(0),
|
||||
cur_addr(0),
|
||||
cur_pass(0),
|
||||
settings_(settings)
|
||||
{
|
||||
fprintf(stderr, "%i : %s\n", fa->code_line, cur_line);
|
||||
fa->failed = true;
|
||||
gdg_buffer = NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
DSPAssembler::~DSPAssembler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DSPAssembler::parse_error(err_t err_code, const char *extra_info)
|
||||
{
|
||||
fprintf(stderr, "%i : %s\n", code_line, cur_line);
|
||||
failed = true;
|
||||
if (!extra_info)
|
||||
extra_info = "-";
|
||||
if (fa->fsrc)
|
||||
fclose(fa->fsrc);
|
||||
if (fsrc)
|
||||
fclose(fsrc);
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: %s : %s\n", err_string[err_code], extra_info);
|
||||
|
@ -92,10 +108,10 @@ void DSPAssembler::parse_error(err_t err_code, fass_t *fa, const char *extra_inf
|
|||
// modified by Hermes
|
||||
|
||||
if (current_param == 0)
|
||||
fprintf(stderr, "ERROR: %s Line: %d : %s\n", err_string[err_code], fa->code_line, extra_info);
|
||||
fprintf(stderr, "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], fa->code_line, current_param, extra_info);
|
||||
err_string[err_code], code_line, current_param, extra_info);
|
||||
}
|
||||
|
||||
char *skip_spaces(char *ptr)
|
||||
|
@ -114,19 +130,12 @@ const char *skip_spaces(const char *ptr)
|
|||
|
||||
void DSPAssembler::gd_ass_register_label(const char *label, u16 lval)
|
||||
{
|
||||
labels[labels_count].label = (char *)malloc(strlen(label) + 1);
|
||||
strcpy(labels[labels_count].label, label);
|
||||
labels[labels_count].addr = lval;
|
||||
labels_count++;
|
||||
labels.push_back(label_t(label, lval));
|
||||
}
|
||||
|
||||
void DSPAssembler::gd_ass_clear_labels()
|
||||
{
|
||||
for (int i = 0; i < labels_count; i++)
|
||||
{
|
||||
free(labels[i].label);
|
||||
}
|
||||
labels_count = 0;
|
||||
labels.clear();
|
||||
}
|
||||
|
||||
// Parse a standalone value - it can be a number in one of several formats or a label.
|
||||
|
@ -156,7 +165,7 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
if (ptr[i] >= '0' && ptr[i] <= '9')
|
||||
val += ptr[i] - '0';
|
||||
else
|
||||
parse_error(ERR_INCORRECT_DEC, cur_fa, str);
|
||||
parse_error(ERR_INCORRECT_DEC, str);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -172,9 +181,9 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
else if (ptr[i] >= 'A' && ptr[i] <= 'F')
|
||||
val += (ptr[i]-'A'+10);
|
||||
else if (ptr[i] >= '0' && ptr[i] <= '9')
|
||||
val += (ptr[i]-'0');
|
||||
val += (ptr[i] - '0');
|
||||
else
|
||||
parse_error(ERR_INCORRECT_HEX, cur_fa, str);
|
||||
parse_error(ERR_INCORRECT_HEX, str);
|
||||
}
|
||||
break;
|
||||
case '\'': // binary
|
||||
|
@ -184,7 +193,7 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
if(ptr[i] >= '0' && ptr[i] <= '1')
|
||||
val += ptr[i] - '0';
|
||||
else
|
||||
parse_error(ERR_INCORRECT_BIN, cur_fa, str);
|
||||
parse_error(ERR_INCORRECT_BIN, str);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -205,19 +214,19 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
if (ptr[i] >= '0' && ptr[i] <= '9')
|
||||
val += ptr[i] - '0';
|
||||
else
|
||||
parse_error(ERR_INCORRECT_DEC, cur_fa, str);
|
||||
parse_error(ERR_INCORRECT_DEC, str);
|
||||
}
|
||||
}
|
||||
else // Everything else is a label.
|
||||
{
|
||||
// Lookup label
|
||||
for (int i = 0; i < labels_count; i++)
|
||||
for (int i = 0; i < labels.size(); i++)
|
||||
{
|
||||
if (strcmp(labels[i].label, ptr) == 0)
|
||||
if (strcmp(labels[i].label.c_str(), ptr) == 0)
|
||||
return labels[i].addr;
|
||||
}
|
||||
if (cur_pass == 2)
|
||||
parse_error(ERR_UNKNOWN_LABEL, cur_fa, str);
|
||||
parse_error(ERR_UNKNOWN_LABEL, str);
|
||||
}
|
||||
}
|
||||
if (negative)
|
||||
|
@ -270,7 +279,7 @@ char *DSPAssembler::find_brackets(char *src, char *dst)
|
|||
}
|
||||
}
|
||||
if (count)
|
||||
parse_error(ERR_NO_MATCHING_BRACKETS, cur_fa);
|
||||
parse_error(ERR_NO_MATCHING_BRACKETS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -333,8 +342,7 @@ u32 DSPAssembler::parse_exp(const char *ptr)
|
|||
if (val < 0)
|
||||
{
|
||||
val = 0x10000 + (val & 0xffff); // ATTENTION: avoid a terrible bug!!! number cannot write with '-' in sprintf
|
||||
if(cur_fa)
|
||||
fprintf(stderr, "WARNING: Number Underflow at Line: %d \n", cur_fa->code_line);
|
||||
fprintf(stderr, "WARNING: Number Underflow at Line: %d \n", code_line);
|
||||
}
|
||||
sprintf(d_buffer, "%d", val);
|
||||
}
|
||||
|
@ -373,14 +381,13 @@ u32 DSPAssembler::parse_exp(const char *ptr)
|
|||
return val;
|
||||
}
|
||||
|
||||
u32 DSPAssembler::parse_exp_f(const char *ptr, fass_t *fa)
|
||||
u32 DSPAssembler::parse_exp_f(const char *ptr)
|
||||
{
|
||||
cur_fa = fa;
|
||||
return parse_exp(ptr);
|
||||
}
|
||||
|
||||
// Destroys parstr
|
||||
u32 DSPAssembler::get_params(char *parstr, param_t *par, fass_t *fa)
|
||||
u32 DSPAssembler::get_params(char *parstr, param_t *par)
|
||||
{
|
||||
u32 count = 0;
|
||||
char *tmpstr = skip_spaces(parstr);
|
||||
|
@ -405,27 +412,27 @@ u32 DSPAssembler::get_params(char *parstr, param_t *par, fass_t *fa)
|
|||
par[i].type = P_STR;
|
||||
break;
|
||||
case '#':
|
||||
par[i].val = parse_exp_f(tmpstr + 1, fa);
|
||||
par[i].val = parse_exp_f(tmpstr + 1);
|
||||
par[i].type = P_IMM;
|
||||
break;
|
||||
case '@':
|
||||
if (tmpstr[1] == '$')
|
||||
{
|
||||
par[i].val = parse_exp_f(tmpstr + 2, fa);
|
||||
par[i].val = parse_exp_f(tmpstr + 2);
|
||||
par[i].type = P_PRG;
|
||||
}
|
||||
else
|
||||
{
|
||||
par[i].val = parse_exp_f(tmpstr + 1, fa);
|
||||
par[i].val = parse_exp_f(tmpstr + 1);
|
||||
par[i].type = P_MEM;
|
||||
}
|
||||
break;
|
||||
case '$':
|
||||
par[i].val = parse_exp_f(tmpstr + 1, fa);
|
||||
par[i].val = parse_exp_f(tmpstr + 1);
|
||||
par[i].type = P_REG;
|
||||
break;
|
||||
default:
|
||||
par[i].val = parse_exp_f(tmpstr, fa);
|
||||
par[i].val = parse_exp_f(tmpstr);
|
||||
par[i].type = P_VAL;
|
||||
break;
|
||||
}
|
||||
|
@ -434,7 +441,7 @@ u32 DSPAssembler::get_params(char *parstr, param_t *par, fass_t *fa)
|
|||
return count;
|
||||
}
|
||||
|
||||
const opc_t *DSPAssembler::find_opcode(const char *opcode, u32 par_count, const opc_t * const opcod, u32 opcod_size, DSPAssembler::fass_t *fa)
|
||||
const opc_t *DSPAssembler::find_opcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size)
|
||||
{
|
||||
if (opcode[0] == 'C' && opcode[1] == 'W')
|
||||
return &cw;
|
||||
|
@ -449,16 +456,16 @@ const opc_t *DSPAssembler::find_opcode(const char *opcode, u32 par_count, const
|
|||
{
|
||||
if (par_count < opc->param_count)
|
||||
{
|
||||
parse_error(ERR_NOT_ENOUGH_PARAMETERS, fa);
|
||||
parse_error(ERR_NOT_ENOUGH_PARAMETERS);
|
||||
}
|
||||
if (par_count > opc->param_count)
|
||||
{
|
||||
parse_error(ERR_TOO_MANY_PARAMETERS, fa);
|
||||
parse_error(ERR_TOO_MANY_PARAMETERS);
|
||||
}
|
||||
return opc;
|
||||
}
|
||||
}
|
||||
parse_error(ERR_UNKNOWN_OPCODE, fa);
|
||||
parse_error(ERR_UNKNOWN_OPCODE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -470,81 +477,93 @@ u16 get_mask_shifted_down(u16 mask)
|
|||
return mask;
|
||||
}
|
||||
|
||||
bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa)
|
||||
bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool ext)
|
||||
{
|
||||
int value;
|
||||
unsigned int valueu;
|
||||
for (u32 i = 0; i < count; i++)
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
current_param = i+1;
|
||||
const int current_param = i + 1; // just for display.
|
||||
if (opc->params[i].type != par[i].type || (par[i].type & P_REG))
|
||||
{
|
||||
if ((opc->params[i].type & P_REG) && (par[i].type & P_REG))
|
||||
{
|
||||
// Just a temp. Should be replaced with more purposeful vars.
|
||||
int value;
|
||||
|
||||
// modified by Hermes: test the register range
|
||||
switch ((unsigned)opc->params[i].type)
|
||||
{
|
||||
case P_REG18:
|
||||
case P_REG19:
|
||||
case P_REG1A:
|
||||
//case P_REG1C:
|
||||
value = (opc->params[i].type >> 8) & 31;
|
||||
if ((int)par[i].val < value ||
|
||||
(int)par[i].val > value + get_mask_shifted_down(opc->params[i].mask))
|
||||
{
|
||||
parse_error(ERR_INVALID_REGISTER, fa);
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
|
||||
parse_error(ERR_INVALID_REGISTER);
|
||||
}
|
||||
break;
|
||||
case P_PRG:
|
||||
if ((int)par[i].val < 0 || (int)par[i].val > 0x3)
|
||||
{
|
||||
parse_error(ERR_INVALID_REGISTER, fa);
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
|
||||
parse_error(ERR_INVALID_REGISTER);
|
||||
}
|
||||
break;
|
||||
case P_ACC:
|
||||
if ((int)par[i].val < 0x20 || (int)par[i].val > 0x21)
|
||||
{
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
if (par[i].val >= 0x1e && par[i].val <= 0x1f)
|
||||
fprintf(stderr, "WARNING: $ACM%d register used instead $ACC%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), fa->code_line, current_param);
|
||||
fprintf(stderr, "WARNING: $ACM%d register used instead of $ACC%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), code_line, current_param, ext);
|
||||
else if (par[i].val >= 0x1c && par[i].val <= 0x1d)
|
||||
fprintf(stderr, "WARNING: $ACL%d register used instead $ACC%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), fa->code_line, current_param);
|
||||
fprintf(stderr, "WARNING: $ACL%d register used instead of $ACC%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), code_line, current_param);
|
||||
else
|
||||
parse_error(ERR_WRONG_PARAMETER_ACC, fa);
|
||||
parse_error(ERR_WRONG_PARAMETER_ACC);
|
||||
}
|
||||
break;
|
||||
case P_ACCM:
|
||||
if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
|
||||
{
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
if (par[i].val >= 0x1c && par[i].val <= 0x1d)
|
||||
fprintf(stderr, "WARNING: $ACL%d register used instead $ACM%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), fa->code_line, current_param);
|
||||
fprintf(stderr, "WARNING: $ACL%d register used instead of $ACM%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), code_line, current_param);
|
||||
else if (par[i].val >= 0x20 && par[i].val <= 0x21)
|
||||
fprintf(stderr, "WARNING: $ACC%d register used instead $ACM%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), fa->code_line, current_param);
|
||||
fprintf(stderr, "WARNING: $ACC%d register used instead of $ACM%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), code_line, current_param);
|
||||
else
|
||||
parse_error(ERR_WRONG_PARAMETER_ACC, fa);
|
||||
parse_error(ERR_WRONG_PARAMETER_ACC);
|
||||
}
|
||||
break;
|
||||
|
||||
case P_ACCL:
|
||||
if ((int)par[i].val < 0x1c || (int)par[i].val > 0x1d)
|
||||
{
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
if (par[i].val >= 0x1e && par[i].val <= 0x1f)
|
||||
fprintf(stderr, "WARNING: $ACM%d register used instead $ACL%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), fa->code_line, current_param);
|
||||
else if (par[i].val >= 0x20 && par[i].val <= 0x21)
|
||||
fprintf(stderr, "WARNING: $ACC%d register used instead $ACL%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), fa->code_line, current_param);
|
||||
{
|
||||
fprintf(stderr, "%s", cur_line.c_str());
|
||||
fprintf(stderr, "WARNING: $ACM%d register used instead of $ACL%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), code_line, current_param);
|
||||
}
|
||||
else if (par[i].val >= 0x20 && par[i].val <= 0x21) {
|
||||
fprintf(stderr, "%s", cur_line.c_str());
|
||||
fprintf(stderr, "WARNING: $ACC%d register used instead of $ACL%d register Line: %d Param: %d\n",
|
||||
(par[i].val & 1), (par[i].val & 1), code_line, current_param);
|
||||
}
|
||||
else
|
||||
parse_error(ERR_WRONG_PARAMETER_ACC, fa);
|
||||
parse_error(ERR_WRONG_PARAMETER_ACC);
|
||||
}
|
||||
break;
|
||||
/* case P_ACCM_D: //P_ACC_MID:
|
||||
if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
|
||||
{
|
||||
parse_error(ERR_WRONG_PARAMETER_MID_ACC, fa);
|
||||
parse_error(ERR_WRONG_PARAMETER_MID_ACC);
|
||||
}
|
||||
break;*/
|
||||
}
|
||||
|
@ -554,42 +573,45 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, u32 count, fass
|
|||
switch (par[i].type & (P_REG | P_VAL | P_MEM | P_IMM))
|
||||
{
|
||||
case P_REG:
|
||||
parse_error(ERR_EXPECTED_PARAM_REG, fa);
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_REG);
|
||||
break;
|
||||
case P_MEM:
|
||||
parse_error(ERR_EXPECTED_PARAM_MEM, fa);
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_MEM);
|
||||
break;
|
||||
case P_VAL:
|
||||
parse_error(ERR_EXPECTED_PARAM_VAL, fa);
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_VAL);
|
||||
break;
|
||||
case P_IMM:
|
||||
parse_error(ERR_EXPECTED_PARAM_IMM, fa);
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_IMM);
|
||||
break;
|
||||
}
|
||||
parse_error(ERR_WRONG_PARAMETER, fa);
|
||||
parse_error(ERR_WRONG_PARAMETER);
|
||||
break;
|
||||
}
|
||||
else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0)
|
||||
{
|
||||
// modified by Hermes: test NUMBER range
|
||||
value = get_mask_shifted_down(opc->params[i].mask);
|
||||
|
||||
valueu = 0xffff & ~(value >> 1);
|
||||
int value = get_mask_shifted_down(opc->params[i].mask);
|
||||
unsigned int valueu = 0xffff & ~(value >> 1);
|
||||
if ((int)par[i].val < 0)
|
||||
{
|
||||
if (value == 7) // value 7 por sbclr/sbset
|
||||
{
|
||||
fprintf(stderr,"Value must be from 0x0 to 0x%x\n", value);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
else if (opc->params[i].type == P_MEM)
|
||||
{
|
||||
if (value < 256)
|
||||
fprintf(stderr,"Address value must be from 0x%x to 0x%x\n",valueu, (value>>1));
|
||||
fprintf(stderr, "Address value must be from 0x%x to 0x%x\n",valueu, (value>>1));
|
||||
else
|
||||
fprintf(stderr,"Address value must be from 0x0 to 0x%x\n", value);
|
||||
fprintf(stderr, "Address value must be from 0x0 to 0x%x\n", value);
|
||||
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
else if ((int)par[i].val < -((value >> 1) + 1))
|
||||
{
|
||||
|
@ -600,7 +622,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, u32 count, fass
|
|||
fprintf(stderr, "Value must be from -0x%x to 0x%x or 0x0 to 0x%x, is %i\n",
|
||||
(value >> 1) + 1, value >> 1, value, par[i].val);
|
||||
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -610,7 +632,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, u32 count, fass
|
|||
if (par[i].val > (unsigned)value)
|
||||
{
|
||||
fprintf(stderr,"Value must be from 0x%x to 0x%x, is %i\n",valueu, value, par[i].val);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
else if (opc->params[i].type == P_MEM)
|
||||
|
@ -624,7 +646,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, u32 count, fass
|
|||
fprintf(stderr,"Address value must be from 0x%x to 0x%x, is %04x\n", valueu, value, par[i].val);
|
||||
else
|
||||
fprintf(stderr,"Address value must be minor of 0x%x\n", value+1);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -637,7 +659,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, u32 count, fass
|
|||
fprintf(stderr,"Value must be from -0x%x to 0x%x, is %i\n", (value + 1), value, par[i].val);
|
||||
else
|
||||
fprintf(stderr,"Value must be minor of 0x%x, is %i\n", value + 1, par[i].val);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER, fa);
|
||||
parse_error(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -672,6 +694,7 @@ void DSPAssembler::build_code(const opc_t *opc, param_t *par, u32 par_count, u16
|
|||
|
||||
void DSPAssembler::gd_ass_init_pass(int pass)
|
||||
{
|
||||
failed = false;
|
||||
if (pass == 1)
|
||||
{
|
||||
// Reset label table. Pre-populate with hw addresses and registers.
|
||||
|
@ -680,7 +703,7 @@ void DSPAssembler::gd_ass_init_pass(int pass)
|
|||
{
|
||||
gd_ass_register_label(regnames[i].name, regnames[i].addr);
|
||||
}
|
||||
for (int i = 0; i < pdlabels_size; i++)
|
||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||
{
|
||||
gd_ass_register_label(pdlabels[i].name, pdlabels[i].addr);
|
||||
}
|
||||
|
@ -696,40 +719,37 @@ void DSPAssembler::gd_ass_init_pass(int pass)
|
|||
segment_addr[SEGMENT_OVERLAY] = 0;
|
||||
}
|
||||
|
||||
bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
||||
bool DSPAssembler::gd_ass_file(const char *fname, int pass)
|
||||
{
|
||||
fass_t fa;
|
||||
int disable_text = 0; // modified by Hermes
|
||||
|
||||
param_t params[10] = {0};
|
||||
param_t params_ext[10] = {0};
|
||||
u32 params_count = 0;
|
||||
u32 params_count_ext = 0;
|
||||
|
||||
fa.failed = false;
|
||||
fa.fsrc = fopen(fname, "r");
|
||||
if (fa.fsrc == NULL)
|
||||
fsrc = fopen(fname, "r");
|
||||
if (fsrc == NULL)
|
||||
{
|
||||
fprintf(stderr, "Cannot open %s file\n", fname);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(fa.fsrc, 0, SEEK_SET);
|
||||
fseek(fsrc, 0, SEEK_SET);
|
||||
|
||||
printf("Pass %d\n", pass);
|
||||
fa.code_line = 0;
|
||||
code_line = 0;
|
||||
cur_pass = pass;
|
||||
|
||||
#define LINEBUF_SIZE 4096
|
||||
#define LINEBUF_SIZE 1024
|
||||
char linebuffer[LINEBUF_SIZE];
|
||||
while (!feof(fa.fsrc) && !fa.failed)
|
||||
while (!feof(fsrc) && !failed)
|
||||
{
|
||||
int opcode_size = 0;
|
||||
memset(linebuffer, 0, LINEBUF_SIZE);
|
||||
if (!fgets(linebuffer, LINEBUF_SIZE, fa.fsrc))
|
||||
if (!fgets(linebuffer, LINEBUF_SIZE, fsrc))
|
||||
break;
|
||||
strcpy(cur_line, linebuffer);
|
||||
cur_line = linebuffer;
|
||||
//printf("A: %s", linebuffer);
|
||||
fa.code_line++;
|
||||
code_line++;
|
||||
|
||||
param_t params[10] = {0};
|
||||
param_t params_ext[10] = {0};
|
||||
|
||||
for (int i = 0; i < LINEBUF_SIZE; i++)
|
||||
{
|
||||
|
@ -744,7 +764,7 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
c = 0x00;
|
||||
else if (linebuffer[i+1] == '*')
|
||||
{
|
||||
// wtf is this?
|
||||
// toggle comment mode.
|
||||
disable_text = !disable_text;
|
||||
}
|
||||
}
|
||||
|
@ -759,8 +779,8 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(disable_text && ((unsigned char )c)>32) c=32;
|
||||
// turn text into spaces if disable_text is on (in a comment).
|
||||
if (disable_text && ((unsigned char)c) > 32) c = 32;
|
||||
|
||||
if (c == 0x0a || c == 0x0d || c == ';')
|
||||
c = 0x00;
|
||||
|
@ -802,9 +822,8 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
opcode = strtok(ptr, " ");
|
||||
char *opcode_ext = NULL;
|
||||
|
||||
char *paramstr;
|
||||
char *paramstr_ext;
|
||||
|
||||
u32 params_count = 0;
|
||||
u32 params_count_ext = 0;
|
||||
if (opcode)
|
||||
{
|
||||
if ((opcode_ext = strstr(opcode, "'")) != NULL)
|
||||
|
@ -819,11 +838,10 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
params_count = 0;
|
||||
params_count_ext = 0;
|
||||
|
||||
paramstr = paramstr_ext = 0;
|
||||
char *paramstr = strtok(NULL, "\0");
|
||||
char *paramstr_ext = 0;
|
||||
// there is valid opcode so probably we have parameters
|
||||
|
||||
paramstr = strtok(NULL, "\0");
|
||||
|
||||
if (paramstr)
|
||||
{
|
||||
if ((paramstr_ext = strstr(paramstr, ":")) != NULL)
|
||||
|
@ -834,9 +852,9 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
}
|
||||
|
||||
if (paramstr)
|
||||
params_count = get_params(paramstr, params, &fa);
|
||||
params_count = get_params(paramstr, params);
|
||||
if (paramstr_ext)
|
||||
params_count_ext = get_params(paramstr_ext, params_ext, &fa);
|
||||
params_count_ext = get_params(paramstr_ext, params_ext);
|
||||
}
|
||||
|
||||
if (label)
|
||||
|
@ -852,10 +870,8 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
}
|
||||
}
|
||||
if (pass == 1)
|
||||
{
|
||||
gd_ass_register_label(label, lval);
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == NULL)
|
||||
continue;
|
||||
|
@ -866,34 +882,30 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
if (params[0].type == P_STR)
|
||||
{
|
||||
char *tmpstr;
|
||||
if (include_dir)
|
||||
if (include_dir.size())
|
||||
{
|
||||
tmpstr = (char *)malloc(strlen(include_dir) + strlen(params[0].str) + 2);
|
||||
sprintf(tmpstr, "%s/%s", include_dir, params[0].str);
|
||||
tmpstr = (char *)malloc(include_dir.size() + strlen(params[0].str) + 2);
|
||||
sprintf(tmpstr, "%s/%s", include_dir.c_str(), params[0].str);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpstr = (char *)malloc(strlen(params[0].str) + 1);
|
||||
strcpy(tmpstr, params[0].str);
|
||||
}
|
||||
gd_ass_file(gdg, tmpstr, pass);
|
||||
gd_ass_file(tmpstr, pass);
|
||||
free(tmpstr);
|
||||
}
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_STR, &fa);
|
||||
parse_error(ERR_EXPECTED_PARAM_STR);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp("INCDIR", opcode) == 0)
|
||||
{
|
||||
if (params[0].type == P_STR)
|
||||
{
|
||||
if (include_dir) free(include_dir);
|
||||
include_dir = (char *)malloc(strlen(params[0].str) + 1);
|
||||
strcpy(include_dir, params[0].str);
|
||||
}
|
||||
include_dir = params[0].str;
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_STR, &fa);
|
||||
parse_error(ERR_EXPECTED_PARAM_STR);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -902,13 +914,13 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
if (params[0].type == P_VAL)
|
||||
cur_addr = params[0].val;
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_VAL, &fa);
|
||||
parse_error(ERR_EXPECTED_PARAM_VAL);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp("SEGMENT", opcode) == 0)
|
||||
{
|
||||
if(params[0].type == P_STR)
|
||||
if (params[0].type == P_STR)
|
||||
{
|
||||
segment_addr[cur_segment] = cur_addr;
|
||||
if (strcmp("DATA", params[0].str) == 0)
|
||||
|
@ -918,17 +930,17 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
cur_addr = segment_addr[cur_segment];
|
||||
}
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_STR, &fa);
|
||||
parse_error(ERR_EXPECTED_PARAM_STR);
|
||||
continue;
|
||||
}
|
||||
|
||||
const opc_t *opc = find_opcode(opcode, params_count, opcodes, opcodes_size, &fa);
|
||||
const opc_t *opc = find_opcode(opcode, params_count, opcodes, opcodes_size);
|
||||
if (!opc)
|
||||
opc = &cw;
|
||||
|
||||
opcode_size = opc->size & ~P_EXT;
|
||||
|
||||
verify_params(opc, params, params_count, &fa);
|
||||
verify_params(opc, params, params_count);
|
||||
|
||||
const opc_t *opc_ext = NULL;
|
||||
// Check for opcode extensions.
|
||||
|
@ -936,37 +948,37 @@ bool DSPAssembler::gd_ass_file(gd_globals_t *gdg, const char *fname, int pass)
|
|||
{
|
||||
if (opcode_ext)
|
||||
{
|
||||
opc_ext = find_opcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size, &fa);
|
||||
verify_params(opc_ext, params_ext, params_count_ext, &fa);
|
||||
opc_ext = find_opcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size);
|
||||
verify_params(opc_ext, params_ext, params_count_ext, true);
|
||||
}
|
||||
else if (params_count_ext)
|
||||
parse_error(ERR_EXT_PAR_NOT_EXT, &fa);
|
||||
parse_error(ERR_EXT_PAR_NOT_EXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (opcode_ext)
|
||||
parse_error(ERR_EXT_CANT_EXTEND_OPCODE, &fa);
|
||||
parse_error(ERR_EXT_CANT_EXTEND_OPCODE);
|
||||
if (params_count_ext)
|
||||
parse_error(ERR_EXT_PAR_NOT_EXT, &fa);
|
||||
parse_error(ERR_EXT_PAR_NOT_EXT);
|
||||
}
|
||||
|
||||
if (pass == 2)
|
||||
{
|
||||
// generate binary
|
||||
((u16 *)gdg->buffer)[cur_addr] = 0x0000;
|
||||
build_code(opc, params, params_count, (u16 *)gdg->buffer);
|
||||
((u16 *)gdg_buffer)[cur_addr] = 0x0000;
|
||||
build_code(opc, params, params_count, (u16 *)gdg_buffer);
|
||||
if (opc_ext)
|
||||
build_code(opc_ext, params_ext, params_count_ext, (u16 *)gdg->buffer);
|
||||
build_code(opc_ext, params_ext, params_count_ext, (u16 *)gdg_buffer);
|
||||
}
|
||||
|
||||
cur_addr += opcode_size;
|
||||
};
|
||||
if (gdg->buffer == NULL)
|
||||
if (gdg_buffer == NULL)
|
||||
{
|
||||
gdg->buffer_size = cur_addr;
|
||||
gdg->buffer = (char *)malloc(gdg->buffer_size * sizeof(u16) + 4);
|
||||
memset(gdg->buffer, 0, gdg->buffer_size * sizeof(u16));
|
||||
gdg_buffer_size = cur_addr;
|
||||
gdg_buffer = (char *)malloc(gdg_buffer_size * sizeof(u16) + 4);
|
||||
memset(gdg_buffer, 0, gdg_buffer_size * sizeof(u16));
|
||||
}
|
||||
fclose(fa.fsrc);
|
||||
return !fa.failed;
|
||||
fclose(fsrc);
|
||||
return !failed;
|
||||
}
|
||||
|
|
|
@ -64,21 +64,15 @@ enum err_t
|
|||
class DSPAssembler
|
||||
{
|
||||
public:
|
||||
DSPAssembler();
|
||||
DSPAssembler(const AssemblerSettings &settings);
|
||||
~DSPAssembler();
|
||||
|
||||
void Assemble(const char *text, std::vector<u16> *code);
|
||||
|
||||
typedef struct fass_t
|
||||
{
|
||||
FILE *fsrc;
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
} fass_t;
|
||||
|
||||
struct label_t
|
||||
{
|
||||
char *label;
|
||||
label_t(const char *lbl, s32 address) : label(lbl), addr(address) {}
|
||||
std::string label;
|
||||
s32 addr;
|
||||
};
|
||||
|
||||
|
@ -97,39 +91,42 @@ public:
|
|||
SEGMENT_MAX
|
||||
};
|
||||
void gd_ass_init_pass(int pass);
|
||||
bool gd_ass_file(gd_globals_t *gdg, const char *fname, int pass);
|
||||
bool gd_ass_file(const char *fname, int pass);
|
||||
|
||||
char *gdg_buffer;
|
||||
int gdg_buffer_size;
|
||||
|
||||
private:
|
||||
void parse_error(err_t err_code, fass_t *fa, 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_clear_labels();
|
||||
s32 strtoval(const char *str);
|
||||
char *find_brackets(char *src, char *dst);
|
||||
u32 parse_exp(const char *ptr);
|
||||
u32 parse_exp_f(const char *ptr, fass_t *fa);
|
||||
u32 get_params(char *parstr, param_t *par, fass_t *fa);
|
||||
const opc_t *find_opcode(const char *opcode, u32 par_count, const opc_t * const opcod, u32 opcod_size, fass_t *fa);
|
||||
bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa);
|
||||
u32 parse_exp_f(const char *ptr);
|
||||
u32 get_params(char *parstr, param_t *par);
|
||||
const opc_t *find_opcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
||||
bool verify_params(const opc_t *opc, param_t *par, int count, bool ext = false);
|
||||
void build_code(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
||||
|
||||
char *include_dir;
|
||||
|
||||
label_t labels[10000];
|
||||
int labels_count;
|
||||
|
||||
char cur_line[4096];
|
||||
std::string include_dir;
|
||||
std::vector<label_t> labels;
|
||||
std::string cur_line;
|
||||
|
||||
u32 cur_addr;
|
||||
u8 cur_pass;
|
||||
fass_t *cur_fa;
|
||||
|
||||
FILE *fsrc;
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
|
||||
typedef std::map<std::string, std::string> AliasMap;
|
||||
AliasMap aliases;
|
||||
|
||||
segment_t cur_segment;
|
||||
u32 segment_addr[SEGMENT_MAX];
|
||||
|
||||
int current_param;
|
||||
const AssemblerSettings settings_;
|
||||
};
|
||||
|
||||
#endif // _DSP_ASSEMBLE_H
|
|
@ -34,25 +34,23 @@
|
|||
#pragma warning(disable:4996)
|
||||
#endif
|
||||
|
||||
u32 unk_opcodes[0x10000];
|
||||
|
||||
extern void nop(const UDSPInstruction& opc);
|
||||
|
||||
DSPDisassembler::DSPDisassembler()
|
||||
DSPDisassembler::DSPDisassembler(const AssemblerSettings &settings)
|
||||
: settings_(settings)
|
||||
{
|
||||
memset(unk_opcodes, 0, sizeof(unk_opcodes));
|
||||
}
|
||||
|
||||
char* DSPDisassembler::gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* opc,
|
||||
u16 op1, u16 op2, char* strbuf)
|
||||
char *DSPDisassembler::gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2, char *strbuf)
|
||||
{
|
||||
char* buf = strbuf;
|
||||
u32 val;
|
||||
|
||||
char *buf = strbuf;
|
||||
for (int j = 0; j < opc->param_count; j++)
|
||||
{
|
||||
if (j > 0)
|
||||
buf += sprintf(buf, ", ");
|
||||
|
||||
u32 val;
|
||||
if (opc->params[j].loc >= 1)
|
||||
val = op2;
|
||||
else
|
||||
|
@ -83,21 +81,21 @@ char* DSPDisassembler::gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* op
|
|||
switch (type)
|
||||
{
|
||||
case P_REG:
|
||||
if (gdg->decode_registers)
|
||||
if (settings_.decode_registers)
|
||||
sprintf(buf, "$%s", pdregname(val));
|
||||
else
|
||||
sprintf(buf, "$%d", val);
|
||||
break;
|
||||
|
||||
case P_PRG:
|
||||
if (gdg->decode_registers)
|
||||
if (settings_.decode_registers)
|
||||
sprintf(buf, "@$%s", pdregname(val));
|
||||
else
|
||||
sprintf(buf, "@$%d", val);
|
||||
break;
|
||||
|
||||
case P_VAL:
|
||||
if (gdg->decode_names)
|
||||
if (settings_.decode_names)
|
||||
sprintf(buf, "%s", pdname(val));
|
||||
else
|
||||
sprintf(buf, "0x%04x", val);
|
||||
|
@ -119,7 +117,7 @@ char* DSPDisassembler::gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* op
|
|||
if (opc->params[j].size != 2)
|
||||
val = (u16)(s8)val;
|
||||
|
||||
if (gdg->decode_names)
|
||||
if (settings_.decode_names)
|
||||
sprintf(buf, "@%s", pdname(val));
|
||||
else
|
||||
sprintf(buf, "@0x%04x", val);
|
||||
|
@ -127,7 +125,6 @@ char* DSPDisassembler::gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* op
|
|||
|
||||
default:
|
||||
ERROR_LOG(DSPLLE, "Unknown parameter type: %x", opc->params[j].type);
|
||||
// exit(-1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -137,6 +134,7 @@ char* DSPDisassembler::gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* op
|
|||
return strbuf;
|
||||
}
|
||||
|
||||
#if 0
|
||||
u16 gd_dis_get_opcode_size(gd_globals_t* gdg)
|
||||
{
|
||||
const DSPOPCTemplate* opc = 0;
|
||||
|
@ -168,7 +166,6 @@ u16 gd_dis_get_opcode_size(gd_globals_t* gdg)
|
|||
if (!opc)
|
||||
{
|
||||
ERROR_LOG(DSPLLE, "get_opcode_size ARGH");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (opc->size & P_EXT && op1 & 0x00ff)
|
||||
|
@ -197,28 +194,27 @@ u16 gd_dis_get_opcode_size(gd_globals_t* gdg)
|
|||
|
||||
return opc->size & ~P_EXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
char* DSPDisassembler::gd_dis_opcode(gd_globals_t* gdg)
|
||||
void DSPDisassembler::gd_dis_opcode(const u16 *binbuf, u16 *pc, std::string *dest)
|
||||
{
|
||||
u32 op2;
|
||||
char *buf = gdg->buffer;
|
||||
|
||||
u16 pc = gdg->pc;
|
||||
|
||||
char buffer[256];
|
||||
char *buf = buffer;
|
||||
// Start with a space.
|
||||
buf[0] = ' ';
|
||||
buf[1] = '\0';
|
||||
buf++;
|
||||
|
||||
if ((pc & 0x7fff) >= 0x1000)
|
||||
if ((*pc & 0x7fff) >= 0x1000)
|
||||
{
|
||||
gdg->pc++;
|
||||
return gdg->buffer;
|
||||
*pc++;
|
||||
return;
|
||||
}
|
||||
|
||||
pc &= 0x0fff;
|
||||
u32 op1 = gdg->binbuf[pc];
|
||||
*pc &= 0x0fff;
|
||||
const u32 op1 = binbuf[*pc];
|
||||
|
||||
const DSPOPCTemplate *opc = NULL;
|
||||
const DSPOPCTemplate *opc_ext = NULL;
|
||||
|
@ -239,7 +235,6 @@ char* DSPDisassembler::gd_dis_opcode(gd_globals_t* gdg)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
const DSPOPCTemplate fake_op = {"CW", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, NULL, NULL,};
|
||||
if (!opc)
|
||||
opc = &fake_op;
|
||||
|
@ -266,23 +261,22 @@ char* DSPDisassembler::gd_dis_opcode(gd_globals_t* gdg)
|
|||
|
||||
// printing
|
||||
|
||||
if (gdg->show_pc)
|
||||
sprintf(buf, "%04x ", gdg->pc);
|
||||
if (settings_.show_pc)
|
||||
sprintf(buf, "%04x ", *pc);
|
||||
|
||||
buf += strlen(buf);
|
||||
|
||||
if ((opc->size & ~P_EXT) == 2)
|
||||
{
|
||||
op2 = gdg->binbuf[pc + 1];
|
||||
|
||||
if (gdg->show_hex)
|
||||
op2 = binbuf[*pc + 1];
|
||||
if (settings_.show_hex)
|
||||
sprintf(buf, "%04x %04x ", op1, op2);
|
||||
}
|
||||
else
|
||||
{
|
||||
op2 = 0;
|
||||
|
||||
if (gdg->show_hex)
|
||||
if (settings_.show_hex)
|
||||
sprintf(buf, "%04x ", op1);
|
||||
}
|
||||
|
||||
|
@ -291,11 +285,11 @@ char* DSPDisassembler::gd_dis_opcode(gd_globals_t* gdg)
|
|||
char tmpbuf[20];
|
||||
|
||||
if (extended)
|
||||
sprintf(tmpbuf, "%s%c%s", opc->name, gdg->ext_separator, opc_ext->name);
|
||||
sprintf(tmpbuf, "%s%c%s", opc->name, settings_.ext_separator, opc_ext->name);
|
||||
else
|
||||
sprintf(tmpbuf, "%s", opc->name);
|
||||
|
||||
if (gdg->print_tabs)
|
||||
if (settings_.print_tabs)
|
||||
sprintf(buf, "%s\t", tmpbuf);
|
||||
else
|
||||
sprintf(buf, "%-12s", tmpbuf);
|
||||
|
@ -303,7 +297,7 @@ char* DSPDisassembler::gd_dis_opcode(gd_globals_t* gdg)
|
|||
buf += strlen(buf);
|
||||
|
||||
if (opc->param_count > 0)
|
||||
gd_dis_params(gdg, opc, op1, op2, buf);
|
||||
gd_dis_params(opc, op1, op2, buf);
|
||||
|
||||
buf += strlen(buf);
|
||||
|
||||
|
@ -318,7 +312,7 @@ char* DSPDisassembler::gd_dis_opcode(gd_globals_t* gdg)
|
|||
buf += strlen(buf);
|
||||
|
||||
if (opc_ext->param_count > 0)
|
||||
gd_dis_params(gdg, opc_ext, op1, op2, buf);
|
||||
gd_dis_params(opc_ext, op1, op2, buf);
|
||||
|
||||
buf += strlen(buf);
|
||||
}
|
||||
|
@ -331,14 +325,14 @@ char* DSPDisassembler::gd_dis_opcode(gd_globals_t* gdg)
|
|||
}
|
||||
|
||||
if (extended)
|
||||
gdg->pc += opc_ext->size;
|
||||
*pc += opc_ext->size;
|
||||
else
|
||||
gdg->pc += opc->size & ~P_EXT;
|
||||
*pc += opc->size & ~P_EXT;
|
||||
|
||||
return gdg->buffer;
|
||||
dest->append(buffer);
|
||||
}
|
||||
|
||||
bool DSPDisassembler::gd_dis_file(gd_globals_t* gdg, const char* name, FILE* output)
|
||||
bool DSPDisassembler::gd_dis_file(const char* name, FILE* output)
|
||||
{
|
||||
gd_dis_open_unkop();
|
||||
|
||||
|
@ -354,23 +348,20 @@ bool DSPDisassembler::gd_dis_file(gd_globals_t* gdg, const char* name, FILE* out
|
|||
fseek(in, 0, SEEK_END);
|
||||
size = (int)ftell(in);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
gdg->binbuf = (u16*)malloc(size);
|
||||
fread(gdg->binbuf, 1, size, in);
|
||||
|
||||
gdg->buffer = (char*)malloc(256);
|
||||
gdg->buffer_size = 256;
|
||||
u16 *binbuf = (u16*)malloc(size);
|
||||
fread(binbuf, 1, size, in);
|
||||
|
||||
for (gdg->pc = 0; gdg->pc < (size / 2);)
|
||||
fprintf(output, "%s\n", gd_dis_opcode(gdg));
|
||||
for (u16 pc = 0; pc < (size / 2);)
|
||||
{
|
||||
std::string str;
|
||||
gd_dis_opcode(binbuf, &pc, &str);
|
||||
fprintf(output, "%s\n", str.c_str());
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
|
||||
free(gdg->binbuf);
|
||||
gdg->binbuf = NULL;
|
||||
|
||||
free(gdg->buffer);
|
||||
gdg->buffer = NULL;
|
||||
gdg->buffer_size = 0;
|
||||
free(binbuf);
|
||||
|
||||
gd_dis_close_unkop();
|
||||
|
||||
|
|
|
@ -28,40 +28,55 @@
|
|||
#include "Common.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
struct gd_globals_t
|
||||
struct AssemblerSettings
|
||||
{
|
||||
AssemblerSettings()
|
||||
: print_tabs(false),
|
||||
show_hex(false),
|
||||
show_pc(false),
|
||||
decode_names(true),
|
||||
decode_registers(true),
|
||||
ext_separator('\'')
|
||||
{
|
||||
}
|
||||
|
||||
bool print_tabs;
|
||||
bool show_hex;
|
||||
bool show_pc;
|
||||
bool decode_names;
|
||||
bool decode_registers;
|
||||
bool lower_case_ops;
|
||||
char ext_separator;
|
||||
|
||||
u16* binbuf;
|
||||
u16 *binbuf;
|
||||
u16 pc;
|
||||
char* buffer;
|
||||
u16 buffer_size;
|
||||
char ext_separator;
|
||||
};
|
||||
|
||||
class DSPDisassembler
|
||||
{
|
||||
public:
|
||||
DSPDisassembler();
|
||||
DSPDisassembler(const AssemblerSettings &settings);
|
||||
~DSPDisassembler() {}
|
||||
|
||||
char* gd_dis_opcode(gd_globals_t* gdg);
|
||||
bool gd_dis_file(gd_globals_t* gdg, const char* name, FILE* output);
|
||||
// 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);
|
||||
|
||||
void gd_dis_close_unkop();
|
||||
void gd_dis_open_unkop();
|
||||
const char* gd_dis_get_reg_name(u16 reg);
|
||||
|
||||
private:
|
||||
char* gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* opc, u16 op1, u16 op2, char* strbuf);
|
||||
char* gd_dis_params(const DSPOPCTemplate* opc, u16 op1, u16 op2, char* strbuf);
|
||||
u32 unk_opcodes[0x10000];
|
||||
|
||||
const AssemblerSettings settings_;
|
||||
};
|
||||
|
||||
const char *gd_get_reg_name(u16 reg);
|
||||
u16 gd_dis_get_opcode_size(gd_globals_t* gdg);
|
||||
//u16 gd_dis_get_opcode_size(gd_globals_t* gdg);
|
||||
|
||||
#endif // _DSP_DISASSEMBLE_H
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@ void RunAsmTests()
|
|||
#define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true;
|
||||
|
||||
// Let's start out easy - a trivial instruction..
|
||||
#if 0
|
||||
CHK(" NOP\n");
|
||||
|
||||
// Now let's do several.
|
||||
|
@ -114,26 +113,30 @@ void RunAsmTests()
|
|||
" si @0xfffd, #0xbeef\n"
|
||||
" si @DIRQ, #0x0001\n");
|
||||
|
||||
// Let's try some messy extended instructions.
|
||||
//CHK(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $AC1.M\n");
|
||||
|
||||
//" ADDAXL'MV $ACC1, $AX1.L : $AX1.H, $AC1.M\n");
|
||||
// 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(21, &rand_code);
|
||||
GenRandomCode(31, &rand_code);
|
||||
std::string rand_code_text;
|
||||
Disassemble(rand_code, &rand_code_text);
|
||||
Disassemble(rand_code, true, &rand_code_text);
|
||||
printf("%s", rand_code_text.c_str());
|
||||
RoundTrip(rand_code);
|
||||
#endif
|
||||
|
||||
*/
|
||||
std::string dsp_test;
|
||||
//File::ReadStringFromFile(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test);
|
||||
|
||||
File::ReadFileToString(true, "C:/devkitPro/trunk/libogc/libasnd/dsp_mixer/dsp_mixer.s", &dsp_test);
|
||||
// This is CLOSE to working. Sorry about the local path btw. This is preliminary code.
|
||||
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
|
||||
SuperTrip(dsp_test.c_str());
|
||||
|
||||
//.File::ReadFileToString(true, "C:/devkitPro/trunk/libogc/libasnd/dsp_mixer/dsp_mixer.s", &dsp_test);
|
||||
// This is CLOSE to working. Sorry about the local path btw. This is preliminary code.
|
||||
|
||||
if (!fail)
|
||||
printf("All passed!\n");
|
||||
}
|
||||
|
|
|
@ -190,26 +190,27 @@ void DSPDebuggerLLE::RebuildDisAsmListView()
|
|||
m_Disasm->DeleteAllItems();
|
||||
|
||||
char Buffer[256];
|
||||
gd_globals_t gdg;
|
||||
AssemblerSettings settings;
|
||||
|
||||
const u16 *binbuf;
|
||||
if (g_dsp.pc & 0x8000)
|
||||
gdg.binbuf = g_dsp.irom;
|
||||
binbuf = g_dsp.irom;
|
||||
else
|
||||
gdg.binbuf = g_dsp.iram;
|
||||
binbuf = g_dsp.iram;
|
||||
|
||||
gdg.buffer = Buffer;
|
||||
gdg.buffer_size = 256;
|
||||
gdg.ext_separator = (char)0xff;
|
||||
settings.buffer = Buffer;
|
||||
settings.buffer_size = 256;
|
||||
settings.ext_separator = (char)0xff;
|
||||
|
||||
gdg.show_pc = false;
|
||||
gdg.show_hex = false;
|
||||
gdg.print_tabs = true;
|
||||
gdg.decode_names = true;
|
||||
gdg.decode_registers = true;
|
||||
settings.show_pc = false;
|
||||
settings.show_hex = false;
|
||||
settings.print_tabs = true;
|
||||
settings.decode_names = true;
|
||||
settings.decode_registers = true;
|
||||
|
||||
for (gdg.pc = 0; gdg.pc < DSP_IROM_SIZE;)
|
||||
for (settings.pc = 0; settings.pc < DSP_IROM_SIZE;)
|
||||
{
|
||||
u16 CurrentPC = gdg.pc;
|
||||
u16 CurrentPC = settings.pc;
|
||||
|
||||
if (g_dsp.pc & 0x8000)
|
||||
CurrentPC |= 0x8000;
|
||||
|
@ -220,13 +221,16 @@ void DSPDebuggerLLE::RebuildDisAsmListView()
|
|||
char Temp2[256];
|
||||
sprintf(Temp2, "0x%04x", dsp_imem_read(CurrentPC));
|
||||
|
||||
DSPDisassembler disasm;
|
||||
char* pOpcode = disasm.gd_dis_opcode(&gdg);
|
||||
AssemblerSettings settings;
|
||||
DSPDisassembler disasm(settings);
|
||||
std::string op_str;
|
||||
disasm.gd_dis_opcode(binbuf,&settings.pc, &op_str);
|
||||
const char* pParameter = NULL;
|
||||
const char* pExtension = NULL;
|
||||
|
||||
size_t WholeString = strlen(pOpcode);
|
||||
size_t WholeString = op_str.size();
|
||||
|
||||
/*
|
||||
for (size_t i = 0; i < WholeString; i++)
|
||||
{
|
||||
if (pOpcode[i] == (char)0xff)
|
||||
|
@ -240,7 +244,7 @@ void DSPDebuggerLLE::RebuildDisAsmListView()
|
|||
pOpcode[i] = 0x00;
|
||||
pParameter = &pOpcode[i + 1];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
const char* pFunctionName = NULL;
|
||||
|
||||
|
@ -249,15 +253,15 @@ void DSPDebuggerLLE::RebuildDisAsmListView()
|
|||
pFunctionName = m_SymbolMap[CurrentPC].Name.c_str();
|
||||
}
|
||||
|
||||
int Item = m_Disasm->InsertItem(gdg.pc, wxEmptyString);
|
||||
int Item = m_Disasm->InsertItem(settings.pc, wxEmptyString);
|
||||
m_Disasm->SetItem(Item, COLUMN_BP, wxEmptyString);
|
||||
m_Disasm->SetItem(Item, COLUMN_FUNCTION, wxString::FromAscii(pFunctionName));
|
||||
m_Disasm->SetItem(Item, COLUMN_ADDRESS, wxString::FromAscii(Temp));
|
||||
m_Disasm->SetItem(Item, COLUMN_MNEMONIC, wxString::FromAscii(Temp2));
|
||||
m_Disasm->SetItem(Item, COLUMN_OPCODE, wxString::FromAscii(pOpcode));
|
||||
m_Disasm->SetItem(Item, COLUMN_OPCODE, wxString::FromAscii(op_str.c_str()));
|
||||
m_Disasm->SetItem(Item, COLUMN_EXT, wxString::FromAscii(pExtension));
|
||||
|
||||
if (!strcasecmp(pOpcode, "CALL"))
|
||||
if (!strcasecmp(op_str.c_str(), "CALL"))
|
||||
{
|
||||
u32 FunctionAddress = -1;
|
||||
sscanf(pParameter, "0x%04x", &FunctionAddress);
|
||||
|
|
|
@ -60,15 +60,15 @@ bool DisasmUCodeDump(u32 crc)
|
|||
FILE* t = fopen(txtFile, "wb");
|
||||
if (t != NULL)
|
||||
{
|
||||
gd_globals_t gdg;
|
||||
memset(&gdg, 0, sizeof(gdg));
|
||||
gdg.show_hex = true;
|
||||
gdg.show_pc = true;
|
||||
gdg.ext_separator = '\t';
|
||||
gdg.decode_names = true;
|
||||
gdg.decode_registers = true;
|
||||
DSPDisassembler disasm;
|
||||
disasm.gd_dis_file(&gdg, binFile, t);
|
||||
AssemblerSettings settings;
|
||||
memset(&settings, 0, sizeof(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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue