summaryrefslogtreecommitdiff
path: root/Source/Core/DSPCore/Src/DSPIntExtOps.cpp
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2009-06-28 10:00:25 +0000
committerhrydgard <hrydgard@gmail.com>2009-06-28 10:00:25 +0000
commit895b02f4102885d8ab8c4419d76dfef7f4c21703 (patch)
treeea834590ba48451eeef493f22e4eddb57892e02d /Source/Core/DSPCore/Src/DSPIntExtOps.cpp
parent7ea2bc5da9681bca748f783f433ccaf689f7b604 (diff)
DSP: Add txt file with luigi ucode comments (very basic). Rename some stuff. Remove function pointer in g_dsp structure, replace with a "Host" function call. Fix a problem where symbols weren't loaded into DSP debugger.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3563 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore/Src/DSPIntExtOps.cpp')
-rw-r--r--Source/Core/DSPCore/Src/DSPIntExtOps.cpp462
1 files changed, 462 insertions, 0 deletions
diff --git a/Source/Core/DSPCore/Src/DSPIntExtOps.cpp b/Source/Core/DSPCore/Src/DSPIntExtOps.cpp
new file mode 100644
index 0000000000..c9671e139b
--- /dev/null
+++ b/Source/Core/DSPCore/Src/DSPIntExtOps.cpp
@@ -0,0 +1,462 @@
+/*====================================================================
+
+ 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 "DSPIntUtil.h"
+#include "DSPMemoryMap.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.
+
+// Most of the suffixes increment or decrement one or more addressing registers
+// (the first four, ARx). The increment/decrement is either 1, or the corresponding
+// "index" register (the second four, IXx). The addressing registers will wrap
+// in odd ways, dictated by the corresponding wrapping register, WP0-3.
+
+// The following should be applied as a decrement (and is applied by dsp_decrement_addr_reg):
+// ar[i] = (ar[i] & wp[i]) == 0 ? ar[i] | wp[i] : ar[i] - 1;
+// I have not found the corresponding algorithms for increments yet.
+// It's gotta be fairly simple though. See R3123, R3125 in Google Code.
+// (May have something to do with (ar[i] ^ wp[i]) == 0)
+
+/*
+
+namespace DSPInterpreter
+{
+
+namespace Ext
+{
+
+// DR $arR
+// xxxx xxxx 0000 01rr
+// Decrement addressing register $arR.
+void dr(const UDSPInstruction& opc) {
+ dsp_decrement_addr_reg(opc.hex & 0x3);
+}
+
+// IR $arR
+// xxxx xxxx 0000 10rr
+// Increment addressing register $arR.
+void ir(const UDSPInstruction& opc) {
+ dsp_increment_addr_reg(opc.hex & 0x3);
+}
+
+// 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];
+ dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
+}
+
+// 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]);
+
+ dsp_increment_addr_reg(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];
+ dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
+}
+
+// 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;
+
+ dsp_increment_addr_reg(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];
+ dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
+}
+
+// Not in duddie's doc
+// LD $ax0.d $ax1.r @$arS
+// xxxx xxxx 11dr 00ss
+void ld(const UDSPInstruction& opc)
+{
+ u8 dreg = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0;
+ u8 rreg = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1;
+ u8 sreg = opc.hex & 0x3;
+ g_dsp.r[dreg] = dsp_dmem_read(g_dsp.r[sreg]);
+ g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]);
+
+ dsp_increment_addr_reg(sreg);
+ dsp_increment_addr_reg(DSP_REG_AR3);
+}
+
+// Not in duddie's doc
+// LDN $ax0.d $ax1.r @$arS
+// xxxx xxxx 11dr 01ss
+void ldn(const UDSPInstruction& opc)
+{
+ u8 dreg = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0;
+ u8 rreg = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1;
+ u8 sreg = opc.hex & 0x3;
+ g_dsp.r[dreg] = dsp_dmem_read(g_dsp.r[sreg]);
+ g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]);
+
+ g_dsp.r[sreg] += g_dsp.r[sreg + DSP_REG_IX0];
+ dsp_increment_addr_reg(DSP_REG_AR3);
+}
+
+// Not in duddie's doc
+// LDM $ax0.d $ax1.r @$arS
+// xxxx xxxx 11dr 10ss
+void ldm(const UDSPInstruction& opc)
+{
+ u8 dreg = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0;
+ u8 rreg = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1;
+ u8 sreg = opc.hex & 0x3;
+ g_dsp.r[dreg] = dsp_dmem_read(g_dsp.r[sreg]);
+ g_dsp.r[rreg] = dsp_dmem_read(g_dsp.r[DSP_REG_AR3]);
+
+ dsp_increment_addr_reg(sreg);
+ g_dsp.r[DSP_REG_AR3] += g_dsp.r[DSP_REG_IX3];
+}
+
+// Not in duddie's doc
+// LDNM $ax0.d $ax1.r @$arS
+// xxxx xxxx 11dr 11ss
+void ldnm(const UDSPInstruction& opc)
+{
+ u8 dreg = (((opc.hex >> 5) & 0x1) << 1) + DSP_REG_AXL0;
+ u8 rreg = (((opc.hex >> 4) & 0x1) << 1) + DSP_REG_AXL1;
+ u8 sreg = opc.hex & 0x3;
+ g_dsp.r[dreg] = dsp_dmem_read(g_dsp.r[sreg]);
+ g_dsp.r[rreg] = 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: //
+ g_dsp.r[reg] = 0;
+ break;
+
+ case 0x01: // DR
+ dsp_decrement_addr_reg(reg);
+ break;
+
+ case 0x02: // IR
+ dsp_increment_addr_reg(reg);
+ break;
+
+ case 0x03: // NR
+ // g_dsp.r[reg] += g_dsp.r[reg + 4];
+ dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
+ 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];
+ dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
+ }
+ else
+ {
+ dsp_increment_addr_reg(dreg); // S
+ }
+}
+
+
+void dsp_op_ext_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;
+
+ if (opc.hex & 0x04) // LN/LSMN
+ {
+ dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
+ // g_dsp.r[sreg] += g_dsp.r[sreg + 4];
+ }
+ else
+ {
+ dsp_increment_addr_reg(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]);
+ u8 sreg = 0x03;
+
+ if (opc.hex & 0x8) // LSM/LSMN
+ {
+ dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
+ // g_dsp.r[0x03] += g_dsp.r[0x07];
+ }
+ else // LS
+ {
+ dsp_increment_addr_reg(sreg);
+ }
+}
+
+
+void dsp_op_ext_ls_epi(const UDSPInstruction& opc)
+{
+ u8 dreg = ((opc.hex >> 4) & 0x3) + DSP_REG_AXL0;
+ 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];
+ dsp_increase_addr_reg(0x00, (s16)g_dsp.r[DSP_REG_IX0]);
+ }
+ else // LS
+ {
+ dsp_increment_addr_reg(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
+ {
+ dsp_increase_addr_reg(0x00, (s16)g_dsp.r[DSP_REG_IX0]);
+ // g_dsp.r[0x00] += g_dsp.r[0x04];
+ }
+ else // SL
+ {
+ dsp_increment_addr_reg(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);
+ u8 sreg = 0x03;
+
+ if (opc.hex & 0x8) // SLM/SLMN
+ {
+ dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
+ // g_dsp.r[0x03] += g_dsp.r[0x07];
+ }
+ else // SL
+ {
+ dsp_increment_addr_reg(sreg);
+ }
+}
+
+
+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
+ {
+ dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
+ //g_dsp.r[sreg] += g_dsp.r[sreg + 0x04];
+ }
+ else
+ {
+ dsp_increment_addr_reg(sreg);
+ }
+
+ if (opc.hex & 0x08) // M
+ {
+ dsp_increase_addr_reg(0x03, (s16)g_dsp.r[DSP_REG_IX0 + 0x03]);
+ // g_dsp.r[0x03] += g_dsp.r[0x07];
+ }
+ else
+ {
+ dsp_increment_addr_reg(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);
+
+ break;
+
+ 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;
+ }
+}