DSPLLE stuff - no real progress, mostly useful as a reference for HLE improvement, Pikmin 1 has sound in intro though (can't be sure if its ok, because its too slow)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4496 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Marko Pusljar 2009-11-04 12:49:26 +00:00
parent 099b89d9e9
commit 10fb287311
7 changed files with 177 additions and 131 deletions

View File

@ -67,17 +67,30 @@ s16 ADPCM_Step(u32& _rSamplePos)
u16 dsp_read_aram_d3()
{
// Zelda ucode reads ARAM through 0xffd3.
const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
u8 value = 0;
u16 val = 0;
switch (gdsp_ifx_regs[DSP_FORMAT]) {
case 0x5: // unsigned 8-bit reads .. I think.
value = DSPHost_ReadHostMemory(Address);
val = DSPHost_ReadHostMemory(Address);
Address++;
break;
case 0x6: // unsigned 16-bit reads .. I think.
val = (DSPHost_ReadHostMemory(Address) << 8) | DSPHost_ReadHostMemory(Address + 1);
Address += 2;
break;
default:
ERROR_LOG(DSPLLE, "dsp_read_aram_d3: Unseen Format %i", gdsp_ifx_regs[DSP_FORMAT]);
break;
}
return value;
if (Address >= EndAddress)
{
// Set address back to start address.
Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
}
gdsp_ifx_regs[DSP_ACCAH] = Address >> 16;
gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff;
return val;
}
void dsp_write_aram_d3(u16 value)

View File

@ -91,8 +91,11 @@ void Step()
ProfilerDump(g_dsp.step_counter);
}
#endif
// if (g_dsp.pc >= 0x0272 && g_dsp.pc <= 0x0282)
// printf("pc %04x acc0 %04x acc1 %04x\n", g_dsp.pc, dsp_get_acc_m(0), dsp_get_acc_m(1));
/*
//Pikmin GC (US)
if (g_dsp.pc == 0x0506)
NOTICE_LOG(DSPLLE,"-> FORMAT JUMPTABLE --> pc:=%04x,ac0.m:=%04x,ac1.m:=%04x", g_dsp.pc, dsp_get_acc_m(0), dsp_get_acc_m(1));
*/
u16 opc = dsp_fetch_code();
ExecuteInstruction(UDSPInstruction(opc));

View File

@ -86,9 +86,13 @@ void movr(const UDSPInstruction& opc);
void movax(const UDSPInstruction& opc);
void xorr(const UDSPInstruction& opc);
void andr(const UDSPInstruction& opc);
void andc(const UDSPInstruction& opc);
void orr(const UDSPInstruction& opc);
void andc(const UDSPInstruction& opc);
void orc(const UDSPInstruction& opc);
void xorc(const UDSPInstruction& opc);
void not(const UDSPInstruction& opc);
void lsrnrx(const UDSPInstruction& opc);
void lsrnr(const UDSPInstruction& opc);
void orf(const UDSPInstruction& opc);
void add(const UDSPInstruction& opc);
void addp(const UDSPInstruction& opc);

View File

