DSP: Further disasm improvements. Make a few mul ops (only two of which I have seen, both in Zelda) behave like Duddie's doc says they should.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2941 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-04-09 14:33:34 +00:00
parent 0f26228ef2
commit 5166251b2c
6 changed files with 55 additions and 34 deletions

View File

@ -589,14 +589,21 @@ void mulc(const UDSPInstruction& opc)
Update_SR_Register64(prod); Update_SR_Register64(prod);
} }
// MULCMVZ
// 110s t01r xxxx xxxx
// (fixed possible bug in duddie's description, s->t)
// Multiply mid part of accumulator register $acS.m by high part $axT.h of
// secondary accumulator $axT (treat them both as signed). Move product
// register before multiplication to accumulator $acR, set low part of
// accumulator $acR.l to zero.
void mulcmvz(const UDSPInstruction& opc) void mulcmvz(const UDSPInstruction& opc)
{ {
s64 TempProd = dsp_get_long_prod(); s64 TempProd = dsp_get_long_prod();
// update prod // update prod
u8 sreg = (opc.hex >> 12) & 0x1; u8 sreg = (opc.hex >> 12) & 0x1;
s64 Prod = (s64)dsp_get_acc_m(sreg) * (s64)dsp_get_acc_h(sreg) * GetMultiplyModifier(); u8 treg = (opc.hex >> 11) & 0x1;
s64 Prod = (s64)dsp_get_acc_m(sreg) * (s64)dsp_get_ax_h(treg) * GetMultiplyModifier();
dsp_set_long_prod(Prod); dsp_set_long_prod(Prod);
// update acc // update acc
@ -607,13 +614,19 @@ void mulcmvz(const UDSPInstruction& opc)
Update_SR_Register64(acc); Update_SR_Register64(acc);
} }
// MULCMV
// 110s t11r xxxx xxxx
// Multiply mid part of accumulator register $acS.m by high part $axS.h of
// secondary accumulator $axT (treat them both as signed). Move product
// register before multiplication to accumulator $acR.
void mulcmv(const UDSPInstruction& opc) void mulcmv(const UDSPInstruction& opc)
{ {
s64 TempProd = dsp_get_long_prod(); s64 TempProd = dsp_get_long_prod();
// update prod // update prod
u8 sreg = (opc.hex >> 12) & 0x1; u8 sreg = (opc.hex >> 12) & 0x1;
s64 Prod = (s64)dsp_get_acc_m(sreg) * (s64)dsp_get_acc_h(sreg) * GetMultiplyModifier(); u8 treg = (opc.hex >> 11) & 0x1;
s64 Prod = (s64)dsp_get_acc_m(sreg) * (s64)dsp_get_ax_h(sreg) * GetMultiplyModifier();
dsp_set_long_prod(Prod); dsp_set_long_prod(Prod);
// update acc // update acc
@ -623,6 +636,8 @@ void mulcmv(const UDSPInstruction& opc)
Update_SR_Register64(TempProd); Update_SR_Register64(TempProd);
} }
// CMPAR
// Not described by Duddie's doc - at least not as a separate instruction.
void cmpar(const UDSPInstruction& opc) void cmpar(const UDSPInstruction& opc)
{ {
u8 rreg = ((opc.hex >> 12) & 0x1) + 0x1a; u8 rreg = ((opc.hex >> 12) & 0x1) + 0x1a;
@ -637,6 +652,9 @@ void cmpar(const UDSPInstruction& opc)
Update_SR_Register64(ar - rr); Update_SR_Register64(ar - rr);
} }
// CMP
// 1000 0010 xxxx xxxx
// Compares accumulator $ac0 with accumulator $ac1.
void cmp(const UDSPInstruction& opc) void cmp(const UDSPInstruction& opc)
{ {
s64 acc0 = dsp_get_long_acc(0); s64 acc0 = dsp_get_long_acc(0);
@ -645,6 +663,9 @@ void cmp(const UDSPInstruction& opc)
Update_SR_Register64(acc0 - acc1); Update_SR_Register64(acc0 - acc1);
} }
// TST
// 1011 r001 xxxx xxxx
// Test accumulator %acR.
void tst(const UDSPInstruction& opc) void tst(const UDSPInstruction& opc)
{ {
tsta((opc.hex >> 11) & 0x1); tsta((opc.hex >> 11) & 0x1);
@ -679,18 +700,24 @@ void addarn(const UDSPInstruction& opc)
g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg]; g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
} }
// MULCAC $acS.m, $axT.h, $acR
// 110s t10r xxxx xxxx
// Multiply mid part of accumulator register $acS.m by high part $axS.h of
// secondary accumulator $axS (treat them both as signed). Add product
// register before multiplication to accumulator $acR.
void mulcac(const UDSPInstruction& opc) void mulcac(const UDSPInstruction& opc)
{ {
s64 TempProd = dsp_get_long_prod(); s64 TempProd = dsp_get_long_prod();
// update prod // update prod
u8 sreg = (opc.hex >> 12) & 0x1; u8 sreg = (opc.hex >> 12) & 0x1;
s64 Prod = (s64)dsp_get_acc_m(sreg) * (s64)dsp_get_acc_h(sreg) * GetMultiplyModifier(); u8 treg = (opc.hex >> 11) & 0x1;
s64 Prod = (s64)dsp_get_acc_m(sreg) * (s64)dsp_get_ax_h(treg) * GetMultiplyModifier();
dsp_set_long_prod(Prod); dsp_set_long_prod(Prod);
// update acc // update acc
u8 rreg = (opc.hex >> 8) & 0x1; u8 rreg = (opc.hex >> 8) & 0x1;
s64 acc = TempProd + g_dsp.r[rreg]; s64 acc = TempProd + dsp_get_long_acc(rreg);
dsp_set_long_acc(rreg, acc); dsp_set_long_acc(rreg, acc);
Update_SR_Register64(acc); Update_SR_Register64(acc);

View File

@ -275,17 +275,15 @@ DSPOPCTemplate opcodes[] =
{"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}, {"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}, {"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},
{"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}, {"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}, {"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}, {"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}, {"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},
{"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},
{"MULC", 0xc000, 0xe7ff, DSPInterpreter::mulc, nop, 1 | P_EXT, 2, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}}, 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},
{"MULCMVZ", 0xc200, 0xe6ff, DSPInterpreter::mulcmvz, nop, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {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},
{"MULCAC", 0xc400, 0xe6ff, DSPInterpreter::mulcac, nop, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {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},
{"MULCMV", 0xc600, 0xe6ff, DSPInterpreter::mulcmv, nop, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 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_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, {"ADDR", 0x4000, 0xf8ff, DSPInterpreter::addr, nop, 1 | P_EXT, 2, {{P_ACCM, 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_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, {"ADDAX", 0x4800, 0xfcff, DSPInterpreter::addax, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},

View File

@ -61,6 +61,12 @@ bool DisasmUCodeDump(u32 crc)
if (t != NULL) if (t != NULL)
{ {
gd_globals_t gdg; 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;
gd_dis_file(&gdg, binFile, t); gd_dis_file(&gdg, binFile, t);
fclose(t); fclose(t);
return true; return true;
@ -88,7 +94,7 @@ u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength)
CRC = (CRC >> 8) ^ Temp; CRC = (CRC >> 8) ^ Temp;
} }
return(CRC ^ 0xFFFFFFFF); return CRC ^ 0xFFFFFFFF;
} }
// TODO make this useful :p // TODO make this useful :p

View File

@ -96,14 +96,14 @@ const pdlabel_t pdlabels[] =
pdlabel_t regnames[] = pdlabel_t regnames[] =
{ {
{0x00, "R00", "Register 00",}, {0x00, "AR0", "Register 00",},
{0x01, "R01", "Register 01",}, {0x01, "AR1", "Register 01",},
{0x02, "R02", "Register 02",}, {0x02, "AR2", "Register 02",},
{0x03, "R03", "Register 03",}, {0x03, "AR3", "Register 03",},
{0x04, "R04", "Register 04",}, {0x04, "IX0", "Register 04",},
{0x05, "R05", "Register 05",}, {0x05, "IX1", "Register 05",},
{0x06, "R06", "Register 06",}, {0x06, "IX2", "Register 06",},
{0x07, "R07", "Register 07",}, {0x07, "IX3", "Register 07",},
{0x08, "R08", "Register 08",}, {0x08, "R08", "Register 08",},
{0x09, "R09", "Register 09",}, {0x09, "R09", "Register 09",},
{0x0a, "R10", "Register 10",}, {0x0a, "R10", "Register 10",},
@ -112,8 +112,8 @@ pdlabel_t regnames[] =
{0x0d, "ST1", "Data stack",}, {0x0d, "ST1", "Data stack",},
{0x0e, "ST2", "Loop addr stack",}, {0x0e, "ST2", "Loop addr stack",},
{0x0f, "ST3", "Loop counter",}, {0x0f, "ST3", "Loop counter",},
{0x00, "ACH0", "Accu High 0",}, {0x00, "AC0.H", "Accu High 0",},
{0x11, "ACH1", "Accu High 1",}, {0x11, "AC1.H", "Accu High 1",},
{0x12, "CR", "Config Register",}, {0x12, "CR", "Config Register",},
{0x13, "SR", "Special Register",}, {0x13, "SR", "Special Register",},
{0x14, "PROD.L", "Prod L",}, {0x14, "PROD.L", "Prod L",},
@ -250,15 +250,6 @@ char* gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* opc, u16 op1, u16 o
return strbuf; return strbuf;
} }
gd_globals_t* gd_init()
{
gd_globals_t* gdg = (gd_globals_t*)malloc(sizeof(gd_globals_t));
memset(gdg, 0, sizeof(gd_globals_t));
return(gdg);
}
u16 gd_dis_get_opcode_size(gd_globals_t* gdg) u16 gd_dis_get_opcode_size(gd_globals_t* gdg)
{ {
DSPOPCTemplate* opc = 0; DSPOPCTemplate* opc = 0;

View File

@ -27,7 +27,7 @@
#include "Common.h" #include "Common.h"
typedef struct gd_globals_t struct gd_globals_t
{ {
bool print_tabs; bool print_tabs;
bool show_hex; bool show_hex;
@ -40,7 +40,7 @@ typedef struct gd_globals_t
char* buffer; char* buffer;
u16 buffer_size; u16 buffer_size;
char ext_separator; char ext_separator;
} gd_globals_t; };
char* gd_dis_opcode(gd_globals_t* gdg); char* gd_dis_opcode(gd_globals_t* gdg);

View File

@ -371,4 +371,3 @@ void gdsp_stop()
{ {
gdsp_running = false; gdsp_running = false;
} }