From e8b9e93465ec9e78de823c1480439f9efb2a8012 Mon Sep 17 00:00:00 2001 From: hrydgard Date: Sun, 12 Apr 2009 10:21:40 +0000 Subject: [PATCH] DSP: Move the LLE core to a library. Added DSP assembler from gdtool, start cleaning it up. Create a new program called "DSPTool" which will become a more up to date replacement for gdtool from the devkitpro, automatically incorporating all our findings as we make them. This program depends on the new library. It can *ALMOST* roundtrip (asm->disasm->asm) hermes' DSP mixer at this point. Sorry about the unfinished Sconscript work - I'll fix it soon if nobody else does it first. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2955 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Common.vcproj | 4 +- Source/Core/Common/Src/DynamicLibrary.cpp | 2 +- Source/Core/Common/Src/FileUtil.cpp | 31 + Source/Core/Common/Src/FileUtil.h | 3 + Source/Core/DSPCore/DSPCore.vcproj | 524 +++++++++ .../DSPCore}/Src/DSPAnalyzer.cpp | 0 .../DSPCore}/Src/DSPAnalyzer.h | 0 Source/Core/DSPCore/Src/DSPHost.h | 31 + .../DSPCore}/Src/DSPInterpreter.cpp | 31 +- .../DSPCore}/Src/DSPInterpreter.h | 4 +- .../DSPCore}/Src/DSPJit.cpp | 0 .../DSPCore}/Src/DSPJit.h | 0 .../DSPCore}/Src/DSPTables.cpp | 923 ++++++++------- .../DSPCore}/Src/DSPTables.h | 49 +- Source/Core/DSPCore/Src/SConscript | 24 + Source/Core/DSPCore/Src/assemble.cpp | 1034 +++++++++++++++++ .../DSPCore}/Src/disassemble.cpp | 171 +-- .../DSPCore}/Src/disassemble.h | 9 +- .../DSPCore}/Src/gdsp_aram.cpp | 13 +- .../DSPCore}/Src/gdsp_aram.h | 0 .../DSPCore}/Src/gdsp_condition_codes.cpp | 0 .../DSPCore}/Src/gdsp_condition_codes.h | 2 +- Source/Core/DSPCore/Src/gdsp_ext_op.cpp | 281 +++++ .../DSPCore}/Src/gdsp_ext_op.h | 32 - .../DSPCore}/Src/gdsp_interface.cpp | 27 +- .../DSPCore}/Src/gdsp_interface.h | 2 +- .../DSPCore}/Src/gdsp_interpreter.cpp | 11 +- .../DSPCore}/Src/gdsp_interpreter.h | 7 +- .../DSPCore}/Src/gdsp_memory.cpp | 1 - .../DSPCore}/Src/gdsp_memory.h | 3 +- .../DSPCore}/Src/gdsp_opcodes_helper.h | 2 +- .../DSPCore}/Src/gdsp_registers.cpp | 2 +- .../DSPCore}/Src/gdsp_registers.h | 4 +- Source/Core/DiscIO/Src/stdafx.h | 3 - Source/Core/DolphinWX/DolphinWX.vcproj | 3 +- Source/DSPTool/DSPTool.vcproj | 484 ++++++++ Source/DSPTool/SConscript | 12 + Source/DSPTool/main.cpp | 246 ++++ Source/Dolphin.sln | 42 + .../Plugin_DSP_LLE/Plugin_DSP_LLE.vcproj | 130 +-- Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp | 51 + .../Plugin_DSP_LLE/Src/Debugger/Debugger.cpp | 10 - .../Plugin_DSP_LLE/Src/Debugger/Debugger.h | 9 +- Source/Plugins/Plugin_DSP_LLE/Src/Globals.h | 2 - Source/Plugins/Plugin_DSP_LLE/Src/SConscript | 14 +- Source/Plugins/Plugin_DSP_LLE/Src/Tools.h | 32 +- .../Plugin_DSP_LLE/Src/gdsp_ext_op.cpp | 438 ------- Source/Plugins/Plugin_DSP_LLE/Src/main.cpp | 1 - 48 files changed, 3442 insertions(+), 1262 deletions(-) create mode 100644 Source/Core/DSPCore/DSPCore.vcproj rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPAnalyzer.cpp (100%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPAnalyzer.h (100%) create mode 100644 Source/Core/DSPCore/Src/DSPHost.h rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPInterpreter.cpp (95%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPInterpreter.h (95%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPJit.cpp (100%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPJit.h (100%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPTables.cpp (68%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/DSPTables.h (75%) create mode 100644 Source/Core/DSPCore/Src/SConscript create mode 100644 Source/Core/DSPCore/Src/assemble.cpp rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/disassemble.cpp (64%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/disassemble.h (89%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_aram.cpp (86%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_aram.h (100%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_condition_codes.cpp (100%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_condition_codes.h (95%) create mode 100644 Source/Core/DSPCore/Src/gdsp_ext_op.cpp rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_ext_op.h (59%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_interface.cpp (93%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_interface.h (98%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_interpreter.cpp (97%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_interpreter.h (95%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_memory.cpp (99%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_memory.h (98%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_opcodes_helper.h (99%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_registers.cpp (98%) rename Source/{Plugins/Plugin_DSP_LLE => Core/DSPCore}/Src/gdsp_registers.h (99%) create mode 100644 Source/DSPTool/DSPTool.vcproj create mode 100644 Source/DSPTool/SConscript create mode 100644 Source/DSPTool/main.cpp create mode 100644 Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp delete mode 100644 Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp diff --git a/Source/Core/Common/Common.vcproj b/Source/Core/Common/Common.vcproj index c4af80238f..149082c6bb 100644 --- a/Source/Core/Common/Common.vcproj +++ b/Source/Core/Common/Common.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.cpp b/Source/Core/DSPCore/Src/DSPAnalyzer.cpp similarity index 100% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.cpp rename to Source/Core/DSPCore/Src/DSPAnalyzer.cpp diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.h b/Source/Core/DSPCore/Src/DSPAnalyzer.h similarity index 100% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPAnalyzer.h rename to Source/Core/DSPCore/Src/DSPAnalyzer.h diff --git a/Source/Core/DSPCore/Src/DSPHost.h b/Source/Core/DSPCore/Src/DSPHost.h new file mode 100644 index 0000000000..294af23c1e --- /dev/null +++ b/Source/Core/DSPCore/Src/DSPHost.h @@ -0,0 +1,31 @@ +// 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 _DSPHOST_H +#define _DSPHOST_H + +// The user of the DSPCore library must supply a few functions so that the +// emulation core can access the environment it runs in. If the emulation +// core isn't used, for example in an asm/disasm tool, then most of these +// can be stubbed out. + +u8 DSPHost_ReadHostMemory(u32 addr); +bool DSPHost_OnThread(); +bool DSPHost_Running(); +u32 DSPHost_CodeLoaded(const u8 *ptr, int size); + +#endif \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp similarity index 95% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPInterpreter.cpp rename to Source/Core/DSPCore/Src/DSPInterpreter.cpp index 2839a44daf..9e94051474 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPInterpreter.cpp +++ b/Source/Core/DSPCore/Src/DSPInterpreter.cpp @@ -19,7 +19,7 @@ #include "DSPInterpreter.h" -#include "Globals.h" +#include "Common.h" #include "gdsp_memory.h" #include "gdsp_interpreter.h" #include "gdsp_condition_codes.h" @@ -116,11 +116,9 @@ void jcc(const UDSPInstruction& opc) // Jump to address; set program counter to a value from register $R. void jmprcc(const UDSPInstruction& opc) { - u8 reg; - if (CheckCondition(opc.hex & 0xf)) { - reg = (opc.hex >> 5) & 0x7; + u8 reg = (opc.hex >> 5) & 0x7; g_dsp.pc = dsp_op_read_reg(reg); } } @@ -826,6 +824,16 @@ void andc(const UDSPInstruction& opc) Update_SR_Register64(dsp_get_long_acc(D)); } +void orc(const UDSPInstruction& opc) +{ + ERROR_LOG(DSPLLE, "orc not implemented"); +} + +void orf(const UDSPInstruction& opc) +{ + ERROR_LOG(DSPLLE, "orf not implemented"); +} + //------------------------------------------------------------- @@ -1752,7 +1760,8 @@ void msubx(const UDSPInstruction& opc) // MADDC $acS.m, $axT.h // 1110 10st xxxx xxxx // Multiply middle part of accumulator $acS.m by high part of secondary -// accumulator $axT.h (treat them both as signed) and add result to product register. +// accumulator $axT.h (treat them both as signed) and add result to product +// register. void maddc(const UDSPInstruction& opc) { u32 sreg = (opc.hex >> 9) & 0x1; @@ -1788,28 +1797,28 @@ void msubc(const UDSPInstruction& opc) Update_SR_Register64(prod); } -// SRS @M, $(DSP_REG_AXL0+S) +// SRS @M, $(0x18+S) // 0010 1sss mmmm mmmm -// Store value from register $(DSP_REG_AXL0+S) to a memory pointed by address M. +// Store value from register $(0x18+S) to a memory pointed by address M. // (8-bit sign extended). // FIXME: Perform additional operation depending on destination register. // Note: pc+=2 in duddie's doc seems wrong void srs(const UDSPInstruction& opc) { - u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0; + u8 reg = ((opc.hex >> 8) & 0x7) + 0x18; u16 addr = (u16)(s16)(s8)opc.hex; dsp_dmem_write(addr, g_dsp.r[reg]); } -// LRS $(DSP_REG_AXL0+D), @M +// LRS $(0x18+D), @M // 0010 0ddd mmmm mmmm // Move value from data memory pointed by address M (8-bit sign -// extended) to register $(DSP_REG_AXL0+D). +// extended) to register $(0x18+D). // FIXME: Perform additional operation depending on destination register. // Note: pc+=2 in duddie's doc seems wrong void lrs(const UDSPInstruction& opc) { - u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0; + u8 reg = ((opc.hex >> 8) & 0x7) + 0x18; u16 addr = (u16)(s16)(s8)opc.hex; g_dsp.r[reg] = dsp_dmem_read(addr); } diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPInterpreter.h b/Source/Core/DSPCore/Src/DSPInterpreter.h similarity index 95% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPInterpreter.h rename to Source/Core/DSPCore/Src/DSPInterpreter.h index b94c784cab..dec7f9e187 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPInterpreter.h +++ b/Source/Core/DSPCore/Src/DSPInterpreter.h @@ -68,8 +68,10 @@ void movr(const UDSPInstruction& opc); void movax(const UDSPInstruction& opc); void xorr(const UDSPInstruction& opc); void andr(const UDSPInstruction& opc); -void orr(const UDSPInstruction& opc); void andc(const UDSPInstruction& opc); +void orr(const UDSPInstruction& opc); +void orc(const UDSPInstruction& opc); +void orf(const UDSPInstruction& opc); void add(const UDSPInstruction& opc); void addp(const UDSPInstruction& opc); void cmpis(const UDSPInstruction& opc); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPJit.cpp b/Source/Core/DSPCore/Src/DSPJit.cpp similarity index 100% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPJit.cpp rename to Source/Core/DSPCore/Src/DSPJit.cpp diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPJit.h b/Source/Core/DSPCore/Src/DSPJit.h similarity index 100% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPJit.h rename to Source/Core/DSPCore/Src/DSPJit.h diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp similarity index 68% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.cpp rename to Source/Core/DSPCore/Src/DSPTables.cpp index 39dce59366..d05e10a06f 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -1,405 +1,518 @@ -// 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/ - -// 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 - -NS -> NOT SIGN -S -> SIGN - -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 "Globals.h" -#include "DSPTables.h" - -#include "DSPInterpreter.h" -#include "DSPJit.h" -#include "gdsp_ext_op.h" - -void nop(const UDSPInstruction& opc) {if(opc.hex) DSPInterpreter::unknown(opc);} - -// Unknown Ops -// All AX games: a100 -// Zelda Four Swords: 02ca - - -DSPOPCTemplate opcodes[] = -{ - {"NOP", 0x0000, 0xffff, nop, nop, 1, 0, {}, NULL, NULL}, - - {"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL}, - {"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL}, - - {"HALT", 0x0021, 0xffff, DSPInterpreter::halt, nop, 1, 0, {}, NULL, NULL}, - - {"RETNS", 0x02d0, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETS", 0x02d1, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETG", 0x02d2, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETLE", 0x02d3, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETNZ", 0x02d4, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETZ", 0x02d5, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETL", 0x02d6, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETGE", 0x02d7, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETLNZ", 0x02dc, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"RETLZ", 0x02dd, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, - {"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}, - - {"IF NS", 0x0270, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF S", 0x0271, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF G", 0x0272, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF LE", 0x0273, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF NZ", 0x0274, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF Z", 0x0275, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF L", 0x0276, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF GE", 0x0277, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF LNZ", 0x027c, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, - {"IF LZ", 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}, - - - {"JRNS", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRS", 0x1701, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRG", 0x1702, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRLE", 0x1703, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRNZ", 0x1704, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRZ", 0x1705, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRL", 0x1706, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRGE", 0x1707, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRLNZ", 0x170c, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JRLZ", 0x170d, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"JMPR", 0x170f, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - - {"CALLRNS", 0x1710, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRS", 0x1711, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRG", 0x1712, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRLE", 0x1713, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRNZ", 0x1714, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRZ", 0x1715, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRL", 0x1716, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRGE", 0x1717, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRLNZ",0x171c, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLRLZ", 0x171d, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - {"CALLR", 0x171f, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, - - {"SBCLR", 0x1200, 0xfff8, DSPInterpreter::sbclr, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL}, - {"SBSET", 0x1300, 0xfff8, DSPInterpreter::sbset, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL}, - - {"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL}, // 0x007f? - {"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL}, // 0x007f? - {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}}, NULL, NULL}, - {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}}, NULL, NULL}, - - - {"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, - {"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, NULL, NULL}, - {"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, nop, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, - - {"MRR", 0x1c00, 0xfc00, DSPInterpreter::mrr, nop, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, - - {"SI", 0x1600, 0xff00, DSPInterpreter::si, nop, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, - - {"LRS", 0x2000, 0xf800, DSPInterpreter::lrs, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}}, NULL, NULL}, - {"SRS", 0x2800, 0xf800, DSPInterpreter::srs, nop, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}}, NULL, NULL}, - - {"LRIS", 0x0800, 0xf800, DSPInterpreter::lris, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, - - {"ADDIS", 0x0400, 0xfe00, DSPInterpreter::addis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, - {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, - {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,}, - {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andfc, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,}, - - {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, - {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, - - {"ORI", 0x0260, 0xfeff, DSPInterpreter::ori, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, - {"ORF", 0x02e0, 0xfeff, nop, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // Hermes: ??? (has it commented out) - - {"ADDI", 0x0200, 0xfeff, DSPInterpreter::addi, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // F|RES: missing S64 - {"CMPI", 0x0280, 0xfeff, DSPInterpreter::cmpi, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, - - {"ILRR", 0x0210, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, - {"ILRRD", 0x0214, 0xfedc, DSPInterpreter::ilrrd, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, // Hermes doesn't list this - {"ILRRI", 0x0218, 0xfedc, DSPInterpreter::ilrri, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, - {"ILRRN", 0x0222, 0xfedc, DSPInterpreter::ilrrn, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, - - // load and store value pointed by indexing reg and increment; LRR/SRR variants - {"LRR", 0x1800, 0xff80, DSPInterpreter::lrr, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, - {"LRRD", 0x1880, 0xff80, DSPInterpreter::lrrd, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, - {"LRRI", 0x1900, 0xff80, DSPInterpreter::lrri, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, - {"LRRN", 0x1980, 0xff80, DSPInterpreter::lrrn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, - - {"SRR", 0x1a00, 0xff80, DSPInterpreter::srr, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, - {"SRRD", 0x1a80, 0xff80, DSPInterpreter::srrd, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, - {"SRRI", 0x1b00, 0xff80, DSPInterpreter::srri, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, - {"SRRN", 0x1b80, 0xff80, DSPInterpreter::srrn, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, - - // 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}, - {"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}, - - {"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, nop, 2, 2, {{P_REG, 1, 0, 0, 0x00c0}, {P_REG, 2, 1, 0, 0x0003}}, NULL, NULL}, - - - // opcodes that can be extended - // extended opcodes, note size of opcode will be set to 0 - - {"NX", 0x8000, 0xf700, DSPInterpreter::nx, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"M2", 0x8a00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"M0", 0x8b00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - // These guys probably change the precision or range of some operations. - // The question is which. 16-bit mode vs 40-bit mode sounds plausible for SET40/SET16. - // Maybe Set15 makes the dsp drop the top bit from all calculations or something? Or clamp? - // SET15/CLR15 is commonly used around MULXAC in Zeldas. - // SET16 is done around complicated loops with many madds etc. - {"CLR15", 0x8c00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"SET15", 0x8d00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"SET40", 0x8e00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"SET16", 0x8f00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - - {"INCM", 0x7400, 0xfeff, DSPInterpreter::incm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"INC", 0x7600, 0xfeff, DSPInterpreter::inc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"DECM", 0x7800, 0xfeff, DSPInterpreter::decm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"DEC", 0x7a00, 0xfeff, DSPInterpreter::dec, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"NEG", 0x7c00, 0xfeff, DSPInterpreter::neg, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MOVNP", 0x7e00, 0xfeff, DSPInterpreter::movnp, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - - {"TST", 0xb100, 0xf7ff, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - // GUESSING NOT SURE AT ALL!!!! - {"TSTAXL", 0xa100, 0xffff, DSPInterpreter::tstaxl, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"TSTAXH", 0x8600, 0xfeff, DSPInterpreter::tstaxh, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"CMP", 0x8200, 0xffff, DSPInterpreter::cmp, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - // This op does NOT exist, at least not under this name, in duddie's docs! - {"CMPAR" , 0xc100, 0xe7ff, DSPInterpreter::cmpar, 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}, - - {"CLRAL0", 0xfc00, 0xffff, DSPInterpreter::clrl, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acl0 - {"CLRAL1", 0xfd00, 0xffff, DSPInterpreter::clrl, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acl1 - {"CLRA0", 0x8100, 0xffff, DSPInterpreter::clr, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acc0 - {"CLRA1", 0x8900, 0xffff, DSPInterpreter::clr, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acc1 - {"CLRP", 0x8400, 0xffff, DSPInterpreter::clrp, nop, 1 | P_EXT, 0, {}, }, - - - {"MOV", 0x6c00, 0xfeff, DSPInterpreter::mov, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MOVAX", 0x6800, 0xfcff, DSPInterpreter::movax, 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}, - {"MOVR", 0x6000, 0xf8ff, DSPInterpreter::movr, 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}, - {"MOVP", 0x6e00, 0xfeff, DSPInterpreter::movp, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MOVPZ", 0xfe00, 0xfeff, DSPInterpreter::movpz, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"ADDPAXZ", 0xf800, 0xfcff, DSPInterpreter::addpaxz, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"ADDP", 0x4e00, 0xfeff, DSPInterpreter::addp, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"LSL16", 0xf000, 0xfeff, DSPInterpreter::lsl16, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"LSR16", 0xf400, 0xfeff, DSPInterpreter::lsr16, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"ASR16", 0x9100, 0xf7ff, DSPInterpreter::asr16, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"XORR", 0x3000, 0xfcff, DSPInterpreter::xorr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"ANDR", 0x3400, 0xfcff, DSPInterpreter::andr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"ORR", 0x3800, 0xfcff, DSPInterpreter::orr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"ANDC", 0x3C00, 0xfeff, DSPInterpreter::andc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this - {"ORC", 0x3E00, 0xfeff, nop, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this - - {"MULX", 0xa000, 0xe7ff, DSPInterpreter::mulx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULXMVZ", 0xa200, 0xe6ff, DSPInterpreter::mulxmvz, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULXAC", 0xa400, 0xe6ff, DSPInterpreter::mulxac, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULXMV", 0xa600, 0xe6ff, DSPInterpreter::mulxmv, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"MUL", 0x9000, 0xf7ff, DSPInterpreter::mul, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULMVZ", 0x9200, 0xf6ff, DSPInterpreter::mulmvz, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULAC", 0x9400, 0xf6ff, DSPInterpreter::mulac, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULMV", 0x9600, 0xf6ff, DSPInterpreter::mulmv, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"MULC", 0xc000, 0xe7ff, DSPInterpreter::mulc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULCMVZ", 0xc200, 0xe6ff, DSPInterpreter::mulcmvz, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULCAC", 0xc400, 0xe6ff, DSPInterpreter::mulcac, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MULCMV", 0xc600, 0xe6ff, DSPInterpreter::mulcmv, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - - {"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}, - {"ADD", 0x4c00, 0xfeff, DSPInterpreter::add, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_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_ACCM, 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_ACCM, 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_ACCM, 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_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_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_ACCM, 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}, - {"MSUB", 0xf600, 0xfeff, DSPInterpreter::msub , 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}, - {"MADDX", 0xe000, 0xfcff, DSPInterpreter::maddx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MSUBX", 0xe400, 0xfcff, DSPInterpreter::msubx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MADDC", 0xe800, 0xfcff, DSPInterpreter::maddc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, - {"MSUBC", 0xec00, 0xfcff, DSPInterpreter::msubc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, -}; - -DSPOPCTemplate opcodes_ext[] = -{ - - {"DR", 0x0004, 0x00fc, DSPInterpreter::Ext::dr, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - {"IR", 0x0008, 0x00fc, DSPInterpreter::Ext::ir, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - {"NR", 0x000c, 0x00fc, DSPInterpreter::Ext::nr, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - - {"MV", 0x0010, 0x00f0, DSPInterpreter::Ext::mv, nop, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}}, NULL, NULL,}, - - {"S", 0x0020, 0x00e4, DSPInterpreter::Ext::s, nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,}, - {"SN", 0x0024, 0x00e4, DSPInterpreter::Ext::sn, nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,}, - - {"L", 0x0040, 0x00c4, DSPInterpreter::Ext::l, nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - {"LN", 0x0044, 0x00c4, DSPInterpreter::Ext::ln, nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - - {"LS", 0x0080, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, - {"SL", 0x0082, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, - {"LSN", 0x0084, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, - {"SLN", 0x0086, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, - {"LSM", 0x0088, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, - {"SLM", 0x008a, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, - {"LSNM", 0x008c, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, - {"SLNM", 0x008e, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, - - // FIXME what are the LDx? for? - /* {"LDX", 0x00c0, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,}, - {"LDXN", 0x00c4, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,}, - {"LDXM", 0x00c8, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,}, - {"LDXNM", 0x00cc, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},*/ - - {"LD", 0x00c0, 0x00cc, DSPInterpreter::Ext::ld, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - {"LDN", 0x00c4, 0x00cc, DSPInterpreter::Ext::ldn, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - {"LDM", 0x00c8, 0x00cc, DSPInterpreter::Ext::ldm, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - {"LDNM", 0x00cc, 0x00cc, DSPInterpreter::Ext::ldnm, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, - - {"XXX", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, NULL, NULL,}, -}; - -const u32 opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate); -const u32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate); - -u8 opSize[OPTABLE_SIZE]; -dspInstFunc opTable[OPTABLE_SIZE]; -dspInstFunc prologueTable[OPTABLE_SIZE]; -dspInstFunc epilogueTable[OPTABLE_SIZE]; - -const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst) -{ - for (u32 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]; - } - return NULL; -} - - -// This function could use the above GetOpTemplate, but then we'd lose the -// nice property that it catches colliding op masks. -void InitInstructionTable() -{ - for (int i = 0; i < OPTABLE_SIZE; i++) - { - opTable[i] = DSPInterpreter::unknown; - prologueTable[i] = NULL; - epilogueTable[i] = NULL; - opSize[i] = 0; - } - - for (int i = 0; i < OPTABLE_SIZE; i++) - { - for (u32 j = 0; j < opcodes_size; j++) - { - u16 mask = opcodes[j].opcode_mask; - if (opcodes[j].size & P_EXT) { - // Ignore extension bits. - mask &= 0xFF00; - } - if ((mask & i) == opcodes[j].opcode) - { - if (opTable[i] == DSPInterpreter::unknown) - { - opTable[i] = opcodes[j].interpFunc; - opSize[i] = opcodes[j].size & 3; - prologueTable[i] = opcodes[j].prologue; - epilogueTable[i] = opcodes[j].epilogue; - } - else - { - ERROR_LOG(DSPLLE, "opcode table place %d already in use for %s", i, opcodes[j].name); - } - } - } - } -} +// 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/ + +// 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 + +NS -> NOT SIGN +S -> SIGN + +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" + +#include "DSPInterpreter.h" +#include "DSPJit.h" +#include "gdsp_ext_op.h" + +void nop(const UDSPInstruction& opc) +{ + // The real nop is 0. Anything else is bad. + if (opc.hex) + DSPInterpreter::unknown(opc); +} + +// Unknown Ops +// All AX games: a100 +// Zelda Four Swords: 02ca + + +// TODO: Fill up the tables with the corresponding instructions +const DSPOPCTemplate opcodes[] = +{ + {"NOP", 0x0000, 0xffff, nop, nop, 1, 0, {}, NULL, NULL}, + + {"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL}, + {"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL}, + + {"HALT", 0x0021, 0xffff, DSPInterpreter::halt, nop, 1, 0, {}, NULL, NULL}, + + {"RETNS", 0x02d0, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETS", 0x02d1, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETG", 0x02d2, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETLE", 0x02d3, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETNZ", 0x02d4, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETZ", 0x02d5, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETL", 0x02d6, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETGE", 0x02d7, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETLNZ", 0x02dc, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"RETLZ", 0x02dd, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL}, + {"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}, + + {"IFNS", 0x0270, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFS", 0x0271, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFG", 0x0272, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFLE", 0x0273, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFNZ", 0x0274, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFZ", 0x0275, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFL", 0x0276, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFGE", 0x0277, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"IFLNZ", 0x027c, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, + {"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}, + + + {"JRNS", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRS", 0x1701, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRG", 0x1702, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRLE", 0x1703, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRNZ", 0x1704, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRZ", 0x1705, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRL", 0x1706, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRGE", 0x1707, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRLNZ", 0x170c, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JRLZ", 0x170d, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"JMPR", 0x170f, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + + {"CALLRNS", 0x1710, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRS", 0x1711, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRG", 0x1712, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRLE", 0x1713, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRNZ", 0x1714, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRZ", 0x1715, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRL", 0x1716, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRGE", 0x1717, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRLNZ",0x171c, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLRLZ", 0x171d, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + {"CALLR", 0x171f, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL}, + + {"SBCLR", 0x1200, 0xfff8, DSPInterpreter::sbclr, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL}, + {"SBSET", 0x1300, 0xfff8, DSPInterpreter::sbset, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL}, + + {"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL}, // 0x007f? + {"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL}, // 0x007f? + {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}}, NULL, NULL}, + {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}}, NULL, NULL}, + + {"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, + {"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, NULL, NULL}, + {"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, nop, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, + + {"MRR", 0x1c00, 0xfc00, DSPInterpreter::mrr, nop, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, + + {"SI", 0x1600, 0xff00, DSPInterpreter::si, nop, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, + + {"LRS", 0x2000, 0xf800, DSPInterpreter::lrs, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}}, NULL, NULL}, + {"SRS", 0x2800, 0xf800, DSPInterpreter::srs, nop, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}}, NULL, NULL}, + + {"LRIS", 0x0800, 0xf800, DSPInterpreter::lris, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, + + {"ADDIS", 0x0400, 0xfe00, DSPInterpreter::addis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, + {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL}, + {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,}, + {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andfc, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,}, + + {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, + {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, + + {"ORI", 0x0260, 0xfeff, DSPInterpreter::ori, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, + {"ORF", 0x02e0, 0xfeff, DSPInterpreter::orf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // Hermes: ??? (has it commented out) + + {"ADDI", 0x0200, 0xfeff, DSPInterpreter::addi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // F|RES: missing S64 + {"CMPI", 0x0280, 0xfeff, DSPInterpreter::cmpi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, + + {"ILRR", 0x0210, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, + {"ILRRD", 0x0214, 0xfedc, DSPInterpreter::ilrrd, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, // Hermes doesn't list this + {"ILRRI", 0x0218, 0xfedc, DSPInterpreter::ilrri, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, + {"ILRRN", 0x0222, 0xfedc, DSPInterpreter::ilrrn, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, + + // load and store value pointed by indexing reg and increment; LRR/SRR variants + {"LRR", 0x1800, 0xff80, DSPInterpreter::lrr, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, + {"LRRD", 0x1880, 0xff80, DSPInterpreter::lrrd, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, + {"LRRI", 0x1900, 0xff80, DSPInterpreter::lrri, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, + {"LRRN", 0x1980, 0xff80, DSPInterpreter::lrrn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL}, + + {"SRR", 0x1a00, 0xff80, DSPInterpreter::srr, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, + {"SRRD", 0x1a80, 0xff80, DSPInterpreter::srrd, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, + {"SRRI", 0x1b00, 0xff80, DSPInterpreter::srri, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, + {"SRRN", 0x1b80, 0xff80, DSPInterpreter::srrn, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, + + // 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}, + {"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}, + + {"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, nop, 2, 2, {{P_REG, 1, 0, 0, 0x00c0}, {P_REG, 2, 1, 0, 0x0003}}, NULL, NULL}, + + + // opcodes that can be extended + // extended opcodes, note size of opcode will be set to 0 + + {"NX", 0x8000, 0xf700, DSPInterpreter::nx, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"M2", 0x8a00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"M0", 0x8b00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + // These guys probably change the precision or range of some operations. + // The question is which. 16-bit mode vs 40-bit mode sounds plausible for SET40/SET16. + // Maybe Set15 makes the dsp drop the top bit from all calculations or something? Or clamp? + // SET15/CLR15 is commonly used around MULXAC in Zeldas. + // SET16 is done around complicated loops with many madds etc. + {"CLR15", 0x8c00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"SET15", 0x8d00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"SET40", 0x8e00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"SET16", 0x8f00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + + {"INCM", 0x7400, 0xfeff, DSPInterpreter::incm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"INC", 0x7600, 0xfeff, DSPInterpreter::inc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"DECM", 0x7800, 0xfeff, DSPInterpreter::decm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"DEC", 0x7a00, 0xfeff, DSPInterpreter::dec, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"NEG", 0x7c00, 0xfeff, DSPInterpreter::neg, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MOVNP", 0x7e00, 0xfeff, DSPInterpreter::movnp, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + + {"TST", 0xb100, 0xf7ff, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + // GUESSING NOT SURE AT ALL!!!! + {"TSTAXL", 0xa100, 0xffff, DSPInterpreter::tstaxl, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"TSTAXH", 0x8600, 0xfeff, DSPInterpreter::tstaxh, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"CMP", 0x8200, 0xffff, DSPInterpreter::cmp, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + // This op does NOT exist, at least not under this name, in duddie's docs! + {"CMPAR" , 0xc100, 0xe7ff, DSPInterpreter::cmpar, 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}, + + {"CLRL", 0xfc00, 0xffff, DSPInterpreter::clrl, nop, 1 | P_EXT, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acl0 + {"CLR", 0x8100, 0xf7ff, DSPInterpreter::clr, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acc0 + {"CLRP", 0x8400, 0xffff, DSPInterpreter::clrp, nop, 1 | P_EXT, 0, {}, }, + + + {"MOV", 0x6c00, 0xfeff, DSPInterpreter::mov, 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}, + {"MOVAX", 0x6800, 0xfcff, DSPInterpreter::movax, 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}, + {"MOVR", 0x6000, 0xf8ff, DSPInterpreter::movr, 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}, + {"MOVP", 0x6e00, 0xfeff, DSPInterpreter::movp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MOVPZ", 0xfe00, 0xfeff, DSPInterpreter::movpz, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"ADDPAXZ", 0xf800, 0xfcff, DSPInterpreter::addpaxz, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, //Think the args are wrong + {"ADDP", 0x4e00, 0xfeff, DSPInterpreter::addp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"LSL16", 0xf000, 0xfeff, DSPInterpreter::lsl16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"LSR16", 0xf400, 0xfeff, DSPInterpreter::lsr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"ASR16", 0x9100, 0xf7ff, DSPInterpreter::asr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"XORR", 0x3000, 0xfcff, DSPInterpreter::xorr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"ANDR", 0x3400, 0xfcff, DSPInterpreter::andr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"ORR", 0x3800, 0xfcff, DSPInterpreter::orr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"ANDC", 0x3C00, 0xfeff, DSPInterpreter::andc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this + {"ORC", 0x3E00, 0xfeff, DSPInterpreter::orc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this + + {"MULX", 0xa000, 0xe7ff, DSPInterpreter::mulx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULXMVZ", 0xa200, 0xe6ff, DSPInterpreter::mulxmvz, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULXAC", 0xa400, 0xe6ff, DSPInterpreter::mulxac, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULXMV", 0xa600, 0xe6ff, DSPInterpreter::mulxmv, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"MUL", 0x9000, 0xf7ff, DSPInterpreter::mul, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULMVZ", 0x9200, 0xf6ff, DSPInterpreter::mulmvz, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULAC", 0x9400, 0xf6ff, DSPInterpreter::mulac, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULMV", 0x9600, 0xf6ff, DSPInterpreter::mulmv, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"MULC", 0xc000, 0xe7ff, DSPInterpreter::mulc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULCMVZ", 0xc200, 0xe6ff, DSPInterpreter::mulcmvz, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULCAC", 0xc400, 0xe6ff, DSPInterpreter::mulcac, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MULCMV", 0xc600, 0xe6ff, DSPInterpreter::mulcmv, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + + {"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}, + {"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}, + {"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}, + {"MSUB", 0xf600, 0xfeff, DSPInterpreter::msub , 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}, + {"MADDX", 0xe000, 0xfcff, DSPInterpreter::maddx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MSUBX", 0xe400, 0xfcff, DSPInterpreter::msubx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MADDC", 0xe800, 0xfcff, DSPInterpreter::maddc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, + {"MSUBC", 0xec00, 0xfcff, DSPInterpreter::msubc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, +}; + +const DSPOPCTemplate cw = + {"CW", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, NULL, NULL,}; + + +const DSPOPCTemplate opcodes_ext[] = +{ + {"L", 0x0040, 0x00c4, nop, nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"LN", 0x0044, 0x00c4, nop, nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"LS", 0x0080, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, + {"LSN", 0x0084, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, + {"LSM", 0x0088, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, + {"LSNM", 0x008c, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,}, + {"SL", 0x0082, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, + {"SLN", 0x0086, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, + {"SLM", 0x008a, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, + {"SLNM", 0x008e, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,}, + {"S", 0x0020, 0x00e4, nop, nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,}, + {"SN", 0x0024, 0x00e4, nop, nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,}, + {"LDX", 0x00c0, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,}, + {"LDXN", 0x00c4, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,}, + {"LDXM", 0x00c8, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,}, + {"LDXNM", 0x00cc, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,}, + {"LD", 0x00c0, 0x00cc, nop, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"LDN", 0x00c4, 0x00cc, nop, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"LDM", 0x00c8, 0x00cc, nop, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"LDNM", 0x00cc, 0x00cc, nop, nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"MV", 0x0010, 0x00f0, nop, nop, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"DR", 0x0004, 0x00fc, nop, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"IR", 0x0008, 0x00fc, nop, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"NR", 0x000c, 0x00fc, nop, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, + {"XXX", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, NULL, NULL,}, +}; + +const u32 opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate); +const u32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate); + +const pdlabel_t pdlabels[] = +{ + {0xffa0, "COEF_A1_0", "COEF_A1_0",}, + {0xffa1, "COEF_A2_0", "COEF_A2_0",}, + {0xffa2, "COEF_A1_1", "COEF_A1_1",}, + {0xffa3, "COEF_A2_1", "COEF_A2_1",}, + {0xffa4, "COEF_A1_2", "COEF_A1_2",}, + {0xffa5, "COEF_A2_2", "COEF_A2_2",}, + {0xffa6, "COEF_A1_3", "COEF_A1_3",}, + {0xffa7, "COEF_A2_3", "COEF_A2_3",}, + {0xffa8, "COEF_A1_4", "COEF_A1_4",}, + {0xffa9, "COEF_A2_4", "COEF_A2_4",}, + {0xffaa, "COEF_A1_5", "COEF_A1_5",}, + {0xffab, "COEF_A2_5", "COEF_A2_5",}, + {0xffac, "COEF_A1_6", "COEF_A1_6",}, + {0xffad, "COEF_A2_6", "COEF_A2_6",}, + {0xffae, "COEF_A1_7", "COEF_A1_7",}, + {0xffaf, "COEF_A2_7", "COEF_A2_7",}, + {0xffc9, "DSCR", "DSP DMA Control Reg",}, + {0xffcb, "DSBL", "DSP DMA Block Length",}, + {0xffcd, "DSPA", "DSP DMA DMEM Address",}, + {0xffce, "DSMAH", "DSP DMA Mem Address H",}, + {0xffcf, "DSMAL", "DSP DMA Mem Address L",}, + {0xffd1, "SampleFormat", "SampleFormat",}, + + {0xffd3, "Unk Zelda", "Unk Zelda writes to it",}, + + {0xffd4, "ACSAH", "Accelerator start address H",}, + {0xffd5, "ACSAL", "Accelerator start address L",}, + {0xffd6, "ACEAH", "Accelerator end address H",}, + {0xffd7, "ACEAL", "Accelerator end address L",}, + {0xffd8, "ACCAH", "Accelerator current address H",}, + {0xffd9, "ACCAL", "Accelerator current address L",}, + {0xffda, "pred_scale", "pred_scale",}, + {0xffdb, "yn1", "yn1",}, + {0xffdc, "yn2", "yn2",}, + {0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",}, + {0xffde, "GAIN", "Gain",}, + {0xffef, "AMDM", "ARAM DMA Request Mask",}, + {0xfffb, "DIRQ", "DSP IRQ Request",}, + {0xfffc, "DMBH", "DSP Mailbox H",}, + {0xfffd, "DMBL", "DSP Mailbox L",}, + {0xfffe, "CMBH", "CPU Mailbox H",}, + {0xffff, "CMBL", "CPU Mailbox L",}, +}; + +const u32 pdlabels_size = sizeof(pdlabels) / sizeof(pdlabel_t); + +const pdlabel_t regnames[] = +{ + {0x00, "AR0", "Register 00",}, + {0x01, "AR1", "Register 01",}, + {0x02, "AR2", "Register 02",}, + {0x03, "AR3", "Register 03",}, + {0x04, "IX0", "Register 04",}, + {0x05, "IX1", "Register 05",}, + {0x06, "IX2", "Register 06",}, + {0x07, "IX3", "Register 07",}, + {0x08, "R08", "Register 08",}, + {0x09, "R09", "Register 09",}, + {0x0a, "R10", "Register 10",}, + {0x0b, "R11", "Register 11",}, + {0x0c, "ST0", "Call stack",}, + {0x0d, "ST1", "Data stack",}, + {0x0e, "ST2", "Loop addr stack",}, + {0x0f, "ST3", "Loop counter",}, + {0x00, "AC0.H", "Accu High 0",}, + {0x11, "AC1.H", "Accu High 1",}, + {0x12, "CR", "Config Register",}, + {0x13, "SR", "Special Register",}, + {0x14, "PROD.L", "Prod L",}, + {0x15, "PROD.M1", "Prod M1",}, + {0x16, "PROD.H", "Prod H",}, + {0x17, "PROD.M2", "Prod M2",}, + {0x18, "AX0.L", "Extra Accu L 0",}, + {0x19, "AX1.L", "Extra Accu L 1",}, + {0x1a, "AX0.H", "Extra Accu H 0",}, + {0x1b, "AX1.H", "Extra Accu H 1",}, + {0x1c, "AC0.L", "Register 28",}, + {0x1d, "AC1.L", "Register 29",}, + {0x1e, "AC0.M", "Register 00",}, + {0x1f, "AC1.M", "Register 00",}, + + // To resolve special names. + {0x20, "ACC0", "Accu Full 0",}, + {0x21, "ACC1", "Accu Full 1",}, + {0x22, "AX0", "Extra Accu 0",}, + {0x23, "AX1", "Extra Accu 1",}, +}; + +u8 opSize[OPTABLE_SIZE]; +dspInstFunc opTable[OPTABLE_SIZE]; +dspInstFunc prologueTable[OPTABLE_SIZE]; +dspInstFunc epilogueTable[OPTABLE_SIZE]; + + +const char* pdname(u16 val) +{ + static char tmpstr[12]; // nasty + + for (int i = 0; i < (int)(sizeof(pdlabels) / sizeof(pdlabel_t)); i++) + { + if (pdlabels[i].addr == val) + return pdlabels[i].name; + } + + sprintf(tmpstr, "0x%04x", val); + return tmpstr; +} + +const char *pdregname(int val) +{ + return regnames[val].name; +} + +const char *pdregnamelong(int val) +{ + return regnames[val].description; +} + +const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst) +{ + for (u32 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]; + } + return NULL; +} + + +// This function could use the above GetOpTemplate, but then we'd lose the +// nice property that it catches colliding op masks. +void InitInstructionTable() +{ + for (int i = 0; i < OPTABLE_SIZE; i++) + { + opTable[i] = DSPInterpreter::unknown; + prologueTable[i] = NULL; + epilogueTable[i] = NULL; + opSize[i] = 0; + } + + for (int i = 0; i < OPTABLE_SIZE; i++) + { + for (u32 j = 0; j < opcodes_size; j++) + { + u16 mask = opcodes[j].opcode_mask; + if (opcodes[j].size & P_EXT) { + // Ignore extension bits. + mask &= 0xFF00; + } + if ((mask & i) == opcodes[j].opcode) + { + if (opTable[i] == DSPInterpreter::unknown) + { + opTable[i] = opcodes[j].interpFunc; + opSize[i] = opcodes[j].size & 3; + prologueTable[i] = opcodes[j].prologue; + epilogueTable[i] = opcodes[j].epilogue; + } + else + { + ERROR_LOG(DSPLLE, "opcode table place %d already in use for %s", i, opcodes[j].name); + } + } + } + } +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.h b/Source/Core/DSPCore/Src/DSPTables.h similarity index 75% rename from Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.h rename to Source/Core/DSPCore/Src/DSPTables.h index fa32afa43a..64ffef51d0 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPTables.h +++ b/Source/Core/DSPCore/Src/DSPTables.h @@ -22,7 +22,9 @@ #include "Common.h" -enum parameterType +// The ones that end with _D are the opposite one - if the bit specify +// ACC0, then ACC_D will be ACC1. +enum partype_t { P_NONE = 0x0000, P_VAL = 0x0001, @@ -31,7 +33,6 @@ enum parameterType P_STR = 0x0004, P_REG = 0x8000, P_REG08 = P_REG | 0x0800, - P_REG10 = P_REG | 0x1000, P_REG18 = P_REG | 0x1800, P_REGM18 = P_REG | 0x1810, // used in multiply instructions P_REG19 = P_REG | 0x1900, @@ -39,17 +40,21 @@ enum parameterType P_REG1A = P_REG | 0x1a00, P_REG1C = P_REG | 0x1c00, // P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value) - P_ACCD = P_REG | 0x1c80, + P_ACC_D = P_REG | 0x1c80, + P_ACCL = P_REG | 0x1c00, // used for mid accum P_ACCM = P_REG | 0x1e00, // used for mid accum // The following are not in gcdsptool P_ACCM_D = P_REG | 0x1e80, - P_ACC = P_REG | 0x2000, - P_ACC_D = P_REG | 0x2080, + P_ACC = P_REG | 0x2000, // used for global accum. P_AX = P_REG | 0x2200, - P_AX_D = P_REG | 0x2280, P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80 P_REF = P_REG | 0x4000, P_PRG = P_REF | P_REG, + + // The following seem like junk: + // P_REG10 = P_REG | 0x1000, + // P_AX_D = P_REG | 0x2280, + }; #define P_EXT 0x80 @@ -81,14 +86,14 @@ union UDSPInstruction typedef void (*dspInstFunc)(const UDSPInstruction&); -typedef struct +struct param2_t { - parameterType type; + partype_t type; u8 size; u8 loc; s8 lshift; u16 mask; -} DSPOParams; +}; typedef struct { @@ -101,21 +106,41 @@ typedef struct u8 size; u8 param_count; - DSPOParams params[8]; + param2_t params[8]; dspInstFunc prologue; dspInstFunc epilogue; } DSPOPCTemplate; -extern DSPOPCTemplate opcodes[]; +typedef DSPOPCTemplate opc_t; + +// Opcodes +extern const DSPOPCTemplate opcodes[]; extern const u32 opcodes_size; -extern DSPOPCTemplate opcodes_ext[]; +extern const DSPOPCTemplate opcodes_ext[]; extern const u32 opcodes_ext_size; extern u8 opSize[OPTABLE_SIZE]; +extern const DSPOPCTemplate cw; extern dspInstFunc opTable[]; extern dspInstFunc prologueTable[OPTABLE_SIZE]; extern dspInstFunc epilogueTable[OPTABLE_SIZE]; +// Predefined labels +struct pdlabel_t +{ + u16 addr; + const char* name; + const char* description; +}; + +extern const pdlabel_t regnames[]; +extern const pdlabel_t pdlabels[]; +extern const u32 pdlabels_size; + +const char *pdname(u16 val); +const char *pdregname(int val); +const char *pdregnamelong(int val); + void InitInstructionTable(); inline void ExecuteInstruction(const UDSPInstruction& inst) diff --git a/Source/Core/DSPCore/Src/SConscript b/Source/Core/DSPCore/Src/SConscript new file mode 100644 index 0000000000..c4a00c16ee --- /dev/null +++ b/Source/Core/DSPCore/Src/SConscript @@ -0,0 +1,24 @@ +# -*- python -*- + +Import('env') + +files = [ + "disassemble.cpp", + "gdsp_aram.cpp", + "gdsp_condition_codes.cpp", + "gdsp_ext_op.cpp", + "gdsp_interface.cpp", + "gdsp_interpreter.cpp", + "gdsp_memory.cpp", + "gdsp_registers.cpp", + "DSPAnalyzer.cpp", + "DSPInterpreter.cpp", + "DSPJit.cpp", + "DSPHost.cpp", + "DSPTables.cpp", + ] + +acenv = env.Clone() +acenv.Append(CXXFLAGS = [ '-fPIC' ]) + +acenv.StaticLibrary('dspcore', files) diff --git a/Source/Core/DSPCore/Src/assemble.cpp b/Source/Core/DSPCore/Src/assemble.cpp new file mode 100644 index 0000000000..403bffbc2f --- /dev/null +++ b/Source/Core/DSPCore/Src/assemble.cpp @@ -0,0 +1,1034 @@ +/*==================================================================== + +$Id: assemble.cpp,v 1.3 2008-11-11 01:04:26 wntrmute Exp $ + +project: GameCube DSP Tool (gcdsp) +mail: duddie@walla.com + +Copyright (c) 2005 Duddie + +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; either version 2 +of the License, or (at your option) any later version. + +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 for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Revision 1.4 2008/10/04 10:30:00 Hermes +added function to export the code to .h file +added support for '/ *' '* /' and '//' for comentaries +added some sintax detection when use registers + +$Log: not supported by cvs2svn $ +Revision 1.2 2005/09/14 02:19:29 wntrmute +added header guards +use standard main function + +Revision 1.1 2005/08/24 22:13:34 wntrmute +Initial import + + +====================================================================*/ + +#include +#include +#include + +#include + +#include "Common.h" +#include "DSPInterpreter.h" +#include "DSPTables.h" +#include "disassemble.h" +//#include "gdsp_tool.h" + +char *include_dir = NULL; + +struct label_t +{ + char *label; + s32 addr; +}; + +struct param_t +{ + u32 val; + partype_t type; + char *str; +}; + +enum segment_t +{ + SEGMENT_CODE = 0, + SEGMENT_DATA, + SEGMENT_OVERLAY, + SEGMENT_MAX +}; + +typedef struct fass_t +{ + FILE *fsrc; + u32 code_line; + bool failed; +} fass_t; + +label_t labels[10000]; +int labels_count = 0; + +segment_t cur_segment; +u32 cur_addr; +u8 cur_pass; +fass_t *cur_fa; + +typedef std::map AliasMap; +AliasMap aliases; + +u32 segment_addr[SEGMENT_MAX]; + +int current_param = 0; + +typedef enum err_t +{ + ERR_OK = 0, + ERR_UNKNOWN, + ERR_UNKNOWN_OPCODE, + ERR_NOT_ENOUGH_PARAMETERS, + ERR_TOO_MANY_PARAMETERS, + ERR_WRONG_PARAMETER, + ERR_EXPECTED_PARAM_STR, + ERR_EXPECTED_PARAM_VAL, + ERR_EXPECTED_PARAM_REG, + ERR_EXPECTED_PARAM_MEM, + ERR_EXPECTED_PARAM_IMM, + ERR_INCORRECT_BIN, + ERR_INCORRECT_HEX, + ERR_INCORRECT_DEC, + ERR_LABEL_EXISTS, + ERR_UNKNOWN_LABEL, + ERR_NO_MATCHING_BRACKETS, + ERR_EXT_CANT_EXTEND_OPCODE, + ERR_EXT_PAR_NOT_EXT, + ERR_WRONG_PARAMETER_ACC, + ERR_WRONG_PARAMETER_MID_ACC, + ERR_INVALID_REGISTER, + ERR_OUT_RANGE_NUMBER +}; + +char *err_string[] = +{ + "", + "Unknown Error", + "Unknown opcode", + "Not enough parameters", + "Too many parameters", + "Wrong parameter", + "Expected parameter of type 'string'", + "Expected parameter of type 'value'", + "Expected parameter of type 'register'", + "Expected parameter of type 'memory pointer'", + "Expected parameter of type 'immediate'", + "Incorrect binary value", + "Incorrect hexadecimal value", + "Incorrect decimal value", + "Label already exists", + "Label not defined", + "No matching brackets", + "This opcode cannot be extended", + "Given extending params for non extensible opcode", + "Wrong parameter: must be accumulator register", + "Wrong parameter: must be mid accumulator register", + "Invalid register", + "Number out of range" +}; + +void parse_error(err_t err_code, fass_t *fa, const char *extra_info = NULL) +{ + fa->failed = true; + if (!extra_info) + extra_info = "-"; + if (fa->fsrc) + fclose(fa->fsrc); + else + { + fprintf(stderr, "ERROR: %s : %s\n", err_string[err_code], extra_info); + } + + // modified by Hermes + + if (current_param == 0) + fprintf(stderr, "ERROR: %s Line: %d : %s\n", err_string[err_code], fa->code_line, extra_info); + else + fprintf(stderr, "ERROR: %s Line: %d Param: %d : %s\n", + err_string[err_code], fa->code_line, current_param, extra_info); +} + +char *skip_spaces(char *ptr) +{ + while (*ptr == ' ') + ptr++; + return ptr; +} + +const char *skip_spaces(const char *ptr) +{ + while (*ptr == ' ') + ptr++; + return ptr; +} + +void gd_ass_register_label(const char *label, u16 lval) +{ + labels[labels_count].label = (char *)malloc(strlen(label) + 1); + strcpy(labels[labels_count].label, label); + labels[labels_count].addr = lval; + labels_count++; +} + +void gd_ass_clear_labels() +{ + for (int i = 0; i < labels_count; i++) + { + free(labels[i].label); + } + labels_count = 0; +} + +// Parse a standalone value - it can be a number in one of several formats or a label. +s32 strtoval(const char *str) +{ + bool negative = false; + s32 val = 0; + const char *ptr = str; + + if (ptr[0] == '#') + { + ptr++; + negative = true; // Wow! # negates??? + } + if (ptr[0] == '0') + { + if (ptr[1] >= '0' && ptr[1] <= '9') + { + for (int i = 0; ptr[i] != 0; i++) + { + val *= 10; + if (ptr[i] >= '0' && ptr[i] <= '9') + val += ptr[i] - '0'; + else + parse_error(ERR_INCORRECT_DEC, cur_fa, str); + } + } + else + { + switch (ptr[1]) + { + case 'X': // hex + for (int i = 2 ; ptr[i] != 0 ; i++) + { + val *=16; + if (ptr[i] >= 'a' && ptr[i] <= 'f') + val += (ptr[i]-'a'+10); + else if (ptr[i] >= 'A' && ptr[i] <= 'F') + val += (ptr[i]-'A'+10); + else if (ptr[i] >= '0' && ptr[i] <= '9') + val += (ptr[i]-'0'); + else + parse_error(ERR_INCORRECT_HEX, cur_fa, str); + } + break; + case '\'': // binary + for (int i = 2; ptr[i] != 0; i++) + { + val *=2; + if(ptr[i] >= '0' && ptr[i] <= '1') + val += ptr[i] - '0'; + else + parse_error(ERR_INCORRECT_BIN, cur_fa, str); + } + break; + default: + // value is 0 or error + val = 0; + break; + } + } + } + else + { + // Symbol starts with a digit - it's a dec number. + if (ptr[0] >= '0' && ptr[0] <= '9') + { + for (int i = 0; ptr[i] != 0; i++) + { + val *= 10; + if (ptr[i] >= '0' && ptr[i] <= '9') + val += ptr[i] - '0'; + else + parse_error(ERR_INCORRECT_DEC, cur_fa, str); + } + } + else // Everything else is a label. + { + // Lookup label + for (int i = 0; i < labels_count; i++) + { + if (strcmp(labels[i].label, ptr) == 0) + return labels[i].addr; + } + if (cur_pass == 2) + parse_error(ERR_UNKNOWN_LABEL, cur_fa, str); + } + } + if (negative) + return -val; + return val; +} + + +// Modifies both src and dst! +// What does it do, really?? +char *find_brackets(char *src, char *dst) +{ + s32 len = (s32) strlen(src); + s32 first = -1; + s32 count = 0; + s32 i, j; + j = 0; + for (i = 0 ; i < len ; i++) + { + if (src[i] == '(') + { + if (first < 0) + { + count = 1; + src[i] = 0x0; + first = i; + } + else + { + count++; + dst[j++] = src[i]; + } + } + else if (src[i] == ')') + { + if (--count == 0) + { + dst[j] = 0; + return &src[i+1]; + } + else + { + dst[j++] = src[i]; + } + } + else + { + if(first >= 0) + dst[j++] = src[i]; + } + } + if (count) + parse_error(ERR_NO_MATCHING_BRACKETS, cur_fa); + return NULL; +} + +// Bizarre in-place expression evaluator. +u32 parse_exp(const char *ptr) +{ + char *pbuf; + s32 val = 0; + + char *d_buffer = (char *)malloc(1024); + char *s_buffer = (char *)malloc(1024); + strcpy(s_buffer, ptr); + + while ((pbuf = find_brackets(s_buffer, d_buffer)) != NULL) + { + val = parse_exp(d_buffer); + sprintf(d_buffer, "%s%d%s", s_buffer, val, pbuf); + strcpy(s_buffer, d_buffer); + } + + int j = 0; + for (int i = 0; i < ((s32)strlen(s_buffer) + 1) ; i++) + { + char c = s_buffer[i]; + if (c != ' ') + d_buffer[j++] = c; + } + + for (int i = 0; i < ((s32)strlen(d_buffer) + 1) ; i++) + { + char c = d_buffer[i]; + if (c == '-') + { + if (i == 0) + c = '#'; + else + { + switch (d_buffer[i - 1]) + { + case '/': + case '%': + case '*': + c = '#'; + } + } + } + d_buffer[i] = c; + } + while ((pbuf = strstr(d_buffer, "+")) != NULL) + { + *pbuf = 0x0; + val = parse_exp(d_buffer) + parse_exp(pbuf+1); + sprintf(d_buffer, "%d", val); + } + + while ((pbuf = strstr(d_buffer, "-")) != NULL) + { + *pbuf = 0x0; + val = parse_exp(d_buffer) - parse_exp(pbuf+1); + if (val < 0) + { + val = 0x10000 + (val & 0xffff); // ATTENTION: avoid a terrible bug!!! number cannot write with '-' in sprintf + if(cur_fa) + fprintf(stderr, "WARNING: Number Underflow at Line: %d \n", cur_fa->code_line); + } + sprintf(d_buffer, "%d", val); + } + + while ((pbuf = strstr(d_buffer, "*")) != NULL) + { + *pbuf = 0x0; + val = parse_exp(d_buffer) * parse_exp(pbuf+1); + sprintf(d_buffer, "%d", val); + } + + while ((pbuf = strstr(d_buffer, "/")) != NULL) + { + *pbuf = 0x0; + val = parse_exp(d_buffer) / parse_exp(pbuf+1); + sprintf(d_buffer, "%d", val); + } + + while ((pbuf = strstr(d_buffer, "|")) != NULL) + { + *pbuf = 0x0; + val = parse_exp(d_buffer) | parse_exp(pbuf+1); + sprintf(d_buffer, "%d", val); + } + + while ((pbuf = strstr(d_buffer, "&")) != NULL) + { + *pbuf = 0x0; + val = parse_exp(d_buffer) & parse_exp(pbuf+1); + sprintf(d_buffer, "%d", val); + } + + val = strtoval(d_buffer); + free(d_buffer); + free(s_buffer); + return val; +} + +u32 parse_exp_f(const char *ptr, fass_t *fa) +{ + cur_fa = fa; + return parse_exp(ptr); +} + +// Destroys parstr +u32 get_params(char *parstr, param_t *par, fass_t *fa) +{ + u32 count = 0; + char *tmpstr = skip_spaces(parstr); + tmpstr = strtok(tmpstr, ",\x00"); + for (int i = 0; i < 10; i++) + { + if (tmpstr == NULL) + break; + tmpstr = skip_spaces(tmpstr); + if (strlen(tmpstr) == 0) + break; + if (tmpstr) + count++; + else + break; + + par[i].type = P_NONE; + switch (tmpstr[0]) + { + case '"': + par[i].str = strtok(tmpstr, "\""); + par[i].type = P_STR; + break; + case '#': + par[i].val = parse_exp_f(tmpstr + 1, fa); + par[i].type = P_IMM; + break; + case '@': + if (tmpstr[1] == '$') + { + par[i].val = parse_exp_f(tmpstr + 2, fa); + par[i].type = P_PRG; + } + else + { + par[i].val = parse_exp_f(tmpstr + 1, fa); + par[i].type = P_MEM; + } + break; + case '$': + par[i].val = parse_exp_f(tmpstr + 1, fa); + par[i].type = P_REG; + break; + default: + par[i].val = parse_exp_f(tmpstr, fa); + par[i].type = P_VAL; + break; + } + tmpstr = strtok(NULL, ",\x00"); + } + return count; +} + +const opc_t *find_opcode(const char *opcode, u32 par_count, const opc_t * const opcod, u32 opcod_size, fass_t *fa) +{ + if (opcode[0] == 'C' && opcode[1] == 'W') + return &cw; + + AliasMap::const_iterator alias_iter = aliases.find(opcode); + if (alias_iter != aliases.end()) + opcode = alias_iter->second.c_str(); + for (int i = 0; i < opcod_size; i++) + { + const opc_t *opc = &opcod[i]; + if (strcmp(opc->name, opcode) == 0) + { + if (par_count < opc->param_count) + { + parse_error(ERR_NOT_ENOUGH_PARAMETERS, fa); + } + if (par_count > opc->param_count) + { + parse_error(ERR_TOO_MANY_PARAMETERS, fa); + } + return opc; + } + } + parse_error(ERR_UNKNOWN_OPCODE, fa); + return NULL; +} + +// weird... +u16 get_mask(u16 mask) +{ + while (!(mask & 1)) + mask >>= 1; + return mask; +} + +bool verify_params(const opc_t *opc, param_t *par, u32 count, fass_t *fa) +{ + int value; + unsigned int valueu; + for (u32 i = 0; i < count; i++) + { + current_param = i+1; + if (opc->params[i].type != par[i].type || (par[i].type & P_REG)) + { + if ((opc->params[i].type & P_REG) && (par[i].type & P_REG)) + { + // modified by Hermes: test the register range + switch ((unsigned)opc->params[i].type) + { + case P_REG18: + case P_REG19: + case P_REG1A: + //case P_REG1C: + value = (opc->params[i].type >> 8) & 31; + if ((int)par[i].val < value || + (int)par[i].val > value + get_mask(opc->params[i].mask)) + { + parse_error(ERR_INVALID_REGISTER, fa); + } + break; + case P_PRG: + if ((int)par[i].val < 0 || (int)par[i].val > 0x3) + { + parse_error(ERR_INVALID_REGISTER, fa); + } + break; + case P_ACC: + if ((int)par[i].val < 0x20 || (int)par[i].val > 0x21) + { + if (par[i].val >= 0x1e && par[i].val <= 0x1f) + fprintf(stderr, "WARNING: $ACM%d register used instead $ACC%d register Line: %d Param: %d\n", + (par[i].val & 1), (par[i].val & 1), fa->code_line, current_param); + else if (par[i].val >= 0x1c && par[i].val <= 0x1d) + fprintf(stderr, "WARNING: $ACL%d register used instead $ACC%d register Line: %d Param: %d\n", + (par[i].val & 1), (par[i].val & 1), fa->code_line, current_param); + else + parse_error(ERR_WRONG_PARAMETER_ACC, fa); + } + break; + case P_ACCM: + if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f) + { + if (par[i].val >= 0x1c && par[i].val <= 0x1d) + fprintf(stderr, "WARNING: $ACL%d register used instead $ACM%d register Line: %d Param: %d\n", + (par[i].val & 1), (par[i].val & 1), fa->code_line, current_param); + else if (par[i].val >= 0x20 && par[i].val <= 0x21) + fprintf(stderr, "WARNING: $ACC%d register used instead $ACM%d register Line: %d Param: %d\n", + (par[i].val & 1), (par[i].val & 1), fa->code_line, current_param); + else + parse_error(ERR_WRONG_PARAMETER_ACC, fa); + } + break; + + case P_ACCL: + if ((int)par[i].val < 0x1c || (int)par[i].val > 0x1d) + { + if (par[i].val >= 0x1e && par[i].val <= 0x1f) + fprintf(stderr, "WARNING: $ACM%d register used instead $ACL%d register Line: %d Param: %d\n", + (par[i].val & 1), (par[i].val & 1), fa->code_line, current_param); + else if (par[i].val >= 0x20 && par[i].val <= 0x21) + fprintf(stderr, "WARNING: $ACC%d register used instead $ACL%d register Line: %d Param: %d\n", + (par[i].val & 1), (par[i].val & 1), fa->code_line, current_param); + else + parse_error(ERR_WRONG_PARAMETER_ACC, fa); + } + break; +/* case P_ACCM_D: //P_ACC_MID: + if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f) + { + parse_error(ERR_WRONG_PARAMETER_MID_ACC, fa); + } + break;*/ + } + continue; + } + + switch (par[i].type & (P_REG | P_VAL | P_MEM | P_IMM)) + { + case P_REG: + parse_error(ERR_EXPECTED_PARAM_REG, fa); + break; + case P_MEM: + parse_error(ERR_EXPECTED_PARAM_MEM, fa); + break; + case P_VAL: + parse_error(ERR_EXPECTED_PARAM_VAL, fa); + break; + case P_IMM: + parse_error(ERR_EXPECTED_PARAM_IMM, fa); + break; + } + parse_error(ERR_WRONG_PARAMETER, fa); + break; + } + else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0) + { + // modified by Hermes: test NUMBER range + value = get_mask(opc->params[i].mask); + + valueu = 0xffff & ~(value >> 1); + if((int)par[i].val < 0) + { + if (value == 7) // value 7 por sbclr/sbset + { + fprintf(stderr,"Value must be from 0x0 to 0x%x\n", value); + parse_error(ERR_OUT_RANGE_NUMBER, fa); + } + else if (opc->params[i].type == P_MEM) + { + if (value < 256) + fprintf(stderr,"Address value must be from 0x%x to 0x%x\n",valueu, (value>>1)); + else + fprintf(stderr,"Address value must be from 0x0 to 0x%x\n", value); + + parse_error(ERR_OUT_RANGE_NUMBER, fa); + } + else if ((int)par[i].val < -((value>>1)+1)) + { + if (value < 128) + fprintf(stderr,"Value must be from -0x%x to 0x%x\n",((value>>1)+1), ((value>>1))); + else + fprintf(stderr,"Value must be from -0x%x to 0x%x or 0x0 to 0x%x\n",((value>>1)+1), ((value>>1)),value); + + parse_error(ERR_OUT_RANGE_NUMBER, fa); + } + } + else + { + if (value == 7) // value 7 por sbclr/sbset + { + if (par[i].val > (unsigned)value) + { + fprintf(stderr,"Value must be from 0x%x to 0x%x\n",valueu, value); + parse_error(ERR_OUT_RANGE_NUMBER, fa); + } + } + else if (opc->params[i].type == P_MEM) + { + if (value < 256) + value >>= 1; // addressing 8 bit with sign + if (par[i].val > (unsigned)value && + (par[i].val < valueu || par[i].val > (unsigned)0xffff)) + { + if (value < 256) + fprintf(stderr,"Address value must be from 0x%x to 0x%x\n", valueu, value); + else + fprintf(stderr,"Address value must be minor of 0x%x\n", value+1); + parse_error(ERR_OUT_RANGE_NUMBER, fa); + } + } + else + { + if (value < 128) + value >>= 1; // special case ASL/ASR/LSL/LSR + if (par[i].val > (unsigned)value) + { + if (value < 64) + fprintf(stderr,"Value must be from -0x%x to 0x%x\n", (value + 1), value); + else + fprintf(stderr,"Value must be minor of 0x%x\n", value + 1); + parse_error(ERR_OUT_RANGE_NUMBER, fa); + } + } + } + continue; + } + } + current_param = 0; + return true; +} + + +// Merge opcode with params. +void build_code(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++) + { + if (opc->params[i].type != P_ACC_D && opc->params[i].type != P_ACCM_D) + { + u16 t16 = outbuf[cur_addr + opc->params[i].loc]; + u16 v16 = par[i].val; + if (opc->params[i].lshift > 0) + v16 <<= opc->params[i].lshift; + else + v16 >>= -opc->params[i].lshift; + v16 &= opc->params[i].mask; + outbuf[cur_addr + opc->params[i].loc] = t16 | v16; + } + } +} + +void gd_ass_init_pass(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 < pdlabels_size; i++) + { + gd_ass_register_label(pdlabels[i].name, pdlabels[i].addr); + } + aliases.clear(); + aliases["S15"] = "SET15"; + aliases["S16"] = "SET16"; + aliases["S40"] = "SET40"; + } + cur_addr = 0; + cur_segment = SEGMENT_CODE; + segment_addr[SEGMENT_CODE] = 0; + segment_addr[SEGMENT_DATA] = 0; + segment_addr[SEGMENT_OVERLAY] = 0; +} + +bool gd_ass_file(gd_globals_t *gdg, const char *fname, int pass) +{ + fass_t fa; + int disable_text = 0; // modified by Hermes + + param_t params[10] = {0}; + param_t params_ext[10] = {0}; + u32 params_count = 0; + u32 params_count_ext = 0; + + fa.failed = false; + fa.fsrc = fopen(fname, "r"); + if (fa.fsrc == NULL) + { + fprintf(stderr, "Cannot open %s file\n", fname); + return false; + } + + fseek(fa.fsrc, 0, SEEK_SET); + printf("Pass %d\n", pass); + fa.code_line = 0; + cur_pass = pass; + +#define LINEBUF_SIZE 4096 + char linebuffer[LINEBUF_SIZE]; + while (!feof(fa.fsrc) && !fa.failed) + { + int opcode_size = 0; + memset(linebuffer, 0, LINEBUF_SIZE); + if (!fgets(linebuffer, LINEBUF_SIZE, fa.fsrc)) + break; + //printf("A: %s", linebuffer); + fa.code_line++; + + for (int i = 0; i < LINEBUF_SIZE; i++) + { + char c = linebuffer[i]; + // This stuff handles /**/ and // comments. + // modified by Hermes : added // and /* */ for long comentaries + if (c == '/') + { + if (i < 1023) + { + if (linebuffer[i+1] == '/') + c = 0x00; + else if (linebuffer[i+1] == '*') + { + // wtf is this? + disable_text = !disable_text; + } + } + } + else if (c == '*') + { + if (i < 1023 && linebuffer[i+1] == '/' && disable_text) + { + disable_text = 0; + c = 32; + linebuffer[i + 1] = 32; + } + } + + + if(disable_text && ((unsigned char )c)>32) c=32; + + if (c == 0x0a || c == 0x0d || c == ';') + c = 0x00; + if (c == 0x09) // tabs to spaces + c = ' '; + if (c >= 'a' && c <= 'z') // convert to uppercase + c = c - 'a' + 'A'; + linebuffer[i] = c; + if (c == 0) + break; // modified by Hermes + } + char *ptr = linebuffer; + + char *opcode = NULL; + char *label = NULL; + char *col_ptr; + if ((col_ptr = strstr(ptr, ":")) != NULL) + { + int j; + bool valid; + j = 0; + valid = true; + while ((ptr+j) < col_ptr) + { + if (j == 0) + if (!((ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_'))) + valid = false; + if (!((ptr[j] >= '0' && ptr[j] <= '9') || (ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_'))) + valid = false; + j++; + } + if (valid) + { + label = strtok(ptr, ":\x20"); + ptr = col_ptr + 1; + } + } + + opcode = strtok(ptr, " "); + char *opcode_ext = NULL; + + char *paramstr; + char *paramstr_ext; + + if (opcode) + { + if ((opcode_ext = strstr(opcode, "'")) != NULL) + { + opcode_ext[0] = '\0'; + opcode_ext++; + if (strlen(opcode_ext) == 0) + opcode_ext = NULL; + } + // now we have opcode and label + + params_count = 0; + params_count_ext = 0; + + paramstr = paramstr_ext = 0; + // there is valid opcode so probably we have parameters + + paramstr = strtok(NULL, "\0"); + + if (paramstr) + { + if ((paramstr_ext = strstr(paramstr, ":")) != NULL) + { + paramstr_ext[0] = '\0'; + paramstr_ext++; + } + } + + if (paramstr) + params_count = get_params(paramstr, params, &fa); + if (paramstr_ext) + params_count_ext = get_params(paramstr_ext, params_ext, &fa); + } + + if (label) + { + // there is a valid label so lets store it in labels table + u32 lval = cur_addr; + if (opcode) + { + if (strcmp(opcode, "EQU") == 0) + { + lval = params[0].val; + opcode = NULL; + } + } + if (pass == 1) + { + gd_ass_register_label(label, lval); + } + } + + if (opcode == NULL) + continue; + + // check if opcode is reserved compiler word + if (strcmp("INCLUDE", opcode) == 0) + { + if (params[0].type == P_STR) + { + char *tmpstr; + if (include_dir) + { + tmpstr = (char *)malloc(strlen(include_dir) + strlen(params[0].str) + 2); + sprintf(tmpstr, "%s/%s", include_dir, params[0].str); + } + else + { + tmpstr = (char *)malloc(strlen(params[0].str) + 1); + strcpy(tmpstr, params[0].str); + } + gd_ass_file(gdg, tmpstr, pass); + free(tmpstr); + } + else + parse_error(ERR_EXPECTED_PARAM_STR, &fa); + continue; + } + + if (strcmp("INCDIR", opcode) == 0) + { + if (params[0].type == P_STR) + { + if (include_dir) free(include_dir); + include_dir = (char *)malloc(strlen(params[0].str) + 1); + strcpy(include_dir, params[0].str); + } + else + parse_error(ERR_EXPECTED_PARAM_STR, &fa); + continue; + } + + if (strcmp("ORG", opcode) == 0) + { + if (params[0].type == P_VAL) + cur_addr = params[0].val; + else + parse_error(ERR_EXPECTED_PARAM_VAL, &fa); + continue; + } + + if (strcmp("SEGMENT", opcode) == 0) + { + if(params[0].type == P_STR) + { + segment_addr[cur_segment] = cur_addr; + if (strcmp("DATA", params[0].str) == 0) + cur_segment = SEGMENT_DATA; + if (strcmp("CODE", params[0].str) == 0) + cur_segment = SEGMENT_CODE; + cur_addr = segment_addr[cur_segment]; + } + else + parse_error(ERR_EXPECTED_PARAM_STR, &fa); + continue; + } + + const opc_t *opc = find_opcode(opcode, params_count, opcodes, opcodes_size, &fa); + if (!opc) + opc = &cw; + + opcode_size = opc->size & ~P_EXT; + + verify_params(opc, params, params_count, &fa); + + const opc_t *opc_ext = NULL; + // Check for opcode extensions. + if (opc->size & P_EXT) + { + if (opcode_ext) + { + opc_ext = find_opcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size, &fa); + verify_params(opc_ext, params_ext, params_count_ext, &fa); + } + else if (params_count_ext) + parse_error(ERR_EXT_PAR_NOT_EXT, &fa); + } + else + { + if (opcode_ext) + parse_error(ERR_EXT_CANT_EXTEND_OPCODE, &fa); + if (params_count_ext) + parse_error(ERR_EXT_PAR_NOT_EXT, &fa); + } + + if (pass == 2) + { + // generate binary + ((u16 *)gdg->buffer)[cur_addr] = 0x0000; + build_code(opc, params, params_count, (u16 *)gdg->buffer); + if (opc_ext) + build_code(opc_ext, params_ext, params_count_ext, (u16 *)gdg->buffer); + } + + cur_addr += opcode_size; + }; + if (gdg->buffer == NULL) + { + gdg->buffer_size = cur_addr; + gdg->buffer = (char *)malloc(gdg->buffer_size * sizeof(u16) + 4); + memset(gdg->buffer, 0, gdg->buffer_size * sizeof(u16)); + } + fclose(fa.fsrc); + return !fa.failed; +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.cpp b/Source/Core/DSPCore/Src/disassemble.cpp similarity index 64% rename from Source/Plugins/Plugin_DSP_LLE/Src/disassemble.cpp rename to Source/Core/DSPCore/Src/disassemble.cpp index 6cabd4ed2c..3c5e14ffb8 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.cpp +++ b/Source/Core/DSPCore/Src/disassemble.cpp @@ -23,15 +23,12 @@ ====================================================================*/ -#include #include +#include #include -#include "Globals.h" - #include "disassemble.h" #include "DSPTables.h" -// #include "gdsp_tool.h" #ifdef _MSC_VER #pragma warning(disable:4996) @@ -39,117 +36,6 @@ u32 unk_opcodes[0x10000]; - -// predefined labels -typedef struct pdlabel_t -{ - u16 addr; - const char* name; - const char* description; -} pdlabels_t; - -const pdlabel_t pdlabels[] = -{ - {0xffa0, "COEF_A1_0", "COEF_A1_0",}, - {0xffa1, "COEF_A2_0", "COEF_A2_0",}, - {0xffa2, "COEF_A1_1", "COEF_A1_1",}, - {0xffa3, "COEF_A2_1", "COEF_A2_1",}, - {0xffa4, "COEF_A1_2", "COEF_A1_2",}, - {0xffa5, "COEF_A2_2", "COEF_A2_2",}, - {0xffa6, "COEF_A1_3", "COEF_A1_3",}, - {0xffa7, "COEF_A2_3", "COEF_A2_3",}, - {0xffa8, "COEF_A1_4", "COEF_A1_4",}, - {0xffa9, "COEF_A2_4", "COEF_A2_4",}, - {0xffaa, "COEF_A1_5", "COEF_A1_5",}, - {0xffab, "COEF_A2_5", "COEF_A2_5",}, - {0xffac, "COEF_A1_6", "COEF_A1_6",}, - {0xffad, "COEF_A2_6", "COEF_A2_6",}, - {0xffae, "COEF_A1_7", "COEF_A1_7",}, - {0xffaf, "COEF_A2_7", "COEF_A2_7",}, - {0xffc9, "DSCR", "DSP DMA Control Reg",}, - {0xffcb, "DSBL", "DSP DMA Block Length",}, - {0xffcd, "DSPA", "DSP DMA DMEM Address",}, - {0xffce, "DSMAH", "DSP DMA Mem Address H",}, - {0xffcf, "DSMAL", "DSP DMA Mem Address L",}, - {0xffd1, "SampleFormat", "SampleFormat",}, - - {0xffd3, "Unk Zelda", "Unk Zelda writes to it",}, - - {0xffd4, "ACSAH", "Accelerator start address H",}, - {0xffd5, "ACSAL", "Accelerator start address L",}, - {0xffd6, "ACEAH", "Accelerator end address H",}, - {0xffd7, "ACEAL", "Accelerator end address L",}, - {0xffd8, "ACCAH", "Accelerator current address H",}, - {0xffd9, "ACCAL", "Accelerator current address L",}, - {0xffda, "pred_scale", "pred_scale",}, - {0xffdb, "yn1", "yn1",}, - {0xffdc, "yn2", "yn2",}, - {0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",}, - {0xffde, "GAIN", "Gain",}, - {0xffef, "AMDM", "ARAM DMA Request Mask",}, - {0xfffb, "DIRQ", "DSP IRQ Request",}, - {0xfffc, "DMBH", "DSP Mailbox H",}, - {0xfffd, "DMBL", "DSP Mailbox L",}, - {0xfffe, "CMBH", "CPU Mailbox H",}, - {0xffff, "CMBL", "CPU Mailbox L",}, -}; - -pdlabel_t regnames[] = -{ - {0x00, "AR0", "Register 00",}, - {0x01, "AR1", "Register 01",}, - {0x02, "AR2", "Register 02",}, - {0x03, "AR3", "Register 03",}, - {0x04, "IX0", "Register 04",}, - {0x05, "IX1", "Register 05",}, - {0x06, "IX2", "Register 06",}, - {0x07, "IX3", "Register 07",}, - {0x08, "R08", "Register 08",}, - {0x09, "R09", "Register 09",}, - {0x0a, "R10", "Register 10",}, - {0x0b, "R11", "Register 11",}, - {0x0c, "ST0", "Call stack",}, - {0x0d, "ST1", "Data stack",}, - {0x0e, "ST2", "Loop addr stack",}, - {0x0f, "ST3", "Loop counter",}, - {0x00, "AC0.H", "Accu High 0",}, - {0x11, "AC1.H", "Accu High 1",}, - {0x12, "CR", "Config Register",}, - {0x13, "SR", "Special Register",}, - {0x14, "PROD.L", "Prod L",}, - {0x15, "PROD.M1", "Prod M1",}, - {0x16, "PROD.H", "Prod H",}, - {0x17, "PROD.M2", "Prod M2",}, - {0x18, "AX0.L", "Extra Accu L 0",}, - {0x19, "AX1.L", "Extra Accu L 1",}, - {0x1a, "AX0.H", "Extra Accu H 0",}, - {0x1b, "AX1.H", "Extra Accu H 1",}, - {0x1c, "AC0.L", "Register 28",}, - {0x1d, "AC1.L", "Register 29",}, - {0x1e, "AC0.M", "Register 00",}, - {0x1f, "AC1.M", "Register 00",}, - - // To resolve special names. - {0x20, "ACC0", "Accu Full 0",}, - {0x21, "ACC1", "Accu Full 1",}, - {0x22, "AX0", "Extra Accu 0",}, - {0x23, "AX1", "Extra Accu 1",}, -}; - -const char* pdname(u16 val) -{ - static char tmpstr[12]; // nasty - - for (int i = 0; i < (int)(sizeof(pdlabels) / sizeof(pdlabel_t)); i++) - { - if (pdlabels[i].addr == val) - return pdlabels[i].name; - } - - sprintf(tmpstr, "0x%04x", val); - return tmpstr; -} - extern void nop(const UDSPInstruction& opc); char* gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* opc, u16 op1, u16 op2, char* strbuf) @@ -185,7 +71,7 @@ char* gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* opc, u16 op1, u16 o if (type & P_REG) { - if (type == P_ACCD) // Used to be P_ACCM_D TODO verify + 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; @@ -197,14 +83,14 @@ char* gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* opc, u16 op1, u16 o { case P_REG: if (gdg->decode_registers) - sprintf(buf, "$%s", regnames[val].name); + sprintf(buf, "$%s", pdregname(val)); else sprintf(buf, "$%d", val); break; case P_PRG: if (gdg->decode_registers) - sprintf(buf, "@$%s", regnames[val].name); + sprintf(buf, "@$%s", pdregname(val)); else sprintf(buf, "@$%d", val); break; @@ -252,10 +138,11 @@ char* gd_dis_params(gd_globals_t* gdg, const DSPOPCTemplate* opc, u16 op1, u16 o u16 gd_dis_get_opcode_size(gd_globals_t* gdg) { - DSPOPCTemplate* opc = 0; - DSPOPCTemplate* opc_ext = 0; + const DSPOPCTemplate* opc = 0; + const DSPOPCTemplate* opc_ext = 0; bool extended; + // Undefined memory. if ((gdg->pc & 0x7fff) >= 0x1000) return 1; @@ -300,30 +187,28 @@ u16 gd_dis_get_opcode_size(gd_globals_t* gdg) break; } } - if (!opc_ext) { ERROR_LOG(DSPLLE, "get_opcode_size ext ARGH"); } - return opc_ext->size; } - return(opc->size & ~P_EXT); + return opc->size & ~P_EXT; } + char* gd_dis_opcode(gd_globals_t* gdg) { - u32 j; - u32 op1, op2; - const DSPOPCTemplate *opc = NULL; - const DSPOPCTemplate *opc_ext = NULL; - u16 pc; - char* buf = gdg->buffer; - bool extended; + u32 op2; + char *buf = gdg->buffer; - pc = gdg->pc; - *buf = '\0'; + u16 pc = gdg->pc; + + // Start with a space. + buf[0] = ' '; + buf[1] = '\0'; + buf++; if ((pc & 0x7fff) >= 0x1000) { @@ -332,10 +217,12 @@ char* gd_dis_opcode(gd_globals_t* gdg) } pc &= 0x0fff; - op1 = gdg->binbuf[pc]; + u32 op1 = gdg->binbuf[pc]; + const DSPOPCTemplate *opc = NULL; + const DSPOPCTemplate *opc_ext = NULL; // find opcode - for (j = 0; j < opcodes_size; j++) + for (int j = 0; j < opcodes_size; j++) { u16 mask; @@ -356,6 +243,7 @@ char* gd_dis_opcode(gd_globals_t* gdg) if (!opc) opc = &fake_op; + bool extended; if (opc->size & P_EXT && op1 & 0x00ff) extended = true; else @@ -365,7 +253,7 @@ char* gd_dis_opcode(gd_globals_t* gdg) { // opcode has an extension // find opcode - for (j = 0; j < opcodes_ext_size; j++) + for (int j = 0; j < opcodes_ext_size; j++) { if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) { @@ -446,10 +334,10 @@ char* gd_dis_opcode(gd_globals_t* gdg) else gdg->pc += opc->size & ~P_EXT; - return(gdg->buffer); + return gdg->buffer; } -bool gd_dis_file(gd_globals_t* gdg, char* name, FILE* output) +bool gd_dis_file(gd_globals_t* gdg, const char* name, FILE* output) { gd_dis_open_unkop(); @@ -457,9 +345,10 @@ bool gd_dis_file(gd_globals_t* gdg, char* name, FILE* output) u32 size; in = fopen(name, "rb"); - - if (in == NULL) + if (in == NULL) { + printf("gd_dis_file: No input\n"); return false; + } fseek(in, 0, SEEK_END); size = (int)ftell(in); @@ -547,9 +436,7 @@ void gd_dis_open_unkop() } else { - int i; - - for (i = 0; i < 0x10000; i++) + for (int i = 0; i < 0x10000; i++) { unk_opcodes[i] = 0; } diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.h b/Source/Core/DSPCore/Src/disassemble.h similarity index 89% rename from Source/Plugins/Plugin_DSP_LLE/Src/disassemble.h rename to Source/Core/DSPCore/Src/disassemble.h index 07e59a95d4..8a01011276 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.h +++ b/Source/Core/DSPCore/Src/disassemble.h @@ -1,6 +1,5 @@ /*==================================================================== - filename: opcodes.h project: GameCube DSP Tool (gcdsp) created: 2005.03.04 mail: duddie@walla.com @@ -23,7 +22,8 @@ ====================================================================*/ -#pragma once +#ifndef _DSP_DISASSEMBLE_H +#define _DSP_DISASSEMBLE_H #include "Common.h" @@ -44,7 +44,10 @@ struct gd_globals_t char* gd_dis_opcode(gd_globals_t* gdg); -bool gd_dis_file(gd_globals_t* gdg, char* name, FILE* output); +bool gd_dis_file(gd_globals_t* gdg, const char* name, FILE* output); + void gd_dis_close_unkop(); void gd_dis_open_unkop(); const char* gd_dis_get_reg_name(u16 reg); + +#endif // _DSP_DISASSEMBLE_H diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp b/Source/Core/DSPCore/Src/gdsp_aram.cpp similarity index 86% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp rename to Source/Core/DSPCore/Src/gdsp_aram.cpp index ccca9b4954..b3cb15d67e 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp +++ b/Source/Core/DSPCore/Src/gdsp_aram.cpp @@ -15,7 +15,8 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "Globals.h" +#include "Common.h" +#include "DSPHost.h" #include "gdsp_interface.h" #include "gdsp_interpreter.h" @@ -26,7 +27,7 @@ s16 ADPCM_Step(u32& _rSamplePos) if (((_rSamplePos) & 15) == 0) { - gdsp_ifx_regs[DSP_PRED_SCALE] = g_dspInitialize.pARAM_Read_U8((_rSamplePos & ~15) >> 1); + gdsp_ifx_regs[DSP_PRED_SCALE] = DSPHost_ReadHostMemory((_rSamplePos & ~15) >> 1); _rSamplePos += 2; } @@ -37,8 +38,8 @@ s16 ADPCM_Step(u32& _rSamplePos) s32 coef2 = pCoefTable[coef_idx * 2 + 1]; int temp = (_rSamplePos & 1) ? - (g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) & 0xF) : - (g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4); + (DSPHost_ReadHostMemory(_rSamplePos >> 1) & 0xF) : + (DSPHost_ReadHostMemory(_rSamplePos >> 1) >> 4); if (temp >= 8) temp -= 16; @@ -77,7 +78,7 @@ u16 dsp_read_aram() break; case 0x0A: // 16-bit PCM audio - val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1); + val = (DSPHost_ReadHostMemory(Address) << 8) | DSPHost_ReadHostMemory(Address + 1); gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1]; gdsp_ifx_regs[DSP_YN1] = val; @@ -86,7 +87,7 @@ u16 dsp_read_aram() break; default: - val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1); + val = (DSPHost_ReadHostMemory(Address) << 8) | DSPHost_ReadHostMemory(Address + 1); Address += 2; ERROR_LOG(DSPLLE, "Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]); break; diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.h b/Source/Core/DSPCore/Src/gdsp_aram.h similarity index 100% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.h rename to Source/Core/DSPCore/Src/gdsp_aram.h diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_condition_codes.cpp b/Source/Core/DSPCore/Src/gdsp_condition_codes.cpp similarity index 100% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_condition_codes.cpp rename to Source/Core/DSPCore/Src/gdsp_condition_codes.cpp diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_condition_codes.h b/Source/Core/DSPCore/Src/gdsp_condition_codes.h similarity index 95% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_condition_codes.h rename to Source/Core/DSPCore/Src/gdsp_condition_codes.h index 33743a067b..df28775210 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_condition_codes.h +++ b/Source/Core/DSPCore/Src/gdsp_condition_codes.h @@ -22,7 +22,7 @@ // Anything to do with SR and conditions goes here. -#include "Globals.h" +#include "Common.h" #include "gdsp_registers.h" diff --git a/Source/Core/DSPCore/Src/gdsp_ext_op.cpp b/Source/Core/DSPCore/Src/gdsp_ext_op.cpp new file mode 100644 index 0000000000..18b604cb08 --- /dev/null +++ b/Source/Core/DSPCore/Src/gdsp_ext_op.cpp @@ -0,0 +1,281 @@ +/*==================================================================== + + filename: opcodes.h + project: GameCube DSP Tool (gcdsp) + created: 2005.03.04 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie + + 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; either version 2 + of the License, or (at your option) any later version. + + 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 for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + + +// THIS MAY BE IMPORTANT +// +// At the moment just ls and sl are using the prolog +// perhaps all actions on r03 must be in the prolog +// + +#include "gdsp_opcodes_helper.h" + +void dsp_op_ext_r_epi(const UDSPInstruction& opc) +{ + u8 op = (opc.hex >> 2) & 0x3; + u8 reg = opc.hex & 0x3; + + switch (op) + { + case 0x00: + ERROR_LOG(DSPLLE, "dsp_op_ext_r_epi"); + break; + + case 0x01: + g_dsp.r[reg]--; + break; + + case 0x02: + g_dsp.r[reg]++; + break; + + case 0x03: + g_dsp.r[reg] += g_dsp.r[reg + 4]; + break; + } +} + + +void dsp_op_ext_mv(const UDSPInstruction& opc) +{ + u8 sreg = opc.hex & 0x3; + u8 dreg = ((opc.hex >> 2) & 0x3); + + g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c]; +} + + +void dsp_op_ext_s(const UDSPInstruction& opc) +{ + u8 dreg = opc.hex & 0x3; + u8 sreg = ((opc.hex >> 3) & 0x3) + 0x1c; + + dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); + + if (opc.hex & 0x04) + { + g_dsp.r[dreg] += g_dsp.r[dreg + 4]; + } + else + { + g_dsp.r[dreg]++; + } +} + + +void dsp_op_ext_l(const UDSPInstruction& opc) +{ + u8 sreg = opc.hex & 0x3; + u8 dreg = ((opc.hex >> 3) & 0x7) + 0x18; + + u16 val = dsp_dmem_read(g_dsp.r[sreg]); + g_dsp.r[dreg] = val; + + if (opc.hex & 0x04) + { + g_dsp.r[sreg] += g_dsp.r[sreg + 4]; + } + else + { + g_dsp.r[sreg]++; + } +} + + +void dsp_op_ext_ls_pro(const UDSPInstruction& opc) +{ + u8 areg = (opc.hex & 0x1) + 0x1e; + dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]); + + if (opc.hex & 0x8) + { + g_dsp.r[0x03] += g_dsp.r[0x07]; + } + else + { + g_dsp.r[0x03]++; + } +} + + +void dsp_op_ext_ls_epi(const UDSPInstruction& opc) +{ + u8 dreg = ((opc.hex >> 4) & 0x3) + 0x18; + u16 val = dsp_dmem_read(g_dsp.r[0x00]); + dsp_op_write_reg(dreg, val); + + if (opc.hex & 0x4) + { + g_dsp.r[0x00] += g_dsp.r[0x04]; + } + else + { + g_dsp.r[0x00]++; + } +} + + +void dsp_op_ext_sl_pro(const UDSPInstruction& opc) +{ + u8 areg = (opc.hex & 0x1) + 0x1e; + dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]); + + if (opc.hex & 0x4) + { + g_dsp.r[0x00] += g_dsp.r[0x04]; + } + else + { + g_dsp.r[0x00]++; + } +} + + +void dsp_op_ext_sl_epi(const UDSPInstruction& opc) +{ + u8 dreg = ((opc.hex >> 4) & 0x3) + 0x18; + u16 val = dsp_dmem_read(g_dsp.r[0x03]); + dsp_op_write_reg(dreg, val); + + if (opc.hex & 0x8) + { + g_dsp.r[0x03] += g_dsp.r[0x07]; + } + else + { + g_dsp.r[0x03]++; + } +} + + +void dsp_op_ext_ld(const UDSPInstruction& opc) +{ + u8 dreg1 = (((opc.hex >> 5) & 0x1) << 1) + 0x18; + u8 dreg2 = (((opc.hex >> 4) & 0x1) << 1) + 0x19; + u8 sreg = opc.hex & 0x3; + g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); + g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]); + + if (opc.hex & 0x04) + { + g_dsp.r[sreg] += g_dsp.r[sreg + 0x04]; + } + else + { + g_dsp.r[sreg]++; + } + + if (opc.hex & 0x08) + { + g_dsp.r[0x03] += g_dsp.r[0x07]; + } + else +{ + g_dsp.r[0x03]++; + } +} + + +// ================================================================================ +// +// +// +// ================================================================================ + +void dsp_op_ext_ops_pro(const UDSPInstruction& opc) +{ + if ((opc.hex & 0xFF) == 0){return;} + + switch ((opc.hex >> 4) & 0xf) + { + case 0x00: + dsp_op_ext_r_epi(opc.hex); + break; + + case 0x01: + dsp_op_ext_mv(opc.hex); + break; + + case 0x02: + case 0x03: + dsp_op_ext_s(opc.hex); + break; + + case 0x04: + case 0x05: + case 0x06: + case 0x07: + dsp_op_ext_l(opc.hex); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + + if (opc.hex & 0x2) + { + dsp_op_ext_sl_pro(opc.hex); + } + else + { + dsp_op_ext_ls_pro(opc.hex); + } + + return; + + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dsp_op_ext_ld(opc.hex); + break; + } +} + + +void dsp_op_ext_ops_epi(const UDSPInstruction& opc) +{ + if ((opc.hex & 0xFF) == 0){return;} + + switch ((opc.hex >> 4) & 0xf) + { + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + + if (opc.hex & 0x2) + { + dsp_op_ext_sl_epi(opc.hex); + } + else + { + dsp_op_ext_ls_epi(opc.hex); + } + + return; + } +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.h b/Source/Core/DSPCore/Src/gdsp_ext_op.h similarity index 59% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.h rename to Source/Core/DSPCore/Src/gdsp_ext_op.h index 16c36b3235..85c045833b 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.h +++ b/Source/Core/DSPCore/Src/gdsp_ext_op.h @@ -37,37 +37,5 @@ void dsp_op_ext_ops_pro(const UDSPInstruction& opc); // run any prologs void dsp_op_ext_ops_epi(const UDSPInstruction& opc); // run any epilogs -namespace DSPInterpreter -{ -namespace Ext -{ - -void l(const UDSPInstruction& opc); -void ln(const UDSPInstruction& opc); -void ls(const UDSPInstruction& opc); -void lsn(const UDSPInstruction& opc); -void lsm(const UDSPInstruction& opc); -void lsnm(const UDSPInstruction& opc); -void sl(const UDSPInstruction& opc); -void sln(const UDSPInstruction& opc); -void slm(const UDSPInstruction& opc); -void slnm(const UDSPInstruction& opc); -void s(const UDSPInstruction& opc); -void sn(const UDSPInstruction& opc); -void ldx(const UDSPInstruction& opc); -void ldxn(const UDSPInstruction& opc); -void ldxm(const UDSPInstruction& opc); -void ldxnm(const UDSPInstruction& opc); -void ld(const UDSPInstruction& opc); -void ldn(const UDSPInstruction& opc); -void ldm(const UDSPInstruction& opc); -void ldnm(const UDSPInstruction& opc); -void mv(const UDSPInstruction& opc); -void dr(const UDSPInstruction& opc); -void ir(const UDSPInstruction& opc); -void nr(const UDSPInstruction& opc); - -} // end namespace Ext -} // end namespace DSPinterpeter #endif diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp b/Source/Core/DSPCore/Src/gdsp_interface.cpp similarity index 93% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp rename to Source/Core/DSPCore/Src/gdsp_interface.cpp index 3a12dcae9e..f5e864bcfa 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp +++ b/Source/Core/DSPCore/Src/gdsp_interface.cpp @@ -25,16 +25,16 @@ #include -#include "Globals.h" #include "Thread.h" #include "MemoryUtil.h" +#include "DSPHost.h" #include "DSPAnalyzer.h" #include "gdsp_aram.h" #include "gdsp_interpreter.h" #include "gdsp_interface.h" -#include "Tools.h" +// #include "Tools.h" void gdsp_dma(); @@ -60,10 +60,10 @@ void gdsp_ifx_init() u32 gdsp_mbox_peek(u8 mbx) { - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Enter(); u32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]); - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Leave(); return value; } @@ -71,21 +71,21 @@ u32 gdsp_mbox_peek(u8 mbx) void gdsp_mbox_write_h(u8 mbx, u16 val) { - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Enter(); gdsp_mbox[mbx][0] = val & 0x7fff; - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Leave(); } void gdsp_mbox_write_l(u8 mbx, u16 val) { - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Enter(); gdsp_mbox[mbx][1] = val; gdsp_mbox[mbx][0] |= 0x8000; - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Leave(); if (mbx == GDSP_MBOX_DSP) @@ -103,7 +103,7 @@ u16 gdsp_mbox_read_h(u8 mbx) u16 gdsp_mbox_read_l(u8 mbx) { - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Enter(); u16 val = gdsp_mbox[mbx][1]; @@ -111,7 +111,7 @@ u16 gdsp_mbox_read_l(u8 mbx) DEBUG_LOG(DSPLLE, "- DSP reads mail from mbx %i: %08x (pc=0x%04x)", mbx, gdsp_mbox_peek(mbx), g_dsp.pc); - if (g_dspInitialize.bOnThread) + if (DSPHost_OnThread()) g_CriticalSection.Leave(); return val; } @@ -212,13 +212,10 @@ void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size) *(u16*)&dst[dsp_addr + i] = Common::swap16(*(const u16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff]); } WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false); - - g_dsp.iram_crc = GenerateCRC(g_dsp.cpu_ram + (addr & 0x0fffffff), size); + INFO_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc); - + g_dsp.iram_crc = DSPHost_CodeLoaded(g_dsp.cpu_ram + (addr & 0x0fffffff), size); DSPAnalyzer::Analyze(); - if (g_dsp.dump_imem) - DumpDSPCode(&dst[dsp_addr], size, g_dsp.iram_crc); } diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.h b/Source/Core/DSPCore/Src/gdsp_interface.h similarity index 98% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.h rename to Source/Core/DSPCore/Src/gdsp_interface.h index ec2f6f29c5..80b429b849 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.h +++ b/Source/Core/DSPCore/Src/gdsp_interface.h @@ -25,7 +25,7 @@ #ifndef _GDSP_INTERFACE_H #define _GDSP_INTERFACE_H -#include "Globals.h" +#include "Common.h" #define GDSP_MBOX_CPU 0 #define GDSP_MBOX_DSP 1 diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp b/Source/Core/DSPCore/Src/gdsp_interpreter.cpp similarity index 97% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp rename to Source/Core/DSPCore/Src/gdsp_interpreter.cpp index 029f36111e..9c5fd4136f 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp +++ b/Source/Core/DSPCore/Src/gdsp_interpreter.cpp @@ -28,10 +28,11 @@ #include "DSPTables.h" #include "DSPAnalyzer.h" +#include "DSPHost.h" #include "gdsp_interface.h" #include "gdsp_opcodes_helper.h" -#include "Tools.h" +// #include "Tools.h" #include "MemoryUtil.h" //------------------------------------------------------------------------------- @@ -53,9 +54,6 @@ void UpdateCachedCR() void gdsp_init() { - // Dump IMEM when ucodes get uploaded. Why not... still a plugin heavily in dev. - g_dsp.dump_imem = true; - g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE); g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE); g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE); @@ -318,11 +316,12 @@ void gdsp_run() while (!cr_halt) { // Are we running? - if (*g_dspInitialize.pEmulatorState) + if (DSPHost_Running()) break; gdsp_check_external_int(); - for (int i = 0; i < 500; i++) + // This number (500) is completely arbitrary. TODO: tweak. + for (int i = 0; i < 500 && !cr_halt; i++) gdsp_step(); if (!gdsp_running) diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.h b/Source/Core/DSPCore/Src/gdsp_interpreter.h similarity index 95% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.h rename to Source/Core/DSPCore/Src/gdsp_interpreter.h index 83bd506560..26fd5d2844 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.h +++ b/Source/Core/DSPCore/Src/gdsp_interpreter.h @@ -43,7 +43,7 @@ #ifndef _GDSP_INTERPRETER_H #define _GDSP_INTERPRETER_H -#include "Globals.h" +#include "Common.h" #define DSP_IRAM_BYTE_SIZE 0x2000 #define DSP_IRAM_SIZE 0x1000 @@ -85,17 +85,16 @@ struct SDSP u8* cpu_ram; u16 cr; u8 reg_stack_ptr[4]; - u8 exceptions; // pending exceptiosn? + u8 exceptions; // pending exceptions? + bool exception_in_progress_hack; // is this the same as "exception enabled"? // lets make stack depth to 32 for now u16 reg_stack[4][DSP_STACK_DEPTH]; void (* irq_request)(void); // for debugger only - bool dump_imem; u32 iram_crc; u64 step_counter; - bool exception_in_progress_hack; }; extern SDSP g_dsp; diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.cpp b/Source/Core/DSPCore/Src/gdsp_memory.cpp similarity index 99% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.cpp rename to Source/Core/DSPCore/Src/gdsp_memory.cpp index 1b5d9461f5..8913c4521f 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.cpp +++ b/Source/Core/DSPCore/Src/gdsp_memory.cpp @@ -25,7 +25,6 @@ #include -#include "Globals.h" #include "gdsp_interpreter.h" #include "gdsp_memory.h" #include "gdsp_interface.h" diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.h b/Source/Core/DSPCore/Src/gdsp_memory.h similarity index 98% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.h rename to Source/Core/DSPCore/Src/gdsp_memory.h index de41097c36..2318eb4c58 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.h +++ b/Source/Core/DSPCore/Src/gdsp_memory.h @@ -25,8 +25,7 @@ #ifndef _GDSP_MEMORY_H #define _GDSP_MEMORY_H -#include "Globals.h" - +#include "Common.h" #include "gdsp_interpreter.h" u16 dsp_imem_read(u16 addr); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_opcodes_helper.h b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h similarity index 99% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_opcodes_helper.h rename to Source/Core/DSPCore/Src/gdsp_opcodes_helper.h index 91ff31d5b1..7bfdadd2b8 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_opcodes_helper.h +++ b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h @@ -26,7 +26,7 @@ #ifndef _GDSP_OPCODES_HELPER_H #define _GDSP_OPCODES_HELPER_H -#include "Globals.h" +#include "Common.h" #include "DSPInterpreter.h" diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.cpp b/Source/Core/DSPCore/Src/gdsp_registers.cpp similarity index 98% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.cpp rename to Source/Core/DSPCore/Src/gdsp_registers.cpp index aa74291ec7..f0bec2b5f9 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.cpp +++ b/Source/Core/DSPCore/Src/gdsp_registers.cpp @@ -23,7 +23,7 @@ ====================================================================*/ -#include "Globals.h" +#include "Common.h" #include "gdsp_registers.h" #include "gdsp_interpreter.h" diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.h b/Source/Core/DSPCore/Src/gdsp_registers.h similarity index 99% rename from Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.h rename to Source/Core/DSPCore/Src/gdsp_registers.h index dd927198db..bd611cf02a 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.h +++ b/Source/Core/DSPCore/Src/gdsp_registers.h @@ -25,8 +25,7 @@ #ifndef _GDSP_REGISTERS_H #define _GDSP_REGISTERS_H -#include "Globals.h" - +#include "Common.h" // Register table taken from libasnd #define DSP_REG_AR0 0x00 // address registers @@ -96,5 +95,4 @@ void dsp_reg_store_stack(u8 stack_reg, u16 val); u16 dsp_reg_load_stack(u8 stack_reg); - #endif diff --git a/Source/Core/DiscIO/Src/stdafx.h b/Source/Core/DiscIO/Src/stdafx.h index cd41c1e39e..9069e384d1 100644 --- a/Source/Core/DiscIO/Src/stdafx.h +++ b/Source/Core/DiscIO/Src/stdafx.h @@ -27,7 +27,4 @@ #define _CRT_SECURE_NO_DEPRECATE #endif -#define _SCL_SECURE_NO_DEPRECATE - - // TODO: reference additional headers your program requires here diff --git a/Source/Core/DolphinWX/DolphinWX.vcproj b/Source/Core/DolphinWX/DolphinWX.vcproj index 37141a2294..9244c06392 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcproj +++ b/Source/Core/DolphinWX/DolphinWX.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/DSPTool/SConscript b/Source/DSPTool/SConscript new file mode 100644 index 0000000000..a0092c0fe9 --- /dev/null +++ b/Source/DSPTool/SConscript @@ -0,0 +1,12 @@ +# -*- python -*- + +Import('env') + +files = [ + 'main.cpp', + ] + +acenv = env.Clone() +acenv.Append(CXXFLAGS = [ '-fPIC' ]) + +acenv.Program('dsptool', files) diff --git a/Source/DSPTool/main.cpp b/Source/DSPTool/main.cpp new file mode 100644 index 0000000000..7a98154ca6 --- /dev/null +++ b/Source/DSPTool/main.cpp @@ -0,0 +1,246 @@ +// 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 "Common.h" +#include "FileUtil.h" +#include "assemble.h" +#include "disassemble.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; } +bool DSPHost_Running() { return true; } +u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;} + +bool Assemble(const char *text, std::vector *code) +{ + const char *fname = "tmp.asm"; + gd_globals_t gdg; + memset(&gdg, 0, sizeof(gdg)); + gdg.pc = 0; + // gdg.decode_registers = false; + // gdg.decode_names = false; + gdg.print_tabs = false; + gdg.ext_separator = '\''; + gdg.buffer = 0; + + if (!File::WriteStringToFile(true, text, fname)) + return false; + + // TODO: fix the terrible api of the assembler. + gd_ass_init_pass(1); + if (!gd_ass_file(&gdg, fname, 1)) + return false; + gd_ass_init_pass(2); + if (!gd_ass_file(&gdg, fname, 2)) + return false; + + code->resize(gdg.buffer_size); + for (int i = 0; i < gdg.buffer_size; i++) { + (*code)[i] = *(u16 *)(gdg.buffer + i * 2); + } + return true; +} + +bool Disassemble(const std::vector &code, std::string *text) +{ + if (code.empty()) + return false; + const char *tmp1 = "tmp1.bin"; + const char *tmp2 = "tmp.txt"; + + // First we have to dump the code to a bin file. + FILE *f = fopen(tmp1, "wb"); + fwrite(&code[0], 1, code.size() * 2, f); + fclose(f); + + FILE* t = fopen(tmp2, "w"); + if (t != NULL) + { + gd_globals_t gdg; + memset(&gdg, 0, sizeof(gdg)); + + // These two prevent roundtripping. + gdg.show_hex = false; + gdg.show_pc = false; + gdg.ext_separator = '\''; + gdg.decode_names = false; + gdg.decode_registers = true; + bool success = gd_dis_file(&gdg, tmp1, t); + fclose(t); + + File::ReadStringFromFile(true, tmp2, text); + return success; + } + return false; +} + +void Compare(const std::vector &code1, const std::vector &code2) +{ + if (code1.size() != code2.size()) + printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size()); + int count_equal = 0; + const int min_size = std::min(code1.size(), code2.size()); + for (int i = 0; i < min_size; i++) + { + if (code1[i] == code2[i]) + count_equal++; + else + printf("!! %04x : %04x vs %04x\n", i, code1[i], code2[i]); + } + printf("Equal instruction words: %i / %i\n", count_equal, min_size); +} + +void GenRandomCode(int size, std::vector *code) +{ + code->resize(size); + for (int i = 0; i < size; i++) + { + (*code)[i] = rand() ^ (rand() << 8); + } +} + +void CodeToHeader(std::vector *code, const char *name, std::string *header) +{ + char buffer[1024]; + header->clear(); + header->reserve(code->size() * 4); + header->append("#ifndef _MSCVER\n"); + sprintf(buffer, "const __declspec(align:64) unsigned short %s = {\n"); + header->append(buffer); + header->append("#else\n"); + 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++) + { + if (((i + 1) & 15) == 0) + header->append("\n "); + sprintf(buffer, "%02x, ", code[i]); + header->append(buffer); + } + header->append("\n};\n"); +} + +// This test goes from text ASM to binary to text ASM and once again back to binary. +// Then the two binaries are compared. +bool RoundTrip(const std::vector &code1) +{ + std::vector code2; + std::string text; + Disassemble(code1, &text); + Assemble(text.c_str(), &code2); + Compare(code1, code2); + return true; +} + +// This test goes from text ASM to binary to text ASM and once again back to binary. +// Very convenient for testing. Then the two binaries are compared. +bool SuperTrip(const char *asm_code) +{ + std::vector code1, code2; + std::string text; + if (!Assemble(asm_code, &code1)) + { + printf("SuperTrip: First assembly failed\n"); + return false; + } + printf("First assembly: %i words\n", (int)code1.size()); + if (!Disassemble(code1, &text)) + { + printf("SuperTrip: Disassembly failed\n"); + return false; + } + else + { + //printf("Disass:\n"); + //printf("%s", text.c_str()); + } + if (!Assemble(text.c_str(), &code2)) + { + printf("SuperTrip: Second assembly failed\n"); + return false; + } + Compare(code1, code2); + return true; +} + +void RunAsmTests() +{ + bool fail = false; +#define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true; + + // Let's start out easy - a trivial instruction.. +#if 0 + CHK(" NOP\n"); + + // Now let's do several. + CHK(" NOP\n" + " NOP\n" + " NOP\n"); + + // Turning it up a notch. + CHK(" SET16\n" + " SET40\n" + " CLR15\n" + " M0\n" + " M2\n"); + + // Time to try labels and parameters, and comments. + CHK("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n" + " si @0xfffc, #0x8888\n" + " si @0xfffd, #0xbeef\n" + " si @DIRQ_TEST, #0x0001\n"); + + // Let's see if registers roundtrip. Also try predefined labels. + CHK(" si @0xfffc, #0x8888\n" + " si @0xfffd, #0xbeef\n" + " si @DIRQ, #0x0001\n"); + + // Let's get brutal. We generate random code bytes and make sure that they can + // be roundtripped. We don't expect it to always succeed but it'll be sure to generate + // interesting test cases. + + puts("Insane Random Code Test\n"); + std::vector rand_code; + GenRandomCode(21, &rand_code); + std::string rand_code_text; + Disassemble(rand_code, &rand_code_text); + printf("%s", rand_code_text.c_str()); + RoundTrip(rand_code); +#endif + + std::string dsp_test; + //File::ReadStringFromFile(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test); + + File::ReadStringFromFile(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. + SuperTrip(dsp_test.c_str()); + + if (!fail) + printf("All passed!\n"); +} + +// 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; +} \ No newline at end of file diff --git a/Source/Dolphin.sln b/Source/Dolphin.sln index 2f3ab20f65..2cd566f555 100644 --- a/Source/Dolphin.sln +++ b/Source/Dolphin.sln @@ -150,11 +150,23 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_DSP_LLE", "Plugins\P ProjectSection(ProjectDependencies) = postProject {11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED} {FBAFB369-07EB-4460-9CAD-08BE5789DAB6} = {FBAFB369-07EB-4460-9CAD-08BE5789DAB6} + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED} = {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED} {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSPCore", "Core\DSPCore\DSPCore.vcproj", "{838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}" + ProjectSection(ProjectDependencies) = postProject + {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSPTool", "DSPTool\DSPTool.vcproj", "{1970D175-3DE8-4738-942A-4D98D1CDBF64}" + ProjectSection(ProjectDependencies) = postProject + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED} = {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED} + {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -520,6 +532,36 @@ Global {3D8156A9-64D1-4C8E-ADBE-1B319030E4A4}.Release|Win32.Build.0 = Release|Win32 {3D8156A9-64D1-4C8E-ADBE-1B319030E4A4}.Release|x64.ActiveCfg = Release|x64 {3D8156A9-64D1-4C8E-ADBE-1B319030E4A4}.Release|x64.Build.0 = Release|x64 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Debug|Win32.Build.0 = Debug|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Debug|x64.ActiveCfg = Debug|x64 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Debug|x64.Build.0 = Debug|x64 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.DebugFast|Win32.ActiveCfg = Debug|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.DebugFast|Win32.Build.0 = Debug|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.DebugFast|x64.ActiveCfg = DebugFast|x64 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.DebugFast|x64.Build.0 = DebugFast|x64 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Release_JITIL|Win32.ActiveCfg = Release|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Release_JITIL|Win32.Build.0 = Release|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Release_JITIL|x64.ActiveCfg = Release|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Release|Win32.ActiveCfg = Release|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Release|Win32.Build.0 = Release|Win32 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Release|x64.ActiveCfg = Release|x64 + {838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}.Release|x64.Build.0 = Release|x64 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Debug|Win32.ActiveCfg = Debug|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Debug|Win32.Build.0 = Debug|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Debug|x64.ActiveCfg = Debug|x64 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Debug|x64.Build.0 = Debug|x64 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.DebugFast|Win32.ActiveCfg = Debug|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.DebugFast|Win32.Build.0 = Debug|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.DebugFast|x64.ActiveCfg = DebugFast|x64 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.DebugFast|x64.Build.0 = DebugFast|x64 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Release_JITIL|Win32.ActiveCfg = Release|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Release_JITIL|Win32.Build.0 = Release|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Release_JITIL|x64.ActiveCfg = Release|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Release|Win32.ActiveCfg = Release|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Release|Win32.Build.0 = Release|Win32 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Release|x64.ActiveCfg = Release|x64 + {1970D175-3DE8-4738-942A-4D98D1CDBF64}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/Plugins/Plugin_DSP_LLE/Plugin_DSP_LLE.vcproj b/Source/Plugins/Plugin_DSP_LLE/Plugin_DSP_LLE.vcproj index 222a2169ac..d3e43db09f 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Plugin_DSP_LLE.vcproj +++ b/Source/Plugins/Plugin_DSP_LLE/Plugin_DSP_LLE.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp new file mode 100644 index 0000000000..677b138148 --- /dev/null +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp @@ -0,0 +1,51 @@ +// 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 "Common.h" +#include "DSPHost.h" +#include "Tools.h" +#include "pluginspecs_dsp.h" + +extern DSPInitialize g_dspInitialize; + +// The user of the DSPCore library must supply a few functions so that the +// emulation core can access the environment it runs in. If the emulation +// core isn't used, for example in an asm/disasm tool, then most of these +// can be stubbed out. + +u8 DSPHost_ReadHostMemory(u32 addr) +{ + return g_dspInitialize.pARAM_Read_U8(addr); +} + +bool DSPHost_OnThread() +{ + return g_dspInitialize.bOnThread; +} + +bool DSPHost_Running() +{ + return !(*g_dspInitialize.pEmulatorState); +} + +u32 DSPHost_CodeLoaded(const u8 *ptr, int size) +{ + u32 crc = GenerateCRC(ptr, size); + + DumpDSPCode(ptr, size, crc); + return crc; +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.cpp index 865a787e83..d109c896ee 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.cpp @@ -29,7 +29,6 @@ BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame) EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState) EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC) - EVT_MENU(ID_DUMPCODETOOL, DSPDebuggerLLE::OnDumpCode) EVT_LIST_ITEM_RIGHT_CLICK(ID_DISASM, DSPDebuggerLLE::OnRightClick) EVT_LIST_ITEM_ACTIVATED(ID_DISASM, DSPDebuggerLLE::OnDoubleClick) @@ -63,8 +62,6 @@ void DSPDebuggerLLE::CreateGUIControls() m_Toolbar->AddTool(ID_SHOWPCTOOL, wxT("Show Pc"), wxNullBitmap, wxT("Reset To PC counter"), wxITEM_NORMAL); m_Toolbar->AddTool(ID_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL); m_Toolbar->AddSeparator(); - m_Toolbar->AddCheckTool(ID_DUMPCODETOOL, wxT("Dump"), wxNullBitmap, wxNullBitmap, wxT("Dump UCode to file and disasm")); - m_Toolbar->AddSeparator(); m_Toolbar->AddCheckTool(ID_CHECK_ASSERTINT, wxT("AssertInt"), wxNullBitmap, wxNullBitmap, wxEmptyString); m_Toolbar->AddCheckTool(ID_CHECK_HALT, wxT("Halt"), wxNullBitmap, wxNullBitmap, wxEmptyString); m_Toolbar->AddCheckTool(ID_CHECK_INIT, wxT("Init"), wxNullBitmap, wxNullBitmap, wxEmptyString); @@ -125,11 +122,6 @@ void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event) FocusOnPC(); } -void DSPDebuggerLLE::OnDumpCode(wxCommandEvent& event) -{ - g_dsp.dump_imem = event.IsChecked(); -} - void DSPDebuggerLLE::OnRightClick(wxListEvent& event) { long item = m_Disasm->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); @@ -340,8 +332,6 @@ void DSPDebuggerLLE::UpdateRegisterFlags() if (m_CachedCR == g_dsp.cr) return; - m_Toolbar->ToggleTool(ID_DUMPCODETOOL, g_dsp.dump_imem); - m_Toolbar->ToggleTool(ID_CHECK_ASSERTINT, g_dsp.cr & 0x02 ? true : false); m_Toolbar->ToggleTool(ID_CHECK_HALT, g_dsp.cr & 0x04 ? true : false); m_Toolbar->ToggleTool(ID_CHECK_INIT, g_dsp.cr & 0x800 ? true : false); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.h b/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.h index 735438e782..b62c0c0111 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.h +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/Debugger.h @@ -34,9 +34,9 @@ #include #include -#include "../disassemble.h" -#include "../gdsp_interpreter.h" -#include "../gdsp_memory.h" +#include "disassemble.h" +#include "gdsp_interpreter.h" +#include "gdsp_memory.h" class DSPRegisterView; @@ -66,7 +66,6 @@ private: ID_STEPTOOL, ID_SHOWPCTOOL, ID_JUMPTOTOOL, - ID_DUMPCODETOOL, ID_DISASMDUMPTOOL, ID_CHECK_ASSERTINT, ID_CHECK_HALT, @@ -128,6 +127,7 @@ private: { } }; + typedef std::mapCSymbolMap; CSymbolMap m_SymbolMap; @@ -149,7 +149,6 @@ private: void OnClose(wxCloseEvent& event); void OnChangeState(wxCommandEvent& event); void OnShowPC(wxCommandEvent& event); - void OnDumpCode(wxCommandEvent& event); void OnRightClick(wxListEvent& event); void OnDoubleClick(wxListEvent& event); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Globals.h b/Source/Plugins/Plugin_DSP_LLE/Src/Globals.h index 9e4e543694..48add97e14 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Globals.h +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Globals.h @@ -24,8 +24,6 @@ #define PROFILE 0 -void DSP_DebugBreak(); - u16 Memory_Read_U16(u32 _uAddress); // For PB address detection u32 Memory_Read_U32(u32 _uAddress); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/SConscript b/Source/Plugins/Plugin_DSP_LLE/Src/SConscript index fe833af89f..09212e130e 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/SConscript +++ b/Source/Plugins/Plugin_DSP_LLE/Src/SConscript @@ -13,19 +13,7 @@ if not env['HAVE_AO']: files = [ "Config.cpp", "DSPConfigDlgLLE.cpp", - "disassemble.cpp", - "gdsp_aram.cpp", - "gdsp_condition_codes.cpp", - "gdsp_ext_op.cpp", - "gdsp_interface.cpp", - "gdsp_interpreter.cpp", - "gdsp_memory.cpp", - "gdsp_registers.cpp", "Globals.cpp", - "DSPAnalyzer.cpp", - "DSPInterpreter.cpp", - "DSPJit.cpp", - "DSPTables.cpp", "main.cpp", "Tools.cpp", "Debugger/Debugger.cpp", @@ -38,7 +26,7 @@ files = [ lleenv = env.Clone() lleenv.Append( CXXFLAGS = [ '-fPIC' ], - LIBS = [ 'common', 'audiocommon' ], + LIBS = [ 'common', 'audiocommon', 'dspcore' ], ) lleenv.SharedLibrary(env['plugin_dir']+name, files) diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h b/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h index 3f5870717b..75d1c05685 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h @@ -15,36 +15,12 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#pragma once - -// UDSPControl -union UDSPControl -{ - u16 Hex; - struct - { - unsigned DSPReset : 1; // Write 1 to reset and waits for 0 - unsigned DSPAssertInt : 1; - unsigned DSPHalt : 1; - - unsigned AI : 1; - unsigned AI_mask : 1; - unsigned ARAM : 1; - unsigned ARAM_mask : 1; - unsigned DSP : 1; - unsigned DSP_mask : 1; - - unsigned ARAM_DMAState : 1; // DSPGetDMAStatus() uses this flag - unsigned unk3 : 1; - unsigned DSPInit : 1; // DSPInit() writes to this flag - unsigned pad : 4; - }; - - UDSPControl(u16 _Hex = 0) - : Hex(_Hex) {} -}; +#ifndef _DSPLLE_TOOLS_H +#define _DSPLLE_TOOLS_H bool DumpDSPCode(const u8 *data, u32 _Length, u32 crc); bool DisasmUCodeDump(u32 crc); u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength); bool DumpCWCode(u32 _Address, u32 _Length); + +#endif //_DSPLLE_TOOLS_H diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp deleted file mode 100644 index de1f423c9f..0000000000 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/*==================================================================== - - filename: opcodes.h - project: GameCube DSP Tool (gcdsp) - created: 2005.03.04 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie - - 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; either version 2 - of the License, or (at your option) any later version. - - 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 for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include "Globals.h" -#include "gdsp_opcodes_helper.h" - -// Extended opcodes do not exist on their own. These opcodes can only be -// attached to opcodes that allow extending (8 lower bits of opcode not used by -// opcode). Extended opcodes do not modify program counter $pc register. - - -namespace DSPInterpreter -{ -namespace Ext -{ - -// DR $arR -// xxxx xxxx 0000 01rr -// Decrement addressing register $arR. -void dr(const UDSPInstruction& opc) { - u8 reg = opc.hex & 0x3; - - g_dsp.r[reg]--; -} - -// IR $arR -// xxxx xxxx 0000 10rr -// Increment addressing register $arR. -void ir(const UDSPInstruction& opc) { - u8 reg = opc.hex & 0x3; - - g_dsp.r[reg]++; -} - -// NR $arR -// xxxx xxxx 0000 11rr -// Add corresponding indexing register $ixR to addressing register $arR. -void nr(const UDSPInstruction& opc) { - u8 reg = opc.hex & 0x3; - - g_dsp.r[reg] += g_dsp.r[reg + DSP_REG_IX0]; -} - -// MV $axD, $acS.l -// xxxx xxxx 0001 ddss -// Move value of $acS.l to the $axD.l. -void mv(const UDSPInstruction& opc) -{ - u8 sreg = opc.hex & 0x3; - u8 dreg = ((opc.hex >> 2) & 0x3); - - g_dsp.r[dreg + DSP_REG_AXL0] = g_dsp.r[sreg + DSP_REG_ACC0]; -} - -// S @$D, $acD.l -// xxxx xxxx 001s s0dd -// Store value of $(acS.l) in the memory pointed by register $D. -// Post increment register $D. -void s(const UDSPInstruction& opc) -{ - u8 dreg = opc.hex & 0x3; - u8 sreg = ((opc.hex >> 3) & 0x3) + DSP_REG_ACC0; - - dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); - - g_dsp.r[dreg]++; -} - -// SN @$D, $acD.l -// xxxx xxxx 001s s1dd -// Store value of register $acS in the memory pointed by register $D. -// Add indexing register $ixD to register $D. -void sn(const UDSPInstruction& opc) -{ - u8 dreg = opc.hex & 0x3; - u8 sreg = ((opc.hex >> 3) & 0x3) + DSP_REG_ACC0; - - dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); - - g_dsp.r[dreg] += g_dsp.r[dreg + DSP_REG_IX0]; -} - -// L axD.l, @$S -// xxxx xxxx 01dd d0ss -// Load $axD with value from memory pointed by register $S. -// Post increment register $S. -void l(const UDSPInstruction& opc) -{ - u8 sreg = opc.hex & 0x3; - u8 dreg = ((opc.hex >> 3) & 0x7) + DSP_REG_AXL0; - - u16 val = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg] = val; - - g_dsp.r[sreg]++; -} - -// LN axD.l, @$S -// xxxx xxxx 01dd d0ss -// Load $axD with value from memory pointed by register $S. -// Add indexing register register $ixS to register $S. -void ln(const UDSPInstruction& opc) -{ - u8 sreg = opc.hex & 0x3; - u8 dreg = ((opc.hex >> 3) & 0x7) + DSP_REG_AXL0; - - u16 val = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg] = val; - - g_dsp.r[sreg] += g_dsp.r[sreg + DSP_REG_IX0]; -} - -// Not in duddie's doc -void ld(const UDSPInstruction& opc) -{ - u8 dreg1 = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0; - u8 dreg2 = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1; - u8 sreg = opc.hex & 0x3; - g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); - - g_dsp.r[sreg]++; - g_dsp.r[DSP_REG_AR3]++; -} - -// Not in duddie's doc -void ldn(const UDSPInstruction& opc) -{ - u8 dreg1 = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0; - u8 dreg2 = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1; - u8 sreg = opc.hex & 0x3; - g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); - - g_dsp.r[sreg] += g_dsp.r[sreg + DSP_REG_IX0]; - g_dsp.r[DSP_REG_AR3]++; -} - -// Not in duddie's doc -void ldm(const UDSPInstruction& opc) -{ - u8 dreg1 = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0; - u8 dreg2 = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1; - u8 sreg = opc.hex & 0x3; - g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); - - g_dsp.r[sreg]++; - g_dsp.r[DSP_REG_AR3] += g_dsp.r[DSP_REG_IX3]; -} - -// Not in duddie's doc -void ldnm(const UDSPInstruction& opc) -{ - u8 dreg1 = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0; - u8 dreg2 = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1; - u8 sreg = opc.hex & 0x3; - g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]); - - g_dsp.r[sreg] += g_dsp.r[sreg + DSP_REG_IX0]; - g_dsp.r[DSP_REG_AR3] += g_dsp.r[DSP_REG_IX3]; -} - -} // end namespace ext -} // end namespace DSPInterpeter - -void dsp_op_ext_r_epi(const UDSPInstruction& opc) -{ - u8 op = (opc.hex >> 2) & 0x3; - u8 reg = opc.hex & 0x3; - - switch (op) { - case 0x00: // - ERROR_LOG(DSPLLE, "dsp_op_ext_r_epi"); - break; - - case 0x01: // DR - g_dsp.r[reg]--; - break; - - case 0x02: // IR - g_dsp.r[reg]++; - break; - - case 0x03: // NR - g_dsp.r[reg] += g_dsp.r[reg + 4]; - break; - } -} - - -void dsp_op_ext_mv(const UDSPInstruction& opc) -{ - u8 sreg = opc.hex & 0x3; - u8 dreg = ((opc.hex >> 2) & 0x3); - - g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c]; -} - - -void dsp_op_ext_s(const UDSPInstruction& opc) -{ - u8 dreg = opc.hex & 0x3; - u8 sreg = ((opc.hex >> 3) & 0x3) + 0x1c; - - dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); - - if (opc.hex & 0x04) // SN - { - g_dsp.r[dreg] += g_dsp.r[dreg + 4]; - } - else - { - g_dsp.r[dreg]++; // S - } -} - - -void dsp_op_ext_l(const UDSPInstruction& opc) -{ - u8 sreg = opc.hex & 0x3; - u8 dreg = ((opc.hex >> 3) & 0x7) + 0x18; - - u16 val = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg] = val; - - if (opc.hex & 0x04) // LN/LSMN - { - g_dsp.r[sreg] += g_dsp.r[sreg + 4]; - } - else - { - g_dsp.r[sreg]++; // LS - } -} - - -void dsp_op_ext_ls_pro(const UDSPInstruction& opc) -{ - u8 areg = (opc.hex & 0x1) + 0x1e; - dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]); - - if (opc.hex & 0x8) // LSM/LSMN - { - g_dsp.r[0x03] += g_dsp.r[0x07]; - } - else // LS - { - g_dsp.r[0x03]++; - } -} - - -void dsp_op_ext_ls_epi(const UDSPInstruction& opc) -{ - u8 dreg = ((opc.hex >> 4) & 0x3) + 0x18; - u16 val = dsp_dmem_read(g_dsp.r[0x00]); - dsp_op_write_reg(dreg, val); - - if (opc.hex & 0x4) // LSN/LSMN - { - g_dsp.r[0x00] += g_dsp.r[0x04]; - } - else // LS - { - g_dsp.r[0x00]++; - } -} - - -void dsp_op_ext_sl_pro(const UDSPInstruction& opc) -{ - u8 areg = (opc.hex & 0x1) + 0x1e; - dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]); - - if (opc.hex & 0x4) // SLN/SLNM - { - g_dsp.r[0x00] += g_dsp.r[0x04]; - } - else // SL - { - g_dsp.r[0x00]++; - } -} - - -void dsp_op_ext_sl_epi(const UDSPInstruction& opc) -{ - u8 dreg = ((opc.hex >> 4) & 0x3) + 0x18; - u16 val = dsp_dmem_read(g_dsp.r[0x03]); - dsp_op_write_reg(dreg, val); - - if (opc.hex & 0x8) // SLM/SLMN - { - g_dsp.r[0x03] += g_dsp.r[0x07]; - } - else // SL - { - g_dsp.r[0x03]++; - } -} - - -void dsp_op_ext_ld(const UDSPInstruction& opc) -{ - u8 dreg1 = (((opc.hex >> 5) & 0x1) << 1) + 0x18; - u8 dreg2 = (((opc.hex >> 4) & 0x1) << 1) + 0x19; - u8 sreg = opc.hex & 0x3; - g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]); - - if (opc.hex & 0x04) // N - { - g_dsp.r[sreg] += g_dsp.r[sreg + 0x04]; - } - else - { - g_dsp.r[sreg]++; - } - - if (opc.hex & 0x08) // M - { - g_dsp.r[0x03] += g_dsp.r[0x07]; - } - else -{ - g_dsp.r[0x03]++; - } -} - - -// ================================================================================ -// -// -// -// ================================================================================ - -void dsp_op_ext_ops_pro(const UDSPInstruction& opc) -{ - if ((opc.hex & 0xFF) == 0){return;} - - switch ((opc.hex >> 4) & 0xf) - { - case 0x00: - dsp_op_ext_r_epi(opc.hex); - break; - - case 0x01: - dsp_op_ext_mv(opc.hex); - break; - - case 0x02: - case 0x03: - dsp_op_ext_s(opc.hex); - break; - - case 0x04: - case 0x05: - case 0x06: - case 0x07: - dsp_op_ext_l(opc.hex); - break; - - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - - if (opc.hex & 0x2) - { - dsp_op_ext_sl_pro(opc.hex); - } - else - { - dsp_op_ext_ls_pro(opc.hex); - } - - return; - - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - dsp_op_ext_ld(opc.hex); - break; - } -} - - -void dsp_op_ext_ops_epi(const UDSPInstruction& opc) -{ - if ((opc.hex & 0xFF) == 0){return;} - - switch ((opc.hex >> 4) & 0xf) - { - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - - if (opc.hex & 0x2) - { - dsp_op_ext_sl_epi(opc.hex); - } - else - { - dsp_op_ext_ls_epi(opc.hex); - } - break; - - return; - } -} - - diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index 5971dcc4d8..b88e79b1af 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -308,7 +308,6 @@ void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail) if (_CPUMailbox) { gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail); - } else {