@ -17,37 +17,6 @@
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
/* NOTES BY HERMES:
LZ flag: original opcodes andf and andcf are swaped. Also "jzr" and "jnz" are swaped but now named 'jlz' and 'jlnz'
As you can see it obtain the same result but now LZ=1 correctly
Added conditional instructions:
conditional names:
NZ -> NOT ZERO
Z -> ZERO
NC -> NOT CARRY
C -> CARRY
LZ -> LOGIC ZERO (only used with andcf-andf instructions?)
LNZ -> LOGIC NOT ZERO
G -> GREATER
LE-> LESS EQUAL
GE-> GREATER EQUAL
L -> LESS
Examples:
jnz, ifs, retlnz
*/
#include "Common.h"
#include "DSPTables.h"
@ -64,7 +33,6 @@ void nop(const UDSPInstruction& opc)
// Unknown Ops
// All AX games: a100
// Zelda Four Swords: 02ca
// TODO: Fill up the tables with the corresponding instructions
const DSPOPCTemplate opcodes[] =
@ -125,7 +93,6 @@ const DSPOPCTemplate opcodes[] =
{"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false},
{"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false},
{"JRGE", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false},
{"JRL", 0x1701, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false},
{"JRG", 0x1702, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false},
@ -153,7 +120,6 @@ const DSPOPCTemplate opcodes[] =
{"SBCLR", 0x1200, 0xfff8, DSPInterpreter::sbclr, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false},
{"SBSET", 0x1300, 0xfff8, DSPInterpreter::sbset, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false},
// actually, given the masks these should probably be 0x3f. need investigation.
{"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false},
{"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false},
{"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false},
@ -163,9 +129,6 @@ const DSPOPCTemplate opcodes[] =
{"LSRN", 0x02ca, 0xffff, DSPInterpreter::lsrn, nop, 1, 0, {}, false},
{"ASRN", 0x02cb, 0xffff, DSPInterpreter::asrn, nop, 1, 0, {}, false},
// andc'ls is behaving weird so it got its own opcode
{"LSRNR", 0x3d80, 0xfdff, DSPInterpreter::lsrnr, nop, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, false},
{"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, false},
{"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, false},
{"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, nop, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, false},
@ -217,23 +180,41 @@ const DSPOPCTemplate opcodes[] =
{"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, false},
// opcodes that can be extended
// extended opcodes, note size of opcode will be set to 0
// opcodes that can be extended
// extended opcodes, note size of opcode will be set to 0
//3 - main opcode defined by 9 bits, extension defined by last 7 bits!!
{"XORR", 0x3000, 0xfc80, DSPInterpreter::xorr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true},
{"ANDR", 0x3400, 0xfc80, DSPInterpreter::andr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true},
{"ORR", 0x3800, 0xfc80, DSPInterpreter::orr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true},
{"ANDC", 0x3c00, 0xfe80, DSPInterpreter::andc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true},
{"ORC", 0x3e00, 0xfe80, DSPInterpreter::orc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true},
{"XORC", 0x3080, 0xfe80, DSPInterpreter::xorc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true}, //new
{"NOT", 0x3280, 0xfe80, DSPInterpreter::not, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true}, //new
{"LSRNRX1", 0x3480, 0xfc80, DSPInterpreter::lsrnrx, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true}, //new
{"LSRNRX2", 0x3880, 0xfc80, DSPInterpreter::lsrnrx, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true}, //new
{"LSRNR", 0x3c80, 0xfc80, DSPInterpreter::lsrnr, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true}, // discovered by luigi!
{"NX", 0x8000, 0xf700, DSPInterpreter::nx, nop, 1 | P_EXT, 0, {}, true},
{"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
//4
{"ADDR", 0x4000, 0xf800, DSPInterpreter::addr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true},
{"ADDAX", 0x4800, 0xfc00, DSPInterpreter::addax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"ADD", 0x4c00, 0xfe00, DSPInterpreter::add, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true},
{"ADDP", 0x4e00, 0xfe00, DSPInterpreter::addp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"SET15", 0x8d00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"SET16", 0x8e00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
//5
{"SUBR", 0x5000, 0xf800, DSPInterpreter::subr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true},
{"SUBAX", 0x5800, 0xfc00, DSPInterpreter::subax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"SUB", 0x5c00, 0xfe00, DSPInterpreter::sub, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true},
{"SUBP", 0x5e00, 0xfe00, DSPInterpreter::subp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
//6
{"MOVR", 0x6000, 0xf800, DSPInterpreter::movr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true},
{"MOVAX", 0x6800, 0xfc00, DSPInterpreter::movax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"MOV", 0x6c00, 0xfe00, DSPInterpreter::mov, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true},
{"MOVP", 0x6e00, 0xfe00, DSPInterpreter::movp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
//7
{"ADDAXL", 0x7000, 0xfc00, DSPInterpreter::addaxl, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"INCM", 0x7400, 0xfe00, DSPInterpreter::incm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true},
{"INC", 0x7600, 0xfe00, DSPInterpreter::inc, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"DECM", 0x7800, 0xfe00, DSPInterpreter::decm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true},
@ -241,71 +222,58 @@ const DSPOPCTemplate opcodes[] =
{"NEG", 0x7c00, 0xfe00, DSPInterpreter::neg, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"MOVNP", 0x7e00, 0xfe00, DSPInterpreter::movnp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"TST", 0xb100, 0xf700, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true},
// Definitely not TSTAXL, it affects one of the accumulators. (a100 or a900, same op, one parameter).
{"TSTAXL", 0xa100, 0xff00, DSPInterpreter::tstaxl, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true},
{"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true},
{"CMP", 0x8200, 0xff00, DSPInterpreter::cmp, nop, 1 | P_EXT, 0, {}, true},
// This op does NOT exist, at least not under this name, in duddie's docs!
{"CMPAR" , 0xc100, 0xe700, DSPInterpreter::cmpar, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true},
{"CLRL", 0xfc00, 0xff00, DSPInterpreter::clrl, nop, 1 | P_EXT, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true}, // clear acl0
//8
{"NX", 0x8000, 0xf700, DSPInterpreter::nx, nop, 1 | P_EXT, 0, {}, true},
{"CLR", 0x8100, 0xf700, DSPInterpreter::clr, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true}, // clear acc0
{"CMP", 0x8200, 0xff00, DSPInterpreter::cmp, nop, 1 | P_EXT, 0, {}, true},
//0x8300 - unknown - not used atm - could be cmp(acc1-acc0)
{"CLRP", 0x8400, 0xff00, DSPInterpreter::clrp, nop, 1 | P_EXT, 0, {}, },
//0x8500 - unknown mul opcode (modifies prod regs) - not used atm
{"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true},
{"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"SET15", 0x8d00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"SET16", 0x8e00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, true},
{"MOV", 0x6c00, 0xfe00, DSPInterpreter::mov, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true},
{"MOVAX", 0x6800, 0xfc00, DSPInterpreter::movax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"MOVR", 0x6000, 0xf800, DSPInterpreter::movr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true},
{"MOVP", 0x6e00, 0xfe00, DSPInterpreter::movp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"MOVPZ", 0xfe00, 0xfe00, DSPInterpreter::movpz, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"ADDPAXZ", 0xf800, 0xfc00, DSPInterpreter::addpaxz, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}}, true}, //Think the args are wrong
{"ADDP", 0x4e00, 0xfe00, DSPInterpreter::addp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"LSL16", 0xf000, 0xfe00, DSPInterpreter::lsl16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"LSR16", 0xf400, 0xfe00, DSPInterpreter::lsr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"ASR16", 0x9100, 0xf700, DSPInterpreter::asr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true},
{"XORR", 0x3000, 0xfc00, DSPInterpreter::xorr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true},
{"ANDR", 0x3400, 0xfc00, DSPInterpreter::andr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true},
{"ORR", 0x3800, 0xfc00, DSPInterpreter::orr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true},
{"MULX", 0xa000, 0xe700, DSPInterpreter::mulx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, true},
{"MULXMVZ", 0xa200, 0xe600, 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}}, true},
{"MULXAC", 0xa400, 0xe600, 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}}, true},
{"MULXMV", 0xa600, 0xe600, 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}}, true},
//9
{"MUL", 0x9000, 0xf700, DSPInterpreter::mul, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, true},
{"ASR16", 0x9100, 0xf700, DSPInterpreter::asr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true},
{"MULMVZ", 0x9200, 0xf600, 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}}, true},
{"MULAC", 0x9400, 0xf600, 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}}, true},
{"MULMV", 0x9600, 0xf600, 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}}, true},
//a-b (!!!retest TST/TSTAXL!!!)
{"MULX", 0xa000, 0xe700, DSPInterpreter::mulx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, true},
{"TST", 0xa100, 0xe700, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true},
//{"TSTAXL", 0xa100, 0xff00, DSPInterpreter::tstaxl, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true}, //Definitely not TSTAXL, it affects one of the accumulators
//{"TST", 0xb100, 0xf700, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true},
{"MULXMVZ", 0xa200, 0xe600, 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}}, true},
{"MULXAC", 0xa400, 0xe600, 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}}, true},
{"MULXMV", 0xa600, 0xe600, 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}}, true},
//c-d
{"MULC", 0xc000, 0xe700, DSPInterpreter::mulc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true},
{"CMPAR" , 0xc100, 0xe700, DSPInterpreter::cmpar, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true}, //MIA in duddie dox
{"MULCMVZ", 0xc200, 0xe600, 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}}, true},
{"MULCAC", 0xc400, 0xe600, 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}}, true},
{"MULCMV", 0xc600, 0xe600, 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}}, true},
{"ADDR", 0x4000, 0xf800, DSPInterpreter::addr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true},
{"ADDAX", 0x4800, 0xfc00, DSPInterpreter::addax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"ADD", 0x4c00, 0xfe00, DSPInterpreter::add, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true},
{"ADDAXL", 0x7000, 0xfc00, DSPInterpreter::addaxl, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"SUBR", 0x5000, 0xf800, DSPInterpreter::subr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true},
{"SUBAX", 0x5800, 0xfc00, DSPInterpreter::subax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true},
{"SUB", 0x5c00, 0xfe00, DSPInterpreter::sub, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true},
{"SUBP", 0x5e00, 0xfe00, DSPInterpreter::subp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"MADD", 0xf200, 0xfe00, DSPInterpreter::madd, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true},
{"MSUB", 0xf600, 0xfe00, DSPInterpreter::msub , nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true},
//e
{"MADDX", 0xe000, 0xfc00, DSPInterpreter::maddx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true},
{"MSUBX", 0xe400, 0xfc00, DSPInterpreter::msubx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true},
{"MADDC", 0xe800, 0xfc00, DSPInterpreter::maddc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, true},
{"MSUBC", 0xec00, 0xfc00, DSPInterpreter::msubc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, true},
//f
{"LSL16", 0xf000, 0xfe00, DSPInterpreter::lsl16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"MADD", 0xf200, 0xfe00, DSPInterpreter::madd, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true},
{"LSR16", 0xf400, 0xfe00, DSPInterpreter::lsr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
{"MSUB", 0xf600, 0xfe00, DSPInterpreter::msub , nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true},
{"ADDPAXZ", 0xf800, 0xfc00, DSPInterpreter::addpaxz, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}}, true}, //Think the args are wrong
{"CLRL", 0xfc00, 0xfe00, DSPInterpreter::clrl, nop, 1 | P_EXT, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true}, // clear acl0
{"MOVPZ", 0xfe00, 0xfe00, DSPInterpreter::movpz, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true},
};
const DSPOPCTemplate cw =
@ -530,10 +498,6 @@ const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst)
for (int i = 0; i < opcodes_size; i++)
{
u16 mask = opcodes[i].opcode_mask;
if (opcodes[i].size & P_EXT) {
// Ignore extension bits.
mask &= 0xFF00;
}
if ((mask & inst.hex) == opcodes[i].opcode)
return &opcodes[i];
}

