DSP: More work on dsptool. Minor bugfixes. Add some testdata for dsptool.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2993 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
c395b93590
commit
e7e4ef4481
|
@ -579,8 +579,8 @@ std::string GetSysDirectory()
|
|||
sysDir += DIR_SEP;
|
||||
INFO_LOG(COMMON, "GetSysDirectory: Setting to %s:", sysDir.c_str());
|
||||
return sysDir;
|
||||
|
||||
}
|
||||
|
||||
// Returns a pointer to a string with a Dolphin data dir in the user's home
|
||||
// directory. To be used in "multi-user" mode (that is, installed).
|
||||
const char *GetUserDirectory()
|
||||
|
|
|
@ -522,6 +522,14 @@
|
|||
RelativePath=".\Src\gdsp_registers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\LabelMap.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\LabelMap.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\SConscript"
|
||||
>
|
||||
|
|
|
@ -71,7 +71,7 @@ bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
|||
if (code1[i] == code2[i])
|
||||
count_equal++;
|
||||
else
|
||||
printf("!! %i : %04x vs %04x\n", i, code1[i], code2[i]);
|
||||
printf("!! %04x : %04x vs %04x\n", i, code1[i], code2[i]);
|
||||
}
|
||||
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
||||
return code1.size() == code2.size() && code1.size() == count_equal;
|
||||
|
@ -86,11 +86,11 @@ void GenRandomCode(int size, std::vector<u16> *code)
|
|||
}
|
||||
}
|
||||
|
||||
void CodeToHeader(std::vector<u16> *code, const char *name, std::string *header)
|
||||
void CodeToHeader(const std::vector<u16> &code, const char *name, std::string *header)
|
||||
{
|
||||
char buffer[1024];
|
||||
header->clear();
|
||||
header->reserve(code->size() * 4);
|
||||
header->reserve(code.size() * 4);
|
||||
header->append("#ifndef _MSCVER\n");
|
||||
sprintf(buffer, "const __declspec(align:64) unsigned short %s = {\n");
|
||||
header->append(buffer);
|
||||
|
@ -98,7 +98,7 @@ void CodeToHeader(std::vector<u16> *code, const char *name, std::string *header)
|
|||
sprintf(buffer, "const unsigned short %s __attribute__(aligned:64) = {\n");
|
||||
header->append(buffer);
|
||||
header->append("#endif\n\n ");
|
||||
for (int i = 0; i < code->size(); i++)
|
||||
for (int i = 0; i < code.size(); i++)
|
||||
{
|
||||
if (((i + 1) & 15) == 0)
|
||||
header->append("\n ");
|
||||
|
|
|
@ -27,7 +27,7 @@ bool Assemble(const char *text, std::vector<u16> *code);
|
|||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string *text);
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
||||
void GenRandomCode(int size, std::vector<u16> *code);
|
||||
void CodeToHeader(std::vector<u16> *code, const char *name, std::string *header);
|
||||
void CodeToHeader(const std::vector<u16> &code, const char *name, std::string *header);
|
||||
|
||||
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string *str);
|
||||
|
|
|
@ -1214,7 +1214,7 @@ void addis(const UDSPInstruction& opc)
|
|||
{
|
||||
u8 areg = (opc.hex >> 8) & 0x1;
|
||||
|
||||
s64 Imm = (s8)opc.hex;
|
||||
s64 Imm = (s8)(u8)opc.hex;
|
||||
Imm <<= 16;
|
||||
s64 acc = dsp_get_long_acc(areg);
|
||||
acc += Imm;
|
||||
|
|
|
@ -66,7 +66,6 @@ void nop(const UDSPInstruction& opc)
|
|||
// All AX games: a100
|
||||
// Zelda Four Swords: 02ca
|
||||
|
||||
|
||||
// TODO: Fill up the tables with the corresponding instructions
|
||||
const DSPOPCTemplate opcodes[] =
|
||||
{
|
||||
|
@ -90,17 +89,17 @@ const DSPOPCTemplate opcodes[] =
|
|||
{"RET", 0x02df, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
|
||||
{"RTI", 0x02ff, 0xffff, DSPInterpreter::rti, nop, 1, 0, {}, NULL, NULL},
|
||||
|
||||
{"CALLNS", 0x02b0, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLS", 0x02b1, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLG", 0x02b2, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLLE", 0x02b3, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLNE", 0x02b4, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLZ", 0x02b5, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLL", 0x02b6, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLGE", 0x02b7, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLLNZ", 0x02bc, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLLZ", 0x02bd, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALL", 0x02bf, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLNS", 0x02b0, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLS", 0x02b1, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLG", 0x02b2, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLLE", 0x02b3, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLNE", 0x02b4, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLZ", 0x02b5, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLL", 0x02b6, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLGE", 0x02b7, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLLNZ", 0x02bc, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALLLZ", 0x02bd, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"CALL", 0x02bf, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
|
||||
{"IFNS", 0x0270, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
|
||||
{"IFS", 0x0271, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
|
||||
|
@ -114,17 +113,17 @@ const DSPOPCTemplate opcodes[] =
|
|||
{"IFLZ", 0x027d, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
|
||||
{"IF", 0x027f, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, // Hermes doesn't list this
|
||||
|
||||
{"JNS", 0x0290, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JS", 0x0291, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JG", 0x0292, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JLE", 0x0293, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JNZ", 0x0294, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JZ", 0x0295, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JL", 0x0296, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JGE", 0x0297, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JLNZ", 0x029c, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JNS", 0x0290, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JS", 0x0291, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JG", 0x0292, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JLE", 0x0293, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JNZ", 0x0294, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JZ", 0x0295, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JL", 0x0296, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JGE", 0x0297, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JLNZ", 0x029c, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
|
||||
|
||||
{"JRNS", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
|
||||
|
@ -205,11 +204,11 @@ const DSPOPCTemplate opcodes[] =
|
|||
|
||||
// LOOPS
|
||||
{"LOOP", 0x0040, 0xffe0, DSPInterpreter::loop, nop, 1, 1, {{P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
|
||||
{"BLOOP", 0x0060, 0xffe0, DSPInterpreter::bloop, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"BLOOP", 0x0060, 0xffe0, DSPInterpreter::bloop, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"LOOPI", 0x1000, 0xff00, DSPInterpreter::loopi, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
|
||||
{"BLOOPI", 0x1100, 0xff00, DSPInterpreter::bloopi, nop, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
{"BLOOPI", 0x1100, 0xff00, DSPInterpreter::bloopi, nop, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||
|
||||
{"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, nop, 2, 2, {{P_REG, 1, 0, 0, 0x00c0}, {P_REG04, 2, 1, 0, 0x0003}}, NULL, NULL},
|
||||
{"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, NULL, NULL},
|
||||
|
||||
|
||||
// opcodes that can be extended
|
||||
|
@ -292,12 +291,12 @@ const DSPOPCTemplate opcodes[] =
|
|||
|
||||
{"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},
|
||||
{"ADD", 0x4c00, 0xfeff, DSPInterpreter::add, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"ADD", 0x4c00, 0xfeff, DSPInterpreter::add, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"ADDAXL", 0x7000, 0xfcff, DSPInterpreter::addaxl, 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},
|
||||
|
||||
{"SUBR", 0x5000, 0xf8ff, DSPInterpreter::subr, 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},
|
||||
{"SUBAX", 0x5800, 0xfcff, DSPInterpreter::subax, 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},
|
||||
{"SUB", 0x5c00, 0xfeff, DSPInterpreter::sub, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"SUB", 0x5c00, 0xfeff, DSPInterpreter::sub, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
{"SUBP", 0x5e00, 0xfeff, DSPInterpreter::subp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
||||
{"MADD", 0xf200, 0xfeff, DSPInterpreter::madd, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "Common.h"
|
||||
|
||||
// The ones that end with _D are the opposite one - if the bit specify
|
||||
// The non-ADDR 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.
|
||||
|
@ -36,6 +36,8 @@ enum partype_t
|
|||
P_IMM = 0x0002,
|
||||
P_MEM = 0x0003,
|
||||
P_STR = 0x0004,
|
||||
P_ADDR_I = 0x0005,
|
||||
P_ADDR_D = 0x0006,
|
||||
P_REG = 0x8000,
|
||||
P_REG04 = P_REG | 0x0400, // IX
|
||||
P_REG08 = P_REG | 0x0800,
|
||||
|
@ -60,7 +62,6 @@ enum partype_t
|
|||
// The following seem like junk:
|
||||
// P_REG10 = P_REG | 0x1000,
|
||||
// P_AX_D = P_REG | 0x2280,
|
||||
|
||||
};
|
||||
|
||||
#define P_EXT 0x80
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "LabelMap.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
LabelMap::LabelMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LabelMap::RegisterDefaults()
|
||||
{
|
||||
for (int i = 0; i < 0x24; i++)
|
||||
{
|
||||
RegisterLabel(regnames[i].name, regnames[i].addr);
|
||||
}
|
||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||
{
|
||||
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelMap::RegisterLabel(const char *label, u16 lval, LabelType type)
|
||||
{
|
||||
u16 old_value;
|
||||
if (GetLabelValue(label, &old_value) && old_value != lval)
|
||||
{
|
||||
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
|
||||
label, lval, old_value);
|
||||
DeleteLabel(label);
|
||||
}
|
||||
labels.push_back(label_t(label, lval, type));
|
||||
}
|
||||
|
||||
void LabelMap::DeleteLabel(const char *label)
|
||||
{
|
||||
for (std::vector<label_t>::iterator iter = labels.begin();
|
||||
iter != labels.end(); ++iter)
|
||||
{
|
||||
if (!strcmp(label, iter->name.c_str()))
|
||||
{
|
||||
labels.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelMap::GetLabelValue(const char *label, u16 *value, LabelType type) const
|
||||
{
|
||||
for (int i = 0; i < labels.size(); i++)
|
||||
{
|
||||
if (!strcmp(labels[i].name.c_str(), label))
|
||||
{
|
||||
if (type & labels[i].type) {
|
||||
*value = labels[i].addr;
|
||||
return true;
|
||||
} else {
|
||||
printf("WARNING: Wrong label type requested. %s\n", label);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LabelMap::Clear()
|
||||
{
|
||||
labels.clear();
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _LABELMAP_H
|
||||
#define _LABELMAP_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
enum LabelType
|
||||
{
|
||||
LABEL_IADDR = 1, // Jump addresses, etc
|
||||
LABEL_DADDR = 2, // Data addresses, etc
|
||||
LABEL_VALUE = 4,
|
||||
LABEL_ANY = 0xFF,
|
||||
};
|
||||
|
||||
class LabelMap
|
||||
{
|
||||
struct label_t
|
||||
{
|
||||
label_t(const char *lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
|
||||
std::string name;
|
||||
s32 addr;
|
||||
LabelType type;
|
||||
};
|
||||
std::vector<label_t> labels;
|
||||
|
||||
public:
|
||||
LabelMap();
|
||||
void RegisterDefaults();
|
||||
void RegisterLabel(const char *label, u16 lval, LabelType type = LABEL_VALUE);
|
||||
void DeleteLabel(const char *label);
|
||||
bool GetLabelValue(const char *label, u16 *value, LabelType type = LABEL_ANY) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
#endif // _LABELMAP_H
|
|
@ -115,12 +115,12 @@ bool DSPAssembler::Assemble(const char *text, std::vector<u16> *code, std::vecto
|
|||
return true;
|
||||
}
|
||||
|
||||
void DSPAssembler::parse_error(err_t err_code, const char *extra_info)
|
||||
void DSPAssembler::ShowError(err_t err_code, const char *extra_info)
|
||||
{
|
||||
failed = true;
|
||||
char error_buffer[1024];
|
||||
char *buf_ptr = error_buffer;
|
||||
buf_ptr += sprintf(buf_ptr, "%i : %s\n", code_line, cur_line);
|
||||
buf_ptr += sprintf(buf_ptr, "%i : %s", code_line, cur_line.c_str());
|
||||
if (!extra_info)
|
||||
extra_info = "-";
|
||||
if (fsrc)
|
||||
|
@ -151,18 +151,8 @@ const char *skip_spaces(const char *ptr)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
void DSPAssembler::gd_ass_register_label(const char *label, u16 lval)
|
||||
{
|
||||
labels.push_back(label_t(label, lval));
|
||||
}
|
||||
|
||||
void DSPAssembler::gd_ass_clear_labels()
|
||||
{
|
||||
labels.clear();
|
||||
}
|
||||
|
||||
// Parse a standalone value - it can be a number in one of several formats or a label.
|
||||
s32 DSPAssembler::strtoval(const char *str)
|
||||
s32 DSPAssembler::ParseValue(const char *str)
|
||||
{
|
||||
bool negative = false;
|
||||
s32 val = 0;
|
||||
|
@ -188,7 +178,7 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
if (ptr[i] >= '0' && ptr[i] <= '9')
|
||||
val += ptr[i] - '0';
|
||||
else
|
||||
parse_error(ERR_INCORRECT_DEC, str);
|
||||
ShowError(ERR_INCORRECT_DEC, str);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -206,7 +196,7 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
else if (ptr[i] >= '0' && ptr[i] <= '9')
|
||||
val += (ptr[i] - '0');
|
||||
else
|
||||
parse_error(ERR_INCORRECT_HEX, str);
|
||||
ShowError(ERR_INCORRECT_HEX, str);
|
||||
}
|
||||
break;
|
||||
case '\'': // binary
|
||||
|
@ -216,7 +206,7 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
if(ptr[i] >= '0' && ptr[i] <= '1')
|
||||
val += ptr[i] - '0';
|
||||
else
|
||||
parse_error(ERR_INCORRECT_BIN, str);
|
||||
ShowError(ERR_INCORRECT_BIN, str);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -237,19 +227,17 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
if (ptr[i] >= '0' && ptr[i] <= '9')
|
||||
val += ptr[i] - '0';
|
||||
else
|
||||
parse_error(ERR_INCORRECT_DEC, str);
|
||||
ShowError(ERR_INCORRECT_DEC, str);
|
||||
}
|
||||
}
|
||||
else // Everything else is a label.
|
||||
{
|
||||
// Lookup label
|
||||
for (int i = 0; i < labels.size(); i++)
|
||||
{
|
||||
if (strcmp(labels[i].label.c_str(), ptr) == 0)
|
||||
return labels[i].addr;
|
||||
}
|
||||
u16 value;
|
||||
if (labels.GetLabelValue(ptr, &value))
|
||||
return value;
|
||||
if (cur_pass == 2)
|
||||
parse_error(ERR_UNKNOWN_LABEL, str);
|
||||
ShowError(ERR_UNKNOWN_LABEL, str);
|
||||
}
|
||||
}
|
||||
if (negative)
|
||||
|
@ -257,10 +245,9 @@ s32 DSPAssembler::strtoval(const char *str)
|
|||
return val;
|
||||
}
|
||||
|
||||
|
||||
// Modifies both src and dst!
|
||||
// What does it do, really??
|
||||
char *DSPAssembler::find_brackets(char *src, char *dst)
|
||||
char *DSPAssembler::FindBrackets(char *src, char *dst)
|
||||
{
|
||||
s32 len = (s32) strlen(src);
|
||||
s32 first = -1;
|
||||
|
@ -302,12 +289,12 @@ char *DSPAssembler::find_brackets(char *src, char *dst)
|
|||
}
|
||||
}
|
||||
if (count)
|
||||
parse_error(ERR_NO_MATCHING_BRACKETS);
|
||||
ShowError(ERR_NO_MATCHING_BRACKETS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Bizarre in-place expression evaluator.
|
||||
u32 DSPAssembler::parse_exp(const char *ptr)
|
||||
u32 DSPAssembler::ParseExpression(const char *ptr)
|
||||
{
|
||||
char *pbuf;
|
||||
s32 val = 0;
|
||||
|
@ -316,9 +303,9 @@ u32 DSPAssembler::parse_exp(const char *ptr)
|
|||
char *s_buffer = (char *)malloc(1024);
|
||||
strcpy(s_buffer, ptr);
|
||||
|
||||
while ((pbuf = find_brackets(s_buffer, d_buffer)) != NULL)
|
||||
while ((pbuf = FindBrackets(s_buffer, d_buffer)) != NULL)
|
||||
{
|
||||
val = parse_exp(d_buffer);
|
||||
val = ParseExpression(d_buffer);
|
||||
sprintf(d_buffer, "%s%d%s", s_buffer, val, pbuf);
|
||||
strcpy(s_buffer, d_buffer);
|
||||
}
|
||||
|
@ -351,17 +338,18 @@ u32 DSPAssembler::parse_exp(const char *ptr)
|
|||
}
|
||||
d_buffer[i] = c;
|
||||
}
|
||||
|
||||
while ((pbuf = strstr(d_buffer, "+")) != NULL)
|
||||
{
|
||||
*pbuf = 0x0;
|
||||
val = parse_exp(d_buffer) + parse_exp(pbuf+1);
|
||||
val = ParseExpression(d_buffer) + ParseExpression(pbuf+1);
|
||||
sprintf(d_buffer, "%d", val);
|
||||
}
|
||||
|
||||
while ((pbuf = strstr(d_buffer, "-")) != NULL)
|
||||
{
|
||||
*pbuf = 0x0;
|
||||
val = parse_exp(d_buffer) - parse_exp(pbuf+1);
|
||||
val = ParseExpression(d_buffer) - ParseExpression(pbuf+1);
|
||||
if (val < 0)
|
||||
{
|
||||
val = 0x10000 + (val & 0xffff); // ATTENTION: avoid a terrible bug!!! number cannot write with '-' in sprintf
|
||||
|
@ -373,44 +361,39 @@ u32 DSPAssembler::parse_exp(const char *ptr)
|
|||
while ((pbuf = strstr(d_buffer, "*")) != NULL)
|
||||
{
|
||||
*pbuf = 0x0;
|
||||
val = parse_exp(d_buffer) * parse_exp(pbuf+1);
|
||||
val = ParseExpression(d_buffer) * ParseExpression(pbuf+1);
|
||||
sprintf(d_buffer, "%d", val);
|
||||
}
|
||||
|
||||
while ((pbuf = strstr(d_buffer, "/")) != NULL)
|
||||
{
|
||||
*pbuf = 0x0;
|
||||
val = parse_exp(d_buffer) / parse_exp(pbuf+1);
|
||||
val = ParseExpression(d_buffer) / ParseExpression(pbuf+1);
|
||||
sprintf(d_buffer, "%d", val);
|
||||
}
|
||||
|
||||
while ((pbuf = strstr(d_buffer, "|")) != NULL)
|
||||
{
|
||||
*pbuf = 0x0;
|
||||
val = parse_exp(d_buffer) | parse_exp(pbuf+1);
|
||||
val = ParseExpression(d_buffer) | ParseExpression(pbuf+1);
|
||||
sprintf(d_buffer, "%d", val);
|
||||
}
|
||||
|
||||
while ((pbuf = strstr(d_buffer, "&")) != NULL)
|
||||
{
|
||||
*pbuf = 0x0;
|
||||
val = parse_exp(d_buffer) & parse_exp(pbuf+1);
|
||||
val = ParseExpression(d_buffer) & ParseExpression(pbuf+1);
|
||||
sprintf(d_buffer, "%d", val);
|
||||
}
|
||||
|
||||
val = strtoval(d_buffer);
|
||||
val = ParseValue(d_buffer);
|
||||
free(d_buffer);
|
||||
free(s_buffer);
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 DSPAssembler::parse_exp_f(const char *ptr)
|
||||
{
|
||||
return parse_exp(ptr);
|
||||
}
|
||||
|
||||
// Destroys parstr
|
||||
u32 DSPAssembler::get_params(char *parstr, param_t *par)
|
||||
u32 DSPAssembler::GetParams(char *parstr, param_t *par)
|
||||
{
|
||||
u32 count = 0;
|
||||
char *tmpstr = skip_spaces(parstr);
|
||||
|
@ -435,27 +418,28 @@ u32 DSPAssembler::get_params(char *parstr, param_t *par)
|
|||
par[i].type = P_STR;
|
||||
break;
|
||||
case '#':
|
||||
par[i].val = parse_exp_f(tmpstr + 1);
|
||||
par[i].val = ParseExpression(tmpstr + 1);
|
||||
par[i].type = P_IMM;
|
||||
break;
|
||||
case '@':
|
||||
if (tmpstr[1] == '$')
|
||||
{
|
||||
par[i].val = parse_exp_f(tmpstr + 2);
|
||||
par[i].val = ParseExpression(tmpstr + 2);
|
||||
par[i].type = P_PRG;
|
||||
}
|
||||
else
|
||||
{
|
||||
par[i].val = parse_exp_f(tmpstr + 1);
|
||||
par[i].val = ParseExpression(tmpstr + 1);
|
||||
par[i].type = P_MEM;
|
||||
}
|
||||
break;
|
||||
case '$':
|
||||
par[i].val = parse_exp_f(tmpstr + 1);
|
||||
par[i].val = ParseExpression(tmpstr + 1);
|
||||
par[i].type = P_REG;
|
||||
break;
|
||||
|
||||
default:
|
||||
par[i].val = parse_exp_f(tmpstr);
|
||||
par[i].val = ParseExpression(tmpstr);
|
||||
par[i].type = P_VAL;
|
||||
break;
|
||||
}
|
||||
|
@ -464,7 +448,7 @@ u32 DSPAssembler::get_params(char *parstr, param_t *par)
|
|||
return count;
|
||||
}
|
||||
|
||||
const opc_t *DSPAssembler::find_opcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size)
|
||||
const opc_t *DSPAssembler::FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size)
|
||||
{
|
||||
if (opcode[0] == 'C' && opcode[1] == 'W')
|
||||
return &cw;
|
||||
|
@ -479,16 +463,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);
|
||||
ShowError(ERR_NOT_ENOUGH_PARAMETERS);
|
||||
}
|
||||
if (par_count > opc->param_count)
|
||||
{
|
||||
parse_error(ERR_TOO_MANY_PARAMETERS);
|
||||
ShowError(ERR_TOO_MANY_PARAMETERS);
|
||||
}
|
||||
return opc;
|
||||
}
|
||||
}
|
||||
parse_error(ERR_UNKNOWN_OPCODE);
|
||||
ShowError(ERR_UNKNOWN_OPCODE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -500,13 +484,20 @@ u16 get_mask_shifted_down(u16 mask)
|
|||
return mask;
|
||||
}
|
||||
|
||||
bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool ext)
|
||||
bool DSPAssembler::VerifyParams(const opc_t *opc, param_t *par, int count, bool ext)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
const int current_param = i + 1; // just for display.
|
||||
if (opc->params[i].type != par[i].type || (par[i].type & P_REG))
|
||||
{
|
||||
if (par[i].type == P_VAL &&
|
||||
(opc->params[i].type == P_ADDR_I || opc->params[i].type == P_ADDR_D))
|
||||
{
|
||||
// Data and instruction addresses are valid as VAL values.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((opc->params[i].type & P_REG) && (par[i].type & P_REG))
|
||||
{
|
||||
// Just a temp. Should be replaced with more purposeful vars.
|
||||
|
@ -524,7 +515,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
{
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
|
||||
parse_error(ERR_INVALID_REGISTER);
|
||||
ShowError(ERR_INVALID_REGISTER);
|
||||
}
|
||||
break;
|
||||
case P_PRG:
|
||||
|
@ -532,21 +523,24 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
{
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
|
||||
parse_error(ERR_INVALID_REGISTER);
|
||||
ShowError(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)
|
||||
if (par[i].val >= 0x1e && par[i].val <= 0x1f) {
|
||||
fprintf(stderr, "%i : %s", code_line, cur_line.c_str());
|
||||
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)
|
||||
}
|
||||
else if (par[i].val >= 0x1c && par[i].val <= 0x1d) {
|
||||
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);
|
||||
ShowError(ERR_WRONG_PARAMETER_ACC);
|
||||
}
|
||||
break;
|
||||
case P_ACCM:
|
||||
|
@ -560,7 +554,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
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);
|
||||
ShowError(ERR_WRONG_PARAMETER_ACC);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -580,39 +574,39 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
(par[i].val & 1), (par[i].val & 1), code_line, current_param);
|
||||
}
|
||||
else
|
||||
parse_error(ERR_WRONG_PARAMETER_ACC);
|
||||
ShowError(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);
|
||||
ShowError(ERR_WRONG_PARAMETER_MID_ACC);
|
||||
}
|
||||
break;*/
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (par[i].type & (P_REG | P_VAL | P_MEM | P_IMM))
|
||||
switch (par[i].type & (P_REG | 7))
|
||||
{
|
||||
case P_REG:
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_REG);
|
||||
ShowError(ERR_EXPECTED_PARAM_REG);
|
||||
break;
|
||||
case P_MEM:
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_MEM);
|
||||
ShowError(ERR_EXPECTED_PARAM_MEM);
|
||||
break;
|
||||
case P_VAL:
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_VAL);
|
||||
ShowError(ERR_EXPECTED_PARAM_VAL);
|
||||
break;
|
||||
case P_IMM:
|
||||
if (ext) fprintf(stderr, "(ext) ");
|
||||
parse_error(ERR_EXPECTED_PARAM_IMM);
|
||||
ShowError(ERR_EXPECTED_PARAM_IMM);
|
||||
break;
|
||||
}
|
||||
parse_error(ERR_WRONG_PARAMETER);
|
||||
ShowError(ERR_WRONG_PARAMETER);
|
||||
break;
|
||||
}
|
||||
else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0)
|
||||
|
@ -625,7 +619,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
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);
|
||||
ShowError(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
else if (opc->params[i].type == P_MEM)
|
||||
{
|
||||
|
@ -634,7 +628,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
else
|
||||
fprintf(stderr, "Address value must be from 0x0 to 0x%x\n", value);
|
||||
|
||||
parse_error(ERR_OUT_RANGE_NUMBER);
|
||||
ShowError(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
else if ((int)par[i].val < -((value >> 1) + 1))
|
||||
{
|
||||
|
@ -645,7 +639,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
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);
|
||||
ShowError(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -655,7 +649,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
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);
|
||||
ShowError(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
else if (opc->params[i].type == P_MEM)
|
||||
|
@ -669,7 +663,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
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);
|
||||
ShowError(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -682,7 +676,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
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);
|
||||
ShowError(ERR_OUT_RANGE_NUMBER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +689,7 @@ bool DSPAssembler::verify_params(const opc_t *opc, param_t *par, int count, bool
|
|||
|
||||
|
||||
// Merge opcode with params.
|
||||
void DSPAssembler::build_code(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf)
|
||||
void DSPAssembler::BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf)
|
||||
{
|
||||
outbuf[cur_addr] |= opc->opcode;
|
||||
for (u32 i = 0; i < par_count; i++)
|
||||
|
@ -721,15 +715,8 @@ void DSPAssembler::InitPass(int pass)
|
|||
if (pass == 1)
|
||||
{
|
||||
// Reset label table. Pre-populate with hw addresses and registers.
|
||||
gd_ass_clear_labels();
|
||||
for (int i = 0; i < 0x24; i++)
|
||||
{
|
||||
gd_ass_register_label(regnames[i].name, regnames[i].addr);
|
||||
}
|
||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||
{
|
||||
gd_ass_register_label(pdlabels[i].name, pdlabels[i].addr);
|
||||
}
|
||||
labels.Clear();
|
||||
labels.RegisterDefaults();
|
||||
aliases.clear();
|
||||
aliases["S15"] = "SET15";
|
||||
aliases["S16"] = "SET16";
|
||||
|
@ -875,9 +862,9 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
|||
}
|
||||
|
||||
if (paramstr)
|
||||
params_count = get_params(paramstr, params);
|
||||
params_count = GetParams(paramstr, params);
|
||||
if (paramstr_ext)
|
||||
params_count_ext = get_params(paramstr_ext, params_ext);
|
||||
params_count_ext = GetParams(paramstr_ext, params_ext);
|
||||
}
|
||||
|
||||
if (label)
|
||||
|
@ -893,7 +880,7 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
|||
}
|
||||
}
|
||||
if (pass == 1)
|
||||
gd_ass_register_label(label, lval);
|
||||
labels.RegisterLabel(label, lval);
|
||||
}
|
||||
|
||||
if (opcode == NULL)
|
||||
|
@ -919,7 +906,7 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
|||
free(tmpstr);
|
||||
}
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_STR);
|
||||
ShowError(ERR_EXPECTED_PARAM_STR);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -928,7 +915,7 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
|||
if (params[0].type == P_STR)
|
||||
include_dir = params[0].str;
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_STR);
|
||||
ShowError(ERR_EXPECTED_PARAM_STR);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -937,7 +924,7 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
|||
if (params[0].type == P_VAL)
|
||||
cur_addr = params[0].val;
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_VAL);
|
||||
ShowError(ERR_EXPECTED_PARAM_VAL);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -953,17 +940,17 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
|||
cur_addr = segment_addr[cur_segment];
|
||||
}
|
||||
else
|
||||
parse_error(ERR_EXPECTED_PARAM_STR);
|
||||
ShowError(ERR_EXPECTED_PARAM_STR);
|
||||
continue;
|
||||
}
|
||||
|
||||
const opc_t *opc = find_opcode(opcode, params_count, opcodes, opcodes_size);
|
||||
const opc_t *opc = FindOpcode(opcode, params_count, opcodes, opcodes_size);
|
||||
if (!opc)
|
||||
opc = &cw;
|
||||
|
||||
opcode_size = opc->size & ~P_EXT;
|
||||
|
||||
verify_params(opc, params, params_count);
|
||||
VerifyParams(opc, params, params_count);
|
||||
|
||||
const opc_t *opc_ext = NULL;
|
||||
// Check for opcode extensions.
|
||||
|
@ -971,27 +958,27 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
|||
{
|
||||
if (opcode_ext)
|
||||
{
|
||||
opc_ext = find_opcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size);
|
||||
verify_params(opc_ext, params_ext, params_count_ext, true);
|
||||
opc_ext = FindOpcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size);
|
||||
VerifyParams(opc_ext, params_ext, params_count_ext, true);
|
||||
}
|
||||
else if (params_count_ext)
|
||||
parse_error(ERR_EXT_PAR_NOT_EXT);
|
||||
ShowError(ERR_EXT_PAR_NOT_EXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (opcode_ext)
|
||||
parse_error(ERR_EXT_CANT_EXTEND_OPCODE);
|
||||
ShowError(ERR_EXT_CANT_EXTEND_OPCODE);
|
||||
if (params_count_ext)
|
||||
parse_error(ERR_EXT_PAR_NOT_EXT);
|
||||
ShowError(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);
|
||||
BuildCode(opc, params, params_count, (u16 *)gdg_buffer);
|
||||
if (opc_ext)
|
||||
build_code(opc_ext, params_ext, params_count_ext, (u16 *)gdg_buffer);
|
||||
BuildCode(opc_ext, params_ext, params_count_ext, (u16 *)gdg_buffer);
|
||||
}
|
||||
|
||||
cur_addr += opcode_size;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "Common.h"
|
||||
#include "disassemble.h"
|
||||
#include "DSPTables.h"
|
||||
#include "LabelMap.h"
|
||||
|
||||
enum err_t
|
||||
{
|
||||
|
@ -59,6 +60,7 @@ enum err_t
|
|||
ERR_OUT_RANGE_NUMBER
|
||||
};
|
||||
|
||||
|
||||
// Unless you want labels to carry over between files, you probably
|
||||
// want to create a new DSPAssembler for every file you assemble.
|
||||
class DSPAssembler
|
||||
|
@ -77,13 +79,6 @@ public:
|
|||
err_t GetError() const { return last_error; }
|
||||
|
||||
private:
|
||||
struct label_t
|
||||
{
|
||||
label_t(const char *lbl, s32 address) : label(lbl), addr(address) {}
|
||||
std::string label;
|
||||
s32 addr;
|
||||
};
|
||||
|
||||
struct param_t
|
||||
{
|
||||
u32 val;
|
||||
|
@ -99,31 +94,34 @@ private:
|
|||
SEGMENT_MAX
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
s32 ParseValue(const char *str);
|
||||
u32 ParseExpression(const char *ptr);
|
||||
|
||||
u32 GetParams(char *parstr, param_t *par);
|
||||
|
||||
void InitPass(int pass);
|
||||
bool AssembleFile(const char *fname, int pass);
|
||||
|
||||
void ShowError(err_t err_code, const char *extra_info = NULL);
|
||||
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
|
||||
|
||||
char *FindBrackets(char *src, char *dst);
|
||||
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
||||
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
|
||||
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
||||
|
||||
char *gdg_buffer;
|
||||
int gdg_buffer_size;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
std::string include_dir;
|
||||
std::vector<label_t> labels;
|
||||
std::string cur_line;
|
||||
|
||||
u32 cur_addr;
|
||||
u8 cur_pass;
|
||||
|
||||
LabelMap labels;
|
||||
|
||||
FILE *fsrc;
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
|
|
|
@ -82,15 +82,8 @@ bool DSPDisassembler::Disassemble(int start_pc, const std::vector<u16> &code, st
|
|||
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;
|
||||
// Run the two passes.
|
||||
return DisFile(tmp1, 1, text) && DisFile(tmp1, 2, text);
|
||||
}
|
||||
|
||||
char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char *strbuf)
|
||||
|
@ -101,31 +94,24 @@ char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, ch
|
|||
if (j > 0)
|
||||
buf += sprintf(buf, ", ");
|
||||
|
||||
u32 val;
|
||||
if (opc.params[j].loc >= 1)
|
||||
val = op2;
|
||||
else
|
||||
val = op1;
|
||||
|
||||
u32 val = (opc.params[j].loc >= 1) ? val = op2 : val = op1;
|
||||
val &= opc.params[j].mask;
|
||||
|
||||
if (opc.params[j].lshift < 0)
|
||||
val = val << (-opc.params[j].lshift);
|
||||
else
|
||||
val = val >> opc.params[j].lshift;
|
||||
|
||||
u32 type = opc.params[j].type;
|
||||
|
||||
if ((type & 0xff) == 0x10)
|
||||
type &= 0xff00;
|
||||
|
||||
if (type & P_REG)
|
||||
{
|
||||
// Check for _D parameter - if so flip.
|
||||
if (type == P_ACC_D) // Used to be P_ACCM_D TODO verify
|
||||
val = (~val & 0x1) | ((type & P_REGS_MASK) >> 8);
|
||||
else
|
||||
val |= (type & P_REGS_MASK) >> 8;
|
||||
|
||||
type &= ~P_REGS_MASK;
|
||||
}
|
||||
|
||||
|
@ -146,8 +132,12 @@ char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, ch
|
|||
break;
|
||||
|
||||
case P_VAL:
|
||||
case P_ADDR_I:
|
||||
case P_ADDR_D:
|
||||
if (settings_.decode_names)
|
||||
{
|
||||
sprintf(buf, "%s", pdname(val));
|
||||
}
|
||||
else
|
||||
sprintf(buf, "0x%04x", val);
|
||||
break;
|
||||
|
@ -156,17 +146,19 @@ char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, ch
|
|||
if (opc.params[j].size != 2)
|
||||
{
|
||||
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); // 6-bit sign extension
|
||||
else
|
||||
sprintf(buf, "#0x%02x", val);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf, "#0x%04x", val);
|
||||
}
|
||||
break;
|
||||
|
||||
case P_MEM:
|
||||
if (opc.params[j].size != 2)
|
||||
val = (u16)(s8)val;
|
||||
val = (u16)(s16)(s8)val;
|
||||
|
||||
if (settings_.decode_names)
|
||||
sprintf(buf, "@%s", pdname(val));
|
||||
|
@ -185,12 +177,22 @@ char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, ch
|
|||
return strbuf;
|
||||
}
|
||||
|
||||
void DSPDisassembler::DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest)
|
||||
static void MakeLowerCase(char *ptr)
|
||||
{
|
||||
int i = 0;
|
||||
while (ptr[i])
|
||||
{
|
||||
ptr[i] = tolower(ptr[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void DSPDisassembler::DisOpcode(const u16 *binbuf, int pass, u16 *pc, std::string *dest)
|
||||
{
|
||||
u32 op2;
|
||||
char buffer[256];
|
||||
char *buf = buffer;
|
||||
// Start with a space.
|
||||
|
||||
// Start with 8 spaces, if there's no label.
|
||||
buf[0] = ' ';
|
||||
buf[1] = '\0';
|
||||
buf++;
|
||||
|
@ -206,6 +208,7 @@ void DSPDisassembler::DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest)
|
|||
|
||||
const DSPOPCTemplate *opc = NULL;
|
||||
const DSPOPCTemplate *opc_ext = NULL;
|
||||
|
||||
// find opcode
|
||||
for (int j = 0; j < opcodes_size; j++)
|
||||
{
|
||||
|
@ -222,13 +225,12 @@ void DSPDisassembler::DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const DSPOPCTemplate fake_op = {"CW", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, NULL, NULL,};
|
||||
if (!opc)
|
||||
opc = &fake_op;
|
||||
|
||||
bool extended;
|
||||
if (opc->size & P_EXT && op1 & 0x00ff)
|
||||
if ((opc->size & P_EXT) && (op1 & 0x00ff))
|
||||
extended = true;
|
||||
else
|
||||
extended = false;
|
||||
|
@ -250,52 +252,52 @@ void DSPDisassembler::DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest)
|
|||
// printing
|
||||
|
||||
if (settings_.show_pc)
|
||||
sprintf(buf, "%04x ", *pc);
|
||||
buf += sprintf(buf, "%04x ", *pc);
|
||||
|
||||
buf += strlen(buf);
|
||||
u32 op2;
|
||||
|
||||
// Size 2 - the op has a large immediate.
|
||||
if ((opc->size & ~P_EXT) == 2)
|
||||
{
|
||||
op2 = binbuf[*pc + 1];
|
||||
if (settings_.show_hex)
|
||||
sprintf(buf, "%04x %04x ", op1, op2);
|
||||
buf += sprintf(buf, "%04x %04x ", op1, op2);
|
||||
}
|
||||
else
|
||||
{
|
||||
op2 = 0;
|
||||
|
||||
if (settings_.show_hex)
|
||||
sprintf(buf, "%04x ", op1);
|
||||
buf += sprintf(buf, "%04x ", op1);
|
||||
}
|
||||
|
||||
buf += strlen(buf);
|
||||
|
||||
char tmpbuf[20];
|
||||
|
||||
char opname[20];
|
||||
strcpy(opname, opc->name);
|
||||
if (settings_.lower_case_ops)
|
||||
MakeLowerCase(opname);
|
||||
char ext_buf[20];
|
||||
if (extended)
|
||||
sprintf(tmpbuf, "%s%c%s", opc->name, settings_.ext_separator, opc_ext->name);
|
||||
sprintf(ext_buf, "%s%c%s", opname, settings_.ext_separator, opc_ext->name);
|
||||
else
|
||||
sprintf(tmpbuf, "%s", opc->name);
|
||||
sprintf(ext_buf, "%s", opname);
|
||||
if (settings_.lower_case_ops)
|
||||
MakeLowerCase(ext_buf);
|
||||
|
||||
if (settings_.print_tabs)
|
||||
sprintf(buf, "%s\t", tmpbuf);
|
||||
buf += sprintf(buf, "%s\t", ext_buf);
|
||||
else
|
||||
sprintf(buf, "%-12s", tmpbuf);
|
||||
|
||||
buf += strlen(buf);
|
||||
buf += sprintf(buf, "%-12s", ext_buf);
|
||||
|
||||
if (opc->param_count > 0)
|
||||
DisParams(*opc, op1, op2, buf);
|
||||
|
||||
buf += strlen(buf);
|
||||
|
||||
// Handle opcode extension.
|
||||
if (extended)
|
||||
{
|
||||
if (opc->param_count > 0)
|
||||
buf += sprintf(buf, " ");
|
||||
|
||||
buf += sprintf(buf, ": ");
|
||||
|
||||
if (opc_ext->param_count > 0)
|
||||
DisParams(*opc_ext, op1, op2, buf);
|
||||
|
||||
|
@ -314,40 +316,33 @@ void DSPDisassembler::DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest)
|
|||
else
|
||||
*pc += opc->size & ~P_EXT;
|
||||
|
||||
if (pass == 2)
|
||||
dest->append(buffer);
|
||||
}
|
||||
|
||||
bool DSPDisassembler::DisFile(const char* name, FILE* output)
|
||||
bool DSPDisassembler::DisFile(const char* name, int pass, std::string *output)
|
||||
{
|
||||
FILE* in;
|
||||
u32 size;
|
||||
|
||||
in = fopen(name, "rb");
|
||||
if (in == NULL) {
|
||||
FILE* in = fopen(name, "rb");
|
||||
if (in == NULL)
|
||||
{
|
||||
printf("gd_dis_file: No input\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
size = (int)ftell(in) & ~1;
|
||||
int size = (int)ftell(in) & ~1;
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
u16 *binbuf = new u16[size / 2];
|
||||
fread(binbuf, 1, size, in);
|
||||
fclose(in);
|
||||
|
||||
// Actually do the disassembly.
|
||||
for (u16 pc = 0; pc < (size / 2);)
|
||||
{
|
||||
std::string str;
|
||||
DisOpcode(binbuf, &pc, &str);
|
||||
fprintf(output, "%s\n", str.c_str());
|
||||
DisOpcode(binbuf, pass, &pc, output);
|
||||
if (pass == 2)
|
||||
output->append("\n");
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
delete [] binbuf;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *gd_get_reg_name(u16 reg)
|
||||
{
|
||||
return regnames[reg].name;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "Common.h"
|
||||
#include "DSPTables.h"
|
||||
#include "LabelMap.h"
|
||||
|
||||
struct AssemblerSettings
|
||||
{
|
||||
|
@ -40,6 +41,7 @@ struct AssemblerSettings
|
|||
decode_names(true),
|
||||
decode_registers(true),
|
||||
ext_separator('\''),
|
||||
lower_case_ops(true),
|
||||
pc(0)
|
||||
{
|
||||
}
|
||||
|
@ -50,6 +52,7 @@ struct AssemblerSettings
|
|||
bool decode_names;
|
||||
bool decode_registers;
|
||||
char ext_separator;
|
||||
bool lower_case_ops;
|
||||
|
||||
u16 pc;
|
||||
};
|
||||
|
@ -63,19 +66,20 @@ public:
|
|||
bool Disassemble(int start_pc, const std::vector<u16> &code, std::string *text);
|
||||
|
||||
// Warning - this one is trickier to use right.
|
||||
void DisOpcode(const u16 *binbuf, u16 *pc, std::string *dest);
|
||||
// Use pass == 2 if you're just using it by itself.
|
||||
void DisOpcode(const u16 *binbuf, int pass, u16 *pc, std::string *dest);
|
||||
|
||||
private:
|
||||
// Moves PC forward and writes the result to dest.
|
||||
bool DisFile(const char* name, FILE *output);
|
||||
bool DisFile(const char* name, int pass, std::string *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);
|
||||
LabelMap labels;
|
||||
};
|
||||
|
||||
#endif // _DSP_DISASSEMBLE_H
|
||||
|
||||
|
|
|
@ -123,7 +123,9 @@ inline s64 dsp_get_long_prod()
|
|||
return val;
|
||||
}
|
||||
|
||||
|
||||
// For accurate emulation, this is wrong - it should take the two multiplicands
|
||||
// as input and set the two mid stages accordingly. most likely it's doing something
|
||||
// pretty simple.
|
||||
inline void dsp_set_long_prod(s64 val)
|
||||
{
|
||||
#if PROFILE
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "FileUtil.h"
|
||||
#include "DSPCodeUtil.h"
|
||||
|
||||
#include "dsp_test.h"
|
||||
|
||||
// Stub out the dsplib host stuff, since this is just a simple cmdline tools.
|
||||
u8 DSPHost_ReadHostMemory(u32 addr) { return 0; }
|
||||
bool DSPHost_OnThread() { return false; }
|
||||
|
@ -41,7 +43,11 @@ bool RoundTrip(const std::vector<u16> &code1)
|
|||
printf("RoundTrip: Assembly failed.\n");
|
||||
return false;
|
||||
}
|
||||
Compare(code1, code2);
|
||||
if (!Compare(code1, code2))
|
||||
{
|
||||
Disassemble(code1, true, &text);
|
||||
printf("%s", text.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -64,8 +70,8 @@ bool SuperTrip(const char *asm_code)
|
|||
}
|
||||
else
|
||||
{
|
||||
//printf("Disass:\n");
|
||||
//printf("%s", text.c_str());
|
||||
printf("Disass:\n");
|
||||
printf("%s", text.c_str());
|
||||
}
|
||||
if (!Assemble(text.c_str(), &code2))
|
||||
{
|
||||
|
@ -119,8 +125,47 @@ void RunAsmTests()
|
|||
//" 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.
|
||||
|
||||
// interesting test cases.
|
||||
/*
|
||||
std::vector<u16> hermes;
|
||||
if (!LoadBinary("testdata/hermes.bin", &hermes))
|
||||
PanicAlert("Failed to load hermes rom");
|
||||
RoundTrip(hermes);
|
||||
*/
|
||||
/*
|
||||
std::vector<u16> code;
|
||||
std::string text_orig;
|
||||
File::ReadFileToString(false, "testdata/dsp_test.S", &text_orig);
|
||||
if (!Assemble(text_orig.c_str(), &code))
|
||||
{
|
||||
printf("SuperTrip: First assembly failed\n");
|
||||
return;
|
||||
}*/
|
||||
|
||||
/*
|
||||
code.clear();
|
||||
for (int i = 0; i < sizeof(dsp_test)/4; i++)
|
||||
{
|
||||
code.push_back(dsp_test[i] >> 16);
|
||||
code.push_back(dsp_test[i] & 0xFFFF);
|
||||
}
|
||||
|
||||
SaveBinary(code, "dsp_test.bin");
|
||||
RoundTrip(code);*/
|
||||
//if (Compare(code, hermes))
|
||||
// printf("Successs\n");
|
||||
/*
|
||||
{
|
||||
std::vector<u16> code;
|
||||
std::string text;
|
||||
LoadBinary("testdata/dsp_test.bin", &code);
|
||||
Disassemble(code, true, &text);
|
||||
Assemble(text.c_str(), &code);
|
||||
Disassemble(code, true, &text);
|
||||
printf("%s", text.c_str());
|
||||
}*/
|
||||
/*
|
||||
puts("Insane Random Code Test\n");
|
||||
std::vector<u16> rand_code;
|
||||
GenRandomCode(30, &rand_code);
|
||||
|
@ -129,24 +174,102 @@ void RunAsmTests()
|
|||
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))
|
||||
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.
|
||||
*/
|
||||
|
||||
std::string dsp_test;
|
||||
if (File::ReadFileToString(true, "Testdata/dsp_test.s", &dsp_test))
|
||||
fail = fail || !SuperTrip(dsp_test.c_str());
|
||||
if (!fail)
|
||||
printf("All passed!\n");
|
||||
}
|
||||
|
||||
|
||||
// Usage:
|
||||
// Run internal tests:
|
||||
// dsptool test
|
||||
// Disassemble a file:
|
||||
// dsptool -d -o asdf.txt asdf.bin
|
||||
// Disassemble a file, output to standard output:
|
||||
// dsptool -d asdf.bin
|
||||
// Assemble a file:
|
||||
// dsptool -o asdf.bin asdf.txt
|
||||
// Assemble a file, output header:
|
||||
// dsptool -h asdf.h asdf.txt
|
||||
|
||||
// So far, all this binary can do is test partially that itself works correctly.
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
if (argc == 2 && !strcmp(argv[1], "test"))
|
||||
{
|
||||
RunAsmTests();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string input_name;
|
||||
std::string output_header_name;
|
||||
std::string output_name;
|
||||
|
||||
bool disassemble = false;
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "-d"))
|
||||
disassemble = true;
|
||||
else if (!strcmp(argv[i], "-o"))
|
||||
output_name = argv[++i];
|
||||
else if (!strcmp(argv[i], "-h"))
|
||||
output_header_name = argv[++i];
|
||||
else
|
||||
{
|
||||
if (!input_name.empty())
|
||||
{
|
||||
printf("Can only take one input file.\n");
|
||||
return 1;
|
||||
}
|
||||
input_name = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (disassemble)
|
||||
{
|
||||
if (input_name.empty())
|
||||
{
|
||||
printf("Must specify input.\n");
|
||||
return 1;
|
||||
}
|
||||
std::string binary_code;
|
||||
std::vector<u16> code;
|
||||
File::ReadFileToString(false, input_name.c_str(), &binary_code);
|
||||
BinaryStringBEToCode(binary_code, &code);
|
||||
std::string text;
|
||||
Disassemble(code, true, &text);
|
||||
File::WriteStringToFile(true, text, output_name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string source;
|
||||
if (File::ReadFileToString(true, input_name.c_str(), &source))
|
||||
{
|
||||
std::vector<u16> code;
|
||||
Assemble(source.c_str(), &code);
|
||||
if (!output_name.empty())
|
||||
{
|
||||
std::string binary_code;
|
||||
CodeToBinaryStringBE(code, &binary_code);
|
||||
File::WriteStringToFile(false, binary_code, output_name.c_str());
|
||||
}
|
||||
if (!output_header_name.empty())
|
||||
{
|
||||
std::string header;
|
||||
CodeToHeader(code, output_header_name.c_str(), &header);
|
||||
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,639 @@
|
|||
|
||||
DSCR: equ 0xffc9 ; DSP DMA Control Reg
|
||||
DSBL: equ 0xffcb ; DSP DMA Block Length
|
||||
DSPA: equ 0xffcd ; DSP DMA DMEM Address
|
||||
DSMAH: equ 0xffce ; DSP DMA Mem Address H
|
||||
DSMAL: equ 0xffcf ; DSP DMA Mem Address L
|
||||
|
||||
ACSAH: equ 0xffd4
|
||||
ACSAL: equ 0xffd5
|
||||
ACEAH: equ 0xffd6
|
||||
ACEAL: equ 0xffd7
|
||||
ACCAH: equ 0xffd8
|
||||
ACCAL: equ 0xffd9
|
||||
AMDM: equ 0xffef ; ARAM DMA Request Mask
|
||||
|
||||
DIRQ: equ 0xfffb ; DSP Irq Request
|
||||
DMBH: equ 0xfffc ; DSP Mailbox H
|
||||
DMBL: equ 0xfffd ; DSP Mailbox L
|
||||
CMBH: equ 0xfffe ; CPU Mailbox H
|
||||
CMBL: equ 0xffff ; CPU Mailbox L
|
||||
|
||||
R00: equ 0x00
|
||||
R01: equ 0x01
|
||||
R02: equ 0x02
|
||||
R03: equ 0x03
|
||||
R04: equ 0x04
|
||||
R05: equ 0x05
|
||||
R06: equ 0x06
|
||||
R07: equ 0x07
|
||||
R08: equ 0x08
|
||||
R09: equ 0x09
|
||||
R0A: equ 0x0a
|
||||
R0B: equ 0x0b
|
||||
R0C: equ 0x0c
|
||||
R0D: equ 0x0d
|
||||
R0E: equ 0x0e
|
||||
R0F: equ 0x0f
|
||||
R10: equ 0x10
|
||||
R11: equ 0x11
|
||||
R12: equ 0x12
|
||||
R13: equ 0x13
|
||||
R14: equ 0x14
|
||||
R15: equ 0x15
|
||||
R16: equ 0x16
|
||||
R17: equ 0x17
|
||||
R18: equ 0x18
|
||||
R19: equ 0x19
|
||||
R1A: equ 0x1a
|
||||
R1B: equ 0x1b
|
||||
R1C: equ 0x1c
|
||||
R1D: equ 0x1d
|
||||
R1E: equ 0x1e
|
||||
R1F: equ 0x1f
|
||||
|
||||
ACH0: equ 0x10
|
||||
ACH1: equ 0x11
|
||||
ACL0: equ 0x1e
|
||||
ACL1: equ 0x1f
|
||||
|
||||
DSP_CR_IMEM: equ 2
|
||||
DSP_CR_TO_CPU: equ 1
|
||||
|
||||
|
||||
REGS_BASE: equ 0x0f80
|
||||
MEM_HI: equ 0x0f7E
|
||||
MEM_LO: equ 0x0f7F
|
||||
|
||||
|
||||
; Interrupt vectors 8 vectors, 2 opcodes each
|
||||
|
||||
jmp irq0
|
||||
jmp irq1
|
||||
jmp irq2
|
||||
jmp irq3
|
||||
jmp irq4
|
||||
jmp irq5
|
||||
jmp irq6
|
||||
jmp irq7
|
||||
|
||||
; Main code at 0x10
|
||||
CW 0x1302
|
||||
CW 0x1303
|
||||
CW 0x1204
|
||||
CW 0x1305
|
||||
CW 0x1306
|
||||
|
||||
s40
|
||||
lri $r12, #0x00ff
|
||||
|
||||
main:
|
||||
|
||||
cw 0x8900
|
||||
cw 0x8100
|
||||
|
||||
; get address of memory dump and copy it
|
||||
|
||||
call wait_for_dsp_mbox
|
||||
si @DMBH, #0x8888
|
||||
si @DMBL, #0xdead
|
||||
si @DIRQ, #0x0001
|
||||
|
||||
call wait_for_cpu_mbox
|
||||
lrs $ACL0, @CMBL
|
||||
andi $acl1, #0x7fff
|
||||
|
||||
sr @MEM_HI, $ACL1
|
||||
sr @MEM_LO, $ACL0
|
||||
|
||||
lri $r18, #0
|
||||
lri $r19, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
|
||||
lri $r1a, #0x2000
|
||||
lr $r1c, @MEM_HI
|
||||
lr $r1e, @MEM_LO
|
||||
call do_dma
|
||||
|
||||
|
||||
; get address of registers and DMA them to memory
|
||||
|
||||
call wait_for_dsp_mbox
|
||||
si @DMBH, #0x8888
|
||||
si @DMBL, #0xbeef
|
||||
si @DIRQ, #0x0001
|
||||
|
||||
call wait_for_cpu_mbox
|
||||
lrs $ACL0, @CMBL
|
||||
andi $acl1, #0x7fff
|
||||
|
||||
sr @MEM_HI, $ACL1
|
||||
sr @MEM_LO, $ACL0
|
||||
|
||||
lri $r18, #REGS_BASE
|
||||
lri $r19, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
|
||||
lri $r1a, #0x80
|
||||
lr $r1c, @MEM_HI
|
||||
lr $r1e, @MEM_LO
|
||||
call do_dma
|
||||
|
||||
|
||||
|
||||
lri $r00, #REGS_BASE+1
|
||||
lrri $r01, @$r00
|
||||
lrri $r02, @$r00
|
||||
lrri $r03, @$r00
|
||||
lrri $r04, @$r00
|
||||
lrri $r05, @$r00
|
||||
lrri $r06, @$r00
|
||||
lrri $r07, @$r00
|
||||
lrri $r08, @$r00
|
||||
lrri $r09, @$r00
|
||||
lrri $r0a, @$r00
|
||||
lrri $r0b, @$r00
|
||||
lrri $r0c, @$r00
|
||||
lrri $r0d, @$r00
|
||||
lrri $r0e, @$r00
|
||||
lrri $r0f, @$r00
|
||||
lrri $r10, @$r00
|
||||
lrri $r11, @$r00
|
||||
lrri $r12, @$r00
|
||||
lrri $r13, @$r00
|
||||
lrri $r14, @$r00
|
||||
lrri $r15, @$r00
|
||||
lrri $r16, @$r00
|
||||
lrri $r17, @$r00
|
||||
lrri $r18, @$r00
|
||||
lrri $r19, @$r00
|
||||
lrri $r1a, @$r00
|
||||
lrri $r1b, @$r00
|
||||
lrri $r1c, @$r00
|
||||
lrri $r1d, @$r00
|
||||
lrri $r1e, @$r00
|
||||
lrri $r1f, @$r00
|
||||
lr $r00, @REGS_BASE
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
|
||||
|
||||
|
||||
cw 0x8600
|
||||
|
||||
call send_back
|
||||
|
||||
JMP ende
|
||||
|
||||
|
||||
; call dump_memory
|
||||
; call send_back
|
||||
|
||||
|
||||
; 0x041e
|
||||
;
|
||||
|
||||
cw 0x00de
|
||||
cw 0x03f1
|
||||
call send_back
|
||||
|
||||
cw 0x0200
|
||||
cw 0x0a60
|
||||
call send_back
|
||||
|
||||
cw 0x1c7e
|
||||
call send_back
|
||||
|
||||
cw 0x8100
|
||||
call send_back
|
||||
|
||||
cw 0x8900
|
||||
call send_back
|
||||
|
||||
cw 0x009f
|
||||
cw 0x00a0
|
||||
call send_back
|
||||
|
||||
cw 0x00de
|
||||
cw 0x03f1
|
||||
call send_back
|
||||
|
||||
cw 0x5d00
|
||||
call send_back
|
||||
|
||||
cw 0x0e50
|
||||
call send_back
|
||||
|
||||
cw 0x0750
|
||||
call send_back
|
||||
|
||||
cw 0x0270
|
||||
call send_back
|
||||
|
||||
cw 0x5d00
|
||||
call send_back
|
||||
|
||||
cw 0x00da
|
||||
cw 0x03f2
|
||||
call send_back
|
||||
|
||||
cw 0x8600
|
||||
call send_back
|
||||
|
||||
JNS g_0c4d
|
||||
; cw 0x0290
|
||||
; cw 0x0c4d
|
||||
; call send_back JX0
|
||||
|
||||
cw 0x00de
|
||||
cw 0x03f3
|
||||
call send_back
|
||||
|
||||
cw 0x5c00
|
||||
call send_back
|
||||
|
||||
JLE g_0c38
|
||||
; cw 0x0293
|
||||
; cw 0x0c38 JX3
|
||||
; call send_back
|
||||
|
||||
JMP g_0c52
|
||||
|
||||
; cw 0x029f
|
||||
; cw 0x0c52
|
||||
; call send_back
|
||||
|
||||
g_0c38:
|
||||
cw 0x00db
|
||||
cw 0x03f7
|
||||
call send_back
|
||||
|
||||
cw 0x009e
|
||||
cw 0x8000
|
||||
call send_back
|
||||
|
||||
cw 0x4600
|
||||
call send_back
|
||||
|
||||
JMP g_0c44
|
||||
; cw 0x029f
|
||||
; cw 0x0c44
|
||||
; call send_back
|
||||
|
||||
g_0c3f:
|
||||
cw 0x00db
|
||||
cw 0x03f7
|
||||
call send_back
|
||||
|
||||
cw 0x009e
|
||||
cw 0x8000
|
||||
call send_back
|
||||
|
||||
cw 0x5600
|
||||
call send_back
|
||||
|
||||
g_0c44:
|
||||
cw 0x00fe
|
||||
cw 0x03f5
|
||||
call send_back
|
||||
|
||||
cw 0x1fda
|
||||
call send_back
|
||||
|
||||
cw 0x7c00
|
||||
call send_back
|
||||
|
||||
cw 0x1f5e
|
||||
call send_back
|
||||
|
||||
cw 0x00fe
|
||||
cw 0x03f2
|
||||
call send_back
|
||||
|
||||
JMP g_0c52
|
||||
; cw 0x029f
|
||||
; cw 0x0c52
|
||||
; call send_back
|
||||
|
||||
g_0c4d:
|
||||
|
||||
cw 0x00de
|
||||
cw 0x03f4
|
||||
call send_back
|
||||
|
||||
cw 0x5d00
|
||||
call send_back
|
||||
|
||||
JLE g_0c3f
|
||||
; cw 0x0293
|
||||
; cw 0x0c3f
|
||||
; call send_back
|
||||
|
||||
g_0c52:
|
||||
cw 0x8900
|
||||
call send_back
|
||||
|
||||
cw 0x00dd
|
||||
cw 0x03f5
|
||||
call send_back
|
||||
|
||||
cw 0x1501
|
||||
call send_back
|
||||
|
||||
cw 0x8100
|
||||
call send_back
|
||||
|
||||
cw 0x00dc
|
||||
cw 0x03f6
|
||||
call send_back
|
||||
|
||||
cw 0x008b
|
||||
cw 0x009f
|
||||
call send_back
|
||||
|
||||
cw 0x0080
|
||||
cw 0x0a00
|
||||
call send_back
|
||||
|
||||
cw 0x0900
|
||||
call send_back
|
||||
|
||||
BLOOPI #0x50, g_0c65
|
||||
; cw 0x1150
|
||||
; cw 0x0c65
|
||||
; call send_back
|
||||
|
||||
|
||||
cw 0x1878
|
||||
call send_back
|
||||
|
||||
cw 0x4c00
|
||||
call send_back
|
||||
|
||||
cw 0x1cfe
|
||||
call send_back
|
||||
|
||||
cw 0x001f
|
||||
call send_back
|
||||
|
||||
cw 0x1fd9
|
||||
call send_back
|
||||
g_0c65:
|
||||
cw 0x1b18
|
||||
call send_back
|
||||
|
||||
cw 0x009f
|
||||
cw 0x0a60
|
||||
call send_back
|
||||
|
||||
cw 0x1fc3
|
||||
call send_back
|
||||
|
||||
cw 0x5c00
|
||||
call send_back
|
||||
|
||||
cw 0x00fe
|
||||
cw 0x03f1
|
||||
call send_back
|
||||
|
||||
cw 0x00fc
|
||||
cw 0x03f6
|
||||
call send_back
|
||||
|
||||
cw 0x008b
|
||||
cw 0xffff
|
||||
call send_back
|
||||
|
||||
|
||||
|
||||
ende:
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
|
||||
|
||||
dead_loop:
|
||||
jmp dead_loop
|
||||
|
||||
do_dma:
|
||||
sr @DSMAH, $r1c
|
||||
sr @DSMAL, $r1e
|
||||
sr @DSPA, $r18
|
||||
sr @DSCR, $r19
|
||||
sr @DSBL, $r1a
|
||||
wait_dma:
|
||||
LRS $ACL1, @DSCR
|
||||
andf $acl1, #0x0004
|
||||
JNZ wait_dma
|
||||
RET
|
||||
|
||||
|
||||
wait_for_dsp_mbox:
|
||||
lrs $ACL1, @DMBH
|
||||
andf $acl1, #0x8000
|
||||
jnz wait_for_dsp_mbox
|
||||
ret
|
||||
|
||||
wait_for_cpu_mbox:
|
||||
lrs $ACL1, @cmbh
|
||||
andcf $acl1, #0x8000
|
||||
jlnz wait_for_cpu_mbox
|
||||
ret
|
||||
|
||||
irq0:
|
||||
lri $acl0, #0x0000
|
||||
jmp irq
|
||||
irq1:
|
||||
lri $acl0, #0x0001
|
||||
jmp irq
|
||||
irq2:
|
||||
lri $acl0, #0x0002
|
||||
jmp irq
|
||||
|
||||
irq3:
|
||||
lri $acl0, #0x0003
|
||||
jmp irq
|
||||
irq4:
|
||||
lri $acl0, #0x0004
|
||||
jmp irq
|
||||
irq5:
|
||||
; jmp finale
|
||||
s40
|
||||
mrr $r0d, $r1c
|
||||
mrr $r0d, $r1e
|
||||
clr $acc0
|
||||
mrr $r1e, $r0d
|
||||
mrr $r1c, $r0d
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rti
|
||||
|
||||
lri $acl0, #0x0005
|
||||
jmp irq
|
||||
irq6:
|
||||
lri $acl0, #0x0006
|
||||
jmp irq
|
||||
irq7:
|
||||
lri $acl0, #0x0007
|
||||
jmp irq
|
||||
|
||||
irq:
|
||||
lrs $ACL1, @DMBH
|
||||
andf $acl1, #0x8000
|
||||
jnz irq
|
||||
si @DMBH, #0x8BAD
|
||||
sr @DMBL, $r0b
|
||||
;sr @DMBL, $acl0
|
||||
si @DIRQ, #0x0001
|
||||
halt
|
||||
|
||||
|
||||
|
||||
|
||||
send_back:
|
||||
|
||||
; store registers to reg table
|
||||
sr @REGS_BASE, $r00
|
||||
lri $r00, #(REGS_BASE + 1)
|
||||
srri @$r00, $r01
|
||||
srri @$r00, $r02
|
||||
srri @$r00, $r03
|
||||
srri @$r00, $r04
|
||||
srri @$r00, $r05
|
||||
srri @$r00, $r06
|
||||
srri @$r00, $r07
|
||||
srri @$r00, $r08
|
||||
srri @$r00, $r09
|
||||
srri @$r00, $r0a
|
||||
srri @$r00, $r0b
|
||||
srri @$r00, $r0c
|
||||
srri @$r00, $r0d
|
||||
srri @$r00, $r0e
|
||||
srri @$r00, $r0f
|
||||
srri @$r00, $r10
|
||||
srri @$r00, $r11
|
||||
srri @$r00, $r12
|
||||
srri @$r00, $r13
|
||||
srri @$r00, $r14
|
||||
srri @$r00, $r15
|
||||
srri @$r00, $r16
|
||||
srri @$r00, $r17
|
||||
srri @$r00, $r18
|
||||
srri @$r00, $r19
|
||||
srri @$r00, $r1a
|
||||
srri @$r00, $r1b
|
||||
srri @$r00, $r1c
|
||||
srri @$r00, $r1d
|
||||
srri @$r00, $r1e
|
||||
srri @$r00, $r1f
|
||||
|
||||
|
||||
lri $r18, #0x0000
|
||||
lri $r19, #1 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
|
||||
lri $r1a, #0x200
|
||||
lr $r1c, @MEM_HI
|
||||
lr $r1e, @MEM_LO
|
||||
|
||||
lri $r01, #8+8
|
||||
|
||||
bloop $r01, dma_copy
|
||||
call do_dma
|
||||
addi $r1e, #0x200
|
||||
mrr $r1f, $r18
|
||||
addi $r1f, #0x100
|
||||
mrr $r18, $r1f
|
||||
nop
|
||||
dma_copy:
|
||||
nop
|
||||
|
||||
call wait_for_dsp_mbox
|
||||
si @DMBH, #0x8888
|
||||
si @DMBL, #0xfeeb
|
||||
si @DIRQ, #0x0001
|
||||
|
||||
; wait for answer before we execute the next op
|
||||
call wait_for_cpu_mbox
|
||||
lrs $ACL0, @CMBL
|
||||
andi $acl1, #0x7fff
|
||||
|
||||
|
||||
|
||||
lri $r00, #REGS_BASE+1
|
||||
lrri $r01, @$r00
|
||||
lrri $r02, @$r00
|
||||
lrri $r03, @$r00
|
||||
lrri $r04, @$r00
|
||||
lrri $r05, @$r00
|
||||
lrri $r06, @$r00
|
||||
lrri $r07, @$r00
|
||||
lrri $r08, @$r00
|
||||
lrri $r09, @$r00
|
||||
lrri $r0a, @$r00
|
||||
lrri $r0b, @$r00
|
||||
lrri $r0c, @$r00
|
||||
lrri $r0d, @$r00
|
||||
lrri $r0e, @$r00
|
||||
lrri $r0f, @$r00
|
||||
lrri $r10, @$r00
|
||||
lrri $r11, @$r00
|
||||
lrri $r12, @$r00
|
||||
lrri $r13, @$r00
|
||||
lrri $r14, @$r00
|
||||
lrri $r15, @$r00
|
||||
lrri $r16, @$r00
|
||||
lrri $r17, @$r00
|
||||
lrri $r18, @$r00
|
||||
lrri $r19, @$r00
|
||||
lrri $r1a, @$r00
|
||||
lrri $r1b, @$r00
|
||||
lrri $r1c, @$r00
|
||||
lrri $r1d, @$r00
|
||||
lrri $r1e, @$r00
|
||||
lrri $r1f, @$r00
|
||||
lr $r00, @REGS_BASE
|
||||
|
||||
ret
|
||||
|
||||
send_back_16:
|
||||
|
||||
cw 0x8e00
|
||||
call send_back
|
||||
cw 0x8f00
|
||||
|
||||
ret
|
||||
|
||||
|
||||
dump_memory:
|
||||
|
||||
lri $r02, #0x0000
|
||||
lri $acl0, #0x1000
|
||||
|
||||
lri $r01, #0x1000
|
||||
bloop $r01, _fill_loop2
|
||||
|
||||
mrr $r03, $acl0
|
||||
cw 0x80f0
|
||||
|
||||
mrr $r1f, $r00
|
||||
mrr $r00, $r02
|
||||
srri @$r00, $r1b
|
||||
mrr $r02, $r00
|
||||
mrr $r00, $r1f
|
||||
|
||||
addis $acc0, #0x1
|
||||
|
||||
_fill_loop2:
|
||||
nop
|
||||
|
||||
|
||||
ret
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,7 @@ wxString CRegTable::GetValue(int row, int col)
|
|||
{
|
||||
switch (col)
|
||||
{
|
||||
case 0: return wxString::FromAscii(gd_get_reg_name(row));
|
||||
case 0: return wxString::FromAscii(pdregname(row));
|
||||
case 1: return wxString::Format(wxT("0x%04x"), g_dsp.r[row]);
|
||||
default: return wxString::FromAscii("");
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ void DSPDebuggerLLE::RebuildDisAsmListView()
|
|||
AssemblerSettings settings;
|
||||
DSPDisassembler disasm(settings);
|
||||
std::string op_str;
|
||||
disasm.DisOpcode(binbuf, &settings.pc, &op_str);
|
||||
disasm.DisOpcode(binbuf, 2, &settings.pc, &op_str);
|
||||
const char* pParameter = NULL;
|
||||
const char* pExtension = NULL;
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ bool DumpDSPCode(const u8 *code_be, int size_in_bytes, u32 crc)
|
|||
AssemblerSettings settings;
|
||||
settings.show_hex = true;
|
||||
settings.show_pc = true;
|
||||
settings.ext_separator = '\t';
|
||||
settings.ext_separator = '\'';
|
||||
settings.decode_names = true;
|
||||
settings.decode_registers = true;
|
||||
|
||||
|
|
Loading…
Reference in New Issue