From 10fb287311b6066d0ead410288aa6484a5e4ffe9 Mon Sep 17 00:00:00 2001 From: Marko Pusljar Date: Wed, 4 Nov 2009 12:49:26 +0000 Subject: [PATCH] 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 --- Source/Core/DSPCore/Src/DSPAccelerator.cpp | 19 ++- Source/Core/DSPCore/Src/DSPInterpreter.cpp | 7 +- Source/Core/DSPCore/Src/DSPInterpreter.h | 6 +- Source/Core/DSPCore/Src/DSPTables.cpp | 164 ++++++++----------- Source/Core/DSPCore/Src/DSPTables.h | 8 +- Source/Core/DSPCore/Src/DspIntArithmetic.cpp | 101 +++++++++--- Source/Core/DSPCore/Src/DspIntLoadStore.cpp | 3 +- 7 files changed, 177 insertions(+), 131 deletions(-) diff --git a/Source/Core/DSPCore/Src/DSPAccelerator.cpp b/Source/Core/DSPCore/Src/DSPAccelerator.cpp index 576c326b33..04dcd88a95 100644 --- a/Source/Core/DSPCore/Src/DSPAccelerator.cpp +++ b/Source/Core/DSPCore/Src/DSPAccelerator.cpp @@ -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) diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp index 4e2011a53c..de226c62c8 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.cpp +++ b/Source/Core/DSPCore/Src/DSPInterpreter.cpp @@ -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)); diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.h b/Source/Core/DSPCore/Src/DSPInterpreter.h index aa188fbb74..692041ab85 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.h +++ b/Source/Core/DSPCore/Src/DSPInterpreter.h @@ -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); diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp index b0afdeb4c8..5900fb5a7f 100644 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -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 - {"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}, + //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, {}, }, - - {"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}, + //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}, - {"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}, + //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}, - - {"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}, - + {"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}, - {"MUL", 0x9000, 0xf700, DSPInterpreter::mul, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 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}, - + //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]; } diff --git a/Source/Core/DSPCore/Src/DSPTables.h b/Source/Core/DSPCore/Src/DSPTables.h index e6966b8596..8f687a65fc 100644 --- a/Source/Core/DSPCore/Src/DSPTables.h +++ b/Source/Core/DSPCore/Src/DSPTables.h @@ -158,8 +158,12 @@ void zeroWriteBackLog(); inline void ExecuteInstruction(const UDSPInstruction& inst) { - if (opTableUseExt[inst.hex]) - extOpTable[inst.hex & 0xFF](inst); + 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(); diff --git a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp b/Source/Core/DSPCore/Src/DspIntArithmetic.cpp index fbce47752b..c22ddae22f 100644 --- a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp +++ b/Source/Core/DSPCore/Src/DspIntArithmetic.cpp @@ -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; @@ -149,15 +150,15 @@ void xorr(const UDSPInstruction& opc) zeroWriteBackLog(); 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; @@ -167,15 +168,15 @@ void andr(const UDSPInstruction& opc) zeroWriteBackLog(); 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); } diff --git a/Source/Core/DSPCore/Src/DspIntLoadStore.cpp b/Source/Core/DSPCore/Src/DspIntLoadStore.cpp index 7400dfdb08..ade6e6752b 100644 --- a/Source/Core/DSPCore/Src/DspIntLoadStore.cpp +++ b/Source/Core/DSPCore/Src/DspIntLoadStore.cpp @@ -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); }