View File

@ -158,8 +158,12 @@ void zeroWriteBackLog();
inline void ExecuteInstruction(const UDSPInstruction& inst)
{
if (opTableUseExt[inst.hex])
if (opTableUseExt[inst.hex]) {
if ((inst.hex >> 12) == 0x3)
extOpTable[inst.hex & 0x7F](inst);
else
extOpTable[inst.hex & 0xFF](inst);
}
opTable[inst.hex](inst);
if (opTableUseExt[inst.hex]) {
applyWriteBackLog();

View File

@ -137,9 +137,10 @@ void movax(const UDSPInstruction& opc)
}
// XORR $acD.m, $axS.h
// 0011 00sd xxxx xxxx
// 0011 00sd 0xxx xxxx
// Logic XOR (exclusive or) middle part of accumulator $acD.m with
// high part of secondary accumulator $axS.h.
// x = extension (7 bits!!)
void xorr(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 9) & 0x1;
@ -150,14 +151,14 @@ void xorr(const UDSPInstruction& opc)
g_dsp.r[DSP_REG_ACM0 + dreg] ^= axh;
s64 acc = dsp_get_long_acc(dreg);
Update_SR_Register64(acc);
Update_SR_Register16(dsp_get_acc_m(dreg));
}
// ANDR $acD.m, $axS.h
// 0011 01sd xxxx xxxx
// 0011 01sd 0xxx xxxx
// Logic AND middle part of accumulator $acD.m with high part of
// secondary accumulator $axS.h.
// x = extension (7 bits!!)
void andr(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 9) & 0x1;
@ -168,14 +169,14 @@ void andr(const UDSPInstruction& opc)
g_dsp.r[DSP_REG_ACM0 + dreg] &= axh;
s64 acc = dsp_get_long_acc(dreg);
Update_SR_Register64(acc);
Update_SR_Register16(dsp_get_acc_m(dreg));
}
// ORR $acD.m, $axS.h
// 0011 10sd xxxx xxxx
// 0011 10sd 0xxx xxxx
// Logic OR middle part of accumulator $acD.m with high part of
// secondary accumulator $axS.h.
// x = extension (7 bits!!)
void orr(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 9) & 0x1;
@ -186,15 +187,14 @@ void orr(const UDSPInstruction& opc)
g_dsp.r[DSP_REG_ACM0 + dreg] |= axh;
s64 acc = dsp_get_long_acc(dreg);
Update_SR_Register64(acc);
Update_SR_Register16(dsp_get_acc_m(dreg));
}
// FIXME: How does it fit what we know about andc'ls
// ANDC $acD.m, $ac(1-D).m
// 0011 110d xxxx xxxx
// 0011 110d 0xxx xxxx
// Logic AND middle part of accumulator $acD.m with middle part of
// accumulator $ac(1-D).m
// x = extension (7 bits!!)
void andc(const UDSPInstruction& opc)
{
u8 D = (opc.hex >> 8) & 0x1;
@ -207,11 +207,11 @@ void andc(const UDSPInstruction& opc)
Update_SR_Register16(dsp_get_acc_m(D));
}
// FIXME: How does it fit what we know about orc'ls
// ORC $acD.m, $ac(1-D).m
// 0011 111d xxxx xxxx
// 0011 111d 0xxx xxxx
// Logic OR middle part of accumulator $acD.m with middle part of
// accumulator $ac(1-D).m.
// x = extension (7 bits!!)
void orc(const UDSPInstruction& opc)
{
u8 D = (opc.hex >> 8) & 0x1;
@ -224,6 +224,36 @@ void orc(const UDSPInstruction& opc)
Update_SR_Register16(dsp_get_acc_m(D));
}
// XORC $acD.m
// 0011 000d 1xxx xxxx
// Logic XOR (exclusive or) middle part of accumulator $acD.m with $ac(1-D).m
// x = extension (7 bits!!)
void xorc(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 8) & 0x1;
u16 res = dsp_get_acc_m(dreg) ^ dsp_get_acc_m(1 - dreg);
zeroWriteBackLog();
g_dsp.r[DSP_REG_ACM0 + dreg] = res;
Update_SR_Register16(res);
}
// NOT $acD.m
// 0011 001d 1xxx xxxx
// Invert all bits in dest reg, aka xor with 0xffff
// x = extension (7 bits!!)
void not(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 8) & 0x1;
u16 res = dsp_get_acc_m(dreg)^0xffff;
zeroWriteBackLog();
g_dsp.r[DSP_REG_ACM0 + dreg] = res;
Update_SR_Register16(res);
}
void orf(const UDSPInstruction& opc)
{
ERROR_LOG(DSPLLE, "orf not implemented");
@ -743,22 +773,51 @@ void asrn(const UDSPInstruction& opc)
Update_SR_Register64(acc);
}
// LSRNRX
// 0011 01sd 1xxx xxxx
// 0011 10sd 1xxx xxxx
// Logically shifts right accumulator $ACC[D] by signed 16-bit value $AX[S].H
// Not described by Duddie's doc.
// x = extension (7 bits!!)
void lsrnrx(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 8) & 0x1; //accD
u8 sreg = (opc.hex >> 9) & 0x1; //axhS
u64 acc = dsp_get_long_acc(dreg);
s16 shift = g_dsp.r[DSP_REG_AXH0 + sreg];
acc & 0x000000FFFFFFFFFFULL;
if (shift > 0) {
acc <<= shift;
} else if (shift < 0) {
acc >>= -shift;
}
zeroWriteBackLog();
dsp_set_long_acc(dreg, acc);
Update_SR_Register64(acc);
}
// LSRNR $acR
// 0011 110d 1100 0000
// Logically shifts right accumulator $ACC0 by signed 16-bit value $AC0.M
// 0011 11?d 1xxx xxxx
// Logically shifts right accumulator $ACC[D] by signed 16-bit value $AC[1-D].M
// Not described by Duddie's doc - at least not as a separate instruction.
// x = extension (7 bits!!)
void lsrnr(const UDSPInstruction& opc)
{
u8 sreg = 1;//Check if it should be (opc.hex >> 8) & 0x1;
s16 shift = dsp_get_acc_m(0);
u64 acc = dsp_get_long_acc(sreg);
u8 D = (opc.hex >> 8) & 0x1;
s16 shift = dsp_get_acc_m(1-D);
u64 acc = dsp_get_long_acc(D);
acc &= 0x000000FFFFFFFFFFULL;
if (shift > 0) {
acc <<= shift;
} else if (shift < 0) {
acc >>= -shift;
}
dsp_set_long_acc(sreg, acc);
zeroWriteBackLog();
dsp_set_long_acc(D, acc);
Update_SR_Register64(acc);
}

View File

@ -232,7 +232,6 @@ void ilrrd(const UDSPInstruction& opc)
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_conditional_extend_accum(dreg);
g_dsp.r[reg] = dsp_decrement_addr_reg(reg);
}
@ -247,7 +246,7 @@ void ilrri(const UDSPInstruction& opc)
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_conditional_extend_accum(dreg);
g_dsp.r[reg] = dsp_increment_addr_reg(reg);
}