summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/dsp56156
diff options
context:
space:
mode:
author mooglyguy <therealmogminer@gmail.com>2019-08-19 15:53:47 +0200
committer mooglyguy <therealmogminer@gmail.com>2019-08-19 15:53:47 +0200
commit450a57568e16822d625c3e0cd390e9c9e6a08718 (patch)
tree32d1157ef80d206fda7bfccbd5557828d1261570 /src/devices/cpu/dsp56156
parent93726462006c604f1f6d728be6e7d18065e2d9e2 (diff)
-dsp56k: Renamed relevant classes, files and namespaces to indicate that it is a DSP56156 core, not a DSP5600x core. [Ryan Holtz]
Diffstat (limited to 'src/devices/cpu/dsp56156')
-rw-r--r--src/devices/cpu/dsp56156/dsp56156.cpp515
-rw-r--r--src/devices/cpu/dsp56156/dsp56156.h259
-rw-r--r--src/devices/cpu/dsp56156/dsp56def.h56
-rw-r--r--src/devices/cpu/dsp56156/dsp56dsm.cpp34
-rw-r--r--src/devices/cpu/dsp56156/dsp56dsm.h26
-rw-r--r--src/devices/cpu/dsp56156/dsp56mem.cpp949
-rw-r--r--src/devices/cpu/dsp56156/dsp56mem.h241
-rw-r--r--src/devices/cpu/dsp56156/dsp56ops.hxx4903
-rw-r--r--src/devices/cpu/dsp56156/dsp56pcu.cpp488
-rw-r--r--src/devices/cpu/dsp56156/dsp56pcu.h150
-rw-r--r--src/devices/cpu/dsp56156/inst.cpp786
-rw-r--r--src/devices/cpu/dsp56156/inst.h3774
-rw-r--r--src/devices/cpu/dsp56156/opcode.cpp81
-rw-r--r--src/devices/cpu/dsp56156/opcode.h46
-rw-r--r--src/devices/cpu/dsp56156/pmove.cpp80
-rw-r--r--src/devices/cpu/dsp56156/pmove.h335
-rw-r--r--src/devices/cpu/dsp56156/tables.cpp900
-rw-r--r--src/devices/cpu/dsp56156/tables.h93
18 files changed, 13716 insertions, 0 deletions
diff --git a/src/devices/cpu/dsp56156/dsp56156.cpp b/src/devices/cpu/dsp56156/dsp56156.cpp
new file mode 100644
index 00000000000..a308e5329bc
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56156.cpp
@@ -0,0 +1,515 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+/***************************************************************************
+
+ dsp56156.cpp
+ Core implementation for the portable DSP56156 emulator.
+ Written by Andrew Gardner
+
+****************************************************************************
+
+ Note:
+ This CPU emulator is very much a work-in-progress.
+
+ DONE:
+ 1: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, , , , , , ,18, , ,
+
+ TODO:
+ X 1-6 Explore CORE naming scheme.
+ - 1-9 paragraph 1 : memory access timings
+ - 1-9 Data ALU arithmetic operations generally use fractional two's complement arithmetic
+ (Unsigned numbers are only supported by the multiply and multiply-accumulate instruction)
+ - 1-9 For fractional arithmetic, the 31-bit product is added to the 40-bit contents of A or B. No pipeline!
+ - 1-10 Two types of rounding: convergent rounding and two's complement rounding. See status register bit R.
+ - 1-10 Logic unit is 16-bits wide and works on MSP portion of accum register
+ - 1-10 The AGU can implement three types of arithmetic: linear, modulo, and reverse carry.
+ - 1-12 "Two external interrupt pins!!!"
+ - 1-12 Take care of all interrupt priority (IPR) stuff!
+ - 1-19 Memory WAIT states
+ - 1-20 The timer's interesting!
+ - 1-21 Vectored exception requests on the Host Interface!
+***************************************************************************/
+
+#include "emu.h"
+#include "dsp56156.h"
+#include "dsp56dsm.h"
+
+#include "opcode.h"
+
+#include "debugger.h"
+
+#include "dsp56def.h"
+
+/***************************************************************************
+ COMPONENT FUNCTIONALITY
+***************************************************************************/
+/* 1-9 ALU */
+// #include "dsp56alu.h"
+
+/* 1-10 Address Generation Unit (AGU) */
+// #include "dsp56agu.h"
+
+/* 1-11 Program Control Unit (PCU) */
+#include "dsp56pcu.h"
+
+/* 5-1 Host Interface (HI) */
+//#include "dsp56hi.h"
+
+/* 4-8 Memory handlers for on-chip peripheral memory. */
+#include "dsp56mem.h"
+
+
+DEFINE_DEVICE_TYPE_NS(DSP56156, DSP_56156, dsp56156_device, "dsp56156", "Motorola DSP56156")
+
+
+namespace DSP_56156 {
+
+enum
+{
+ // PCU
+ DSP56156_PC=1,
+ DSP56156_SR,
+ DSP56156_LC,
+ DSP56156_LA,
+ DSP56156_SP,
+ DSP56156_OMR,
+
+ // ALU
+ DSP56156_X, DSP56156_Y,
+ DSP56156_A, DSP56156_B,
+
+ // AGU
+ DSP56156_R0,DSP56156_R1,DSP56156_R2,DSP56156_R3,
+ DSP56156_N0,DSP56156_N1,DSP56156_N2,DSP56156_N3,
+ DSP56156_M0,DSP56156_M1,DSP56156_M2,DSP56156_M3,
+ DSP56156_TEMP,
+ DSP56156_STATUS,
+
+ // CPU STACK
+ DSP56156_ST0,
+ DSP56156_ST1,
+ DSP56156_ST2,
+ DSP56156_ST3,
+ DSP56156_ST4,
+ DSP56156_ST5,
+ DSP56156_ST6,
+ DSP56156_ST7,
+ DSP56156_ST8,
+ DSP56156_ST9,
+ DSP56156_ST10,
+ DSP56156_ST11,
+ DSP56156_ST12,
+ DSP56156_ST13,
+ DSP56156_ST14,
+ DSP56156_ST15
+};
+
+
+/****************************************************************************
+ * Internal Memory Maps
+ ****************************************************************************/
+void dsp56156_device::dsp56156_program_map(address_map &map)
+{
+ map(0x0000, 0x07ff).ram().share("dsk56156_program_ram"); /* 1-5 */
+// AM_RANGE(0x2f00,0x2fff) AM_ROM /* 1-5 PROM reserved memory. Is this the right spot for it? */
+}
+
+void dsp56156_device::dsp56156_x_data_map(address_map &map)
+{
+ map(0x0000, 0x07ff).ram(); /* 1-5 */
+ map(0xffc0, 0xffff).rw(FUNC(dsp56156_device::peripheral_register_r), FUNC(dsp56156_device::peripheral_register_w)); /* 1-5 On-chip peripheral registers memory mapped in data space */
+}
+
+
+dsp56156_device::dsp56156_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : cpu_device(mconfig, DSP56156, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1, address_map_constructor(FUNC(dsp56156_device::dsp56156_program_map), this))
+ , m_data_config("data", ENDIANNESS_LITTLE, 16, 16, -1, address_map_constructor(FUNC(dsp56156_device::dsp56156_x_data_map), this))
+ , m_program_ram(*this, "dsk56156_program_ram")
+{
+}
+
+device_memory_interface::space_config_vector dsp56156_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config),
+ std::make_pair(AS_DATA, &m_data_config)
+ };
+}
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+#define ROPCODE(pc) cpustate->cache->read_word(pc)
+
+
+/***************************************************************************
+ IRQ HANDLING
+***************************************************************************/
+void dsp56156_device::execute_set_input(int irqline, int state)
+{
+ //logerror("DSP56156 set irq line %d %d\n", irqline, state);
+
+ switch(irqline)
+ {
+ case DSP56156_IRQ_MODA:
+ // TODO: 1-12 Get this triggering right
+ if (irqa_trigger(&m_core))
+ logerror("DSP56156 IRQA is set to fire on the \"Negative Edge\".\n");
+
+ if (state != CLEAR_LINE)
+ m_core.modA_state = true;
+ else
+ m_core.modA_state = false;
+
+ if (m_core.reset_state != true)
+ dsp56156_add_pending_interrupt(&m_core, "IRQA");
+ break;
+
+ case DSP56156_IRQ_MODB:
+ // TODO: 1-12 Get this triggering right
+ if (irqb_trigger(&m_core))
+ logerror("DSP56156 IRQB is set to fire on the \"Negative Edge\".\n");
+
+ if (state != CLEAR_LINE)
+ m_core.modB_state = true;
+ else
+ m_core.modB_state = false;
+
+ if (m_core.reset_state != true)
+ dsp56156_add_pending_interrupt(&m_core, "IRQB");
+ break;
+
+ case DSP56156_IRQ_MODC:
+ if (state != CLEAR_LINE)
+ m_core.modC_state = true;
+ else
+ m_core.modC_state = false;
+
+ // TODO : Set bus mode or whatever
+ break;
+
+ case DSP56156_IRQ_RESET:
+ if (state != CLEAR_LINE)
+ m_core.reset_state = true;
+ else
+ {
+ /* If it changes state from asserted to cleared. Call the reset function. */
+ if (m_core.reset_state == true)
+ device_reset();
+
+ m_core.reset_state = false;
+ }
+
+ // dsp56156_add_pending_interrupt("Hardware RESET");
+ break;
+
+ default:
+ logerror("DSP56156 setting some weird irq line : %d", irqline);
+ break;
+ }
+
+ /* If the reset line isn't asserted, service interrupts */
+ // TODO: Is it right to immediately service interrupts?
+ //if (cpustate->reset_state != true)
+ // pcu_service_interrupts();
+}
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+void dsp56156_device::agu_init()
+{
+ /* save states - dsp56156_agu members */
+ save_item(NAME(m_core.AGU.r0));
+ save_item(NAME(m_core.AGU.r1));
+ save_item(NAME(m_core.AGU.r2));
+ save_item(NAME(m_core.AGU.r3));
+ save_item(NAME(m_core.AGU.n0));
+ save_item(NAME(m_core.AGU.n1));
+ save_item(NAME(m_core.AGU.n2));
+ save_item(NAME(m_core.AGU.n3));
+ save_item(NAME(m_core.AGU.m0));
+ save_item(NAME(m_core.AGU.m1));
+ save_item(NAME(m_core.AGU.m2));
+ save_item(NAME(m_core.AGU.m3));
+ save_item(NAME(m_core.AGU.temp));
+}
+
+void dsp56156_device::alu_init()
+{
+ /* save states - dsp56156_alu members */
+ save_item(NAME(m_core.ALU.x));
+ save_item(NAME(m_core.ALU.y));
+ save_item(NAME(m_core.ALU.a));
+ save_item(NAME(m_core.ALU.b));
+}
+
+void dsp56156_device::device_start()
+{
+ memset(&m_core, 0, sizeof(m_core));
+
+ m_core.device = this;
+ m_core.program_ram = m_program_ram;
+
+ /* Call specific module inits */
+ pcu_init(&m_core, this);
+ agu_init();
+ alu_init();
+
+ /* HACK - You're not in bootstrap mode upon bootup */
+ m_core.bootstrap_mode = BOOTSTRAP_OFF;
+
+ /* Clear the irq states */
+ m_core.modA_state = false;
+ m_core.modB_state = false;
+ m_core.modC_state = false;
+ m_core.reset_state = false;
+
+ /* save states - dsp56156_core members */
+ save_item(NAME(m_core.modA_state));
+ save_item(NAME(m_core.modB_state));
+ save_item(NAME(m_core.modC_state));
+ save_item(NAME(m_core.reset_state));
+ save_item(NAME(m_core.bootstrap_mode));
+ save_item(NAME(m_core.repFlag));
+ save_item(NAME(m_core.repAddr));
+ save_item(NAME(m_core.ppc));
+ save_item(NAME(m_core.op));
+ save_item(NAME(m_core.interrupt_cycles));
+
+ /* save states - dsp56156_host_interface members */
+ save_item(NAME(m_core.HI.icr));
+ save_item(NAME(m_core.HI.cvr));
+ save_item(NAME(m_core.HI.isr));
+ save_item(NAME(m_core.HI.ivr));
+ save_item(NAME(m_core.HI.trxh));
+ save_item(NAME(m_core.HI.trxl));
+ save_item(NAME(m_core.HI.bootstrap_offset));
+
+ save_item(NAME(m_core.peripheral_ram));
+
+ m_core.program = &space(AS_PROGRAM);
+ m_core.cache = m_core.program->cache<1, -1, ENDIANNESS_LITTLE>();
+ m_core.data = &space(AS_DATA);
+
+ state_add(DSP56156_PC, "PC", m_core.PCU.pc).formatstr("%04X");
+ state_add(DSP56156_SR, "SR", m_core.PCU.sr).formatstr("%04X");
+ state_add(DSP56156_LC, "LC", m_core.PCU.lc).formatstr("%04X");
+ state_add(DSP56156_LA, "LA", m_core.PCU.la).formatstr("%04X");
+ state_add(DSP56156_SP, "SP", m_core.PCU.sp).formatstr("%02X");
+ state_add(DSP56156_OMR, "OMR", m_core.PCU.omr).formatstr("%02X");
+
+ state_add(DSP56156_X, "X", m_core.ALU.x.d).mask(0xffffffff).formatstr("%9s");
+ state_add(DSP56156_Y, "Y", m_core.ALU.y.d).mask(0xffffffff).formatstr("%9s");
+
+ state_add(DSP56156_A, "A", m_core.ALU.a.q).mask(u64(0xffffffffffffffffU)).formatstr("%12s"); /* could benefit from a better mask? */
+ state_add(DSP56156_B, "B", m_core.ALU.b.q).mask(u64(0xffffffffffffffffU)).formatstr("%12s"); /* could benefit from a better mask? */
+
+ state_add(DSP56156_R0, "R0", m_core.AGU.r0).formatstr("%04X");
+ state_add(DSP56156_R1, "R1", m_core.AGU.r1).formatstr("%04X");
+ state_add(DSP56156_R2, "R2", m_core.AGU.r2).formatstr("%04X");
+ state_add(DSP56156_R3, "R3", m_core.AGU.r3).formatstr("%04X");
+
+ state_add(DSP56156_N0, "N0", m_core.AGU.n0).formatstr("%04X");
+ state_add(DSP56156_N1, "N1", m_core.AGU.n1).formatstr("%04X");
+ state_add(DSP56156_N2, "N2", m_core.AGU.n2).formatstr("%04X");
+ state_add(DSP56156_N3, "N3", m_core.AGU.n3).formatstr("%04X");
+
+ state_add(DSP56156_M0, "M0", m_core.AGU.m0).formatstr("%04X");
+ state_add(DSP56156_M1, "M1", m_core.AGU.m1).formatstr("%04X");
+ state_add(DSP56156_M2, "M2", m_core.AGU.m2).formatstr("%04X");
+ state_add(DSP56156_M3, "M3", m_core.AGU.m3).formatstr("%04X");
+
+ state_add(DSP56156_TEMP, "TMP", m_core.AGU.temp).formatstr("%04X").noshow();
+ //state_add(DSP56156_STATUS, "STS", STATUS).formatstr("%02X");
+
+ state_add(DSP56156_ST0, "ST0", m_core.PCU.ss[0].d).formatstr("%08X");
+ state_add(DSP56156_ST1, "ST1", m_core.PCU.ss[1].d).formatstr("%08X");
+ state_add(DSP56156_ST2, "ST2", m_core.PCU.ss[2].d).formatstr("%08X");
+ state_add(DSP56156_ST3, "ST3", m_core.PCU.ss[3].d).formatstr("%08X");
+ state_add(DSP56156_ST4, "ST4", m_core.PCU.ss[4].d).formatstr("%08X");
+ state_add(DSP56156_ST5, "ST5", m_core.PCU.ss[5].d).formatstr("%08X");
+ state_add(DSP56156_ST6, "ST6", m_core.PCU.ss[6].d).formatstr("%08X");
+ state_add(DSP56156_ST7, "ST7", m_core.PCU.ss[7].d).formatstr("%08X");
+ state_add(DSP56156_ST8, "ST8", m_core.PCU.ss[8].d).formatstr("%08X");
+ state_add(DSP56156_ST9, "ST9", m_core.PCU.ss[9].d).formatstr("%08X");
+ state_add(DSP56156_ST10, "ST10", m_core.PCU.ss[10].d).formatstr("%08X");
+ state_add(DSP56156_ST11, "ST11", m_core.PCU.ss[11].d).formatstr("%08X");
+ state_add(DSP56156_ST12, "ST12", m_core.PCU.ss[12].d).formatstr("%08X");
+ state_add(DSP56156_ST13, "ST13", m_core.PCU.ss[13].d).formatstr("%08X");
+ state_add(DSP56156_ST14, "ST14", m_core.PCU.ss[14].d).formatstr("%08X");
+ state_add(DSP56156_ST15, "ST15", m_core.PCU.ss[15].d).formatstr("%08X");
+
+ state_add(STATE_GENPC, "GENPC", m_core.PCU.pc).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_core.ppc).noshow();
+ state_add(STATE_GENSP, "GENSP", m_core.PCU.sp).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_core.PCU.sr).formatstr("%14s").noshow();
+
+ set_icountptr(m_core.icount);
+}
+
+
+void dsp56156_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ const dsp56156_core *cpustate = &m_core;
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%s%s %s%s%s%s%s%s%s%s %s%s",
+ /* Status Register */
+ LF_bit(cpustate) ? "L" : ".",
+ FV_bit(cpustate) ? "F" : ".",
+
+ S_bit(cpustate) ? "S" : ".",
+ L_bit(cpustate) ? "L" : ".",
+ E_bit(cpustate) ? "E" : ".",
+ U_bit(cpustate) ? "U" : ".",
+ N_bit(cpustate) ? "N" : ".",
+ Z_bit(cpustate) ? "Z" : ".",
+ V_bit(cpustate) ? "V" : ".",
+ C_bit(cpustate) ? "C" : ".",
+
+ /* Stack Pointer */
+ UF_bit(cpustate) ? "U" : ".",
+ SE_bit(cpustate) ? "S" : ".");
+ break;
+
+ case DSP56156_X:
+ str = string_format("%04x %04x", X1, X0);
+ break;
+
+ case DSP56156_Y:
+ str = string_format("%04x %04x", Y1, Y0);
+ break;
+
+ case DSP56156_A:
+ str = string_format("%02x %04x %04x", A2, A1, A0);
+ break;
+
+ case DSP56156_B:
+ str = string_format("%02x %04x %04x", B2, B1, B0);
+ break;
+ }
+}
+
+/***************************************************************************
+ RESET BEHAVIOR
+***************************************************************************/
+static void agu_reset(dsp56156_core* cpustate)
+{
+ /* FM.4-3 */
+ R0 = 0x0000;
+ R1 = 0x0000;
+ R2 = 0x0000;
+ R3 = 0x0000;
+
+ N0 = 0x0000;
+ N1 = 0x0000;
+ N2 = 0x0000;
+ N3 = 0x0000;
+
+ M0 = 0xffff;
+ M1 = 0xffff;
+ M2 = 0xffff;
+ M3 = 0xffff;
+
+ TEMP = 0x0000;
+}
+
+static void alu_reset(dsp56156_core* cpustate)
+{
+ X = 0x00000000;
+ Y = 0x00000000;
+ A = 0x0000000000;
+ B = 0x0000000000;
+}
+
+void dsp56156_device::device_reset()
+{
+ logerror("DSP56156 reset\n");
+
+ m_core.interrupt_cycles = 0;
+
+ m_core.repFlag = 0;
+ m_core.repAddr = 0x0000;
+
+ pcu_reset(&m_core);
+ mem_reset(&m_core);
+ agu_reset(&m_core);
+ alu_reset(&m_core);
+
+ m_core.ppc = m_core.PCU.pc;
+
+ /* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */
+ m_core.program->write_word(0x0000, 0x0124);
+}
+
+
+
+/***************************************************************************
+ CORE INCLUDE
+***************************************************************************/
+#include "dsp56ops.hxx"
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+// Execute a single opcode and return how many cycles it took.
+static size_t execute_one_new(dsp56156_core* cpustate)
+{
+ // For MAME
+ cpustate->ppc = PC;
+ if (cpustate->device->machine().debug_flags & DEBUG_FLAG_CALL_HOOK) // FIXME: if this was a member, the helper would work
+ cpustate->device->debug()->instruction_hook(PC);
+
+ cpustate->op = ROPCODE(PC);
+ uint16_t w0 = ROPCODE(PC);
+ uint16_t w1 = ROPCODE(PC + 1);
+
+ Opcode op(w0, w1);
+ op.evaluate(cpustate);
+ PC += op.evalSize(); // Special size function needed to handle jmps, etc.
+
+ // TODO: Currently all operations take up 4 cycles (inst->cycles()).
+ return 4;
+}
+
+void dsp56156_device::execute_run()
+{
+ /* If reset line is asserted, do nothing */
+ if (m_core.reset_state)
+ {
+ m_core.icount = 0;
+ return;
+ }
+
+ /* HACK - if you're in bootstrap mode, simply pretend you ate up all your cycles waiting for data. */
+ if (m_core.bootstrap_mode != BOOTSTRAP_OFF)
+ {
+ m_core.icount = 0;
+ return;
+ }
+
+ //m_core.icount -= m_core.interrupt_cycles;
+ //m_core.interrupt_cycles = 0;
+
+ while(m_core.icount > 0)
+ {
+ execute_one(&m_core);
+ if (0) m_core.icount -= execute_one_new(&m_core);
+ pcu_service_interrupts(&m_core); // TODO: Is it incorrect to service after each instruction?
+ }
+}
+
+
+std::unique_ptr<util::disasm_interface> dsp56156_device::create_disassembler()
+{
+ return std::make_unique<dsp56156_disassembler>();
+}
+
+} // namespace DSP_56156
diff --git a/src/devices/cpu/dsp56156/dsp56156.h b/src/devices/cpu/dsp56156/dsp56156.h
new file mode 100644
index 00000000000..9276e4e8702
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56156.h
@@ -0,0 +1,259 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+/***************************************************************************
+
+ dsp56156.h
+ Interface file for the portable Motorola/Freescale DSP56156 emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+
+#ifndef MAME_CPU_DSP56156_DSP56156_H
+#define MAME_CPU_DSP56156_DSP56156_H
+
+#pragma once
+
+
+
+// IRQ Lines
+// MODA and MODB are also known as IRQA and IRQB
+#define DSP56156_IRQ_MODA 0
+#define DSP56156_IRQ_MODB 1
+#define DSP56156_IRQ_MODC 2
+#define DSP56156_IRQ_RESET 3 /* Is this needed? */
+
+
+namespace DSP_56156 {
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+// 5-4 Host Interface
+struct dsp56156_host_interface
+{
+ // **** DSP56156 side **** //
+ // Host Control Register
+ uint16_t* hcr;
+
+ // Host Status Register
+ uint16_t* hsr;
+
+ // Host Transmit/Receive Data
+ uint16_t* htrx;
+
+ // **** Host CPU side **** //
+ // Interrupt Control Register
+ uint8_t icr;
+
+ // Command Vector Register
+ uint8_t cvr;
+
+ // Interrupt Status Register
+ uint8_t isr;
+
+ // Interrupt Vector Register
+ uint8_t ivr;
+
+ // Transmit / Receive Registers
+ uint8_t trxh;
+ uint8_t trxl;
+
+ // HACK - Host interface bootstrap write offset
+ uint16_t bootstrap_offset;
+
+};
+
+// 1-9 ALU
+struct dsp56156_data_alu
+{
+ // Four 16-bit input registers (can be accessed as 2 32-bit registers)
+ PAIR x;
+ PAIR y;
+
+ // Two 32-bit accumulator registers + 8-bit accumulator extension registers
+ PAIR64 a;
+ PAIR64 b;
+
+ // An accumulation shifter
+ // One data bus shifter/limiter
+ // A parallel, single cycle, non-pipelined Multiply-Accumulator (MAC) unit
+ // Basics
+};
+
+// 1-10 Address Generation Unit (AGU)
+struct dsp56156_agu
+{
+ // Four address registers
+ uint16_t r0;
+ uint16_t r1;
+ uint16_t r2;
+ uint16_t r3;
+
+ // Four offset registers
+ uint16_t n0;
+ uint16_t n1;
+ uint16_t n2;
+ uint16_t n3;
+
+ // Four modifier registers
+ uint16_t m0;
+ uint16_t m1;
+ uint16_t m2;
+ uint16_t m3;
+
+ // Used in loop processing
+ uint16_t temp;
+
+ // FM.4-5 - hmmm?
+ // uint8_t status;
+
+ // Basics
+};
+
+// 1-11 Program Control Unit (PCU)
+struct dsp56156_pcu
+{
+ // Program Counter
+ uint16_t pc;
+
+ // Loop Address
+ uint16_t la;
+
+ // Loop Counter
+ uint16_t lc;
+
+ // Status Register
+ uint16_t sr;
+
+ // Operating Mode Register
+ uint16_t omr;
+
+ // Stack Pointer
+ uint16_t sp;
+
+ // Stack (TODO: 15-level?)
+ PAIR ss[16];
+
+ // Controls IRQ processing
+ void (*service_interrupts)(void);
+
+ // A list of pending interrupts (indices into dsp56156_interrupt_sources array)
+ int8_t pending_interrupts[32];
+
+ // Basics
+
+ // Other PCU internals
+ uint16_t reset_vector;
+
+};
+
+// 1-8 The dsp56156 CORE
+struct dsp56156_core
+{
+ // PROGRAM CONTROLLER
+ dsp56156_pcu PCU;
+
+ // ADR ALU (AGU)
+ dsp56156_agu AGU;
+
+ // CLOCK GEN
+ //static emu_timer *dsp56156_timer; // 1-5, 1-8 - Clock gen
+
+ // DATA ALU
+ dsp56156_data_alu ALU;
+
+ // OnCE
+
+ // IBS and BITFIELD UNIT
+
+ // Host Interface
+ dsp56156_host_interface HI;
+
+ // IRQ line states
+ bool modA_state;
+ bool modB_state;
+ bool modC_state;
+ bool reset_state;
+
+ // HACK - Bootstrap mode state variable.
+ uint8_t bootstrap_mode;
+
+ uint8_t repFlag; // Knowing if we're in a 'repeat' state (dunno how the processor does this)
+ uint32_t repAddr; // The address of the instruction to repeat...
+
+
+ /* MAME internal stuff */
+ int icount;
+
+ uint32_t ppc;
+ uint32_t op;
+ int interrupt_cycles;
+ void (*output_pins_changed)(uint32_t pins);
+ cpu_device *device;
+ address_space *program;
+ memory_access_cache<1, -1, ENDIANNESS_LITTLE> *cache;
+ address_space *data;
+
+ uint16_t peripheral_ram[0x40];
+ uint16_t *program_ram;
+};
+
+
+class dsp56156_device : public cpu_device
+{
+public:
+ dsp56156_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
+
+ DECLARE_READ16_MEMBER( peripheral_register_r );
+ DECLARE_WRITE16_MEMBER( peripheral_register_w );
+
+ void host_interface_write(uint8_t offset, uint8_t data);
+ uint8_t host_interface_read(uint8_t offset);
+
+ uint16_t get_peripheral_memory(uint16_t addr);
+
+ void dsp56156_program_map(address_map &map);
+ void dsp56156_x_data_map(address_map &map);
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const override { return (clocks + 2 - 1) / 2; }
+ virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const override { return (cycles * 2); }
+ virtual uint32_t execute_min_cycles() const override { return 1; }
+ virtual uint32_t execute_max_cycles() const override { return 8; }
+ virtual uint32_t execute_input_lines() const override { return 4; }
+ virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == DSP56156_IRQ_RESET; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+private:
+ address_space_config m_program_config;
+ address_space_config m_data_config;
+ required_shared_ptr<uint16_t> m_program_ram;
+
+ dsp56156_core m_core;
+
+ void agu_init();
+ void alu_init();
+};
+
+} // namespace DSP_56156
+
+
+DECLARE_DEVICE_TYPE_NS(DSP56156, DSP_56156, dsp56156_device)
+using DSP_56156::dsp56156_device;
+
+#endif // MAME_CPU_DSP56156_DSP56156_H
diff --git a/src/devices/cpu/dsp56156/dsp56def.h b/src/devices/cpu/dsp56156/dsp56def.h
new file mode 100644
index 00000000000..3ae4dd414ec
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56def.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+///////////////////////////////////////////
+// All the macros that are fit to print. //
+///////////////////////////////////////////
+
+#ifndef __DSP56_DEF_H__
+#define __DSP56_DEF_H__
+
+#include "dsp56156.h"
+
+namespace DSP_56156
+{
+/***************************************************************************
+ ALU
+***************************************************************************/
+#define X cpustate->ALU.x.d
+#define X1 cpustate->ALU.x.w.h
+#define X0 cpustate->ALU.x.w.l
+#define Y cpustate->ALU.y.d
+#define Y1 cpustate->ALU.y.w.h
+#define Y0 cpustate->ALU.y.w.l
+
+#define A cpustate->ALU.a.q
+#define A2 cpustate->ALU.a.b.h4
+#define A1 cpustate->ALU.a.w.h
+#define A0 cpustate->ALU.a.w.l
+#define B cpustate->ALU.b.q
+#define B2 cpustate->ALU.b.b.h4
+#define B1 cpustate->ALU.b.w.h
+#define B0 cpustate->ALU.b.w.l
+
+
+/***************************************************************************
+ AGU
+***************************************************************************/
+#define R0 cpustate->AGU.r0
+#define R1 cpustate->AGU.r1
+#define R2 cpustate->AGU.r2
+#define R3 cpustate->AGU.r3
+
+#define N0 cpustate->AGU.n0
+#define N1 cpustate->AGU.n1
+#define N2 cpustate->AGU.n2
+#define N3 cpustate->AGU.n3
+
+#define M0 cpustate->AGU.m0
+#define M1 cpustate->AGU.m1
+#define M2 cpustate->AGU.m2
+#define M3 cpustate->AGU.m3
+
+#define TEMP cpustate->AGU.temp
+
+} // namespace DSP_56156
+
+#endif
diff --git a/src/devices/cpu/dsp56156/dsp56dsm.cpp b/src/devices/cpu/dsp56156/dsp56dsm.cpp
new file mode 100644
index 00000000000..58397c3284f
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56dsm.cpp
@@ -0,0 +1,34 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+/***************************************************************************
+
+ dsp56dsm.cpp
+ Disassembler for the portable Motorola/Freescale DSP56156 emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+#include "emu.h"
+#include "opcode.h"
+#include "dsp56dsm.h"
+
+u32 dsp56156_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+/*****************************/
+/* Main disassembly function */
+/*****************************/
+offs_t dsp56156_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ const uint16_t w0 = opcodes.r16(pc);
+ const uint16_t w1 = opcodes.r16(pc+1);
+
+ // Decode and disassemble.
+ DSP_56156::Opcode op(w0, w1);
+ stream << op.disassemble();
+
+ const unsigned size = op.size();
+ return (size | SUPPORTED);
+}
diff --git a/src/devices/cpu/dsp56156/dsp56dsm.h b/src/devices/cpu/dsp56156/dsp56dsm.h
new file mode 100644
index 00000000000..c750bebfdb1
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56dsm.h
@@ -0,0 +1,26 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+/***************************************************************************
+
+ dsp56dsm.cpp
+ Disassembler for the portable Motorola/Freescale DSP56156 emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+#ifndef MAME_CPU_DSP56156_DSP56156DSM_H
+#define MAME_CPU_DSP56156_DSP56156DSM_H
+
+#pragma once
+
+class dsp56156_disassembler : public util::disasm_interface
+{
+public:
+ dsp56156_disassembler() = default;
+ virtual ~dsp56156_disassembler() = default;
+
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+};
+
+#endif
diff --git a/src/devices/cpu/dsp56156/dsp56mem.cpp b/src/devices/cpu/dsp56156/dsp56mem.cpp
new file mode 100644
index 00000000000..37e249f15ca
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56mem.cpp
@@ -0,0 +1,949 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+// This file contains functions which handle the On-Chip peripheral Memory Map
+// as well as the Host Interface and the SSI0/SSI1 Serial Interfaces.
+
+#include "emu.h"
+#include "dsp56mem.h"
+#include "dsp56pcu.h"
+
+namespace DSP_56156 {
+
+/* IPR Accessor Implementations */
+void IPR_set(dsp56156_core* cpustate, uint16_t value)
+{
+ /* TODO: Is there anything else? */
+ IPR = value;
+}
+
+int8_t irqa_ipl(dsp56156_core* cpustate) { return ((IPR & 0x0003) >> 0) - 1; }
+uint8_t irqa_trigger(dsp56156_core* cpustate){ return (IPR & 0x0004) >> 2; }
+int8_t irqb_ipl(dsp56156_core* cpustate) { return ((IPR & 0x0018) >> 3) - 1; }
+uint8_t irqb_trigger(dsp56156_core* cpustate){ return (IPR & 0x0002) >> 5; }
+int8_t codec_ipl(dsp56156_core* cpustate) { return ((IPR & 0x00c0) >> 6) - 1; }
+int8_t host_ipl(dsp56156_core* cpustate) { return ((IPR & 0x0300) >> 8) - 1; }
+int8_t ssi0_ipl(dsp56156_core* cpustate) { return ((IPR & 0x0c00) >> 10) - 1; }
+int8_t ssi1_ipl(dsp56156_core* cpustate) { return ((IPR & 0x3000) >> 12) - 1; }
+int8_t tm_ipl(dsp56156_core* cpustate) { return ((IPR & 0xc000) >> 14) - 1; }
+
+void mem_reset(dsp56156_core* cpustate)
+{
+ // Reset the HI registers
+ dsp56156_host_interface_reset(cpustate);
+
+ // Reset the IO registers
+ dsp56156_io_reset(cpustate);
+}
+
+
+/***************************************************************************
+ HOST INTERFACE
+***************************************************************************/
+/***************/
+/* DSP56k SIDE */
+/***************/
+/************************************/
+/* Host Control Register (HCR) Bits */
+/************************************/
+void HCR_set(dsp56156_core* cpustate, uint16_t value)
+{
+ HF3_bit_set (cpustate, (value & 0x0010) >> 4);
+ HF2_bit_set (cpustate, (value & 0x0008) >> 3);
+ HCIE_bit_set(cpustate, (value & 0x0004) >> 2);
+ HTIE_bit_set(cpustate, (value & 0x0002) >> 1);
+ HRIE_bit_set(cpustate, (value & 0x0001) >> 0);
+}
+//uint16_t HF3_bit(dsp56156_core* cpustate) { return ((HCR & 0x0010) != 0); }
+//uint16_t HF2_bit(dsp56156_core* cpustate) { return ((HCR & 0x0008) != 0); }
+uint16_t HCIE_bit(dsp56156_core* cpustate) { return ((HCR & 0x0004) != 0); }
+uint16_t HTIE_bit(dsp56156_core* cpustate) { return ((HCR & 0x0002) != 0); }
+uint16_t HRIE_bit(dsp56156_core* cpustate) { return ((HCR & 0x0001) != 0); }
+
+void HF3_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0010);
+ HCR |= (value << 4);
+
+ HF3_bit_host_set(cpustate, value);
+}
+void HF2_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0008);
+ HCR |= (value << 3);
+
+ HF2_bit_host_set(cpustate, value);
+}
+void HCIE_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0004);
+ HCR |= (value << 2);
+}
+void HTIE_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0002);
+ HCR |= (value << 1);
+}
+void HRIE_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0001);
+ HCR |= (value << 0);
+}
+
+/***********************************/
+/* Host Status Register (HSR) Bits */
+/***********************************/
+//uint16_t DMA_bit(dsp56156_core* cpustate) { return ((HSR & 0x0080) != 0); }
+//uint16_t HF1_bit(dsp56156_core* cpustate) { return ((HSR & 0x0010) != 0); }
+//uint16_t HF0_bit(dsp56156_core* cpustate) { return ((HSR & 0x0008) != 0); }
+//uint16_t HCP_bit(dsp56156_core* cpustate) { return ((HSR & 0x0004) != 0); }
+uint16_t HTDE_bit(dsp56156_core* cpustate) { return ((HSR & 0x0002) != 0); }
+uint16_t HRDF_bit(dsp56156_core* cpustate) { return ((HSR & 0x0001) != 0); }
+
+void DMA_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0080);
+ HSR |= (value << 7);
+ // TODO: 5-12 When the DMA bit is set, the DMA mode is enabled by the Host Mode bits HM0 & HM1
+}
+void HF1_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0010);
+ HSR |= (value << 4);
+}
+void HF0_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0008);
+ HSR |= (value << 3);
+}
+void HCP_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0004);
+ HSR |= (value << 2);
+
+ if (value && HCIE_bit(cpustate))
+ dsp56156_add_pending_interrupt(cpustate, "Host Command");
+}
+void HTDE_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0002);
+ HSR |= (value << 1);
+
+ // 5-10 If HTIE bit is set, whip out a Host Transmit Data interrupt
+ if (value && HTIE_bit(cpustate))
+ dsp56156_add_pending_interrupt(cpustate, "Host Transmit Data");
+
+ // 5-5 If both me and RXDF are cleared, transmit data to the host
+ if (!value && !RXDF_bit(cpustate))
+ dsp56156_host_interface_HTX_to_host(cpustate);
+}
+void HRDF_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0001);
+ HSR |= (value << 0);
+
+ // 5-10 If HRIE is set, whip out a Host Receive Data interrupt
+ if (value && HRIE_bit(cpustate))
+ dsp56156_add_pending_interrupt(cpustate, "Host Receive Data");
+
+ // 5-5 If both me and TXDE are cleared, transmit data to the dsp56156
+ if (!value && !TXDE_bit(cpustate))
+ dsp56156_host_interface_host_to_HTX(cpustate);
+}
+
+
+
+/*************/
+/* HOST SIDE */
+/*************/
+/*****************************************/
+/* Interrupt Control Register (ICR) Bits */
+/*****************************************/
+void ICR_set(dsp56156_core* cpustate, uint8_t value)
+{
+ HF1_bit_host_set(cpustate, (value & 0x10) >> 4);
+ HF0_bit_host_set(cpustate, (value & 0x08) >> 3);
+ TREQ_bit_set(cpustate, (value & 0x02) >> 1);
+ RREQ_bit_set(cpustate, (value & 0x01) >> 0);
+}
+
+//uint8_t INIT_bit(dsp56156_core* cpustate); #define x_initBIT ((dsp56156.HI.ICR & 0x0080) != 0)
+//uint8_t HM1_bit(dsp56156_core* cpustate); #define x_hm1BIT ((dsp56156.HI.ICR & 0x0040) != 0)
+//uint8_t HM0_bit(dsp56156_core* cpustate); #define x_hm0BIT ((dsp56156.HI.ICR & 0x0020) != 0)
+//uint8_t HF1_bit_host(dsp56156_core* cpustate); #define x_hf1BIT ((dsp56156.HI.ICR & 0x0010) != 0)
+//uint8_t HF0_bit_host(dsp56156_core* cpustate); #define x_hf0BIT ((dsp56156.HI.ICR & 0x0008) != 0)
+//uint8_t TREQ_bit(dsp56156_core* cpustate); #define x_treqBIT ((dsp56156.HI.ICR & 0x0002) != 0)
+//uint8_t RREQ_bit(dsp56156_core* cpustate); #define x_rreqBIT ((dsp56156.HI.ICR & 0x0001) != 0)
+
+//void INIT_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_initBIT() (dsp56156.HI.ICR &= (~0x0080))
+//void HM1_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_hm1BIT() (dsp56156.HI.ICR &= (~0x0040))
+//void HM0_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_hm0BIT() (dsp56156.HI.ICR &= (~0x0020))
+void HF1_bit_host_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x10);
+ ICR |= (value << 4);
+
+ HF1_bit_set(cpustate, value); // 5-14
+}
+void HF0_bit_host_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x08);
+ ICR |= (value << 3);
+
+ HF0_bit_set(cpustate, value); // 5-13
+}
+void TREQ_bit_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x02);
+ ICR |= (value << 1);
+}
+void RREQ_bit_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x01);
+ ICR |= (value << 0);
+
+ // 5-12
+ if (value)
+ {
+ // TODO : HREQ_assert();
+ }
+}
+
+
+
+/**************************************/
+/* Command Vector Register (CVR) Bits */
+/**************************************/
+uint8_t HV_bits(dsp56156_core* cpustate) { return (CVR & 0x1f); }
+
+void CVR_set(dsp56156_core* cpustate, uint8_t value)
+{
+ /* A single, unified place to run all callbacks for each of the bits */
+ HC_bit_set(cpustate, (value & 0x80) >> 7);
+ HV_bits_set(cpustate, (value & 0x1f));
+}
+
+void HC_bit_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ CVR &= ~(0x80);
+ CVR |= (value << 7);
+
+ HCP_bit_set(cpustate, value); // 5-9 & 5-11
+}
+void HV_bits_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x1f;
+ CVR &= ~(0x1f);
+ CVR |= (value << 0);
+}
+
+
+/****************************************/
+/* Interrupt Status Register (ISR) Bits */
+/****************************************/
+uint8_t TXDE_bit(dsp56156_core* cpustate) { return ((ISR & 0x0002) != 0); }
+uint8_t RXDF_bit(dsp56156_core* cpustate) { return ((ISR & 0x0001) != 0); }
+
+void HF3_bit_host_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0010);
+ ISR |= (value << 4);
+}
+void HF2_bit_host_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0008);
+ ISR |= (value << 3);
+}
+
+void TXDE_bit_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0002);
+ ISR |= (value << 1);
+
+ // If both me and the HRDF are cleared, transmit data to the dsp56156
+ if (!value && !HRDF_bit(cpustate))
+ dsp56156_host_interface_host_to_HTX(cpustate);
+}
+
+void RXDF_bit_set(dsp56156_core* cpustate, uint8_t value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0001);
+ ISR |= (value << 0);
+
+ // If both me and HTDE are cleared, transmit data to the host
+ if (!value && !HTDE_bit(cpustate))
+ dsp56156_host_interface_HTX_to_host(cpustate);
+}
+
+
+// TODO: 5-11 What is the host processor Initialize function?
+
+void dsp56156_host_interface_reset(dsp56156_core* cpustate)
+{
+ // Hook up the CPU-side pointers properly.
+ cpustate->HI.hcr = &cpustate->peripheral_ram[A2O(0xffc4)];
+ cpustate->HI.hsr = &cpustate->peripheral_ram[A2O(0xffe4)];
+ cpustate->HI.htrx = &cpustate->peripheral_ram[A2O(0xffe5)];
+
+ // The Bootstrap hack is initialized to write to address 0x0000
+ cpustate->HI.bootstrap_offset = 0x0000;
+
+ /* HCR */
+ HCR_set(cpustate, 0x0000); // 5-10
+
+ /* HSR */
+ HRDF_bit_set(cpustate, 0); // 5-11
+ HTDE_bit_set(cpustate, 1); // 5-11
+ HCP_bit_set(cpustate, 0); // 5-11
+ HF0_bit_set(cpustate, 0); // 5-12
+ HF1_bit_set(cpustate, 0); // 5-12
+ DMA_bit_set(cpustate, 0); // 5-12
+
+ /* CVR*/
+ HV_bits_set(cpustate, 0x16); // 5-7
+ HC_bit_set(cpustate, 0); // 5-9
+
+ /* TODO: ISR (at least) */
+}
+
+void dsp56156_host_interface_HTX_to_host(dsp56156_core* cpustate)
+{
+ RXH = ((HTX & 0xff00) >> 8);
+ RXL = ((HTX & 0x00ff));
+ RXDF_bit_set(cpustate, 1);
+ HTDE_bit_set(cpustate, 1);
+}
+
+void dsp56156_host_interface_host_to_HTX(dsp56156_core* cpustate)
+{
+ HRX &= 0x00ff;
+ HRX |= (TXH << 8);
+ HRX &= 0xff00;
+ HRX |= TXL;
+ TXDE_bit_set(cpustate, 1);
+ HRDF_bit_set(cpustate, 1);
+}
+
+
+/***************************************************************************
+ I/O INTERFACE
+***************************************************************************/
+/* BCR */
+void BCR_set(dsp56156_core* cpustate, uint16_t value)
+{
+ RH_bit_set(cpustate, (value & 0x8000) >> 15);
+ BS_bit_set(cpustate, (value & 0x4000) >> 14);
+ external_x_wait_states_set(cpustate, (value & 0x03e0) >> 5);
+ external_p_wait_states_set(cpustate, (value & 0x001f) >> 0);
+}
+
+//uint16_t RH_bit(dsp56156_core* cpustate);
+//uint16_t BS_bit(dsp56156_core* cpustate);
+//uint16_t external_x_wait_states(dsp56156_core* cpustate);
+//uint16_t external_p_wait_states(dsp56156_core* cpustate);
+
+void RH_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x0001;
+ BCR &= ~(0x8000);
+ BCR |= (value << 15);
+
+ // TODO: 4-6 Assert BR pin?
+}
+void BS_bit_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x0001;
+ BCR &= ~(0x4000);
+ BCR |= (value << 14);
+
+ // TODO: 4-6 Respond to BR pin?
+}
+void external_x_wait_states_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x001f;
+ BCR &= ~(0x03e0);
+ BCR |= (value << 5);
+}
+void external_p_wait_states_set(dsp56156_core* cpustate, uint16_t value)
+{
+ value = value & 0x001f;
+ BCR &= ~(0x001f);
+ BCR |= (value << 0);
+}
+
+
+/* Port B Control Register PBC */
+void PBC_set(dsp56156_core* cpustate, uint16_t value)
+{
+ if (value & 0xfffe)
+ cpustate->device->logerror("Dsp56k : Attempting to set reserved bits in the PBC. Ignoring.\n");
+
+ value = value & 0x0001;
+ PBC &= ~(0x0001);
+ PBC |= (value << 0);
+}
+
+#ifdef UNUSED_FUNCTION
+int host_interface_active(dsp56156_core* cpustate)
+{
+ /* The host interface is active if the 0th bit in the PBC is set */
+ return PBC & 0x0001;
+}
+#endif
+
+/* Port B Data Direction Register (PBDDR) */
+void PBDDR_set(dsp56156_core* cpustate, uint16_t value)
+{
+ if (value & 0x8000)
+ cpustate->device->logerror("Dsp56k : Attempting to set reserved bits in the PBDDR. Ignoring.\n");
+
+ value = value & 0x7fff;
+ PBDDR &= ~(0x7fff);
+ PBDDR |= (value << 0);
+
+ /* TODO: Implement dsp56156 io restrictions, etc. */
+}
+
+/* Port B Data Register (PBD) */
+void PBD_set(dsp56156_core* cpustate, uint16_t value)
+{
+ if (value & 0x8000)
+ cpustate->device->logerror("Dsp56k : Attempting to set reserved bits in the PBD. Ignoring.\n");
+
+ value = value & 0x7fff;
+ PBD &= ~(0x7fff);
+ PBD |= (value << 0);
+
+ /* TODO: Implement dsp56156 io restrictions, etc. */
+}
+
+/* Port C Control Register (PCC) */
+void PCC_set(dsp56156_core* cpustate, uint16_t value)
+{
+ if (value & 0xf000)
+ cpustate->device->logerror("Dsp56k : Attempting to set reserved bits in the PCC. Ignoring.\n");
+
+ value = value & 0x0fff;
+ PCC &= ~(0x0fff);
+ PCC |= (value << 0);
+
+ /* TODO: Implement dsp56156 timer and control glue */
+}
+
+/* Port C Data Direction Register (PCDDR) */
+void PCDDR_set(dsp56156_core* cpustate, uint16_t value)
+{
+ if (value & 0xf000)
+ cpustate->device->logerror("Dsp56k : Attempting to set reserved bits in the PCDDR. Ignoring.\n");
+
+ value = value & 0x0fff;
+ PCDDR &= ~(0x0fff);
+ PCDDR |= (value << 0);
+
+ /* TODO: Implement dsp56156 io restrictions, etc. */
+}
+
+/* Port C Data Register (PCD) */
+void PCD_set(dsp56156_core* cpustate, uint16_t value)
+{
+ if (value & 0xf000)
+ cpustate->device->logerror("Dsp56k : Attempting to set reserved bits in the PCD. Ignoring.\n");
+
+ /* TODO: Temporary */
+ cpustate->device->logerror("Dsp56k : Setting general output port C data to 0x%04x\n", value);
+
+ value = value & 0x0fff;
+ PCD &= ~(0x0fff);
+ PCD |= (value << 0);
+}
+
+void dsp56156_io_reset(dsp56156_core* cpustate)
+{
+ /* The BCR = 0x43ff */
+ RH_bit_set(cpustate, 0);
+ BS_bit_set(cpustate, 1);
+ external_x_wait_states_set(cpustate, 0x1f);
+ external_p_wait_states_set(cpustate, 0x1f);
+}
+
+
+/* Work */
+READ16_MEMBER( dsp56156_device::peripheral_register_r )
+{
+ dsp56156_core* cpustate = &m_core;
+ // (printf) cpustate->device->logerror("Peripheral read 0x%04x\n", O2A(offset));
+
+ switch (O2A(offset))
+ {
+ // Port B Control Register (PBC)
+ case 0xffc0: break;
+
+ // Port C Control Register (PCC)
+ case 0xffc1: break;
+
+ // Port B Data Direction Register (PBDDR)
+ case 0xffc2: break;
+
+ // Port C Data Direction Register (PCDDR)
+ case 0xffc3: break;
+
+ // HCR: Host Control Register
+ case 0xffc4: break;
+
+ // COCR
+ case 0xffc8: break;
+
+ // reserved for test
+ case 0xffc9: break;
+
+ // CRA-SSI0 Control Register A
+ case 0xffd0: break;
+
+ // CRB-SSI0 Control Register B
+ case 0xffd1: break;
+
+ // CRA-SSI1 Control Register A
+ case 0xffd8: break;
+
+ // CRB-SSI1 Control Register B
+ case 0xffd9: break;
+
+ // PLCR
+ case 0xffdc: break;
+
+ // reserved for future use
+ case 0xffdd: break;
+
+ // BCR: Bus Control Register
+ case 0xffde: break;
+
+ // IPR: Interrupt Priority Register
+ case 0xffdf: break;
+
+ // Port B Data Register (PBD)
+ case 0xffe2: break;
+
+ // Port C Data Register (PCD)
+ case 0xffe3: break;
+
+ // HSR: Host Status Register
+ case 0xffe4: break;
+
+ // HTX/HRX: Host TX/RX Register
+ case 0xffe5:
+ // 5-5
+ if (!DSP_56156::HRDF_bit(cpustate))
+ return 0xbeef;
+ else
+ {
+ uint16_t value = HRX; // TODO: Maybe not exactly right? Just being safe.
+ DSP_56156::HRDF_bit_set(cpustate, 0);
+ return value;
+ }
+ // COSR
+ case 0xffe8: break;
+
+ // CRX/CTX
+ case 0xffe9: break;
+
+ // Timer Control Register (TCR)
+ case 0xffec: break;
+
+ // Timer Count Register (TCTR)
+ case 0xffed: break;
+
+ // Timer Compare Register (TCPR)
+ case 0xffee: break;
+
+ // Timer Preload Register (TPR)
+ case 0xffef: break;
+
+ // SR/TSR SSI0 Status Register
+ case 0xfff0: break;
+
+ // TX/RX SSI0 Tx/RX Registers
+ case 0xfff1: break;
+
+ // RSMA0 SSI0 Register
+ case 0xfff2: break;
+
+ // RSMB0 SSI0 Register
+ case 0xfff3: break;
+
+ // TSMA0 SSI0 Register
+ case 0xfff4: break;
+
+ // TSMB0 SSI0 Register
+ case 0xfff5: break;
+
+ // SR/TSR SSI1 Status Register
+ case 0xfff8: break;
+
+ // TX/RX SSI1 TX/RX Registers
+ case 0xfff9: break;
+
+ // RSMA1 SSI1 Register
+ case 0xfffa: break;
+
+ // RSMB1 SSI1 Register
+ case 0xfffb: break;
+
+ // TSMA1 SSI1 Register
+ case 0xfffc: break;
+
+ // TSMB1 SSI1 Register
+ case 0xfffd: break;
+
+ // Reserved for on-chip emulation
+ case 0xffff: break;
+ }
+
+ // Its primary behavior is RAM
+ return cpustate->peripheral_ram[offset];
+}
+
+WRITE16_MEMBER( dsp56156_device::peripheral_register_w )
+{
+ dsp56156_core* cpustate = &m_core;
+
+ // Its primary behavior is RAM
+ // COMBINE_DATA(&cpustate->peripheral_ram[offset]);
+
+ // (printf) cpustate->device->logerror("Peripheral write 0x%04x = %04x\n", O2A(offset), data);
+
+ // 4-8
+ switch (O2A(offset))
+ {
+ // Port B Control Register (PBC)
+ case 0xffc0:
+ DSP_56156::PBC_set(cpustate, data);
+ break;
+
+ // Port C Control Register (PCC)
+ case 0xffc1:
+ DSP_56156::PCC_set(cpustate, data);
+ break;
+
+ // Port B Data Direction Register (PBDDR)
+ case 0xffc2:
+ DSP_56156::PBDDR_set(cpustate, data);
+ break;
+
+ // Port C Data Direction Register (PCDDR)
+ case 0xffc3:
+ DSP_56156::PCDDR_set(cpustate, data);
+ break;
+
+ // HCR: Host Control Register
+ case 0xffc4:
+ DSP_56156::HCR_set(cpustate, data);
+ break;
+
+ // COCR
+ case 0xffc8: break;
+
+ // reserved for test
+ case 0xffc9:
+ cpustate->device->logerror("DSP56k : Warning write to 0xffc9 reserved for test.\n");
+ break;
+
+ // CRA-SSI0 Control Register A
+ case 0xffd0: break;
+
+ // CRB-SSI0 Control Register B
+ case 0xffd1: break;
+
+ // CRA-SSI1 Control Register A
+ case 0xffd8: break;
+
+ // CRB-SSI1 Control Register B
+ case 0xffd9: break;
+
+ // PLCR
+ case 0xffdc: break;
+
+ // reserved for future use
+ case 0xffdd:
+ cpustate->device->logerror("DSP56k : Warning write to 0xffdd reserved for future use.\n");
+ break;
+
+ // BCR: Bus Control Register
+ case 0xffde:
+ DSP_56156::BCR_set(cpustate, data);
+ break;
+
+ // IPR: Interrupt Priority Register
+ case 0xffdf:
+ DSP_56156::IPR_set(cpustate, data);
+ break;
+
+ // Port B Data Register (PBD)
+ case 0xffe2:
+ DSP_56156::PBD_set(cpustate, data);
+ break;
+
+ // Port C Data Register (PCD)
+ case 0xffe3:
+ DSP_56156::PCD_set(cpustate, data);
+ break;
+
+ // HSR: Host Status Register
+ case 0xffe4: break;
+
+ // HTX/HRX: Host TX/RX Register
+ case 0xffe5:
+ HTX = data;
+ DSP_56156::HTDE_bit_set(cpustate, 0); // 5-5
+ break;
+
+ // COSR
+ case 0xffe8: break;
+
+ // CRX/CTX
+ case 0xffe9: break;
+
+ // Timer Control Register (TCR)
+ case 0xffec: break;
+
+ // Timer Count Register (TCTR)
+ case 0xffed: break;
+
+ // Timer Compare Register (TCPR)
+ case 0xffee: break;
+
+ // Timer Preload Register (TPR)
+ case 0xffef: break;
+
+ // SR/TSR SSI0 Status Register
+ case 0xfff0: break;
+
+ // TX/RX SSI0 Tx/RX Registers
+ case 0xfff1: break;
+
+ // RSMA0 SSI0 Register
+ case 0xfff2: break;
+
+ // RSMB0 SSI0 Register
+ case 0xfff3: break;
+
+ // TSMA0 SSI0 Register
+ case 0xfff4: break;
+
+ // TSMB0 SSI0 Register
+ case 0xfff5: break;
+
+ // SR/TSR SSI1 Status Register
+ case 0xfff8: break;
+
+ // TX/RX SSI1 TX/RX Registers
+ case 0xfff9: break;
+
+ // RSMA1 SSI1 Register
+ case 0xfffa: break;
+
+ // RSMB1 SSI1 Register
+ case 0xfffb: break;
+
+ // TSMA1 SSI1 Register
+ case 0xfffc: break;
+
+ // TSMB1 SSI1 Register
+ case 0xfffd: break;
+
+ // Reserved for on-chip emulation
+ case 0xffff:
+ cpustate->device->logerror("DSP56k : Warning write to 0xffff reserved for on-chip emulation.\n");
+ break;
+ }
+}
+
+/* These two functions are exposed to the outside world */
+/* They represent the host side of the dsp56156's host interface */
+void dsp56156_device::host_interface_write(uint8_t offset, uint8_t data)
+{
+ dsp56156_core* cpustate = &m_core;
+
+ /* Not exactly correct since the bootstrap hack doesn't need this to be true */
+ /*
+ if (!host_interface_active())
+ cpustate->device->logerror("Dsp56k : Host interface write called without HI being set active by the PBC.\n");
+ */
+
+ switch (offset)
+ {
+ // Interrupt Control Register (ICR)
+ case 0x00:
+ // HACK
+ if (cpustate->bootstrap_mode == BOOTSTRAP_HI)
+ {
+ // A-4 If they set HF0 while in bootstrap mode, it stops the bootstrap short.
+ if (data & 0x08)
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_OFF;
+ PC = 0x0000;
+ // TODO: Do we set HF0 then, or let it slide?
+ // TODO: Do I allow it to do an ICR_set(), or intercept it and throw everything away?
+ break;
+ }
+ }
+ DSP_56156::ICR_set(cpustate, data);
+ break;
+
+ // Command Vector Register (CVR)
+ case 0x01:
+ DSP_56156::CVR_set(cpustate, data);
+ break;
+
+ // Interrupt status register (ISR) - Read only!
+ case 0x02:
+ cpustate->device->logerror("DSP56k : Interrupt status register is read only.\n");
+ break;
+
+ // Interrupt vector register (IVR)
+ case 0x03: break;
+
+ // Not used
+ case 0x04:
+ cpustate->device->logerror("DSP56k : Address 0x4 on the host side of the host interface is not used.\n");
+ break;
+
+ // Reserved
+ case 0x05:
+ cpustate->device->logerror("DSP56k : Address 0x5 on the host side of the host interface is reserved.\n");
+ break;
+
+ // Transmit byte register - high byte (TXH)
+ case 0x06:
+ // HACK
+ if (cpustate->bootstrap_mode == BOOTSTRAP_HI)
+ {
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] &= 0x00ff;
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] |= (data << 8);
+ break; /* Probably the right thing to do, given this is a hack */
+ }
+
+ if (DSP_56156::TXDE_bit(cpustate)) // 5-5
+ {
+ TXH = data;
+ }
+ break;
+
+ // Transmit byte register - low byte (TXL)
+ case 0x07:
+ // HACK
+ if (cpustate->bootstrap_mode == BOOTSTRAP_HI)
+ {
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] &= 0xff00;
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] |= data;
+ cpustate->HI.bootstrap_offset++;
+
+ if (cpustate->HI.bootstrap_offset == 0x800)
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_OFF;
+ }
+ break; /* Probably the right thing to do, given this is a hack */
+ }
+
+ if (DSP_56156::TXDE_bit(cpustate)) // 5-5
+ {
+ TXL = data;
+ DSP_56156::TXDE_bit_set(cpustate, 0);
+ }
+ break;
+
+ default: cpustate->device->logerror("DSP56k : dsp56156_host_interface_write called with invalid address 0x%02x.\n", offset);
+ }
+}
+
+uint8_t dsp56156_device::host_interface_read(uint8_t offset)
+{
+ dsp56156_core* cpustate = &m_core;
+
+ /* Not exactly correct since the bootstrap hack doesn't need this to be true */
+ /*
+ if (!host_interface_active())
+ cpustate->device->logerror("Dsp56k : Host interface write called without HI being set active by the PBC.\n");
+ */
+
+ switch (offset)
+ {
+ // Interrupt Control Register (ICR)
+ case 0x00:
+ return ICR;
+
+ // Command Vector Register (CVR)
+ case 0x01:
+ return CVR;
+
+ // Interrupt status register (ISR)
+ case 0x02:
+ return ISR;
+
+ // Interrupt vector register (IVR)
+ case 0x03:
+ return IVR;
+
+ // Read zeroes
+ case 0x04:
+ return 0x00;
+
+ // Reserved
+ case 0x05:
+ cpustate->device->logerror("DSP56k : Address 0x5 on the host side of the host interface is reserved.\n");
+ break;
+
+ // Receive byte register - high byte (RXH)
+ case 0x06:
+ // 5-5
+ if (!DSP_56156::RXDF_bit(cpustate))
+ return 0xbf;
+ else
+ return RXH;
+
+ // Receive byte register - low byte (RXL)
+ case 0x07:
+ // 5-5
+ if (!DSP_56156::RXDF_bit(cpustate))
+ return 0xbf;
+ else
+ {
+ uint8_t value = RXL; // TODO: Maybe not exactly right? I'm just being safe.
+ DSP_56156::RXDF_bit_set(cpustate, 0);
+ return value;
+ }
+
+ default: cpustate->device->logerror("DSP56k : dsp56156_host_interface_read called with invalid address 0x%02x.\n", offset);
+ }
+
+ /* Shouldn't get here */
+ return 0xff;
+}
+
+/* MISC*/
+uint16_t dsp56156_device::get_peripheral_memory(uint16_t addr)
+{
+ dsp56156_core* cpustate = &m_core;
+ return cpustate->peripheral_ram[A2O(addr)];
+}
+
+
+} // namespace DSP_56156
diff --git a/src/devices/cpu/dsp56156/dsp56mem.h b/src/devices/cpu/dsp56156/dsp56mem.h
new file mode 100644
index 00000000000..fb5ac5f4334
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56mem.h
@@ -0,0 +1,241 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#ifndef MAME_CPU_DSP56156_DSP56MEM_H
+#define MAME_CPU_DSP56156_DSP56MEM_H
+
+#include "dsp56156.h"
+
+namespace DSP_56156 {
+
+/***************************************************************************
+ MEMORY
+***************************************************************************/
+void mem_reset(dsp56156_core* cpustate);
+
+// Adjusts the documented address to match the offset in peripheral RAM
+#define A2O(a) (a - 0xffc0)
+
+// Adjusts the offset in peripheral RAM to match the documented address
+#define O2A(a) (a + 0xffc0)
+
+// The memory 'registers'
+#define PBC (cpustate->peripheral_ram[A2O(0xffc0)])
+#define PCC (cpustate->peripheral_ram[A2O(0xffc1)])
+#define PBDDR (cpustate->peripheral_ram[A2O(0xffc2)])
+#define PCDDR (cpustate->peripheral_ram[A2O(0xffc3)])
+#define HCR (cpustate->peripheral_ram[A2O(0xffc4)])
+#define COCR (cpustate->peripheral_ram[A2O(0xffc8)])
+#define CRASSI0 (cpustate->peripheral_ram[A2O(0xffd0)])
+#define CRBSSI0 (cpustate->peripheral_ram[A2O(0xffd1)])
+#define CRASSI1 (cpustate->peripheral_ram[A2O(0xffd8)])
+#define CRBSSI1 (cpustate->peripheral_ram[A2O(0xffd9)])
+#define PLCR (cpustate->peripheral_ram[A2O(0xffdc)])
+#define BCR (cpustate->peripheral_ram[A2O(0xffde)])
+#define IPR (cpustate->peripheral_ram[A2O(0xffdf)])
+#define PBD (cpustate->peripheral_ram[A2O(0xffe2)])
+#define PCD (cpustate->peripheral_ram[A2O(0xffe3)])
+#define HSR (cpustate->peripheral_ram[A2O(0xffe4)])
+#define HTXHRX (cpustate->peripheral_ram[A2O(0xffe5)])
+#define COSR (cpustate->peripheral_ram[A2O(0xffe8)])
+#define CRXCTX (cpustate->peripheral_ram[A2O(0xffe9)])
+#define TCR (cpustate->peripheral_ram[A2O(0xffec)])
+#define TCTR (cpustate->peripheral_ram[A2O(0xffed)])
+#define TCPR (cpustate->peripheral_ram[A2O(0xffee)])
+#define TPR (cpustate->peripheral_ram[A2O(0xffef)])
+#define TSRSSI0 (cpustate->peripheral_ram[A2O(0xfff0)])
+#define TRXSSI0 (cpustate->peripheral_ram[A2O(0xfff1)])
+#define RSMA0 (cpustate->peripheral_ram[A2O(0xfff2)])
+#define RSMB0 (cpustate->peripheral_ram[A2O(0xfff3)])
+#define TSMA0 (cpustate->peripheral_ram[A2O(0xfff4)])
+#define TSMB0 (cpustate->peripheral_ram[A2O(0xfff5)])
+#define TSRSSI1 (cpustate->peripheral_ram[A2O(0xfff8)])
+#define TRXSSI1 (cpustate->peripheral_ram[A2O(0xfff9)])
+#define RSMA1 (cpustate->peripheral_ram[A2O(0xfffa)])
+#define RSMB1 (cpustate->peripheral_ram[A2O(0xfffb)])
+#define TSMA1 (cpustate->peripheral_ram[A2O(0xfffc)])
+#define TSMB1 (cpustate->peripheral_ram[A2O(0xfffd)])
+
+/* Interrupt priority register (IPR) bits */
+void IPR_set(dsp56156_core* cpustate, uint16_t value);
+
+/* A return value of -1 means disabled */
+int8_t irqa_ipl(dsp56156_core* cpustate);
+int8_t irqb_ipl(dsp56156_core* cpustate);
+uint8_t irqa_trigger(dsp56156_core* cpustate);
+uint8_t irqb_trigger(dsp56156_core* cpustate);
+
+int8_t codec_ipl(dsp56156_core* cpustate);
+int8_t host_ipl(dsp56156_core* cpustate);
+int8_t ssi0_ipl(dsp56156_core* cpustate);
+int8_t ssi1_ipl(dsp56156_core* cpustate);
+int8_t tm_ipl(dsp56156_core* cpustate);
+
+
+/***************************************************************************
+ HOST INTERFACE
+***************************************************************************/
+void dsp56156_host_interface_reset(dsp56156_core* cpustate);
+#define HTX (HTXHRX)
+#define HRX (HTXHRX)
+
+#define ICR (cpustate->HI.icr)
+#define CVR (cpustate->HI.cvr)
+#define ISR (cpustate->HI.isr)
+#define IVR (cpustate->HI.ivr)
+#define TXH (cpustate->HI.trxh)
+#define TXL (cpustate->HI.trxl)
+#define RXH (cpustate->HI.trxh)
+#define RXL (cpustate->HI.trxl)
+
+/*****************/
+/* DSP56156 SIDE */
+/*****************/
+/* Host Control Register (HCR) Bits */
+void HCR_set(dsp56156_core* cpustate, uint16_t value);
+
+//uint16_t HF3_bit(dsp56156_core* cpustate); #define hf3BIT ((HCR & 0x0010) != 0)
+//uint16_t HF2_bit(dsp56156_core* cpustate); #define hf2BIT ((HCR & 0x0008) != 0)
+uint16_t HCIE_bit(dsp56156_core* cpustate);
+uint16_t HTIE_bit(dsp56156_core* cpustate);
+uint16_t HRIE_bit(dsp56156_core* cpustate);
+
+void HF3_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HF2_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HCIE_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HTIE_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HRIE_bit_set(dsp56156_core* cpustate, uint16_t value);
+
+/* Host Status Register (HSR) Bits */
+//void HSR_set(dsp56156_core* cpustate, uint16_t value);
+
+//uint16_t DMA_bit(dsp56156_core* cpustate); #define dmaBIT ((HSR & 0x0080) != 0)
+//uint16_t HF1_bit(dsp56156_core* cpustate); #define hf1BIT ((HSR & 0x0010) != 0)
+//uint16_t HF0_bit(dsp56156_core* cpustate); #define hf0BIT ((HSR & 0x0008) != 0)
+//uint16_t HCP_bit(dsp56156_core* cpustate); #define hcpBIT ((HSR & 0x0004) != 0)
+uint16_t HTDE_bit(dsp56156_core* cpustate);
+uint16_t HRDF_bit(dsp56156_core* cpustate);
+
+void DMA_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HF1_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HF0_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HCP_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HTDE_bit_set(dsp56156_core* cpustate, uint16_t value);
+void HRDF_bit_set(dsp56156_core* cpustate, uint16_t value);
+
+/*************/
+/* HOST SIDE */
+/*************/
+/* Interrupt Control Register (ICR) Bits */
+void ICR_set(dsp56156_core* cpustate, uint8_t value);
+
+//uint8_t INIT_bit(dsp56156_core* cpustate); #define x_initBIT ((dsp56156.HI.ICR & 0x0080) != 0)
+//uint8_t HM1_bit(dsp56156_core* cpustate); #define x_hm1BIT ((dsp56156.HI.ICR & 0x0040) != 0)
+//uint8_t HM0_bit(dsp56156_core* cpustate); #define x_hm0BIT ((dsp56156.HI.ICR & 0x0020) != 0)
+//uint8_t HF1_bit_host(dsp56156_core* cpustate); #define x_hf1BIT ((dsp56156.HI.ICR & 0x0010) != 0)
+//uint8_t HF0_bit_host(dsp56156_core* cpustate); #define x_hf0BIT ((dsp56156.HI.ICR & 0x0008) != 0)
+//uint8_t TREQ_bit(dsp56156_core* cpustate); #define x_treqBIT ((dsp56156.HI.ICR & 0x0002) != 0)
+//uint8_t RREQ_bit(dsp56156_core* cpustate); #define x_rreqBIT ((dsp56156.HI.ICR & 0x0001) != 0)
+
+//void INIT_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_initBIT() (dsp56156.HI.ICR &= (~0x0080))
+//void HM1_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_hm1BIT() (dsp56156.HI.ICR &= (~0x0040))
+//void HM0_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_hm0BIT() (dsp56156.HI.ICR &= (~0x0020))
+void HF1_bit_host_set(dsp56156_core* cpustate, uint8_t value);
+void HF0_bit_host_set(dsp56156_core* cpustate, uint8_t value);
+void TREQ_bit_set(dsp56156_core* cpustate, uint8_t value);
+void RREQ_bit_set(dsp56156_core* cpustate, uint8_t value);
+
+/* Command Vector Register (CVR) Bits */
+void CVR_set(dsp56156_core* cpustate, uint8_t value);
+
+//uint8_t HC_bit();
+uint8_t HV_bits(dsp56156_core* cpustate);
+
+void HC_bit_set(dsp56156_core* cpustate, uint8_t value);
+void HV_bits_set(dsp56156_core* cpustate, uint8_t value);
+
+/* Interrupt Status Register (ISR) Bits */
+// void ISR_set(dsp56156_core* cpustate, uint8_t value);
+
+//uint8_t HREQ_bit(dsp56156_core* cpustate); #define x_hreqBIT ((dsp56156.HI.ISR & 0x0080) != 0)
+//uint8_t DMA_bit(dsp56156_core* cpustate); #define x_dmaBIT ((dsp56156.HI.ISR & 0x0040) != 0)
+//uint8_t HF3_bit_host(dsp56156_core* cpustate); #define x_hf3BIT ((dsp56156.HI.ISR & 0x0010) != 0)
+//uint8_t HF2_bit_host(dsp56156_core* cpustate); #define x_hf2BIT ((dsp56156.HI.ISR & 0x0008) != 0)
+//uint8_t TRDY_bit(dsp56156_core* cpustate); #define x_trdyBIT ((dsp56156.HI.ISR & 0x0004) != 0)
+uint8_t TXDE_bit(dsp56156_core* cpustate);
+uint8_t RXDF_bit(dsp56156_core* cpustate);
+
+//void HREQ_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_hreqBIT() (dsp56156.HI.ISR &= (~0x0080))
+//void DMA_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_dmaBIT() (dsp56156.HI.ISR &= (~0x0040))
+void HF3_bit_host_set(dsp56156_core* cpustate, uint8_t value);
+void HF2_bit_host_set(dsp56156_core* cpustate, uint8_t value);
+//void TRDY_bit_set(dsp56156_core* cpustate, uint8_t value); #define CLEAR_x_trdyBIT() (dsp56156.HI.ISR &= (~0x0004))
+void TXDE_bit_set(dsp56156_core* cpustate, uint8_t value);
+void RXDF_bit_set(dsp56156_core* cpustate, uint8_t value);
+
+/* Interrupt Vector Register (IVR) Bits */
+//void IVR_set(dsp56156_core* cpustate, uint8_t value);
+
+//uint8_t IV7_bit(dsp56156_core* cpustate);
+//uint8_t IV6_bit(dsp56156_core* cpustate);
+//uint8_t IV5_bit(dsp56156_core* cpustate);
+//uint8_t IV4_bit(dsp56156_core* cpustate);
+//uint8_t IV3_bit(dsp56156_core* cpustate);
+//uint8_t IV2_bit(dsp56156_core* cpustate);
+//uint8_t IV1_bit(dsp56156_core* cpustate);
+//uint8_t IV0_bit(dsp56156_core* cpustate);
+
+//void IV7_bit_set(dsp56156_core* cpustate, uint8_t value);
+//void IV6_bit_set(dsp56156_core* cpustate, uint8_t value);
+//void IV5_bit_set(dsp56156_core* cpustate, uint8_t value);
+//void IV4_bit_set(dsp56156_core* cpustate, uint8_t value);
+//void IV3_bit_set(dsp56156_core* cpustate, uint8_t value);
+//void IV2_bit_set(dsp56156_core* cpustate, uint8_t value);
+//void IV1_bit_set(dsp56156_core* cpustate, uint8_t value);
+//void IV0_bit_set(dsp56156_core* cpustate, uint8_t value);
+
+
+/* PROTOTYPES */
+void dsp56156_host_interface_HTX_to_host(dsp56156_core* cpustate);
+void dsp56156_host_interface_host_to_HTX(dsp56156_core* cpustate);
+
+
+/***************************************************************************
+ I/O INTERFACE
+***************************************************************************/
+void dsp56156_io_reset(dsp56156_core* cpustate);
+
+/* Port A Bus Control Register (BCR) */
+void BCR_set(dsp56156_core* cpustate, uint16_t value);
+
+//uint16_t RH_bit(dsp56156_core* cpustate);
+//uint16_t BS_bit(dsp56156_core* cpustate);
+//uint16_t external_x_wait_states(dsp56156_core* cpustate);
+//uint16_t external_p_wait_states(dsp56156_core* cpustate);
+
+void RH_bit_set(dsp56156_core* cpustate, uint16_t value);
+void BS_bit_set(dsp56156_core* cpustate, uint16_t value);
+void external_x_wait_states_set(dsp56156_core* cpustate, uint16_t value);
+void external_p_wait_states_set(dsp56156_core* cpustate, uint16_t value);
+
+/* Port B Control Register (PBC) */
+void PBC_set(dsp56156_core* cpustate, uint16_t value);
+//int host_interface_active(dsp56156_core* cpustate);
+
+/* Port B Data Direction Register (PBDDR) */
+void PBDDR_set(dsp56156_core* cpustate, uint16_t value);
+
+/* Port B Data Register (PBD) */
+void PBD_set(dsp56156_core* cpustate, uint16_t value);
+
+/* Port C Control Register (PCC) */
+void PCC_set(dsp56156_core* cpustate, uint16_t value);
+
+/* Port C Data Direction Register (PCDDR) */
+void PCDDR_set(dsp56156_core* cpustate, uint16_t value);
+
+/* Port C Dtaa Register (PCD) */
+void PCD_set(dsp56156_core* cpustate, uint16_t value);
+
+} // namespace DSP_56156
+
+#endif // MAME_CPU_DSP56156_DSP56MEM_H
diff --git a/src/devices/cpu/dsp56156/dsp56ops.hxx b/src/devices/cpu/dsp56156/dsp56ops.hxx
new file mode 100644
index 00000000000..52ff4f5560c
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56ops.hxx
@@ -0,0 +1,4903 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+/***************************************************************************
+
+ dsp56ops.hxx
+ Core implementation for the portable Motorola/Freescale DSP56156 emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+/* NOTES For register setting:
+ FM.3-4 : When A2 or B2 is read, the register contents occupy the low-order portion
+ (bits 7-0) of the word; the high-order portion (bits 16-8) is sign-extended. When A2 or B2
+ is written, the register receives the low-order portion of the word; the high-order portion is not used
+ : ...much more!
+ : ...shifter/limiter/overflow notes too.
+
+*/
+
+/*
+TODO:
+ - 0x01ee: should this move sign extend? otherwise the test-against-minus means nothing.
+ - Restore only the proper bits upon loop termination!
+ - BFCLR has some errata in the docs that may need to be applied.
+*/
+
+/************************/
+/* Datatypes and macros */
+/************************/
+enum addSubOpType { OP_ADD,
+ OP_SUB,
+ OP_OTHER };
+
+enum dataType { DT_BYTE,
+ DT_WORD,
+ DT_DOUBLE_WORD,
+ DT_LONG_WORD };
+
+struct typed_pointer
+{
+ void* addr;
+ char data_type;
+};
+
+#define BITS(CUR,MASK) (Dsp56156OpMask(CUR,MASK))
+
+/*********************/
+/* Opcode prototypes */
+/*********************/
+static size_t dsp56156_op_addsub_2 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles);
+static size_t dsp56156_op_mac_1 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles);
+static size_t dsp56156_op_macr_1 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles);
+static size_t dsp56156_op_move_1 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles);
+static size_t dsp56156_op_mpy_1 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles);
+static size_t dsp56156_op_mpyr_1 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles);
+static size_t dsp56156_op_tfr_2 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles);
+static size_t dsp56156_op_mpy_2 (dsp56156_core* cpustate, const uint16_t op_byte, uint8_t* cycles);
+static size_t dsp56156_op_mac_2 (dsp56156_core* cpustate, const uint16_t op_byte, uint8_t* cycles);
+static size_t dsp56156_op_clr (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_add (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_move (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_tfr (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_rnd (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_tst (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_inc (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_inc24 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_or (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_asr (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_asl (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_lsr (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_lsl (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_eor (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_subl (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_sub (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_clr24 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_sbc (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_cmp (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_neg (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_not (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_dec (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_dec24 (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_and (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_abs (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_ror (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_rol (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_cmpm (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_mpy (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_mpyr (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_mac (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_macr (dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles);
+static size_t dsp56156_op_adc (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_andi (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_asl4 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_asr4 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_asr16 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_bfop (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_bfop_1 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_bfop_2 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_bcc (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_bcc_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_bcc_2 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_bra (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_bra_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_bra_2 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_brkcc (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_bscc (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_bscc_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_bsr (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_bsr_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_chkaau (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_debug (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_debugcc (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_div (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_dmac (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_do (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_do_1 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_do_2 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_doforever(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_enddo (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_ext (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_illegal (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_imac (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_impy (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_jcc (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_jcc_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_jmp (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_jmp_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_jscc (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_jscc_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_jsr (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_jsr_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_jsr_2 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_lea (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_lea_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_macsuuu (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_move_2 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_movec (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movec_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movec_2 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movec_3 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_movec_4 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movec_5 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_movei (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movem (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movem_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movem_2 (dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles);
+static size_t dsp56156_op_movep (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_movep_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_moves (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_mpysuuu (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_negc (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_nop (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_norm (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_ori (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_rep (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_rep_1 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_rep_2 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_repcc (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_reset (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_rti (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_rts (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_stop (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_swap (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_swi (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_tcc (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_tfr2 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_tfr3 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_tst2 (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_wait (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+static size_t dsp56156_op_zero (dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles);
+
+
+static void execute_register_to_register_data_move(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value);
+static void execute_address_register_update(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value);
+static void execute_x_memory_data_move (dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value);
+static void execute_x_memory_data_move2(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register);
+static void execute_dual_x_memory_data_read(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register);
+static void execute_x_memory_data_move_with_short_displacement(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2);
+
+static uint16_t decode_BBB_bitmask(dsp56156_core* cpustate, uint16_t BBB, uint16_t *iVal);
+static int decode_cccc_table(dsp56156_core* cpustate, uint16_t cccc);
+static void decode_DDDDD_table(dsp56156_core* cpustate, uint16_t DDDDD, typed_pointer* ret);
+static void decode_DD_table(dsp56156_core* cpustate, uint16_t DD, typed_pointer* ret);
+static void decode_DDF_table(dsp56156_core* cpustate, uint16_t DD, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_F_table(dsp56156_core* cpustate, uint16_t F, typed_pointer* ret);
+static void decode_h0hF_table(dsp56156_core* cpustate, uint16_t h0h, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_HH_table(dsp56156_core* cpustate, uint16_t HH, typed_pointer* ret);
+static void decode_HHH_table(dsp56156_core* cpustate, uint16_t HHH, typed_pointer* ret);
+static void decode_IIII_table(dsp56156_core* cpustate, uint16_t IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void* working);
+static void decode_JJJF_table(dsp56156_core* cpustate, uint16_t JJJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_JJF_table(dsp56156_core* cpustate, uint16_t JJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_JF_table(dsp56156_core* cpustate, uint16_t JJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_KKK_table(dsp56156_core* cpustate, uint16_t KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working);
+static void decode_QQF_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D);
+static void decode_QQF_special_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D);
+static void decode_QQQF_table(dsp56156_core* cpustate, uint16_t QQQ, uint16_t F, void **S1, void **S2, void **D);
+static void decode_RR_table(dsp56156_core* cpustate, uint16_t RR, typed_pointer* ret);
+static void decode_TT_table(dsp56156_core* cpustate, uint16_t TT, typed_pointer* ret);
+static void decode_uuuuF_table(dsp56156_core* cpustate, uint16_t uuuu, uint16_t F, uint8_t add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_Z_table(dsp56156_core* cpustate, uint16_t Z, typed_pointer* ret);
+
+static void execute_m_table(dsp56156_core* cpustate, int x, uint16_t m);
+static void execute_mm_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t mm);
+static void execute_MM_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t MM);
+static uint16_t execute_q_table(dsp56156_core* cpustate, int RR, uint16_t q);
+static void execute_z_table(dsp56156_core* cpustate, int RR, uint16_t z);
+
+static uint16_t assemble_address_from_Pppppp_table(dsp56156_core* cpustate, uint16_t P, uint16_t ppppp);
+static uint16_t assemble_address_from_IO_short_address(dsp56156_core* cpustate, uint16_t pp);
+static uint16_t assemble_address_from_6bit_signed_relative_short_address(dsp56156_core* cpustate, uint16_t srs);
+
+static void dsp56156_process_loop(dsp56156_core* cpustate);
+static void dsp56156_process_rep(dsp56156_core* cpustate, size_t repSize);
+
+
+
+/********************/
+/* Helper Functions */
+/********************/
+static uint16_t Dsp56156OpMask(uint16_t op, uint16_t mask);
+
+/* These arguments are written source->destination to fall in line with the processor's paradigm. */
+static void SetDestinationValue(typed_pointer source, typed_pointer dest);
+
+static void SetDataMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr);
+static void SetProgramMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr);
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static void execute_one(dsp56156_core* cpustate)
+{
+ uint16_t op;
+ uint16_t op2;
+ size_t size = 0x1337;
+ uint8_t cycle_count = 0;
+
+ /* For MAME */
+ cpustate->ppc = PC;
+ if (cpustate->device->machine().debug_flags & DEBUG_FLAG_CALL_HOOK) // FIXME: if this was a member, the helper would work
+ cpustate->device->debug()->instruction_hook(PC);
+
+ cpustate->op = ROPCODE(PC);
+ /* The words we're going to be working with */
+ op = ROPCODE(PC);
+ op2 = ROPCODE(PC + 1);
+
+
+ /* DECODE */
+ /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+ if ((op & 0xe000) == 0x6000)
+ {
+ typed_pointer d_register = {nullptr, DT_BYTE};
+
+ /* Quote: (MOVE, MAC(R), MPY(R), ADD, SUB, TFR) */
+ uint16_t op_byte = op & 0x00ff;
+
+ /* ADD : 011m mKKK 0rru Fuuu : A-22 */
+ /* SUB : 011m mKKK 0rru Fuuu : A-202 */
+ /* Note: 0x0094 check allows command to drop through to MOVE and TFR */
+ if (((op & 0xe080) == 0x6000) && ((op & 0x0094) != 0x0010))
+ {
+ size = dsp56156_op_addsub_2(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */
+ else if ((op & 0xe094) == 0x6084)
+ {
+ size = dsp56156_op_mac_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MACR: 011m mKKK 1--1 F1QQ : A-124 */
+ else if ((op & 0xe094) == 0x6094)
+ {
+ size = dsp56156_op_macr_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* TFR : 011m mKKK 0rr1 F0DD : A-212 */
+ else if ((op & 0xe094) == 0x6010)
+ {
+ size = dsp56156_op_tfr_2(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MOVE : 011m mKKK 0rr1 0000 : A-128 */
+ else if ((op & 0xe09f) == 0x6010)
+ {
+ /* Note: The opcode encoding : 011x xxxx 0xx1 0000 (move + double memory read)
+ is .identical. to (tfr X0,A + two parallel reads). This sparks the notion
+ that these 'move' opcodes don't actually exist and are just there as
+ documentation. Real-world examples would need to be examined to come
+ to a satisfactory conclusion, but as it stands, tfr will override this
+ move operation. */
+ size = dsp56156_op_move_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */
+ else if ((op & 0xe094) == 0x6080)
+ {
+ size = dsp56156_op_mpy_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */
+ else if ((op & 0xe094) == 0x6090)
+ {
+ size = dsp56156_op_mpyr_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+
+ /* Now evaluate the parallel data move */
+ execute_dual_x_memory_data_read(cpustate, op, &d_register);
+ }
+ /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+ else if ((op & 0xfe00) == 0x1600)
+ {
+ /* Quote: (MPY or MAC) */
+ uint16_t op_byte = op & 0x00ff;
+
+ /* MPY : 0001 0110 RRDD FQQQ : A-160 */
+ if ((op & 0xff00) == 0x1600)
+ {
+ size = dsp56156_op_mpy_2(cpustate, op_byte, &cycle_count);
+ }
+ /* MAC : 0001 0111 RRDD FQQQ : A-122 */
+ else if ((op & 0xff00) == 0x1700)
+ {
+ size = dsp56156_op_mac_2(cpustate, op_byte, &cycle_count);
+ }
+
+ /* Now evaluate the parallel data move */
+ /* TODO // decode_x_memory_data_write_and_register_data_move(op, parallel_move_str, parallel_move_str2); */
+ cpustate->device->logerror("DSP56156: Unemulated Dual X Memory Data And Register Data Move @ 0x%x\n", PC);
+ }
+
+ /* Handle Other parallel types */
+ else
+ {
+ /***************************************/
+ /* 32 General parallel move operations */
+ /***************************************/
+
+ enum pType { kNoParallelDataMove,
+ kRegisterToRegister,
+ kAddressRegister,
+ kXMemoryDataMove,
+ kXMemoryDataMove2,
+ kXMemoryDataMoveWithDisp };
+
+ int parallelType = -1;
+ uint16_t op_byte = 0x0000;
+ typed_pointer d_register = {nullptr, DT_BYTE};
+ uint64_t prev_accum_value = 0x0000000000000000U;
+
+ /* Note: it's important that NPDM comes before RtRDM here */
+ /* No Parallel Data Move : 0100 1010 .... .... : A-131 */
+ if ((op & 0xff00) == 0x4a00)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kNoParallelDataMove;
+ }
+ /* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+ else if ((op & 0xf000) == 0x4000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kRegisterToRegister;
+ }
+ /* Address Register Update : 0011 0zRR .... .... : A-135 */
+ else if ((op & 0xf800) == 0x3000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kAddressRegister;
+ }
+ /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+ else if ((op & 0x8000) == 0x8000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kXMemoryDataMove;
+ }
+ /* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+ else if ((op & 0xf000) == 0x5000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kXMemoryDataMove2;
+ }
+ /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+ else if ((op & 0xff00) == 0x0500)
+ {
+ /* Now check it against all the other potential collisions */
+ /* This is necessary because "don't care bits" get in the way. */
+ /*
+ MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152
+ MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144
+ MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128
+ */
+ if (((op2 & 0xfe20) != 0x0200) &&
+ ((op2 & 0xf810) != 0x3800) &&
+ ((op2 & 0x00ff) != 0x0011))
+ {
+ op_byte = op2 & 0x00ff;
+ parallelType = kXMemoryDataMoveWithDisp;
+ }
+ }
+
+
+ if (parallelType != -1)
+ {
+ /* Note: There is much overlap between opcodes down here */
+ /* To this end, certain ops must come before others in the list */
+
+ /* CLR : .... .... 0000 F001 : A-60 */
+ if ((op_byte & 0x00f7) == 0x0001)
+ {
+ size = dsp56156_op_clr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ADD : .... .... 0000 FJJJ : A-22 */
+ else if ((op_byte & 0x00f0) == 0x0000)
+ {
+ size = dsp56156_op_add(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* MOVE : .... .... 0001 0001 : A-128 */
+ else if ((op_byte & 0x00ff) == 0x0011)
+ {
+ size = dsp56156_op_move(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* TFR : .... .... 0001 FJJJ : A-212 */
+ else if ((op_byte & 0x00f0) == 0x0010)
+ {
+ size = dsp56156_op_tfr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* RND : .... .... 0010 F000 : A-188 */
+ else if ((op_byte & 0x00f7) == 0x0020)
+ {
+ size = dsp56156_op_rnd(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* TST : .... .... 0010 F001 : A-218 */
+ else if ((op_byte & 0x00f7) == 0x0021)
+ {
+ size = dsp56156_op_tst(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* INC : .... .... 0010 F010 : A-104 */
+ else if ((op_byte & 0x00f7) == 0x0022)
+ {
+ size = dsp56156_op_inc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* INC24 : .... .... 0010 F011 : A-106 */
+ else if ((op_byte & 0x00f7) == 0x0023)
+ {
+ size = dsp56156_op_inc24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* OR : .... .... 0010 F1JJ : A-176 */
+ else if ((op_byte & 0x00f4) == 0x0024)
+ {
+ size = dsp56156_op_or(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* ASR : .... .... 0011 F000 : A-32 */
+ else if ((op_byte & 0x00f7) == 0x0030)
+ {
+ size = dsp56156_op_asr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ASL : .... .... 0011 F001 : A-28 */
+ else if ((op_byte & 0x00f7) == 0x0031)
+ {
+ size = dsp56156_op_asl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* LSR : .... .... 0011 F010 : A-120 */
+ else if ((op_byte & 0x00f7) == 0x0032)
+ {
+ size = dsp56156_op_lsr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* LSL : .... .... 0011 F011 : A-118 */
+ else if ((op_byte & 0x00f7) == 0x0033)
+ {
+ size = dsp56156_op_lsl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* EOR : .... .... 0011 F1JJ : A-94 */
+ else if ((op_byte & 0x00f4) == 0x0034)
+ {
+ size = dsp56156_op_eor(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* SUBL : .... .... 0100 F001 : A-204 */
+ else if ((op_byte & 0x00f7) == 0x0041)
+ {
+ size = dsp56156_op_subl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* SUB : .... .... 0100 FJJJ : A-202 */
+ else if ((op_byte & 0x00f0) == 0x0040)
+ {
+ size = dsp56156_op_sub(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* CLR24 : .... .... 0101 F001 : A-62 */
+ else if ((op_byte & 0x00f7) == 0x0051)
+ {
+ size = dsp56156_op_clr24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* SBC : .... .... 0101 F01J : A-198 */
+ else if ((op_byte & 0x00f6) == 0x0052)
+ {
+ size = dsp56156_op_sbc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* CMP : .... .... 0101 FJJJ : A-64 */
+ else if ((op_byte & 0x00f0) == 0x0050)
+ {
+ size = dsp56156_op_cmp(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* NEG : .... .... 0110 F000 : A-166 */
+ else if ((op_byte & 0x00f7) == 0x0060)
+ {
+ size = dsp56156_op_neg(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* NOT : .... .... 0110 F001 : A-174 */
+ else if ((op_byte & 0x00f7) == 0x0061)
+ {
+ size = dsp56156_op_not(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* DEC : .... .... 0110 F010 : A-72 */
+ else if ((op_byte & 0x00f7) == 0x0062)
+ {
+ size = dsp56156_op_dec(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* DEC24 : .... .... 0110 F011 : A-74 */
+ else if ((op_byte & 0x00f7) == 0x0063)
+ {
+ size = dsp56156_op_dec24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* AND : .... .... 0110 F1JJ : A-24 */
+ else if ((op_byte & 0x00f4) == 0x0064)
+ {
+ size = dsp56156_op_and(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* ABS : .... .... 0111 F001 : A-18 */
+ if ((op_byte & 0x00f7) == 0x0071)
+ {
+ size = dsp56156_op_abs(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ROR : .... .... 0111 F010 : A-192 */
+ else if ((op_byte & 0x00f7) == 0x0072)
+ {
+ size = dsp56156_op_ror(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ROL : .... .... 0111 F011 : A-190 */
+ else if ((op_byte & 0x00f7) == 0x0073)
+ {
+ size = dsp56156_op_rol(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* CMPM : .... .... 0111 FJJJ : A-66 */
+ else if ((op_byte & 0x00f0) == 0x0070)
+ {
+ size = dsp56156_op_cmpm(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */
+ else if ((op_byte & 0x00b0) == 0x0080)
+ {
+ size = dsp56156_op_mpy(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* MPYR : .... .... 1k01 FQQQ : A-162 */
+ else if ((op_byte & 0x00b0) == 0x0090)
+ {
+ size = dsp56156_op_mpyr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* MAC : .... .... 1k10 FQQQ : A-122 */
+ else if ((op_byte & 0x00b0) == 0x00a0)
+ {
+ size = dsp56156_op_mac(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */
+ else if ((op_byte & 0x00b0) == 0x00b0)
+ {
+ size = dsp56156_op_macr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* Now evaluate the parallel data move */
+ switch (parallelType)
+ {
+ case kNoParallelDataMove:
+ /* DO NOTHING */
+ break;
+ case kRegisterToRegister:
+ execute_register_to_register_data_move(cpustate, op, &d_register, &prev_accum_value);
+ break;
+ case kAddressRegister:
+ execute_address_register_update(cpustate, op, &d_register, &prev_accum_value);
+ break;
+ case kXMemoryDataMove:
+ execute_x_memory_data_move(cpustate, op, &d_register, &prev_accum_value);
+ break;
+ case kXMemoryDataMove2:
+ execute_x_memory_data_move2(cpustate, op, &d_register);
+ break;
+ case kXMemoryDataMoveWithDisp:
+ execute_x_memory_data_move_with_short_displacement(cpustate, op, op2);
+ size = 2;
+ break;
+ }
+ }
+ }
+
+ /* Drop out if you've already completed your work. */
+ if (size != 0x1337)
+ {
+ PC += (uint16_t)size;
+
+ dsp56156_process_loop(cpustate);
+ dsp56156_process_rep(cpustate, size);
+
+ cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */
+ return;
+ }
+
+
+ /******************************/
+ /* Remaining non-parallel ops */
+ /******************************/
+
+ /* ADC : 0001 0101 0000 F01J : A-20 */
+ if ((op & 0xfff6) == 0x1502)
+ {
+ size = dsp56156_op_adc(cpustate, op, &cycle_count);
+ }
+ /* ANDI : 0001 1EE0 iiii iiii : A-26 */
+ /* (MoveP sneaks in here if you don't check 0x0600) */
+ else if (((op & 0xf900) == 0x1800) & ((op & 0x0600) != 0x0000))
+ {
+ size = dsp56156_op_andi(cpustate, op, &cycle_count);
+ }
+ /* ASL4 : 0001 0101 0011 F001 : A-30 */
+ else if ((op & 0xfff7) == 0x1531)
+ {
+ size = dsp56156_op_asl4(cpustate, op, &cycle_count);
+ }
+ /* ASR4 : 0001 0101 0011 F000 : A-34 */
+ else if ((op & 0xfff7) == 0x1530)
+ {
+ size = dsp56156_op_asr4(cpustate, op, &cycle_count);
+ }
+ /* ASR16 : 0001 0101 0111 F000 : A-36 */
+ else if ((op & 0xfff7) == 0x1570)
+ {
+ size = dsp56156_op_asr16(cpustate, op, &cycle_count);
+ }
+ /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+ else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1200))
+ {
+ size = dsp56156_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+ else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1200))
+ {
+ size = dsp56156_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+ else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1200))
+ {
+ size = dsp56156_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+ else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x0400))
+ {
+ size = dsp56156_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+ else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x0400))
+ {
+ size = dsp56156_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+ else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x0400))
+ {
+ size = dsp56156_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+ else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1800))
+ {
+ size = dsp56156_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+ else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1800))
+ {
+ size = dsp56156_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+ else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1800))
+ {
+ size = dsp56156_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+ else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x1000))
+ {
+ size = dsp56156_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+ else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x1000))
+ {
+ size = dsp56156_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+ else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x1000))
+ {
+ size = dsp56156_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+ else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x0000))
+ {
+ size = dsp56156_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+ else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x0000))
+ {
+ size = dsp56156_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+ else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x0000))
+ {
+ size = dsp56156_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */
+ else if (((op & 0xff30) == 0x0730) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_bcc(cpustate, op, op2, &cycle_count);
+ }
+ /* Bcc : 0010 11cc ccee eeee : A-48 */
+ else if ((op & 0xfc00) == 0x2c00)
+ {
+ size = dsp56156_op_bcc_1(cpustate, op, &cycle_count);
+ }
+ /* Bcc : 0000 0111 RR10 cccc : A-48 */
+ else if ((op & 0xff30) == 0x0720)
+ {
+ size = dsp56156_op_bcc_2(cpustate, op, &cycle_count);
+ }
+ /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */
+ else if (((op & 0xfffc) == 0x013c) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_bra(cpustate, op, op2, &cycle_count);
+ }
+ /* BRA : 0000 1011 aaaa aaaa : A-50 */
+ else if ((op & 0xff00) == 0x0b00)
+ {
+ size = dsp56156_op_bra_1(cpustate, op, &cycle_count);
+ }
+ /* BRA : 0000 0001 0010 11RR : A-50 */
+ else if ((op & 0xfffc) == 0x012c)
+ {
+ size = dsp56156_op_bra_2(cpustate, op, &cycle_count);
+ }
+ /* BRKc : 0000 0001 0001 cccc : A-52 */
+ else if ((op & 0xfff0) == 0x0110)
+ {
+ size = dsp56156_op_brkcc(cpustate, op, &cycle_count);
+ }
+ /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */
+ else if (((op & 0xff30) == 0x0710) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_bscc(cpustate, op, op2, &cycle_count);
+ }
+ /* BScc : 0000 0111 RR00 cccc : A-54 */
+ else if ((op & 0xff30) == 0x0700)
+ {
+ size = dsp56156_op_bscc_1(cpustate, op, &cycle_count);
+ }
+ /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */
+ else if (((op & 0xfffc) == 0x0138) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_bsr(cpustate, op, op2, &cycle_count);
+ }
+ /* BSR : 0000 0001 0010 10RR : A-56 */
+ else if ((op & 0xfffc) == 0x0128)
+ {
+ size = dsp56156_op_bsr_1(cpustate, op, &cycle_count);
+ }
+ /* CHKAAU : 0000 0000 0000 0100 : A-58 */
+ else if ((op & 0xffff) == 0x0004)
+ {
+ size = dsp56156_op_chkaau(cpustate, op, &cycle_count);
+ }
+ /* DEBUG : 0000 0000 0000 0001 : A-68 */
+ else if ((op & 0xffff) == 0x0001)
+ {
+ size = dsp56156_op_debug(cpustate, op, &cycle_count);
+ }
+ /* DEBUGcc : 0000 0000 0101 cccc : A-70 */
+ else if ((op & 0xfff0) == 0x0050)
+ {
+ size = dsp56156_op_debugcc(cpustate, op, &cycle_count);
+ }
+ /* DIV : 0001 0101 0--0 F1DD : A-76 */
+ else if ((op & 0xff94) == 0x1504)
+ {
+ size = dsp56156_op_div(cpustate, op, &cycle_count);
+ }
+ /* DMAC : 0001 0101 10s1 FsQQ : A-80 */
+ else if ((op & 0xffd0) == 0x1590)
+ {
+ size = dsp56156_op_dmac(cpustate, op, &cycle_count);
+ }
+ /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */
+ else if (((op & 0xffe0) == 0x00c0) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_do(cpustate, op, op2, &cycle_count);
+ }
+ /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */
+ else if (((op & 0xff00) == 0x0e00) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_do_1(cpustate, op, op2, &cycle_count);
+ }
+ /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */
+ else if (((op & 0xffe0) == 0x0400) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_do_2(cpustate, op, op2, &cycle_count);
+ }
+ /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */
+ else if (((op & 0xffff) == 0x0002) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_doforever(cpustate, op, op2, &cycle_count);
+ }
+ /* ENDDO : 0000 0000 0000 1001 : A-92 */
+ else if ((op & 0xffff) == 0x0009)
+ {
+ size = dsp56156_op_enddo(cpustate, op, &cycle_count);
+ }
+ /* EXT : 0001 0101 0101 F010 : A-96 */
+ else if ((op & 0xfff7) == 0x1552)
+ {
+ size = dsp56156_op_ext(cpustate, op, &cycle_count);
+ }
+ /* ILLEGAL : 0000 0000 0000 1111 : A-98 */
+ else if ((op & 0xffff) == 0x000f)
+ {
+ size = dsp56156_op_illegal(cpustate, op, &cycle_count);
+ }
+ /* IMAC : 0001 0101 1010 FQQQ : A-100 */
+ else if ((op & 0xfff0) == 0x15a0)
+ {
+ size = dsp56156_op_imac(cpustate, op, &cycle_count);
+ }
+ /* IMPY : 0001 0101 1000 FQQQ : A-102 */
+ else if ((op & 0xfff0) == 0x1580)
+ {
+ size = dsp56156_op_impy(cpustate, op, &cycle_count);
+ }
+ /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */
+ else if (((op & 0xff30) == 0x0630) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_jcc(cpustate, op, op2, &cycle_count);
+ }
+ /* Jcc : 0000 0110 RR10 cccc : A-108 */
+ else if ((op & 0xff30) == 0x0620 )
+ {
+ size = dsp56156_op_jcc_1(cpustate, op, &cycle_count);
+ }
+ /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */
+ else if (((op & 0xfffc) == 0x0134) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_jmp(cpustate, op, op2, &cycle_count);
+ }
+ /* JMP : 0000 0001 0010 01RR : A-110 */
+ else if ((op & 0xfffc) == 0x0124)
+ {
+ size = dsp56156_op_jmp_1(cpustate, op, &cycle_count);
+ }
+ /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */
+ else if (((op & 0xff30) == 0x0610) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_jscc(cpustate, op, op2, &cycle_count);
+ }
+ /* JScc : 0000 0110 RR00 cccc : A-112 */
+ else if ((op & 0xff30) == 0x0600)
+ {
+ size = dsp56156_op_jscc_1(cpustate, op, &cycle_count);
+ }
+ /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */
+ else if (((op & 0xfffc) == 0x0130) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_jsr(cpustate, op, op2, &cycle_count);
+ }
+ /* JSR : 0000 1010 AAAA AAAA : A-114 */
+ else if ((op & 0xff00) == 0x0a00)
+ {
+ size = dsp56156_op_jsr_1(cpustate, op, &cycle_count);
+ }
+ /* JSR : 0000 0001 0010 00RR : A-114 */
+ else if ((op & 0xfffc) == 0x0120)
+ {
+ size = dsp56156_op_jsr_2(cpustate, op, &cycle_count);
+ }
+ /* LEA : 0000 0001 11TT MMRR : A-116 */
+ else if ((op & 0xffc0) == 0x01c0)
+ {
+ size = dsp56156_op_lea(cpustate, op, &cycle_count);
+ }
+ /* LEA : 0000 0001 10NN MMRR : A-116 */
+ else if ((op & 0xffc0) == 0x0180)
+ {
+ size = dsp56156_op_lea_1(cpustate, op, &cycle_count);
+ }
+ /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */
+ else if ((op & 0xfff0) == 0x15e0)
+ {
+ size = dsp56156_op_macsuuu(cpustate, op, &cycle_count);
+ }
+ /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */
+ else if (((op & 0xff00) == 0x0500) && ((op2 & 0x00ff) == 0x0011))
+ {
+ size = dsp56156_op_move_2(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */
+ else if ((op & 0xf810) == 0x3800)
+ {
+ size = dsp56156_op_movec(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */
+ else if ((op & 0xf814) == 0x3810)
+ {
+ size = dsp56156_op_movec_1(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */
+ else if ((op & 0xf816) == 0x3816)
+ {
+ size = dsp56156_op_movec_2(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */
+ else if (((op & 0xf816) == 0x3814) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56156_op_movec_3(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */
+ else if ((op & 0xfc00) == 0x2800)
+ {
+ size = dsp56156_op_movec_4(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */
+ else if (((op & 0xff00) == 0x0500) && ((op2 & 0xf810) == 0x3800))
+ {
+ size = dsp56156_op_movec_5(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */
+ else if ((op & 0xfc00) == 0x2000)
+ {
+ size = dsp56156_op_movei(cpustate, op, &cycle_count);
+ }
+ /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */
+ else if ((op & 0xfe20) == 0x0200)
+ {
+ size = dsp56156_op_movem(cpustate, op, &cycle_count);
+ }
+ /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */
+ else if ((op & 0xfe30) == 0x0230)
+ {
+ size = dsp56156_op_movem_1(cpustate, op, &cycle_count);
+ }
+ /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */
+ else if (((op & 0xff00) == 0x0500) && ((op2 & 0xfe20) == 0x0200))
+ {
+ size = dsp56156_op_movem_2(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(P) : 0001 100W HH1p pppp : A-156 */
+ else if ((op & 0xfe20) == 0x1820)
+ {
+ size = dsp56156_op_movep(cpustate, op, &cycle_count);
+ }
+ /* MOVE(P) : 0000 110W RRmp pppp : A-156 */
+ else if ((op & 0xfe00) == 0x0c00)
+ {
+ size = dsp56156_op_movep_1(cpustate, op, &cycle_count);
+ }
+ /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */
+ else if ((op & 0xfe20) == 0x1800)
+ {
+ size = dsp56156_op_moves(cpustate, op, &cycle_count);
+ }
+ /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */
+ else if ((op & 0xfff0) == 0x15c0)
+ {
+ size = dsp56156_op_mpysuuu(cpustate, op, &cycle_count);
+ }
+ /* NEGC : 0001 0101 0110 F000 : A-168 */
+ else if ((op & 0xfff7) == 0x1560)
+ {
+ size = dsp56156_op_negc(cpustate, op, &cycle_count);
+ }
+ /* NOP : 0000 0000 0000 0000 : A-170 */
+ else if ((op & 0xffff) == 0x0000)
+ {
+ size = dsp56156_op_nop(cpustate, op, &cycle_count);
+ }
+ /* NORM : 0001 0101 0010 F0RR : A-172 */
+ else if ((op & 0xfff4) == 0x1520)
+ {
+ size = dsp56156_op_norm(cpustate, op, &cycle_count);
+ }
+ /* ORI : 0001 1EE1 iiii iiii : A-178 */
+ else if ((op & 0xf900) == 0x1900)
+ {
+ size = dsp56156_op_ori(cpustate, op, &cycle_count);
+ }
+ /* REP : 0000 0000 111- --RR : A-180 */
+ else if ((op & 0xffe0) == 0x00e0)
+ {
+ size = dsp56156_op_rep(cpustate, op, &cycle_count);
+ }
+ /* REP : 0000 1111 iiii iiii : A-180 */
+ else if ((op & 0xff00) == 0x0f00)
+ {
+ size = dsp56156_op_rep_1(cpustate, op, &cycle_count);
+ }
+ /* REP : 0000 0100 001D DDDD : A-180 */
+ else if ((op & 0xffe0) == 0x0420)
+ {
+ size = dsp56156_op_rep_2(cpustate, op, &cycle_count);
+ }
+ /* REPcc : 0000 0001 0101 cccc : A-184 */
+ else if ((op & 0xfff0) == 0x0150)
+ {
+ size = dsp56156_op_repcc(cpustate, op, &cycle_count);
+ }
+ /* RESET : 0000 0000 0000 1000 : A-186 */
+ else if ((op & 0xffff) == 0x0008)
+ {
+ size = dsp56156_op_reset(cpustate, op, &cycle_count);
+ }
+ /* RTI : 0000 0000 0000 0111 : A-194 */
+ else if ((op & 0xffff) == 0x0007)
+ {
+ size = dsp56156_op_rti(cpustate, op, &cycle_count);
+ }
+ /* RTS : 0000 0000 0000 0110 : A-196 */
+ else if ((op & 0xffff) == 0x0006)
+ {
+ size = dsp56156_op_rts(cpustate, op, &cycle_count);
+ }
+ /* STOP : 0000 0000 0000 1010 : A-200 */
+ else if ((op & 0xffff) == 0x000a)
+ {
+ size = dsp56156_op_stop(cpustate, op, &cycle_count);
+ }
+ /* SWAP : 0001 0101 0111 F001 : A-206 */
+ else if ((op & 0xfff7) == 0x1571)
+ {
+ size = dsp56156_op_swap(cpustate, op, &cycle_count);
+ }
+ /* SWI : 0000 0000 0000 0101 : A-208 */
+ else if ((op & 0xffff) == 0x0005)
+ {
+ size = dsp56156_op_swi(cpustate, op, &cycle_count);
+ }
+ /* Tcc : 0001 00cc ccTT Fh0h : A-210 */
+ else if ((op & 0xfc02) == 0x1000)
+ {
+ size = dsp56156_op_tcc(cpustate, op, &cycle_count);
+ }
+ /* TFR(2) : 0001 0101 0000 F00J : A-214 */
+ else if ((op & 0xfff6) == 0x1500)
+ {
+ size = dsp56156_op_tfr2(cpustate, op, &cycle_count);
+ }
+ /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */
+ else if ((op & 0xfc00) == 0x2400)
+ {
+ size = dsp56156_op_tfr3(cpustate, op, &cycle_count);
+ }
+ /* TST(2) : 0001 0101 0001 -1DD : A-220 */
+ else if ((op & 0xfff4) == 0x1514)
+ {
+ size = dsp56156_op_tst2(cpustate, op, &cycle_count);
+ }
+ /* WAIT : 0000 0000 0000 1011 : A-222 */
+ else if ((op & 0xffff) == 0x000b)
+ {
+ size = dsp56156_op_wait(cpustate, op, &cycle_count);
+ }
+ /* ZERO : 0001 0101 0101 F000 : A-224 */
+ else if ((op & 0xfff7) == 0x1550)
+ {
+ size = dsp56156_op_zero(cpustate, op, &cycle_count);
+ }
+
+
+ /* Not recognized? Nudge debugger onto the next word */
+ if (size == 0x1337)
+ {
+ cpustate->device->logerror("DSP56156: Unimplemented opcode at 0x%04x : %04x\n", PC, op);
+ size = 1 ; /* Just to get the debugger past the bad opcode */
+ }
+
+ /* Must have been a good opcode */
+ PC += (uint16_t)size;
+
+ dsp56156_process_loop(cpustate);
+ dsp56156_process_rep(cpustate, size);
+
+ cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */
+}
+
+
+
+
+/***************************************************************************
+ Opcode implementations
+***************************************************************************/
+
+/*******************************/
+/* 32 Parallel move operations */
+/*******************************/
+
+/* ADD : 011m mKKK 0rru Fuuu : A-22 */
+/* SUB : 011m mKKK 0rru Fuuu : A-202 */
+static size_t dsp56156_op_addsub_2(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles)
+{
+ uint64_t useVal = 0;
+ uint8_t op_type = OP_OTHER;
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_uuuuF_table(cpustate, BITS(op_byte,0x0017), BITS(op_byte,0x0008), op_type, &S, &D);
+
+ /* If you gave an invalid operation type, presume it's a nop and move on with the parallel move */
+ if (op_type == OP_OTHER)
+ {
+ d_register->addr = nullptr;
+ d_register->data_type = DT_BYTE;
+ cycles += 2;
+ return 1;
+ }
+
+ /* It's a real operation. Get on with it. */
+ switch(S.data_type)
+ {
+ case DT_WORD: useVal = (uint64_t)*((uint16_t*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: useVal = (uint64_t)*((uint32_t*)S.addr); break;
+ case DT_LONG_WORD: useVal = (uint64_t)*((uint64_t*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper add/sub op */
+ if ((S.data_type == DT_WORD) && (useVal & 0x0000000080000000U))
+ useVal |= 0x000000ff00000000U;
+
+ /* Operate*/
+ if (op_type == OP_ADD)
+ *((uint64_t*)D.addr) += useVal;
+ else if (op_type == OP_SUB)
+ *((uint64_t*)D.addr) -= useVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO S, L, E, U, V, C */
+ if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* MAC : 011m mKKK 1xx0 F1QQ : A-122 */
+static size_t dsp56156_op_mac_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles)
+{
+ int64_t opD = 0;
+ int64_t result = 0;
+
+ int32_t s1 = 0;
+ int32_t s2 = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ /* Cast both values as being signed */
+ s1 = *((int16_t*)S1);
+ s2 = *((int16_t*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((uint64_t*)D));
+ if (opD & 0x0000008000000000U)
+ opD |= 0xffffff0000000000U;
+ else
+ opD &= 0x000000ffffffffffU;
+
+ /* Accumulate */
+ opD += result;
+
+ /* And out the bits that don't live in the register */
+ opD &= 0x000000ffffffffffU;
+
+ (*((uint64_t*)D)) = (uint64_t)opD;
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MACR: 011m mKKK 1--1 F1QQ : A-124 */
+static size_t dsp56156_op_macr_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* MOVE : 011m mKKK 0rr1 0000 : A-128 */
+static size_t dsp56156_op_move_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MPY : 011m mKKK 1xx0 F0QQ : A-160 */
+static size_t dsp56156_op_mpy_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles)
+{
+ int64_t result = 0;
+
+ int32_t s1 = 0;
+ int32_t s2 = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ /* Cast both values as being signed */
+ s1 = *((int16_t*)S1);
+ s2 = *((int16_t*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* And out the bits that don't live in the register */
+ (*((uint64_t*)D)) = result & 0x000000ffffffffffU;
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MPYR : 011m mKKK 1--1 F0QQ : A-162 */
+static size_t dsp56156_op_mpyr_1(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* TFR : 011m mKKK 0rr1 F0DD : A-212 */
+static size_t dsp56156_op_tfr_2(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* MPY : 0001 0110 RRDD FQQQ : A-160 */
+static size_t dsp56156_op_mpy_2(dsp56156_core* cpustate, const uint16_t op_byte, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* MAC : 0001 0111 RRDD FQQQ : A-122 */
+static size_t dsp56156_op_mac_2(dsp56156_core* cpustate, const uint16_t op_byte, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* CLR : .... .... 0000 F001 : A-60 */
+static size_t dsp56156_op_clr(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_LONG_WORD};
+ typed_pointer clear = {nullptr, DT_LONG_WORD};
+ uint64_t clear_val = 0x0000000000000000U;
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ clear.addr = &clear_val;
+ clear.data_type = DT_LONG_WORD;
+ SetDestinationValue(clear, D);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * 0 - */
+ /* TODO - S, L */
+ DSP56156_E_CLEAR();
+ DSP56156_U_SET();
+ DSP56156_N_CLEAR();
+ DSP56156_Z_SET();
+ DSP56156_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* ADD : .... .... 0000 FJJJ : A-22 */
+static size_t dsp56156_op_add(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint64_t addVal = 0;
+
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ switch(S.data_type)
+ {
+ case DT_WORD: addVal = (uint64_t)*((uint16_t*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: addVal = (uint64_t)*((uint32_t*)S.addr); break;
+ case DT_LONG_WORD: addVal = (uint64_t)*((uint64_t*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper add/sub op */
+ if ((S.data_type == DT_WORD) && (addVal & 0x0000000080000000U))
+ addVal |= 0x000000ff00000000U;
+
+ /* Operate*/
+ *((uint64_t*)D.addr) += addVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO S, L, E, U, V, C */
+ if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* MOVE : .... .... 0001 0001 : A-128 */
+static size_t dsp56156_op_move(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* Equivalent to a nop with a parallel move */
+ /* These can't be used later. Hopefully compilers would pick this up. */
+ *p_accum = 0;
+ d_register->addr = nullptr;
+ d_register->data_type = DT_BYTE;
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* TFR : .... .... 0001 FJJJ : A-212 */
+static size_t dsp56156_op_tfr(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ SetDestinationValue(S, D);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* RND : .... .... 0010 F000 : A-188 */
+static size_t dsp56156_op_rnd(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */
+ if ((*((uint64_t*)D.addr) & 0x000000000000ffffU) >= 0x8000)
+ *((uint64_t*)D.addr) += 0x0000000000010000U;
+
+ *((uint64_t*)D.addr) = *((uint64_t*)D.addr) & 0x000000ffffff0000U;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, U, V */
+ if ((*((uint64_t*)D.addr)) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr)) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* TST : .... .... 0010 F001 : A-218 */
+static size_t dsp56156_op_tst(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_LONG_WORD};
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* 0 * * * * * 0 0 */
+ /* TODO: S, L, E, U */
+ if ((*((uint64_t*)D.addr)) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr)) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+ DSP56156_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* INC : .... .... 0010 F010 : A-104 */
+static size_t dsp56156_op_inc(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* Make sure the destination is a real 40-bit value */
+ *((uint64_t*)D.addr) &= 0x000000ffffffffffU;
+
+ /* Increment */
+ *((uint64_t*)D.addr) = *((uint64_t*)D.addr) + 1;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO: S, L, E, U */
+ if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* INC24 : .... .... 0010 F011 : A-106 */
+static size_t dsp56156_op_inc24(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint32_t workBits24;
+
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* TODO: I wonder if workBits24 should be signed? */
+ workBits24 = ((*((uint64_t*)D.addr)) & 0x000000ffffff0000U) >> 16;
+ workBits24++;
+ //workBits24 &= 0x00ffffff; /* Solves -x issues - TODO: huh? */
+
+ /* Set the D bits with the dec result */
+ *((uint64_t*)D.addr) &= 0x000000000000ffffU;
+ *((uint64_t*)D.addr) |= (((uint64_t)(workBits24)) << 16);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * ? * * */
+ /* TODO: S, L, E, U */
+ if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ if ((workBits24 & 0xff000000) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR();
+ if ((workBits24 & 0xff000000) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* OR : .... .... 0010 F1JJ : A-176 */
+static size_t dsp56156_op_or(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* OR a word of S with A1|B1 */
+ ((PAIR64*)D.addr)->w.h = *((uint16_t*)S.addr) | ((PAIR64*)D.addr)->w.h;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* TODO: S, L */
+ if ( *((uint64_t*)D.addr) & 0x0000000080000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* ASR : .... .... 0011 F000 : A-32 */
+static size_t dsp56156_op_asr(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) >> 1;
+
+ /* Make sure the MSB is maintained */
+ if (*p_accum & 0x0000008000000000U)
+ *((uint64_t*)D.addr) |= 0x0000008000000000U;
+ else
+ *((uint64_t*)D.addr) &= (~u64(0x0000008000000000U));
+
+ /* For the parallel move */
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * 0 ? */
+ /* TODO: S, L, E, U */
+ if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+ if (*p_accum & 0x0000000000000001U) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* ASL : .... .... 0011 F001 : A-28 */
+static size_t dsp56156_op_asl(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * ? ? */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ /* C - Set if bit 39 of source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* LSR : .... .... 0011 F010 : A-120 */
+static size_t dsp56156_op_lsr(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ ((PAIR64*)D.addr)->w.h = (((PAIR64*)D.addr)->w.h) >> 1;
+
+ /* Make sure bit 31 gets a 0 */
+ ((PAIR64*)D.addr)->w.h &= (~0x8000);
+
+ /* For the parallel move */
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* TODO: S, L */
+ DSP56156_N_CLEAR();
+ if (((PAIR64*)D.addr)->w.h == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+ if (*p_accum & 0x0000000000010000U) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* LSL : .... .... 0011 F011 : A-118 */
+static size_t dsp56156_op_lsl(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* EOR : .... .... 0011 F1JJ : A-94 */
+static size_t dsp56156_op_eor(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ return 0;
+}
+
+/* SUBL : .... .... 0100 F001 : A-204 */
+static size_t dsp56156_op_subl(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * ? * */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ return 0;
+}
+
+/* SUB : .... .... 0100 FJJJ : A-202 */
+static size_t dsp56156_op_sub(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint64_t useVal = 0;
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S, &D);
+
+ /* Get on with it. */
+ switch(S.data_type)
+ {
+ case DT_WORD: useVal = (uint64_t)*((uint16_t*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: useVal = (uint64_t)*((uint32_t*)S.addr); break;
+ case DT_LONG_WORD: useVal = (uint64_t)*((uint64_t*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper sub op */
+ if ((S.data_type == DT_WORD) && useVal & 0x0000000080000000U)
+ useVal |= 0x000000ff00000000U;
+
+ /* Make sure they're both real 40-bit values */
+ useVal &= 0x000000ffffffffffU;
+ *((uint64_t*)D.addr) &= 0x000000ffffffffffU;
+
+ /* Operate*/
+ *((uint64_t*)D.addr) -= useVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO S, L, E, U */
+ if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ( *((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* CLR24 : .... .... 0101 F001 : A-62 */
+static size_t dsp56156_op_clr24(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * ? 0 - */
+ /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */
+ return 0;
+}
+
+/* SBC : .... .... 0101 F01J : A-198 */
+static size_t dsp56156_op_sbc(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ return 0;
+}
+
+/* CMP : .... .... 0101 FJJJ : A-64 */
+static size_t dsp56156_op_cmp(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint64_t cmpVal = 0;
+ uint64_t result = 0;
+
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ switch(S.data_type)
+ {
+ case DT_WORD: cmpVal = (uint64_t)*((uint16_t*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: cmpVal = (uint64_t)*((uint32_t*)S.addr); break;
+ case DT_LONG_WORD: cmpVal = (uint64_t)*((uint64_t*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper subtraction op */
+ if ((S.data_type == DT_WORD) && cmpVal & 0x0000000080000000U)
+ cmpVal |= 0x000000ff00000000U;
+
+ /* Make sure they're both real 40-bit values */
+ cmpVal &= 0x000000ffffffffffU;
+ *((uint64_t*)D.addr) &= 0x000000ffffffffffU;
+
+ /* Operate */
+ result = *((uint64_t*)D.addr) - cmpVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO: S, L, E, U */
+ if ( result & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ( result == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ if ((result & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR();
+ if ((result & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* NEG : .... .... 0110 F000 : A-166 */
+static size_t dsp56156_op_neg(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ return 0;
+}
+
+/* NOT : .... .... 0110 F001 : A-174 */
+static size_t dsp56156_op_not(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* Invert bits [16:31] of D */
+ ((PAIR64*)D.addr)->w.h = ~(((PAIR64*)D.addr)->w.h);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* TODO: S?, L */
+ if ( *((uint64_t*)D.addr) & 0x0000000080000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* DEC : .... .... 0110 F010 : A-72 */
+static size_t dsp56156_op_dec(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ return 0;
+}
+
+/* DEC24 : .... .... 0110 F011 : A-74 */
+static size_t dsp56156_op_dec24(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint32_t workBits24;
+
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* TODO: I wonder if workBits24 should be signed? */
+ workBits24 = ((*((uint64_t*)D.addr)) & 0x000000ffffff0000U) >> 16;
+ workBits24--;
+ workBits24 &= 0x00ffffff; /* Solves -x issues */
+
+ /* Set the D bits with the dec result */
+ *((uint64_t*)D.addr) &= 0x000000000000ffffU;
+ *((uint64_t*)D.addr) |= (((uint64_t)(workBits24)) << 16);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * ? * * */
+ /* TODO: S, L, E, U, V, C */
+ if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* AND : .... .... 0110 F1JJ : A-24 */
+static size_t dsp56156_op_and(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* AND a word of S with A1|B1 */
+ ((PAIR64*)D.addr)->w.h = *((uint16_t*)S.addr) & ((PAIR64*)D.addr)->w.h;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* TODO: S, L */
+ if ( *((uint64_t*)D.addr) & 0x0000000080000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* ABS : .... .... 0111 F001 : A-18 */
+static size_t dsp56156_op_abs(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ int64_t opD = 0;
+ typed_pointer D = {nullptr, DT_LONG_WORD};
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* Sign extend D into a temp variable */
+ opD = *p_accum;
+ if (opD & 0x0000008000000000U)
+ opD |= 0xffffff0000000000U;
+ else
+ opD &= 0x000000ffffffffffU;
+
+ /* Take the absolute value and clean up */
+ opD = (opD < 0) ? -opD : opD;
+ opD &= 0x000000ffffffffffU;
+
+ /* Reassign */
+ *((uint64_t*)D.addr) = opD;
+
+ /* Special overflow case */
+ if ((*p_accum) == 0x0000008000000000U)
+ *((uint64_t*)D.addr) = 0x0000007fffffffffU;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, U */
+ if ( *((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D.addr) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ if ((*p_accum) == 0x0000008000000000U) DSP56156_V_SET(); else DSP56156_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* ROR : .... .... 0111 F010 : A-192 */
+static size_t dsp56156_op_ror(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ /* C - Set if bit 16 of the source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* ROL : .... .... 0111 F011 : A-190 */
+static size_t dsp56156_op_rol(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* CMPM : .... .... 0111 FJJJ : A-66 */
+static size_t dsp56156_op_cmpm(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ int64_t absS;
+ int64_t absD;
+ int64_t absResult;
+
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((uint64_t*)D.addr);
+
+ /* Sign extend and get absolute value of the source */
+ if (S.addr == &A || S.addr == &B)
+ {
+ absS = *((uint64_t*)S.addr);
+ if (absS & 0x0000008000000000U)
+ absS |= 0xffffff8000000000U;
+ }
+ else
+ {
+ absS = (*((uint16_t*)S.addr)) << 16;
+ if (absS & 0x0000000080000000U)
+ absS |= 0xffffffff80000000U;
+ }
+ absS = (absS < 0) ? -absS : absS;
+
+ /* Sign extend and get absolute value of the destination */
+ if (D.addr == &A || D.addr == &B)
+ {
+ absD = *((uint64_t*)D.addr);
+ if (absD & 0x0000008000000000U)
+ absD |= 0xffffff8000000000U;
+ }
+ else
+ {
+ absD = (*((uint16_t*)D.addr)) << 16;
+ if (absS & 0x0000000080000000U)
+ absS |= 0xffffffff80000000U;
+ }
+ absD = (absD < 0) ? -absD : absD;
+
+ /* Compare */
+ absResult = absD - absS;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO: S, L, E, U */
+ if ( (absResult) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if (((absResult) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ if ( (absResult & 0xffffff0000000000U) != 0) DSP56156_V_SET(); else DSP56156_V_CLEAR();
+ if ( (absResult & 0xffffff0000000000U) != 0) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */
+static size_t dsp56156_op_mpy(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint16_t k = 0;
+ int64_t result = 0;
+
+ int32_t s1 = 0;
+ int32_t s2 = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ k = BITS(op_byte,0x0040);
+
+ /* Cast both values as being signed */
+ s1 = *((int16_t*)S1);
+ s2 = *((int16_t*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Negate the product if necessary */
+ if (k)
+ result *= -1;
+
+ (*((uint64_t*)D)) = result & 0x000000ffffffffffU;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MPYR : .... .... 1k01 FQQQ : A-162 */
+static size_t dsp56156_op_mpyr(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* MAC : .... .... 1k10 FQQQ : A-122 */
+static size_t dsp56156_op_mac(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint16_t k = 0;
+ int64_t opD = 0;
+ int64_t result = 0;
+
+ int32_t s1 = 0;
+ int32_t s2 = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ k = BITS(op_byte,0x0040);
+
+ /* Cast both values as being signed */
+ s1 = *((int16_t*)S1);
+ s2 = *((int16_t*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((uint64_t*)D));
+ if (opD & 0x0000008000000000U)
+ opD |= 0xffffff0000000000U;
+ else
+ opD &= 0x000000ffffffffffU;
+
+ /* Negate if necessary */
+ if (k)
+ result *= -1;
+
+ /* Accumulate */
+ opD += result;
+
+ /* And out the bits that don't live in the register */
+ opD &= 0x000000ffffffffffU;
+
+ (*((uint64_t*)D)) = (uint64_t)opD;
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */
+static size_t dsp56156_op_macr(dsp56156_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles)
+{
+ uint16_t k = 0;
+ int64_t opD = 0;
+ int64_t result = 0;
+
+ int32_t s1 = 0;
+ int32_t s2 = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ k = BITS(op_byte,0x0040);
+
+ /* Cast both values as being signed */
+ s1 = *((int16_t*)S1);
+ s2 = *((int16_t*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((uint64_t*)D));
+ if (opD & 0x0000008000000000U)
+ opD |= 0xffffff0000000000U;
+ else
+ opD &= 0x000000ffffffffffU;
+
+ /* Negate if necessary */
+ if (k)
+ result *= -1;
+
+ /* Accumulate */
+ opD += result;
+
+ /* Round the result */
+ /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */
+ if ((opD & 0x000000000000ffffU) >= 0x8000)
+ opD += 0x0000000000010000U;
+
+ opD &= 0x000000ffffff0000U;
+
+ /* And out the bits that don't live in the register */
+ opD &= 0x000000ffffffffffU;
+
+ /* Store the result */
+ (*((uint64_t*)D)) = (uint64_t)opD;
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+
+/******************************/
+/* Remaining non-parallel ops */
+/******************************/
+
+/* ADC : 0001 0101 0000 F01J : A-20 */
+static size_t dsp56156_op_adc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * * */
+ return 0;
+}
+
+/* ANDI : 0001 1EE0 iiii iiii : A-26 */
+static size_t dsp56156_op_andi(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint16_t immediate = BITS(op,0x00ff);
+
+ /* There is not currently a good way to refer to CCR or MR. Explicitly decode here. */
+ switch(BITS(op,0x0600))
+ {
+ case 0x01: /* MR */
+ SR &= ((immediate << 8) | 0x00ff);
+ break;
+
+ case 0x02: /* CCR */
+ SR &= (immediate | 0xff00);
+ break;
+
+ case 0x03: /* OMR */
+ OMR &= (uint8_t)(immediate);
+ break;
+
+ default:
+ fatalerror("DSP56156 - BAD EE value in andi operation\n") ;
+ }
+
+ /* S L E U N Z V C */
+ /* - ? ? ? ? ? ? ? */
+ /* All ? bits - Cleared if the corresponding bit in the immediate data is cleared and if the operand
+ is the CCR. Not affected otherwise. */
+ cycles += 2;
+ return 1;
+}
+
+/* ASL4 : 0001 0101 0011 F001 : A-30 */
+static size_t dsp56156_op_asl4(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint64_t p_accum = 0;
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op,0x0008), &D);
+
+ p_accum = *((uint64_t*)D.addr);
+
+ *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) << 4;
+ *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) & 0x000000ffffffffffU;
+
+ /* S L E U N Z V C */
+ /* - ? * * * * ? ? */
+ /* TODO: L, E, U */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if bit 35 through 39 are
+ not the same. */
+ /* C - Set if bit 36 of source operand is set. Cleared otherwise. */
+ if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ if ( (*((uint64_t*)D.addr) & 0x000000ff00000000U) != (p_accum & 0x000000ff00000000U) ) DSP56156_V_SET(); else DSP56156_V_CLEAR();
+ if (p_accum & 0x0000001000000000U) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* ASR4 : 0001 0101 0011 F000 : A-34 */
+static size_t dsp56156_op_asr4(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint64_t p_accum = 0;
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_F_table(cpustate, BITS(op,0x0008), &D);
+
+ p_accum = *((uint64_t*)D.addr);
+
+ *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) >> 4;
+ *((uint64_t*)D.addr) = (*((uint64_t*)D.addr)) & 0x000000ffffffffffU;
+
+ /* The top 4 bits become the old bit 39 */
+ if (p_accum & 0x0000008000000000U)
+ *((uint64_t*)D.addr) |= 0x000000f000000000U;
+ else
+ *((uint64_t*)D.addr) &= (~u64(0x000000f000000000U));
+
+ /* S L E U N Z V C */
+ /* - * * * * * 0 ? */
+ /* TODO: E, U */
+ /* C - Set if bit 3 of source operand is set. Cleared otherwise. */
+ if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+ if (p_accum & 0x0000000000000008U) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* ASR16 : 0001 0101 0111 F000 : A-36 */
+static size_t dsp56156_op_asr16(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint64_t backupVal;
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_F_table(cpustate, BITS(op,0x0008), &D);
+
+ backupVal = *((uint64_t*)D.addr);
+
+ *((uint64_t*)D.addr) = *((uint64_t*)D.addr) >> 16;
+
+ if (backupVal & 0x0000008000000000U)
+ *((uint64_t*)D.addr) |= 0x000000ffff000000U;
+ else
+ *((uint64_t*)D.addr) &= 0x0000000000ffffffU;
+
+ /* S L E U N Z V C */
+ /* - * * * * * 0 ? */
+ /* TODO: E, U */
+ if (*((uint64_t*)D.addr) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if (*((uint64_t*)D.addr) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+ if (backupVal & 0x0000000000008000U) DSP56156_C_SET(); else DSP56156_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+static size_t dsp56156_op_bfop(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ uint16_t workAddr = 0x0000;
+ uint16_t workingWord = 0x0000;
+ uint16_t previousValue = 0x0000;
+ typed_pointer tempTP = { nullptr, DT_BYTE };
+
+ uint16_t iVal = op2 & 0x00ff;
+ decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal);
+
+ workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(op,0x0020), BITS(op,0x001f));
+ previousValue = cpustate->data->read_word(workAddr);
+ workingWord = previousValue;
+
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ workingWord ^= iVal;
+ break;
+ case 0x04: /* BFCLR */
+ workingWord = workingWord & (~iVal);
+ break;
+ case 0x18: /* BFSET */
+ workingWord = workingWord | iVal;
+ break;
+ case 0x10: /* BFTSTH */
+ /* Just the test below */
+ break;
+ case 0x00: /* BFTSTL */
+ /* Just the test below */
+ break;
+ }
+
+ tempTP.addr = &workingWord;
+ tempTP.data_type = DT_WORD;
+ SetDataMemoryValue(cpustate, tempTP, workAddr);
+
+ /* S L E U N Z V C */
+ /* - * - - - - - ? */
+ /* TODO: L */
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x04: /* BFCLR */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x18: /* BFSET */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x10: /* BFTSTH */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x00: /* BFTSTL */
+ if ((iVal & previousValue) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ }
+
+ cycles += 4; /* TODO: + mvb oscillator clock cycles */
+ return 2;
+}
+
+/* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+static size_t dsp56156_op_bfop_1(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ uint16_t workAddr = 0x0000;
+ uint16_t workingWord = 0x0000;
+ uint16_t previousValue = 0x0000;
+ typed_pointer R = { nullptr, DT_BYTE };
+ typed_pointer tempTP = { nullptr, DT_BYTE };
+
+ uint16_t iVal = op2 & 0x00ff;
+ decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal);
+
+ decode_RR_table(cpustate, BITS(op,0x0003), &R);
+
+ workAddr = *((uint16_t*)R.addr);
+ previousValue = cpustate->data->read_word(workAddr);
+ workingWord = previousValue;
+
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ workingWord ^= iVal;
+ break;
+ case 0x04: /* BFCLR */
+ workingWord = workingWord & (~iVal);
+ break;
+ case 0x18: /* BFSET */
+ workingWord = workingWord | iVal;
+ break;
+ case 0x10: /* BFTSTH */
+ /* Just the test below */
+ break;
+ case 0x00: /* BFTSTL */
+ /* Just the test below */
+ break;
+ }
+
+ tempTP.addr = &workingWord;
+ tempTP.data_type = DT_WORD;
+ SetDataMemoryValue(cpustate, tempTP, workAddr);
+
+ /* S L E U N Z V C */
+ /* - * - - - - - ? */
+ /* TODO: L */
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x04: /* BFCLR */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x18: /* BFSET */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x10: /* BFTSTH */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x00: /* BFTSTL */
+ if ((iVal & previousValue) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ }
+
+ cycles += 4; /* TODO: + mvb oscillator clock cycles */
+ return 2;
+}
+
+/* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+static size_t dsp56156_op_bfop_2(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ uint16_t workingWord = 0x0000;
+ uint16_t previousValue = 0x0000;
+
+ uint16_t iVal = op2 & 0x00ff;
+ typed_pointer S = { nullptr, DT_BYTE };
+
+ decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal);
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &S);
+
+ /* A & B are special */
+ if (S.data_type == DT_LONG_WORD)
+ previousValue = ((PAIR64*)S.addr)->w.h;
+ else
+ previousValue = *((uint16_t*)S.addr);
+
+ workingWord = previousValue;
+
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ workingWord ^= iVal;
+ break;
+ case 0x04: /* BFCLR */
+ workingWord = workingWord & (~iVal);
+ break;
+ case 0x18: /* BFSET */
+ workingWord = workingWord | iVal;
+ break;
+ case 0x10: /* BFTSTH */
+ /* Just the test below */
+ break;
+ case 0x00: /* BFTSTL */
+ /* Just the test below */
+ break;
+ }
+
+ /* Put the data back where it belongs (A & B are special) */
+ if (S.data_type == DT_LONG_WORD)
+ ((PAIR64*)S.addr)->w.h = workingWord;
+ else
+ *((uint16_t*)S.addr) = workingWord;
+
+ /* S L E U N Z V C */
+ /* - * - - - - - ? */
+ /* TODO: L */
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x04: /* BFCLR */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x18: /* BFSET */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x10: /* BFTSTH */
+ if ((iVal & previousValue) == iVal) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ case 0x00: /* BFTSTL */
+ if ((iVal & previousValue) == 0x0000) DSP56156_C_SET(); else DSP56156_C_CLEAR(); break;
+ }
+
+ cycles += 4; /* TODO: + mvb oscillator clock cycles */
+ return 2;
+}
+
+/* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */
+static size_t dsp56156_op_bcc(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if (shouldBranch)
+ {
+ int16_t offset = (int16_t)op2;
+
+ PC += offset + 2;
+
+ cycles += 4;
+ return 0;
+ }
+ else
+ {
+ cycles += 4;
+ return 2;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Bcc : 0010 11cc ccee eeee : A-48 */
+static size_t dsp56156_op_bcc_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x03c0));
+
+ if (shouldBranch)
+ {
+ int16_t offset = (int16_t)assemble_address_from_6bit_signed_relative_short_address(cpustate, BITS(op,0x003f));
+
+ PC += offset + 1;
+
+ cycles += 4;
+ return 0;
+ }
+ else
+ {
+ cycles += 4;
+ return 1;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Bcc : 0000 0111 RR10 cccc : A-48 */
+static size_t dsp56156_op_bcc_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */
+static size_t dsp56156_op_bra(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BRA : 0000 1011 aaaa aaaa : A-50 */
+static size_t dsp56156_op_bra_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* 8 bit immediate, relative offset */
+ int8_t branchOffset = (int8_t)BITS(op,0x00ff);
+
+ /* "The PC Contains the address of the next instruction" */
+ PC += 1;
+
+ /* Jump */
+ PC += branchOffset;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 0;
+}
+
+/* BRA : 0000 0001 0010 11RR : A-50 */
+static size_t dsp56156_op_bra_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BRKcc : 0000 0001 0001 cccc : A-52 */
+static size_t dsp56156_op_brkcc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ int shouldBreak = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if (shouldBreak)
+ {
+ /* TODO: I think this PC = LA thing is off-by-1, but it's working this way because its consistently so */
+ PC = LA;
+
+ SR = SSL; /* TODO: A-83. I believe only the Loop Flag and Forever Flag come back here. */
+ SP--;
+
+ LA = SSH;
+ LC = SSL;
+ SP--;
+
+ cycles += 8;
+ return 0;
+ }
+ else
+ {
+ cycles += 2;
+ return 1;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */
+static size_t dsp56156_op_bscc(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if (shouldBranch)
+ {
+ /* The PC Contains the address of the next instruction */
+ PC += 2;
+
+ /* Push */
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ /* Change */
+ PC = PC + (int16_t)op2;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 0;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 2;
+}
+
+/* BScc : 0000 0111 RR00 cccc : A-54 */
+static size_t dsp56156_op_bscc_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */
+static size_t dsp56156_op_bsr(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* The PC Contains the address of the next instruction */
+ PC += 2;
+
+ /* Push */
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ /* Change */
+ PC = PC + (int16_t)op2;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 0;
+}
+
+/* BSR : 0000 0001 0010 10RR : A-56 */
+static size_t dsp56156_op_bsr_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* CHKAAU : 0000 0000 0000 0100 : A-58 */
+static size_t dsp56156_op_chkaau(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - ? ? ? - */
+ /* V - Set if the result of the last address ALU update performed a modulo wrap. Cleared if
+ result of the last address ALU did not perform a modulo wrap.*/
+ /* Z - Set if the result of the last address ALU update is 0. Cleared if the result of the last
+ address ALU is positive. */
+ /* N - Set if the result of the last address ALU update is negative. Cleared if the result of the
+ last address ALU is positive. */
+ return 0;
+}
+
+/* DEBUG : 0000 0000 0000 0001 : A-68 */
+static size_t dsp56156_op_debug(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* DEBUGcc : 0000 0000 0101 cccc : A-70 */
+static size_t dsp56156_op_debugcc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* DIV : 0001 0101 0--0 F1DD : A-76 */
+/* WARNING : DOCS SAY THERE IS A PARALLEL MOVE HERE !!! */
+static size_t dsp56156_op_div(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* WARNING : THIS DOES NOT WORK. IT DOESN'T EVEN TRY !!! */
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_DDF_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S, &D);
+
+ /* S L E U N Z V C */
+ /* - * - - - - ? ? */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ /* C - Set if bit 39 of the result is cleared. Cleared otherwise. */
+ cycles += 2;
+ return 1;
+}
+
+/* DMAC : 0001 0101 10s1 FsQQ : A-80 */
+static size_t dsp56156_op_dmac(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint8_t ss = 0;
+ int64_t result = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
+
+ ss = BITS(op,0x0024);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ if (ss == 0x00 || ss == 0x01)
+ {
+ /* Signed * Signed */
+ int32_t s1 = ((int32_t)(*((uint16_t*)S1)));
+ int32_t s2 = ((int32_t)(*((uint16_t*)S2)));
+ result = ( s1 * s2 ) << 1;
+ }
+ else if (ss == 0x2)
+ {
+ /* Signed * Unsigned */
+ /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
+ int32_t s1 = ((int32_t)(*((uint16_t*)S1)));
+ int32_t s2 = (uint32_t)(*((uint16_t*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+ else if (ss == 0x3)
+ {
+ /* Unsigned * Unsigned */
+ uint32_t s1 = (uint32_t)(*((uint16_t*)S1));
+ uint32_t s2 = (uint32_t)(*((uint16_t*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+
+ /* Shift right, then accumulate */
+ (*((uint64_t*)D)) = (*((uint64_t*)D)) >> 16;
+ (*((uint64_t*)D)) += result;
+
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ /* TODO: L, E, U, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */
+static size_t dsp56156_op_do(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ return 0;
+}
+
+/* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */
+static size_t dsp56156_op_do_1(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ uint8_t retSize = 0;
+ uint8_t iValue = BITS(op,0x00ff);
+
+ /* Don't execute if the loop counter == 0 */
+ if (iValue != 0x00)
+ {
+ /* First instruction cycle */
+ SP++; /* TODO: Should i really inc here first? */
+ SSH = LA;
+ SSL = LC;
+ LC = (uint16_t)iValue;
+
+
+ /* Second instruction cycle */
+ SP++; /* TODO: See above */
+ SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */
+ SSL = SR;
+ LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */
+
+
+ /* Third instruction cycle */
+ LF_bit_set(cpustate, 1);
+
+ /* Undocumented, but it must be true to nest Dos in DoForevers */
+ FV_bit_set(cpustate, 0);
+
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO : L */
+
+ cycles += 6; /* TODO: + mv oscillator cycles */
+ retSize = 2;
+ }
+ else
+ {
+ /* Skip over the contents of the loop */
+ PC = PC + 2 + op2;
+
+ cycles += 10; /* TODO: + mv oscillator cycles */
+ retSize = 0;
+ }
+
+ return retSize;
+}
+
+/* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */
+static size_t dsp56156_op_do_2(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ uint8_t retSize = 0;
+ uint16_t lValue = 0x0000;
+ typed_pointer S = {nullptr, DT_BYTE};
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &S);
+
+ /* TODO: Does not properly shift-limit sources A&B - Fix per the docs. */
+ /* TODO: There are other cases besides A&B this code won't work. */
+ if (S.addr == &A) lValue = *((uint16_t*)(&A1));
+ else if (S.addr == &B) lValue = *((uint16_t*)(&B1));
+ else lValue = *((uint16_t*)S.addr);
+
+ /* HACK */
+ if (lValue >= 0xfff0)
+ {
+ cpustate->device->logerror("Dsp56156 : DO_2 operation changed %04x to 0000.\n", lValue);
+ lValue = 0x0000;
+ }
+
+ /* TODO: Fix for special cased SP S */
+ if (S.addr == &SP)
+ cpustate->device->logerror("DSP56156: do with SP as the source not properly implemented yet.\n");
+
+ /* TODO: Fix for special cased SSSL S */
+ if (S.addr == &SSL)
+ cpustate->device->logerror("DSP56156: do with SP as the source not properly implemented yet.\n");
+
+ /* Don't execute if the loop counter == 0 */
+ if (lValue != 0x00)
+ {
+ /* First instruction cycle */
+ SP++; /* TODO: Should i really inc here first? */
+ SSH = LA;
+ SSL = LC;
+ LC = (uint16_t)lValue;
+
+
+ /* Second instruction cycle */
+ SP++; /* TODO: See above */
+ SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */
+ SSL = SR;
+ LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */
+
+
+ /* Third instruction cycle */
+ LF_bit_set(cpustate, 1);
+
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO : L */
+
+ cycles += 6; /* TODO: + mv oscillator cycles */
+ retSize = 2;
+ }
+ else
+ {
+ /* Skip over the contents of the loop */
+ PC = PC + 2 + op2;
+
+ cycles += 10; /* TODO: + mv oscillator cycles */
+ retSize = 0;
+ }
+
+ return retSize;
+}
+
+/* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */
+static size_t dsp56156_op_doforever(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* First instruction cycle */
+ SP++;
+ SSH = LA;
+ SSL = LC;
+
+ /* Second instruction cycle */
+ SP++;
+ SSH = PC + 2;
+ SSL = SR;
+ LA = PC + 2 + op2;
+
+ /* Third instruction cycle */
+ LF_bit_set(cpustate, 1);
+ FV_bit_set(cpustate, 1);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 6;
+ return 2;
+}
+
+/* ENDDO : 0000 0000 0000 1001 : A-92 */
+static size_t dsp56156_op_enddo(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* EXT : 0001 0101 0101 F010 : A-96 */
+static size_t dsp56156_op_ext(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ return 0;
+}
+
+/* ILLEGAL : 0000 0000 0000 1111 : A-98 */
+static size_t dsp56156_op_illegal(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* IMAC : 0001 0101 1010 FQQQ : A-100 */
+static size_t dsp56156_op_imac(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ int64_t opD = 0;
+ int64_t result = 0;
+
+ int32_t s1 = 0;
+ int32_t s2 = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQQF_table(cpustate, BITS(op,0x0007), BITS(op,0x0008), &S1, &S2, &D);
+
+ /* Cast both values as being signed */
+ s1 = *((int16_t*)S1);
+ s2 = *((int16_t*)S2);
+
+ /* Integral multiply doesn't require the shift */
+ result = (s1 * s2);
+
+ /* Shift result 16 bits to the left before adding to destination */
+ result = (result << 16) & 0xffff0000;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((uint64_t*)D));
+ if (opD & 0x0000008000000000U)
+ opD |= 0xffffff0000000000U;
+ else
+ opD &= 0x000000ffffffffffU;
+
+ /* Accumulate */
+ opD += result;
+
+ /* And out the bits that don't live in the register */
+ opD &= 0x000000ffffffffffU;
+
+ (*((uint64_t*)D)) = (uint64_t)opD;
+
+ /* S L E U N Z V C */
+ /* - * ? ? * ? ? - */
+ /* TODO: L */
+ /* U,E - Will not be set correctly by this instruction*/
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffff0000U) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ DSP56156_V_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* IMPY : 0001 0101 1000 FQQQ : A-102 */
+static size_t dsp56156_op_impy(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * ? ? * ? ? - */
+ /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */
+ /* U,E - Will not be set correctly by this instruction*/
+ /* V - Set to zero regardless of the overflow */
+ return 0;
+}
+
+/* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */
+static size_t dsp56156_op_jcc(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Jcc : 0000 0110 RR10 cccc : A-108 */
+static size_t dsp56156_op_jcc_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */
+static size_t dsp56156_op_jmp(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ PC = op2;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+
+ cycles += 4; /* TODO: + jx */
+ return 0;
+}
+
+/* JMP : 0000 0001 0010 01RR : A-110 */
+static size_t dsp56156_op_jmp_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ typed_pointer R = { nullptr, DT_BYTE };
+ decode_RR_table(cpustate, BITS(op,0x0003), &R);
+
+ PC = *((uint16_t*)R.addr);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+
+ cycles += 4; /* TODO: + jx */
+ return 0;
+}
+
+/* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */
+static size_t dsp56156_op_jscc(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ int shouldJump = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if(shouldJump)
+ {
+ /* TODO: It says "signed" absolute offset. Weird. */
+ uint16_t branchOffset = op2;
+
+ /* TODO: Verify, since it's not in the docs, but it must be true */
+ PC += 2;
+
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ PC = branchOffset;
+
+ cycles += 4; /* TODO: +jx oscillator clock cycles */
+ return 0;
+ }
+ else
+ {
+ cycles += 4; /* TODO: +jx oscillator clock cycles */
+ return 2;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JScc : 0000 0110 RR00 cccc : A-112 */
+static size_t dsp56156_op_jscc_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */
+static size_t dsp56156_op_jsr(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* TODO: It says "signed" absolute offset. Weird. */
+ uint16_t branchOffset = op2;
+
+ /* TODO: Verify, since it's not in the docs, but it must be true */
+ PC += 2;
+
+ /* TODO: This is a hacky implementation of Long vs Fast Interrupts. Do it right someday! */
+ if (PC < 0x80)
+ {
+ /* Long interrupt gets the previous PC, not the current one */
+ SP++;
+ SSH = cpustate->ppc;
+ SSL = SR;
+
+ PC = branchOffset;
+ }
+ else
+ {
+ /* Normal operation */
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ PC = branchOffset;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator cycles */
+ return 0;
+}
+
+/* JSR : 0000 1010 AAAA AAAA : A-114 */
+static size_t dsp56156_op_jsr_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JSR : 0000 0001 0010 00RR : A-114 */
+static size_t dsp56156_op_jsr_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* LEA : 0000 0001 11TT MMRR : A-116 */
+static size_t dsp56156_op_lea(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint16_t ea = 0;
+ uint16_t *rX = nullptr;
+ uint16_t *nX = nullptr;
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_TT_table(cpustate, BITS(op,0x0030), &D);
+
+ /* TODO: change the execute_mm_functions to return values. Maybe */
+ /* Because this calculation isn't applied, do everything locally */
+ /* RR table */
+ switch(BITS(op,0x0003))
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ /* MM table */
+ switch(BITS(op,0x000c))
+ {
+ case 0x0: ea = *rX; break;
+ case 0x1: ea = *rX + 1; break;
+ case 0x2: ea = *rX - 1; break;
+ case 0x3: ea = *rX + *nX; break;
+ }
+
+ *((uint16_t*)D.addr) = ea;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 1;
+}
+
+/* LEA : 0000 0001 10NN MMRR : A-116 */
+static size_t dsp56156_op_lea_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */
+static size_t dsp56156_op_macsuuu(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint8_t s = 0;
+ int64_t result = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
+
+ s = BITS(op,0x0004);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ if (s)
+ {
+ /* Unsigned * Unsigned */
+ uint32_t s1 = (uint32_t)(*((uint16_t*)S1));
+ uint32_t s2 = (uint32_t)(*((uint16_t*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+ else
+ {
+ /* Signed * Unsigned */
+ /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
+ int32_t s1 = ((int32_t)(*((uint16_t*)S1)));
+ int32_t s2 = (uint32_t)(*((uint16_t*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+
+ (*((uint64_t*)D)) += result;
+
+ /* And out the bits that don't live in the register */
+ (*((uint64_t*)D)) &= 0x000000ffffffffffU;
+
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ /* TODO: L, E, U, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */
+static size_t dsp56156_op_move_2(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */
+static size_t dsp56156_op_movec(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint8_t W;
+ typed_pointer R = { nullptr, DT_BYTE };
+ typed_pointer SD = { nullptr, DT_BYTE };
+
+ W = BITS(op,0x0400);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+ decode_RR_table(cpustate, BITS(op,0x0003), &R);
+
+ if (W)
+ {
+ /* Write D */
+ uint16_t value = cpustate->data->read_word(*((uint16_t*)R.addr)) ;
+ typed_pointer temp_src = { &value, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ uint16_t dataMemOffset = *((uint16_t*)R.addr);
+ SetDataMemoryValue(cpustate, SD, dataMemOffset);
+ }
+
+ execute_MM_table(cpustate, BITS(op,0x0003), BITS(op,0x000c));
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* TODO: + mvc */
+ return 1;
+}
+
+/* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */
+static size_t dsp56156_op_movec_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint8_t W;
+ uint16_t memOffset;
+ typed_pointer SD = {nullptr, DT_BYTE};
+
+ W = BITS(op,0x0400);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+ memOffset = execute_q_table(cpustate, BITS(op,0x0003), BITS(op,0x0008));
+
+ if (W)
+ {
+ /* Write D */
+ uint16_t tempData = cpustate->data->read_word(memOffset);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ uint16_t tempData = *((uint16_t*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, memOffset);
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* + mvc oscillator clock cycles */
+ return 1;
+}
+
+/* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */
+static size_t dsp56156_op_movec_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint8_t W;
+ uint16_t memOffset;
+ typed_pointer SD = {nullptr, DT_BYTE};
+ typed_pointer XMemOffset = {nullptr, DT_BYTE};
+
+ W = BITS(op,0x0400);
+ decode_Z_table(cpustate, BITS(op,0x0008), &XMemOffset);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+
+ memOffset = *((uint16_t*)XMemOffset.addr);
+
+ if (W)
+ {
+ /* Write D */
+ uint16_t tempData = cpustate->data->read_word(memOffset);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ uint16_t tempData = *((uint16_t*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, memOffset);
+ }
+
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* + mvc oscillator clock cycles */
+ return 1;
+}
+
+/* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */
+static size_t dsp56156_op_movec_3(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ uint8_t W;
+ uint8_t t;
+ typed_pointer SD = { nullptr, DT_BYTE };
+
+ W = BITS(op,0x0400);
+ t = BITS(op,0x0008);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+
+ if (W)
+ {
+ /* Write D */
+ if (t)
+ {
+ /* 16-bit long data */
+ typed_pointer temp_src = { (void*)&op2, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* 16-bit long address */
+ uint16_t tempD = cpustate->data->read_word(op2);
+ typed_pointer tempTP = {&tempD, DT_WORD};
+ SetDestinationValue(tempTP, SD);
+ }
+ }
+ else
+ {
+ /* Read S */
+ if (t)
+ {
+ /* 16-bit long data */
+ cpustate->device->logerror("DSP56156: Movec - I don't think this exists?");
+ }
+ else
+ {
+ /* 16-bit long address */
+ SetDataMemoryValue(cpustate, SD, op2);
+ }
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* TODO: + mvc */
+ return 2;
+}
+
+/* MOVE(C) : 0010 10dd dddD DDDD : A-144 */
+static size_t dsp56156_op_movec_4(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &S);
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &D);
+
+ SetDestinationValue(S, D);
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (D.addr != &SR)
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2;
+ return 1;
+}
+
+/* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */
+static size_t dsp56156_op_movec_5(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ int8_t xx;
+ uint8_t W;
+ uint16_t memOffset;
+ typed_pointer SD = { nullptr, DT_BYTE };
+
+ xx = (int8_t)(op & 0x00ff);
+ W = BITS(op2,0x0400);
+ decode_DDDDD_table(cpustate, BITS(op2,0x03e0), &SD);
+
+ memOffset = R2 + (int16_t)xx;
+
+ if (W)
+ {
+ /* Write D */
+ uint16_t tempData = cpustate->data->read_word(memOffset);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ uint16_t tempData = *((uint16_t*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, memOffset);
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* TODO: + mvc oscillator clock cycles */
+ return 2;
+}
+
+/* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */
+static size_t dsp56156_op_movei(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_BYTE};
+ typed_pointer immTP = {nullptr, DT_BYTE};
+
+ /* Typecasting to int16_t sign-extends the BBBBBBBB operand */
+ uint16_t immediateSignExtended = (int16_t)(op & 0x00ff);
+ immTP.addr = &immediateSignExtended;
+ immTP.data_type = DT_WORD;
+
+ decode_DD_table(cpustate, BITS(op,0x0300), &D);
+
+ SetDestinationValue(immTP, D);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 2;
+ return 1;
+}
+
+/* MOVE(M) : 0000 001W RR0M MHHH : A-152 */
+static size_t dsp56156_op_movem(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint8_t W;
+ typed_pointer R = { nullptr, DT_BYTE };
+ typed_pointer SD = { nullptr, DT_BYTE };
+
+ W = BITS(op,0x0100);
+ decode_RR_table(cpustate, BITS(op,0x00c0), &R);
+ decode_HHH_table(cpustate, BITS(op,0x0007), &SD);
+
+ if (W)
+ {
+ /* Read from Program Memory */
+ typed_pointer data;
+ uint16_t ldata = cpustate->program->read_word(*((uint16_t*)R.addr));
+
+ data.addr = &ldata;
+ data.data_type = DT_WORD;
+ SetDestinationValue(data, SD) ;
+ }
+ else
+ {
+ /* Write to Program Memory */
+ SetProgramMemoryValue(cpustate, SD, *((uint16_t*)R.addr)) ;
+ }
+
+ execute_MM_table(cpustate, BITS(op,0x00c0), BITS(op,0x0018));
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 2; /* TODO: + mvm oscillator clock cycles */
+ return 1;
+}
+
+/* MOVE(M) : 0000 001W RR11 mmRR : A-152 */
+static size_t dsp56156_op_movem_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */
+static size_t dsp56156_op_movem_2(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MOVE(P) : 0001 100W HH1p pppp : A-156 */
+static size_t dsp56156_op_movep(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint16_t W;
+ uint16_t pp;
+ typed_pointer SD = {nullptr, DT_BYTE};
+
+ decode_HH_table(cpustate, BITS(op,0x00c0), &SD);
+ /* TODO: Special cases for A & B */
+
+ pp = op & 0x001f;
+ pp = assemble_address_from_IO_short_address(cpustate, pp);
+
+ W = BITS(op,0x0100);
+
+ if (W)
+ {
+ uint16_t data = cpustate->data->read_word(pp);
+
+ typed_pointer tempTP;
+ tempTP.addr = &data;
+ tempTP.data_type = DT_WORD;
+
+ SetDestinationValue(tempTP, SD);
+ }
+ else
+ {
+ SetDataMemoryValue(cpustate, SD, pp);
+ }
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+
+ cycles += 4; /* TODO: + mvp oscillator cycles */
+ return 1;
+}
+
+/* MOVE(P) : 0000 110W RRmp pppp : A-156 */
+static size_t dsp56156_op_movep_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* X:<Rx> and X:<pp> */
+ uint16_t W;
+ uint16_t pp;
+
+ typed_pointer SD = {nullptr, DT_BYTE};
+ decode_RR_table(cpustate, BITS(op,0x00c0), &SD);
+
+ pp = op & 0x001f;
+ pp = assemble_address_from_IO_short_address(cpustate, pp);
+
+ W = BITS(op,0x0100);
+
+ /* A little different than most W if's - opposite read and write */
+ if (W)
+ {
+ uint16_t data = cpustate->data->read_word(*((uint16_t*)SD.addr));
+
+ typed_pointer tempTP;
+ tempTP.addr = &data;
+ tempTP.data_type = DT_WORD;
+
+ SetDataMemoryValue(cpustate, tempTP, pp);
+ }
+ else
+ {
+ /* TODO */
+ fatalerror("dsp56156 : move(p) NOTHING HERE (yet)\n") ;
+ }
+
+ /* Postincrement */
+ execute_m_table(cpustate, BITS(op,0x00c0), BITS(op,0x0020));
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 4; /* TODO: + mvp oscillator cycles */
+ return 1;
+}
+
+/* MOVE(S) : 0001 100W HH0a aaaa : A-158 */
+static size_t dsp56156_op_moves(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */
+static size_t dsp56156_op_mpysuuu(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ uint8_t s = 0;
+ int64_t result = 0;
+
+ void* D = nullptr;
+ void* S1 = nullptr;
+ void* S2 = nullptr;
+
+ decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
+
+ s = BITS(op,0x0004);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ if (s)
+ {
+ /* Unsigned * Unsigned */
+ uint32_t s1 = (uint32_t)(*((uint16_t*)S1));
+ uint32_t s2 = (uint32_t)(*((uint16_t*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+ else
+ {
+ /* Signed * Unsigned */
+ /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
+ int32_t s1 = ((int32_t)(*((uint16_t*)S1)));
+ int32_t s2 = (uint32_t)(*((uint16_t*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+
+ (*((uint64_t*)D)) = result;
+
+ /* And out the bits that don't live in the register */
+ (*((uint64_t*)D)) &= 0x000000ffffffffffU;
+
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ /* TODO: L, E, U, V */
+ if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* NEGC : 0001 0101 0110 F000 : A-168 */
+static size_t dsp56156_op_negc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * * */
+ return 0;
+}
+
+/* NOP : 0000 0000 0000 0000 : A-170 */
+static size_t dsp56156_op_nop(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 1;
+}
+
+/* NORM : 0001 0101 0010 F0RR : A-172 */
+static size_t dsp56156_op_norm(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * ? - */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ return 0;
+}
+
+/* ORI : 0001 1EE1 iiii iiii : A-178 */
+static size_t dsp56156_op_ori(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - ? ? ? ? ? ? ? */
+ /* All ? bits - Set if the corresponding bit in the immediate data is set and if the operand is the
+ CCR. Not affected otherwise. */
+ return 0;
+}
+
+/* REP : 0000 0000 111- --RR : A-180 */
+static size_t dsp56156_op_rep(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ return 0;
+}
+
+/* REP : 0000 1111 iiii iiii : A-180 */
+static size_t dsp56156_op_rep_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* TODO: This is non-interruptable, probably have to turn off interrupts here */
+ uint16_t iVal = op & 0x00ff;
+
+ if (iVal != 0)
+ {
+ TEMP = LC;
+ LC = iVal;
+
+ cpustate->repFlag = 1;
+ cpustate->repAddr = PC + 2;
+
+ cycles += 4; /* TODO: + mv oscillator clock cycles */
+ }
+ else
+ {
+ cycles += 6; /* TODO: + mv oscillator clock cycles */
+ }
+
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO: L */
+ return 1;
+}
+
+/* REP : 0000 0100 001D DDDD : A-180 */
+static size_t dsp56156_op_rep_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* TODO: This is non-interruptable, probably have to turn off interrupts here */
+ uint16_t repValue;
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &D);
+
+ /* TODO: handle special A&B source cases */
+ if (D.addr == &A || D.addr == &B)
+ cpustate->device->logerror("DSP56156 ERROR : Rep with A or B instruction not implemented yet!\n");
+
+ repValue = *((uint16_t*)D.addr);
+
+ if (repValue != 0)
+ {
+ TEMP = LC;
+ LC = repValue;
+
+ cpustate->repFlag = 1;
+ cpustate->repAddr = PC + 2;
+
+ cycles += 4; /* TODO: + mv oscillator clock cycles */
+ }
+ else
+ {
+ cycles += 6; /* TODO: + mv oscillator clock cycles */
+ }
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO: L */
+ return 1;
+}
+
+/* REPcc : 0000 0001 0101 cccc : A-184 */
+static size_t dsp56156_op_repcc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* RESET : 0000 0000 0000 1000 : A-186 */
+static size_t dsp56156_op_reset(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* RTI : 0000 0000 0000 0111 : A-194 */
+static size_t dsp56156_op_rti(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* WARNING : THERE SHOULD BE A MORE GENERAL HANDLING OF STACK ERRORS. */
+ if (SP == 0)
+ {
+ dsp56156_add_pending_interrupt(cpustate, "Stack Error");
+ return 0;
+ }
+
+ PC = SSH;
+
+ SR = SSL;
+ SP = SP - 1;
+
+ /* S L E U N Z V C */
+ /* ? ? ? ? ? ? ? ? */
+ /* All ? bits - Set according to value pulled from the stack. */
+ cycles += 4; /* TODO: + rx oscillator clock cycles */
+ return 0;
+}
+
+/* RTS : 0000 0000 0000 0110 : A-196 */
+static size_t dsp56156_op_rts(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* Pop */
+ PC = SSH;
+
+ /* SR = SSL; The status register is not affected. */
+
+ SP--;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + rx oscillator clock cycles */
+ return 0;
+}
+
+/* STOP : 0000 0000 0000 1010 : A-200 */
+static size_t dsp56156_op_stop(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* SWAP : 0001 0101 0111 F001 : A-206 */
+static size_t dsp56156_op_swap(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* SWI : 0000 0000 0000 0101 : A-208 */
+static size_t dsp56156_op_swi(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Tcc : 0001 00cc ccTT Fh0h : A-210 */
+static size_t dsp56156_op_tcc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ int shouldTransfer = decode_cccc_table(cpustate, BITS(op,0x03c0));
+
+ if (shouldTransfer)
+ {
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+ typed_pointer S2 = {&R0, DT_WORD};
+ typed_pointer D2 = {nullptr, DT_BYTE};
+
+ decode_h0hF_table(cpustate, BITS(op,0x0007),BITS(op,0x0008), &S, &D);
+ SetDestinationValue(S, D);
+
+ /* TODO: What's up with that A,A* thing in the docs? Can you only ignore the R0->RX transfer if you do an A,A? */
+ decode_RR_table(cpustate, BITS(op,0x0030), &D2); /* TT is the same as RR */
+ SetDestinationValue(S2, D2);
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 2;
+ return 1;
+}
+
+/* TFR(2) : 0001 0101 0000 F00J : A-214 */
+static size_t dsp56156_op_tfr2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_JF_table(cpustate, BITS(op,0x0001), BITS(op,0x0008), &S, &D);
+
+ SetDestinationValue(S, D);
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO: L */
+ cycles += 2;
+ return 1;
+}
+
+/* TFR(3) : 0010 01mW RRDD FHHH : A-216 */
+static size_t dsp56156_op_tfr3(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* TST(2) : 0001 0101 0001 -1DD : A-220 */
+static size_t dsp56156_op_tst2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ typed_pointer D = {nullptr, DT_BYTE};
+ decode_DD_table(cpustate, BITS(op,0x0003), &D);
+
+ /* S L E U N Z V C */
+ /* - * * * * * 0 0 */
+ /* (L,E,U should be set to 0) */
+ DSP56156_L_CLEAR();
+ DSP56156_E_CLEAR();
+ /* U_CLEAR(); */ /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */
+ if ((*((uint16_t*)D.addr)) & 0x8000) DSP56156_N_SET(); else DSP56156_N_CLEAR();
+ if ((*((uint16_t*)D.addr)) == 0x0000) DSP56156_Z_SET(); else DSP56156_Z_CLEAR();
+ /* DSP56156_V_CLEAR(); */ /* Unaffected */
+ DSP56156_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* WAIT : 0000 0000 0000 1011 : A-222 */
+static size_t dsp56156_op_wait(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* ZERO : 0001 0101 0101 F000 : A-224 */
+static size_t dsp56156_op_zero(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ return 0;
+}
+
+
+
+/***************************************************************************
+ Table decoding
+***************************************************************************/
+static uint16_t decode_BBB_bitmask(dsp56156_core* cpustate, uint16_t BBB, uint16_t *iVal)
+{
+ uint16_t retVal = 0x0000;
+
+ switch(BBB)
+ {
+ case 0x4: retVal = 0xff00; *iVal <<= 8; break;
+ case 0x2: retVal = 0x0ff0; *iVal <<= 4; break;
+ case 0x1: retVal = 0x00ff; *iVal <<= 0; break;
+ }
+
+ return retVal;
+}
+
+static int decode_cccc_table(dsp56156_core* cpustate, uint16_t cccc)
+{
+ int retVal = 0;
+
+ /* Not fully tested */
+ switch (cccc)
+ {
+ /* Arranged according to mnemonic table - not decoding table */
+ case 0x0: if( C() == 0) retVal = 1; break; /* cc(hs) */
+ case 0x8: if( C() == 1) retVal = 1; break; /* cs(lo) */
+ case 0x5: if( E() == 0) retVal = 1; break; /* ec */
+ case 0xa: if( Z() == 1) retVal = 1; break; /* eq */
+ case 0xd: if( E() == 1) retVal = 1; break; /* es */
+ case 0x1: if((N() ^ V()) == 0) retVal = 1; break; /* ge */
+ case 0x7: if((Z() | (N() ^ V())) == 0) retVal = 1; break; /* gt */
+ case 0x6: if( L() == 0) retVal = 1; break; /* lc */
+ case 0xf: if((Z() | (N() ^ V())) == 1) retVal = 1; break; /* le */
+ case 0xe: if( L() == 1) retVal = 1; break; /* ls */
+ case 0x9: if((N() ^ V()) == 1) retVal = 1; break; /* lt */
+ case 0xb: if( N() == 1) retVal = 1; break; /* mi */
+ case 0x2: if( Z() == 0) retVal = 1; break; /* ne */
+ case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; /* nr */
+ case 0x3: if( N() == 0) retVal = 1; break; /* pl */
+ case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; /* nn */
+ }
+
+ return retVal;
+}
+
+static void decode_DDDDD_table(dsp56156_core* cpustate, uint16_t DDDDD, typed_pointer* ret)
+{
+ switch(DDDDD)
+ {
+ case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break;
+ case 0x04: ret->addr = &A ; ret->data_type = DT_LONG_WORD; break;
+ case 0x05: ret->addr = &B ; ret->data_type = DT_LONG_WORD; break;
+ case 0x06: ret->addr = &A0; ret->data_type = DT_WORD; break;
+ case 0x07: ret->addr = &B0; ret->data_type = DT_WORD; break;
+ case 0x08: ret->addr = &LC; ret->data_type = DT_WORD; break;
+ case 0x09: ret->addr = &SR; ret->data_type = DT_WORD; break;
+ case 0x0a: ret->addr = &OMR; ret->data_type = DT_BYTE; break;
+ case 0x0b: ret->addr = &SP; ret->data_type = DT_BYTE; break;
+ case 0x0c: ret->addr = &A1; ret->data_type = DT_WORD; break;
+ case 0x0d: ret->addr = &B1; ret->data_type = DT_WORD; break;
+ case 0x0e: ret->addr = &A2; ret->data_type = DT_BYTE; break;
+ case 0x0f: ret->addr = &B2; ret->data_type = DT_BYTE; break;
+
+ case 0x10: ret->addr = &R0; ret->data_type = DT_WORD; break;
+ case 0x11: ret->addr = &R1; ret->data_type = DT_WORD; break;
+ case 0x12: ret->addr = &R2; ret->data_type = DT_WORD; break;
+ case 0x13: ret->addr = &R3; ret->data_type = DT_WORD; break;
+ case 0x14: ret->addr = &M0; ret->data_type = DT_WORD; break;
+ case 0x15: ret->addr = &M1; ret->data_type = DT_WORD; break;
+ case 0x16: ret->addr = &M2; ret->data_type = DT_WORD; break;
+ case 0x17: ret->addr = &M3; ret->data_type = DT_WORD; break;
+ case 0x18: ret->addr = &SSH; ret->data_type = DT_WORD; break;
+ case 0x19: ret->addr = &SSL; ret->data_type = DT_WORD; break;
+ case 0x1a: ret->addr = &LA; ret->data_type = DT_WORD; break;
+ /*no 0x1b */
+ case 0x1c: ret->addr = &N0; ret->data_type = DT_WORD; break;
+ case 0x1d: ret->addr = &N1; ret->data_type = DT_WORD; break;
+ case 0x1e: ret->addr = &N2; ret->data_type = DT_WORD; break;
+ case 0x1f: ret->addr = &N3; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_DD_table(dsp56156_core* cpustate, uint16_t DD, typed_pointer* ret)
+{
+ switch(DD)
+ {
+ case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_DDF_table(dsp56156_core* cpustate, uint16_t DD, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ uint16_t switchVal = (DD << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_F_table(dsp56156_core* cpustate, uint16_t F, typed_pointer* ret)
+{
+ switch(F)
+ {
+ case 0x0: ret->addr = &A; ret->data_type = DT_LONG_WORD; break;
+ case 0x1: ret->addr = &B; ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_h0hF_table(dsp56156_core* cpustate, uint16_t h0h, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ uint16_t switchVal = (h0h << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_HH_table(dsp56156_core* cpustate, uint16_t HH, typed_pointer* ret)
+{
+ switch(HH)
+ {
+ case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x2: ret->addr = &A; ret->data_type = DT_LONG_WORD; break;
+ case 0x3: ret->addr = &B; ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_HHH_table(dsp56156_core* cpustate, uint16_t HHH, typed_pointer* ret)
+{
+ switch(HHH)
+ {
+ case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x2: ret->addr = &X1; ret->data_type = DT_WORD; break;
+ case 0x3: ret->addr = &Y1; ret->data_type = DT_WORD; break;
+ case 0x4: ret->addr = &A; ret->data_type = DT_LONG_WORD; break;
+ case 0x5: ret->addr = &B; ret->data_type = DT_LONG_WORD; break;
+ case 0x6: ret->addr = &A0; ret->data_type = DT_WORD; break;
+ case 0x7: ret->addr = &B0; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_IIII_table(dsp56156_core* cpustate, uint16_t IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void *working)
+{
+ void *opposite = nullptr ;
+
+ if (working == &A) opposite = &B ;
+ else opposite = &A ;
+
+ switch(IIII)
+ {
+ case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break;
+ case 0x5: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break;
+ case 0x6: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break;
+ case 0x7: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break;
+ case 0x8: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x9: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xc: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break;
+ case 0xd: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break;
+ case 0xe: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break;
+ case 0xf: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_JJJF_table(dsp56156_core* cpustate, uint16_t JJJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ uint16_t switchVal = (JJJ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x5: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x6: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x7: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xc: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xd: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xe: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xf: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_JJF_table(dsp56156_core* cpustate, uint16_t JJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ uint16_t switchVal = (JJ << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_JF_table(dsp56156_core* cpustate, uint16_t J, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ uint16_t switchVal = (J << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x0: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x1: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ }
+}
+
+static void decode_KKK_table(dsp56156_core* cpustate, uint16_t KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working)
+{
+ void *opposite = nullptr ;
+
+ if (working == &A) opposite = &B ;
+ else opposite = &A ;
+
+ switch(KKK)
+ {
+ case 0x0: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x1: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x2: dst_ret1->addr = &X1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x3: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x4: dst_ret1->addr = &X0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break;
+ case 0x5: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break;
+ case 0x6: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &Y0; dst_ret2->data_type = DT_WORD; break;
+ case 0x7: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_QQF_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D)
+{
+ uint16_t switchVal = (QQ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: *S1 = &X0; *S2 = &Y0; *D = &A; break;
+ case 0x1: *S1 = &X0; *S2 = &Y0; *D = &B; break;
+ case 0x2: *S1 = &X0; *S2 = &Y1; *D = &A; break;
+ case 0x3: *S1 = &X0; *S2 = &Y1; *D = &B; break;
+ case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break;
+ case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break;
+ case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break;
+ case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break;
+ }
+}
+
+static void decode_QQF_special_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D)
+{
+ uint16_t switchVal = (QQ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: *S1 = &Y0; *S2 = &X0; *D = &A; break;
+ case 0x1: *S1 = &Y0; *S2 = &X0; *D = &B; break;
+ case 0x2: *S1 = &Y1; *S2 = &X0; *D = &A; break;
+ case 0x3: *S1 = &Y1; *S2 = &X0; *D = &B; break;
+ case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break;
+ case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break;
+ case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break;
+ case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break;
+ }
+}
+
+static void decode_QQQF_table(dsp56156_core* cpustate, uint16_t QQQ, uint16_t F, void **S1, void **S2, void **D)
+{
+ uint16_t switchVal = (QQQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: *S1 = &X0; *S2 = &X0; *D = &A; break;
+ case 0x1: *S1 = &X0; *S2 = &X0; *D = &B; break;
+ case 0x2: *S1 = &X1; *S2 = &X0; *D = &A; break;
+ case 0x3: *S1 = &X1; *S2 = &X0; *D = &B; break;
+ case 0x4: *S1 = &A1; *S2 = &Y0; *D = &A; break;
+ case 0x5: *S1 = &A1; *S2 = &Y0; *D = &B; break;
+ case 0x6: *S1 = &B1; *S2 = &X0; *D = &A; break;
+ case 0x7: *S1 = &B1; *S2 = &X0; *D = &B; break;
+ case 0x8: *S1 = &Y0; *S2 = &X0; *D = &A; break;
+ case 0x9: *S1 = &Y0; *S2 = &X0; *D = &B; break;
+ case 0xa: *S1 = &Y1; *S2 = &X0; *D = &A; break;
+ case 0xb: *S1 = &Y1; *S2 = &X0; *D = &B; break;
+ case 0xc: *S1 = &Y0; *S2 = &X1; *D = &A; break;
+ case 0xd: *S1 = &Y0; *S2 = &X1; *D = &B; break;
+ case 0xe: *S1 = &Y1; *S2 = &X1; *D = &A; break;
+ case 0xf: *S1 = &Y1; *S2 = &X1; *D = &B; break;
+ }
+}
+
+static void decode_RR_table(dsp56156_core* cpustate, uint16_t RR, typed_pointer* ret)
+{
+ switch(RR)
+ {
+ case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_TT_table(dsp56156_core* cpustate, uint16_t TT, typed_pointer* ret)
+{
+ switch(TT)
+ {
+ case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break;
+ }
+}
+
+
+static void decode_uuuuF_table(dsp56156_core* cpustate, uint16_t uuuu, uint16_t F, uint8_t add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ uint16_t switchVal = (uuuu << 1) | F;
+
+ /* Unknown uuuuFs have been seen in the wild */
+ add_sub_other = OP_OTHER;
+ src_ret->addr = nullptr; src_ret->data_type = DT_BYTE;
+ dst_ret->addr = nullptr; dst_ret->data_type = DT_BYTE;
+
+ switch(switchVal)
+ {
+ case 0x00: add_sub_other = OP_ADD;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x08: add_sub_other = OP_SUB;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x01: add_sub_other = OP_ADD;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x09: add_sub_other = OP_SUB;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x02: add_sub_other = OP_ADD;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0a: add_sub_other = OP_SUB;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x03: add_sub_other = OP_ADD;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0b: add_sub_other = OP_SUB;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x04: add_sub_other = OP_ADD;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0c: add_sub_other = OP_SUB;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x05: add_sub_other = OP_ADD;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0d: add_sub_other = OP_SUB;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x06: add_sub_other = OP_ADD;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0e: add_sub_other = OP_SUB;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x07: add_sub_other = OP_ADD;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0f: add_sub_other = OP_SUB;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x18: add_sub_other = OP_ADD;
+ src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1a: add_sub_other = OP_SUB;
+ src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x19: add_sub_other = OP_ADD;
+ src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1b: add_sub_other = OP_SUB;
+ src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_Z_table(dsp56156_core* cpustate, uint16_t Z, typed_pointer* ret)
+{
+ switch(Z)
+ {
+ /* Fixed as per the Family Manual addendum */
+ case 0x01: ret->addr = &A1; ret->data_type = DT_WORD; break;
+ case 0x00: ret->addr = &B1; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void execute_m_table(dsp56156_core* cpustate, int x, uint16_t m)
+{
+ uint16_t *rX = nullptr ;
+ uint16_t *nX = nullptr ;
+
+ switch(x)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(m)
+ {
+ case 0x0: (*rX)++; break;
+ case 0x1: (*rX) = (*rX)+(*nX); break;
+ }
+}
+
+static void execute_mm_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t mm)
+{
+ uint16_t *rX = nullptr;
+ uint16_t *nX = nullptr;
+
+ switch(rnum)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: fatalerror("Dsp56156: Error. execute_mm_table specified R3 as its first source!\n"); break;
+ }
+
+ switch(mm)
+ {
+ case 0x0: (*rX)++; R3++; break;
+ case 0x1: (*rX)++; R3 = R3 + N3; break;
+ case 0x2: (*rX) = (*rX) + (*nX); R3++; break;
+ case 0x3: (*rX) = (*rX) + (*nX); R3 = R3 + N3; break;
+ }
+}
+
+static void execute_MM_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t MM)
+{
+ uint16_t *rX = nullptr ;
+ uint16_t *nX = nullptr ;
+
+ switch(rnum)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(MM)
+ {
+ case 0x0: /* do nothing */ break;
+ case 0x1: (*rX)++ ; break;
+ case 0x2: (*rX)-- ; break;
+ case 0x3: (*rX) = (*rX)+(*nX) ; break;
+ }
+}
+
+/* Returns R value */
+static uint16_t execute_q_table(dsp56156_core* cpustate, int RR, uint16_t q)
+{
+ uint16_t *rX = nullptr;
+ uint16_t *nX = nullptr;
+
+ switch(RR)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(q)
+ {
+ case 0x0: /* No permanent changes */ ; return (*rX)+(*nX);
+ case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */
+ }
+
+ /* Should not get here */
+ fatalerror("dsp56156: execute_q_table did something impossible!\n");
+ return 0;
+}
+
+static void execute_z_table(dsp56156_core* cpustate, int RR, uint16_t z)
+{
+ uint16_t *rX = nullptr;
+ uint16_t *nX = nullptr;
+
+ switch(RR)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(z)
+ {
+ case 0x0: (*rX)--; break;
+ case 0x1: (*rX) = (*rX) + (*nX); break;
+ }
+}
+
+static uint16_t assemble_address_from_Pppppp_table(dsp56156_core* cpustate, uint16_t P, uint16_t ppppp)
+{
+ uint16_t destAddr = 0x00 ;
+
+ switch (P)
+ {
+ case 0x0: destAddr = ppppp; break; /* TODO: Does this really only address up to 0x32? */
+ case 0x1: destAddr = assemble_address_from_IO_short_address(cpustate, ppppp); break;
+ }
+
+ return destAddr ;
+}
+
+static uint16_t assemble_address_from_IO_short_address(dsp56156_core* cpustate, uint16_t pp)
+{
+ uint16_t fullAddy = 0xffe0;
+ fullAddy |= pp;
+ return fullAddy;
+}
+
+static uint16_t assemble_address_from_6bit_signed_relative_short_address(dsp56156_core* cpustate, uint16_t srs)
+{
+ uint16_t fullAddy = srs ;
+ if (fullAddy & 0x0020)
+ fullAddy |= 0xffc0 ;
+
+ return fullAddy ;
+}
+
+static void dsp56156_process_loop(dsp56156_core* cpustate)
+{
+ /* TODO: This might not work for dos nested in doForevers */
+ if (LF_bit(cpustate) && FV_bit(cpustate))
+ {
+ /* Do Forever*/
+ if (PC == LA)
+ {
+ LC--;
+
+ PC = SSH;
+ }
+ }
+ else if (LF_bit(cpustate))
+ {
+ /* Do */
+ if (PC == LA)
+ {
+ if (LC == 1)
+ {
+ /* End of loop processing */
+ SR = SSL; /* TODO: A-83. I believe only the Loop Flag comes back here. And maybe the do forever bit too. */
+ SP--;
+
+ LA = SSH;
+ LC = SSL;
+ SP--;
+ }
+ else
+ {
+ LC--;
+ PC = SSH;
+ }
+ }
+ }
+}
+
+static void dsp56156_process_rep(dsp56156_core* cpustate, size_t repSize)
+{
+ if (cpustate->repFlag)
+ {
+ if (PC == cpustate->repAddr)
+ {
+ if (LC == 1)
+ {
+ /* End of rep processing */
+ LC = TEMP;
+ cpustate->repFlag = 0;
+ cpustate->repAddr = 0x0000;
+ }
+ else
+ {
+ LC--;
+ PC -= repSize; /* A little strange - rewind by the size of the rep'd op */
+ }
+ }
+ }
+}
+
+
+/***************************************************************************
+ Parallel Memory Ops
+***************************************************************************/
+/* Register to Register Data Move : 0100 IIII .... .... : A-132 */
+static void execute_register_to_register_data_move(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value)
+{
+ typed_pointer S = {nullptr, DT_BYTE};
+ typed_pointer D = {nullptr, DT_BYTE};
+
+ decode_IIII_table(cpustate, BITS(op,0x0f00), &S, &D, d_register->addr);
+
+ /* If the source is the same as the ALU destination, use the previous accumulator value */
+ if (d_register->addr == S.addr)
+ {
+ typed_pointer tempTP;
+ tempTP.addr = prev_accum_value;
+ tempTP.data_type = DT_LONG_WORD;
+ SetDestinationValue(tempTP, D);
+ }
+ else
+ {
+ SetDestinationValue(S, D);
+ }
+}
+
+/* Address Register Update : 0011 0zRR .... .... : A-135 */
+static void execute_address_register_update(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value)
+{
+ execute_z_table(cpustate, BITS(op,0x0300), BITS(op,0x0400));
+}
+
+/* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+static void execute_x_memory_data_move(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value)
+{
+ uint16_t W;
+ typed_pointer R = {nullptr, DT_BYTE};
+ typed_pointer SD = {nullptr, DT_BYTE};
+
+ W = BITS(op,0x0100);
+ decode_HHH_table(cpustate, BITS(op,0x0e00), &SD);
+ decode_RR_table(cpustate, BITS(op,0x3000),&R);
+
+ if (W)
+ {
+ /* From X:<ea> to SD */
+ uint16_t data = cpustate->data->read_word(*((uint16_t*)R.addr));
+
+ typed_pointer tempTP;
+ tempTP.addr = &data;
+ tempTP.data_type = DT_WORD;
+
+ SetDestinationValue(tempTP, SD);
+ }
+ else
+ {
+ /* From SD to X:<ea> */
+ /* If the source is the same as the ALU destination, use the previous accumulator value */
+ if (d_register->addr == SD.addr)
+ {
+ typed_pointer tempTP;
+ tempTP.addr = prev_accum_value;
+ tempTP.data_type = DT_LONG_WORD;
+
+ SetDataMemoryValue(cpustate, tempTP, *((uint16_t*)R.addr)) ;
+ }
+ else
+ {
+ SetDataMemoryValue(cpustate, SD, *((uint16_t*)R.addr)) ;
+ }
+ }
+
+ execute_m_table(cpustate, BITS(op,0x3000), BITS(op,0x4000));
+}
+
+/* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+/* NOTE: previous accumulator value is not needed since ^F1 is always the opposite accumulator */
+static void execute_x_memory_data_move2(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register)
+{
+ uint16_t W;
+ uint16_t* mem_offset = nullptr;
+ typed_pointer SD = {nullptr, DT_BYTE};
+
+ W = BITS(op,0x0100);
+ decode_HHH_table(cpustate, BITS(op,0x0e000), &SD);
+
+ if (d_register->addr == &A)
+ mem_offset = &B1;
+ else
+ mem_offset = &A1;
+
+ if (W)
+ {
+ /* Write D */
+ uint16_t value = cpustate->data->read_word(*mem_offset);
+ typed_pointer tempV = {&value, DT_WORD};
+ SetDestinationValue(tempV, SD);
+ }
+ else
+ {
+ /* Read S */
+ SetDataMemoryValue(cpustate, SD, *mem_offset);
+ }
+}
+
+/* X Memory Data Move With Short Displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+static void execute_x_memory_data_move_with_short_displacement(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2)
+{
+ int8_t xx;
+ uint8_t W;
+ uint16_t memOffset;
+ typed_pointer SD = { nullptr, DT_BYTE };
+
+ xx = (int8_t)(op & 0x00ff);
+ W = BITS(op2,0x0100);
+ decode_HHH_table(cpustate, BITS(op2,0x0e00), &SD);
+
+ memOffset = R2 + (int16_t)xx;
+
+ if (W)
+ {
+ /* Write D */
+ uint16_t tempData = cpustate->data->read_word(memOffset);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ uint16_t tempData = *((uint16_t*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, memOffset);
+ }
+}
+
+/* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+static void execute_dual_x_memory_data_read(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register)
+{
+ typed_pointer tempV;
+ uint16_t srcVal1 = 0x0000;
+ uint16_t srcVal2 = 0x0000;
+ typed_pointer R = {nullptr, DT_BYTE};
+ typed_pointer D1 = {nullptr, DT_BYTE};
+ typed_pointer D2 = {nullptr, DT_BYTE};
+
+ decode_RR_table(cpustate, BITS(op,0x0060), &R);
+ decode_KKK_table(cpustate, BITS(op,0x0700), &D1, &D2, d_register->addr);
+
+ /* Can't do an R3 for S1 */
+ if (R.addr == &R3)
+ fatalerror("Dsp56156: Error. Dual x memory data read specified R3 as its first source!\n");
+
+ /* The note on A-142 is very interesting.
+ You can effectively access external memory in the last 64 bytes of X data memory! */
+ if (*((uint16_t*)D2.addr) >= 0xffc0)
+ fatalerror("Dsp56156: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read.\n");
+
+ /* First memmove */
+ srcVal1 = cpustate->data->read_word(*((uint16_t*)R.addr));
+ tempV.addr = &srcVal1;
+ tempV.data_type = DT_WORD;
+ SetDestinationValue(tempV, D1);
+
+ /* Second memmove */
+ srcVal2 = cpustate->data->read_word(R3);
+ tempV.addr = &srcVal2;
+ tempV.data_type = DT_WORD;
+ SetDestinationValue(tempV, D2);
+
+ /* Touch up the R regs after all the moves */
+ execute_mm_table(cpustate, BITS(op,0x0060), BITS(op,0x1800));
+}
+
+/***************************************************************************
+ Helper Functions
+***************************************************************************/
+static uint16_t Dsp56156OpMask(uint16_t cur, uint16_t mask)
+{
+ int i ;
+
+ uint16_t retVal = (cur & mask) ;
+ uint16_t temp = 0x0000 ;
+ int offsetCount = 0 ;
+
+ /* Shift everything right, eliminating 'whitespace' */
+ for (i = 0; i < 16; i++)
+ {
+ if (mask & (0x1<<i)) /* If mask bit is non-zero */
+ {
+ temp |= (((retVal >> i) & 0x1) << offsetCount) ;
+ offsetCount++ ;
+ }
+ }
+
+ return temp ;
+}
+
+static void SetDestinationValue(typed_pointer source, typed_pointer dest)
+{
+ uint64_t destinationValue = 0 ;
+
+ switch(dest.data_type)
+ {
+ /* Copying to an 8-bit value */
+ case DT_BYTE:
+ switch(source.data_type)
+ {
+ /* From a ? */
+ case DT_BYTE: *((uint8_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break;
+ case DT_WORD: *((uint8_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0x00ff; break;
+ case DT_DOUBLE_WORD: *((uint8_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0x000000ff; break;
+ case DT_LONG_WORD: *((uint8_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000000000ffU; break;
+ }
+ break ;
+
+ /* Copying to a 16-bit value */
+ case DT_WORD:
+ switch(source.data_type)
+ {
+ case DT_BYTE: *((uint16_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break;
+ case DT_WORD: *((uint16_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0xffff; break;
+ case DT_DOUBLE_WORD: *((uint16_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0x0000ffff; break;
+ case DT_LONG_WORD: *((uint16_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000000000ffffU; break; /* TODO: Shift limiter action! A-147 */
+ }
+ break ;
+
+ /* Copying to a 32-bit value */
+ case DT_DOUBLE_WORD:
+ switch(source.data_type)
+ {
+ case DT_BYTE: *((uint32_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break;
+ case DT_WORD: *((uint32_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0xffff; break;
+ case DT_DOUBLE_WORD: *((uint32_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0xffffffff; break;
+ case DT_LONG_WORD: *((uint32_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000ffffffffU; break;
+ }
+ break ;
+
+ /* Copying to a 64-bit value */
+ case DT_LONG_WORD:
+ switch(source.data_type)
+ {
+ case DT_BYTE: *((uint64_t*)dest.addr) = (*((uint8_t*)source.addr)) & 0xff; break;
+
+ case DT_WORD: destinationValue = (*((uint16_t*)source.addr)) << 16;
+ if (destinationValue & 0x0000000080000000U)
+ destinationValue |= 0x000000ff00000000U;
+ *((uint64_t*)dest.addr) = (uint64_t)destinationValue; break; /* Forget not, yon shift register */
+
+ case DT_DOUBLE_WORD: *((uint64_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0xffffffff; break;
+ case DT_LONG_WORD: *((uint64_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000ffffffffffU; break;
+ }
+ break ;
+ }
+}
+
+/* TODO: Wait-state timings! */
+static void SetDataMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr)
+{
+ switch(source.data_type)
+ {
+ case DT_BYTE: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff) ) ) ; break ;
+ case DT_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff) ) ) ; break ;
+ case DT_DOUBLE_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff) ) ) ; break ;
+
+ /* !!! Is this universal ??? */
+ /* !!! Forget not, yon shift-limiter !!! */
+ case DT_LONG_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( ((*((uint64_t*)source.addr)) & 0x00000000ffff0000U) >> 16) ) ; break ;
+ }
+}
+
+/* TODO: Wait-state timings! */
+static void SetProgramMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr)
+{
+ switch(source.data_type)
+ {
+ case DT_BYTE: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff) ) ) ; break ;
+ case DT_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff) ) ) ; break ;
+ case DT_DOUBLE_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff) ) ) ; break ;
+
+ /* !!! Is this universal ??? */
+ /* !!! Forget not, yon shift-limiter !!! */
+ case DT_LONG_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( ((*((uint64_t*)source.addr)) & 0x00000000ffff0000U) >> 16) ) ; break ;
+ }
+}
diff --git a/src/devices/cpu/dsp56156/dsp56pcu.cpp b/src/devices/cpu/dsp56156/dsp56pcu.cpp
new file mode 100644
index 00000000000..94ca3b1caae
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56pcu.cpp
@@ -0,0 +1,488 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#include "emu.h"
+#include "dsp56pcu.h"
+#include "dsp56mem.h"
+
+namespace DSP_56156
+{
+/* ************************************************************************* */
+/* Status Register */
+/* ************************************************************************* */
+/* MR CCR */
+/* |-------------------------------------| |-------------------------------| */
+/* | LF | FV | * | * | S1 | S0 | I1 | I0 | | S | L | E | U | N | Z | V | C | */
+/* |-------------------------------------| |-------------------------------| */
+/* */
+/* ************************************************************************* */
+uint8_t LF_bit(const dsp56156_core* cpustate) { return (SR & 0x8000) >> 15; }
+uint8_t FV_bit(const dsp56156_core* cpustate) { return (SR & 0x4000) >> 14; }
+// uint8_t S_bits(const dsp56156_core* cpustate) { return (SR & 0x0c00) >> 10; }
+uint8_t I_bits(const dsp56156_core* cpustate) { return (SR & 0x0300) >> 8; }
+uint8_t S_bit (const dsp56156_core* cpustate) { return (SR & 0x0080) >> 7; }
+uint8_t L_bit (const dsp56156_core* cpustate) { return (SR & 0x0040) >> 6; }
+uint8_t E_bit (const dsp56156_core* cpustate) { return (SR & 0x0020) >> 5; }
+uint8_t U_bit (const dsp56156_core* cpustate) { return (SR & 0x0010) >> 4; }
+uint8_t N_bit (const dsp56156_core* cpustate) { return (SR & 0x0008) >> 3; }
+uint8_t Z_bit (const dsp56156_core* cpustate) { return (SR & 0x0004) >> 2; }
+uint8_t V_bit (const dsp56156_core* cpustate) { return (SR & 0x0002) >> 1; }
+uint8_t C_bit (const dsp56156_core* cpustate) { return (SR & 0x0001) >> 0; }
+
+/* MR setters */
+void LF_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x8000); else (SR &= (~0x8000)); }
+void FV_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x4000); else (SR &= (~0x4000)); }
+void S_bits_set(dsp56156_core* cpustate, uint8_t value) { value = value & 0x03; SR &= ~(0x0c00); SR |= (value << 10); }
+void I_bits_set(dsp56156_core* cpustate, uint8_t value) { value = value & 0x03; SR &= ~(0x0300); SR |= (value << 8); }
+
+/* CCR setters */
+void S_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0080); else (SR &= (~0x0080)); }
+void L_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0040); else (SR &= (~0x0040)); }
+void E_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0020); else (SR &= (~0x0020)); }
+void U_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0010); else (SR &= (~0x0010)); }
+void N_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0008); else (SR &= (~0x0008)); }
+void Z_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0004); else (SR &= (~0x0004)); }
+void V_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0002); else (SR &= (~0x0002)); }
+void C_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0001); else (SR &= (~0x0001)); }
+
+
+
+/* ************************************************************************* */
+/* Operating Mode Register */
+/* ************************************************************************* */
+/* */
+/* |---------------------------------------------------------------------| */
+/* | * | * | * | * | * | * | * | * | CD | SD | R | SA | * | MC | MB | MA | */
+/* |---------------------------------------------------------------------| */
+/* */
+/* ************************************************************************* */
+// uint8_t CD_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0080) != 0); }
+// uint8_t SD_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0040) != 0); }
+// uint8_t R_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0020) != 0); }
+// uint8_t SA_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0010) != 0); }
+// uint8_t MC_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0004) != 0); }
+uint8_t MB_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0002) != 0); }
+uint8_t MA_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0001) != 0); }
+
+void CD_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0080); else (OMR &= (~0x0080)); }
+void SD_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0040); else (OMR &= (~0x0040)); }
+void R_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0020); else (OMR &= (~0x0020)); }
+void SA_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0010); else (OMR &= (~0x0010)); }
+void MC_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0004); else (OMR &= (~0x0004)); }
+void MB_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0002); else (OMR &= (~0x0002)); }
+void MA_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0001); else (OMR &= (~0x0001)); }
+
+uint8_t dsp56156_operating_mode(const dsp56156_core* cpustate)
+{
+ return ((MB_bit(cpustate) << 1) | MA_bit(cpustate));
+}
+
+
+
+/* ************************************************************************* */
+/* Stack Pointer */
+/* ************************************************************************* */
+/* */
+/* |---------------------------------------------------------------------| */
+/* | * | * | * | * | * | * | * | * | * | * | UF | SE | P3 | P2 | P1 | P0 | */
+/* |---------------------------------------------------------------------| */
+/* */
+/* ************************************************************************* */
+uint8_t UF_bit(const dsp56156_core* cpustate) { return ((SP & 0x0020) != 0); }
+uint8_t SE_bit(const dsp56156_core* cpustate) { return ((SP & 0x0010) != 0); }
+
+//void UF_bit_set(dsp56156_core* cpustate, uint8_t value) {};
+//void SE_bit_set(dsp56156_core* cpustate, uint8_t value) {};
+
+
+
+/***************************************************************************
+ INITIALIZATION AND RESET
+***************************************************************************/
+void pcu_init(dsp56156_core* cpustate, device_t *device)
+{
+ /* Init the irq table */
+ dsp56156_irq_table_init();
+
+ /* save states - dsp56156_pcu members */
+ device->save_item(NAME(cpustate->PCU.pc));
+ device->save_item(NAME(cpustate->PCU.la));
+ device->save_item(NAME(cpustate->PCU.lc));
+ device->save_item(NAME(cpustate->PCU.sr));
+ device->save_item(NAME(cpustate->PCU.omr));
+ device->save_item(NAME(cpustate->PCU.sp));
+ device->save_item(NAME(cpustate->PCU.ss));
+ device->save_item(NAME(cpustate->PCU.pending_interrupts));
+ device->save_item(NAME(cpustate->PCU.reset_vector));
+}
+
+void pcu_reset(dsp56156_core* cpustate)
+{
+ int i;
+
+ /* When reset is deasserted, set MA, MB, and MC from MODA, MODB, and MODC lines. */
+ MA_bit_set(cpustate, cpustate->modA_state);
+ MB_bit_set(cpustate, cpustate->modB_state);
+ MC_bit_set(cpustate, cpustate->modC_state);
+
+ /* Reset based on the operating mode. */
+ switch(dsp56156_operating_mode(cpustate))
+ {
+ case 0x00:
+ cpustate->device->logerror("Dsp56156 in Special Bootstrap Mode 1\n");
+
+ /* HACK - We don't need to put the bootstrap mode on here since */
+ /* we'll simulate it entirely in this function */
+ cpustate->bootstrap_mode = BOOTSTRAP_OFF;
+
+ /* HACK - Simply copy over 0x1000 bytes of data located at program memory 0xc000. */
+ /* This, in actuality, is handled with the internal boot ROM. */
+ for (i = 0; i < 0x800; i++)
+ {
+ uint32_t mem_offset = (0xc000<<1) + (i<<1); /* TODO: TEST */
+
+ /* TODO - DO I HAVE TO FLIP THIS WORD? */
+ /* P:$c000 -> Internal P:$0000 low byte */
+ /* P:$c001 -> Internal P:$0000 high byte */
+ /* ... */
+ /* P:$cffe -> Internal P:$07ff low byte */
+ /* P:$cfff -> Internal P:$07ff high byte */
+ uint8_t mem_value_low = cpustate->program->read_byte(mem_offset); /* TODO: IS THIS READING RIGHT? */
+ uint8_t mem_value_high = cpustate->program->read_byte(mem_offset);
+ cpustate->program_ram[i] = (mem_value_high << 8) | mem_value_low;
+ }
+
+ /* HACK - Set the PC to 0x0000 as per the boot ROM. */
+ PC = 0x0000;
+
+ /* HACK - All done! Set the Operating Mode to 2 as per the boot ROM. */
+ MB_bit_set(cpustate, 1);
+ MA_bit_set(cpustate, 0);
+ cpustate->PCU.reset_vector = 0xe000;
+ break;
+
+ case 0x01:
+ cpustate->device->logerror("Dsp56156 in Special Bootstrap Mode 2\n");
+
+ /* HACK - Turn bootstrap mode on. This hijacks the CPU execute loop and lets */
+ /* Either the host interface or the SSIO interface suck in all the data */
+ /* they need. Once they've had their fill, they turn bootstrap mode off */
+ /* and the CPU begins execution at 0x0000; */
+ /* HACK - Read bit 15 at 0xc000 to see if we're working with the SSIO or host interface. */
+ if (cpustate->program->read_word(0xc000<<1) & 0x8000)
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_SSIX;
+ cpustate->device->logerror("DSP56156 : Currently in (hacked) bootstrap mode - reading from SSIx.\n");
+ }
+ else
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_HI;
+ cpustate->device->logerror("DSP56156 : Currently in (hacked) bootstrap mode - reading from Host Interface.\n");
+ }
+
+ /* HACK - Set the PC to 0x0000 as per the boot ROM. */
+ PC = 0x0000;
+
+ /* HACK - Not done yet, but set the Operating Mode to 2 in preparation. */
+ MB_bit_set(cpustate, 1);
+ MA_bit_set(cpustate, 0);
+ cpustate->PCU.reset_vector = 0xe000;
+ break;
+
+ case 0x02:
+ cpustate->device->logerror("Dsp56156 in Normal Expanded Mode\n");
+ PC = 0xe000;
+ cpustate->PCU.reset_vector = 0xe000;
+ break;
+
+ case 0x03:
+ cpustate->device->logerror("Dsp56156 in Development Expanded Mode\n");
+ /* TODO: Disable internal ROM, etc. Likely a tricky thing for MAME? */
+ PC = 0x0000;
+ cpustate->PCU.reset_vector = 0x0000;
+ break;
+ }
+
+ /* Set registers properly */
+ /* 1-17 Clear Interrupt Priority Register (IPR) */
+ IPR = 0x0000;
+
+ /* FM.5-4 */
+ I_bits_set(cpustate, 0x03);
+ S_bits_set(cpustate, 0);
+ L_bit_set(cpustate, 0);
+ S_bit_set(cpustate, 0);
+ FV_bit_set(cpustate, 0);
+
+ /* FM.7-25 */
+ E_bit_set(cpustate, 0);
+ U_bit_set(cpustate, 0);
+ N_bit_set(cpustate, 0);
+ V_bit_set(cpustate, 0);
+ Z_bit_set(cpustate, 0);
+
+ /* FM.5-4+ */
+ C_bit_set(cpustate, 0);
+ LF_bit_set(cpustate, 0);
+ SP = 0x0000;
+
+ /* FM.5-14 (OMR) */
+ SA_bit_set(cpustate, 0);
+ R_bit_set(cpustate, 0);
+ SD_bit_set(cpustate, 0);
+ CD_bit_set(cpustate, 0);
+
+ /* Clear out the pending interrupt list */
+ dsp56156_clear_pending_interrupts(cpustate);
+}
+
+/***************************************************************************
+ INTERRUPT HANDLING
+***************************************************************************/
+struct dsp56156_irq_data
+{
+ uint16_t irq_vector;
+ char irq_source[128];
+};
+
+dsp56156_irq_data dsp56156_interrupt_sources[32];
+
+/* TODO: Figure out how to switch on level versus edge-triggered. */
+void pcu_service_interrupts(dsp56156_core* cpustate)
+{
+ int i;
+
+ /* Count list of pending interrupts */
+ int num_servicable = dsp56156_count_pending_interrupts(cpustate);
+
+ if (num_servicable == 0)
+ return;
+
+ /* Sort list according to priority */
+ dsp56156_sort_pending_interrupts(cpustate, num_servicable);
+
+ /* Service each interrupt in order */
+ /* TODO: This just *can't* be right :) */
+ for (i = 0; i < num_servicable; i++)
+ {
+ const int interrupt_index = cpustate->PCU.pending_interrupts[i];
+
+ /* Get the priority of the interrupt - a return value of -1 means disabled! */
+ int8_t priority = dsp56156_get_irq_priority(cpustate, interrupt_index);
+
+ /* 1-12 Make sure you're not masked out against the Interrupt Mask Bits (disabled is handled for free here) */
+ if (priority >= I_bits(cpustate))
+ {
+ /* TODO: Implement long interrupts & fast interrupts correctly! */
+ /* Right now they are handled in the JSR & BSR ops. SupahLame. */
+
+ /* Are you anything but the Host Command interrupt? */
+ if (interrupt_index != 22)
+ {
+ /* Execute a normal interrupt */
+ PC = dsp56156_interrupt_sources[interrupt_index].irq_vector;
+ }
+ else
+ {
+ /* The host command input has a floating vector. */
+ const uint16_t irq_vector = HV_bits(cpustate) << 1;
+
+ PC = irq_vector;
+
+ /* TODO: 5-9 5-11 Gotta' Clear HC (HCP gets it too) when taking this exception! */
+ HC_bit_set(cpustate, 0);
+ }
+ }
+ }
+
+ dsp56156_clear_pending_interrupts(cpustate);
+}
+
+
+/* Register an interrupt */
+void dsp56156_add_pending_interrupt(dsp56156_core* cpustate, const char* name)
+{
+ int i;
+ int irq_index = dsp56156_get_irq_index_by_tag(name);
+
+ for (i = 0; i < 32; i++)
+ {
+ if (cpustate->PCU.pending_interrupts[i] == -1)
+ {
+ cpustate->PCU.pending_interrupts[i] = irq_index;
+ break;
+ }
+ }
+}
+
+/* Utility function to construct IRQ table */
+void dsp56156_set_irq_source(uint8_t irq_num, uint16_t iv, const char* source)
+{
+ dsp56156_interrupt_sources[irq_num].irq_vector = iv;
+ strcpy(dsp56156_interrupt_sources[irq_num].irq_source, source);
+}
+
+/* Construct a table containing pertient IRQ information */
+void dsp56156_irq_table_init(void)
+{
+ /* 1-14 + 1-18 */
+ /* TODO: Cull host command stuff appropriately */
+ /* array index . vector . token */
+ dsp56156_set_irq_source(0, 0x0000, "Hardware RESET");
+ dsp56156_set_irq_source(1, 0x0002, "Illegal Instruction");
+ dsp56156_set_irq_source(2, 0x0004, "Stack Error");
+ dsp56156_set_irq_source(3, 0x0006, "Reserved");
+ dsp56156_set_irq_source(4, 0x0008, "SWI");
+ dsp56156_set_irq_source(5, 0x000a, "IRQA");
+ dsp56156_set_irq_source(6, 0x000c, "IRQB");
+ dsp56156_set_irq_source(7, 0x000e, "Reserved");
+ dsp56156_set_irq_source(8, 0x0010, "SSI0 Receive Data with Exception");
+ dsp56156_set_irq_source(9, 0x0012, "SSI0 Receive Data");
+ dsp56156_set_irq_source(10, 0x0014, "SSI0 Transmit Data with Exception");
+ dsp56156_set_irq_source(11, 0x0016, "SSI0 Transmit Data");
+ dsp56156_set_irq_source(12, 0x0018, "SSI1 Receive Data with Exception");
+ dsp56156_set_irq_source(13, 0x001a, "SSI1 Receive Data");
+ dsp56156_set_irq_source(14, 0x001c, "SSI1 Transmit Data with Exception");
+ dsp56156_set_irq_source(15, 0x001e, "SSI1 Transmit Data");
+ dsp56156_set_irq_source(16, 0x0020, "Timer Overflow");
+ dsp56156_set_irq_source(17, 0x0022, "Timer Compare");
+ dsp56156_set_irq_source(18, 0x0024, "Host DMA Receive Data");
+ dsp56156_set_irq_source(19, 0x0026, "Host DMA Transmit Data");
+ dsp56156_set_irq_source(20, 0x0028, "Host Receive Data");
+ dsp56156_set_irq_source(21, 0x002a, "Host Transmit Data");
+ dsp56156_set_irq_source(22, 0x002c, "Host Command"); /* Default vector for the host command */
+ dsp56156_set_irq_source(23, 0x002e, "Codec Receive/Transmit");
+ dsp56156_set_irq_source(24, 0x0030, "Host Command 1");
+ dsp56156_set_irq_source(25, 0x0032, "Host Command 2");
+ dsp56156_set_irq_source(26, 0x0034, "Host Command 3");
+ dsp56156_set_irq_source(27, 0x0036, "Host Command 4");
+ dsp56156_set_irq_source(28, 0x0038, "Host Command 5");
+ dsp56156_set_irq_source(29, 0x003a, "Host Command 6");
+ dsp56156_set_irq_source(30, 0x003c, "Host Command 7");
+ dsp56156_set_irq_source(31, 0x003e, "Host Command 8");
+}
+
+/* Clear all entries from the pending table */
+void dsp56156_clear_pending_interrupts(dsp56156_core* cpustate)
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ cpustate->PCU.pending_interrupts[i] = -1;
+ }
+}
+
+/* Recover number of pending irqs */
+int dsp56156_count_pending_interrupts(dsp56156_core* cpustate)
+{
+ int numI = 0;
+ while (cpustate->PCU.pending_interrupts[numI] != -1)
+ {
+ numI++;
+ }
+
+ return numI;
+}
+
+/* Sort the pending irqs by priority */
+void dsp56156_sort_pending_interrupts(dsp56156_core* cpustate, int num)
+{
+ int i, j;
+
+ /* We're going to be sorting the priorities */
+ int priority_list[32];
+ for (i = 0; i < num; i++)
+ {
+ priority_list[i] = dsp56156_get_irq_priority(cpustate, cpustate->PCU.pending_interrupts[i]);
+ }
+
+ /* Bubble sort should be good enough for us */
+ for (i = 0; i < num; i++)
+ {
+ for(j = 0; j < num-1; j++)
+ {
+ if (priority_list[j] > priority_list[j+1])
+ {
+ int holder;
+
+ /* Swap priorities */
+ holder = priority_list[j+1];
+ priority_list[j+1] = priority_list[j];
+ priority_list[j] = holder;
+
+ /* Swap irq indices. */
+ holder = cpustate->PCU.pending_interrupts[j+1];
+ cpustate->PCU.pending_interrupts[j+1] = cpustate->PCU.pending_interrupts[j];
+ cpustate->PCU.pending_interrupts[j] = holder;
+ }
+ }
+ }
+
+ /* TODO: 1-17 Now sort each of the priority levels within their categories. */
+}
+
+/* Given an index into the irq table, return the interrupt's current priority */
+int8_t dsp56156_get_irq_priority(dsp56156_core* cpustate, int index)
+{
+ /* 1-12 */
+ switch (index)
+ {
+ /* Non-maskable */
+ case 0: return 3; /* Hardware RESET */
+ case 1: return 3; /* Illegal Instruction */
+ case 2: return 3; /* Stack Error */
+ case 3: return 3; /* Reserved */
+ case 4: return 3; /* SWI */
+
+ /* Poll the IPR for these guys. */
+ case 5: return irqa_ipl(cpustate); /* IRQA */
+ case 6: return irqb_ipl(cpustate); /* IRQB */
+ case 7: return -1; /* Reserved */
+ case 8: return ssi0_ipl(cpustate); /* SSI0 Receive Data with Exception */
+ case 9: return ssi0_ipl(cpustate); /* SSI0 Receive Data */
+ case 10: return ssi0_ipl(cpustate); /* SSI0 Transmit Data with Exception */
+ case 11: return ssi0_ipl(cpustate); /* SSI0 Transmit Data */
+ case 12: return ssi1_ipl(cpustate); /* SSI1 Receive Data with Exception */
+ case 13: return ssi1_ipl(cpustate); /* SSI1 Receive Data */
+ case 14: return ssi1_ipl(cpustate); /* SSI1 Transmit Data with Exception */
+ case 15: return ssi1_ipl(cpustate); /* SSI1 Transmit Data */
+ case 16: return tm_ipl(cpustate); /* Timer Overflow */
+ case 17: return tm_ipl(cpustate); /* Timer Compare */
+ case 18: return host_ipl(cpustate); /* Host DMA Receive Data */
+ case 19: return host_ipl(cpustate); /* Host DMA Transmit Data */
+ case 20: return host_ipl(cpustate); /* Host Receive Data */
+ case 21: return host_ipl(cpustate); /* Host Transmit Data */
+ case 22: return host_ipl(cpustate); /* Host Command 0 (Default) */
+ case 23: return codec_ipl(cpustate); /* Codec Receive/Transmit */
+ case 24: return host_ipl(cpustate); /* Host Command 1 // TODO: Are all host ipl's the same? */
+ case 25: return host_ipl(cpustate); /* Host Command 2 */
+ case 26: return host_ipl(cpustate); /* Host Command 3 */
+ case 27: return host_ipl(cpustate); /* Host Command 4 */
+ case 28: return host_ipl(cpustate); /* Host Command 5 */
+ case 29: return host_ipl(cpustate); /* Host Command 6 */
+ case 30: return host_ipl(cpustate); /* Host Command 7 */
+ case 31: return host_ipl(cpustate); /* Host Command 8 */
+
+ default: break;
+ }
+
+ return -1;
+}
+
+/* Given an IRQ name, return its index in the irq table */
+int dsp56156_get_irq_index_by_tag(const char* tag)
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ if (strcmp(tag, dsp56156_interrupt_sources[i].irq_source) == 0)
+ {
+ return i;
+ }
+ }
+
+ fatalerror("DSP56156 ERROR : IRQ TAG specified incorrectly (get_vector_by_tag) : %s.\n", tag);
+ // never executed
+ //return -1;
+}
+
+} // namespace DSP_56156
diff --git a/src/devices/cpu/dsp56156/dsp56pcu.h b/src/devices/cpu/dsp56156/dsp56pcu.h
new file mode 100644
index 00000000000..a04f7bf1f26
--- /dev/null
+++ b/src/devices/cpu/dsp56156/dsp56pcu.h
@@ -0,0 +1,150 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#ifndef DSP56156_PCU_H
+#define DSP56156_PCU_H
+
+#include "dsp56156.h"
+
+namespace DSP_56156
+{
+/***************************************************************************
+ PCU
+***************************************************************************/
+void pcu_reset(dsp56156_core* cpustate);
+void pcu_init(dsp56156_core* cpustate, device_t *device);
+#define PC (cpustate->PCU.pc)
+#define LA (cpustate->PCU.la)
+#define LC (cpustate->PCU.lc)
+#define SR (cpustate->PCU.sr)
+#define OMR (cpustate->PCU.omr)
+#define SP (cpustate->PCU.sp)
+#define SS (cpustate->PCU.ss)
+
+#define SSH (SS[SP].w.h)
+#define SSL (SS[SP].w.l)
+
+#define ST0 (SS[0].d)
+#define ST1 (SS[1].d)
+#define ST2 (SS[2].d)
+#define ST3 (SS[3].d)
+#define ST4 (SS[4].d)
+#define ST5 (SS[5].d)
+#define ST6 (SS[6].d)
+#define ST7 (SS[7].d)
+#define ST8 (SS[8].d)
+#define ST9 (SS[9].d)
+#define ST10 (SS[10].d)
+#define ST11 (SS[11].d)
+#define ST12 (SS[12].d)
+#define ST13 (SS[13].d)
+#define ST14 (SS[14].d)
+#define ST15 (SS[15].d)
+
+/* STATUS REGISTER (SR) BITS (1-25) */
+/* MR */
+uint8_t LF_bit(const dsp56156_core* cpustate);
+uint8_t FV_bit(const dsp56156_core* cpustate);
+//uint8_t S_bits(const dsp56156_core* cpustate);
+uint8_t I_bits(const dsp56156_core* cpustate);
+
+/* CCR - with macros for easy access */
+#define S() (S_bit(cpustate))
+uint8_t S_bit(const dsp56156_core* cpustate);
+#define L() (L_bit(cpustate))
+uint8_t L_bit(const dsp56156_core* cpustate);
+#define E() (E_bit(cpustate))
+uint8_t E_bit(const dsp56156_core* cpustate);
+#define U() (U_bit(cpustate))
+uint8_t U_bit(const dsp56156_core* cpustate);
+#define N() (N_bit(cpustate))
+uint8_t N_bit(const dsp56156_core* cpustate);
+#define Z() (Z_bit(cpustate))
+uint8_t Z_bit(const dsp56156_core* cpustate);
+#define V() (V_bit(cpustate))
+uint8_t V_bit(const dsp56156_core* cpustate);
+#define C() (C_bit(cpustate))
+uint8_t C_bit(const dsp56156_core* cpustate);
+
+/* MR setters */
+void LF_bit_set(dsp56156_core* cpustate, uint8_t value);
+void FV_bit_set(dsp56156_core* cpustate, uint8_t value);
+void S_bits_set(dsp56156_core* cpustate, uint8_t value);
+void I_bits_set(dsp56156_core* cpustate, uint8_t value);
+
+/* CCR setters - with macros for easy access */
+#define DSP56156_S_SET() (S_bit_set(cpustate, 1))
+#define DSP56156_S_CLEAR() (S_bit_set(cpustate, 0))
+void S_bit_set(dsp56156_core* cpustate, uint8_t value);
+#define DSP56156_L_SET() (L_bit_set(cpustate, 1))
+#define DSP56156_L_CLEAR() (L_bit_set(cpustate, 0))
+void L_bit_set(dsp56156_core* cpustate, uint8_t value);
+#define DSP56156_E_SET() (E_bit_set(cpustate, 1))
+#define DSP56156_E_CLEAR() (E_bit_set(cpustate, 0))
+void E_bit_set(dsp56156_core* cpustate, uint8_t value);
+#define DSP56156_U_SET() (U_bit_set(cpustate, 1))
+#define DSP56156_U_CLEAR() (U_bit_set(cpustate, 0))
+void U_bit_set(dsp56156_core* cpustate, uint8_t value);
+#define DSP56156_N_SET() (N_bit_set(cpustate, 1))
+#define DSP56156_N_CLEAR() (N_bit_set(cpustate, 0))
+void N_bit_set(dsp56156_core* cpustate, uint8_t value);
+#define DSP56156_Z_SET() (Z_bit_set(cpustate, 1))
+#define DSP56156_Z_CLEAR() (Z_bit_set(cpustate, 0))
+void Z_bit_set(dsp56156_core* cpustate, uint8_t value);
+#define DSP56156_V_SET() (V_bit_set(cpustate, 1))
+#define DSP56156_V_CLEAR() (V_bit_set(cpustate, 0))
+void V_bit_set(dsp56156_core* cpustate, uint8_t value);
+#define DSP56156_C_SET() (C_bit_set(cpustate, 1))
+#define DSP56156_C_CLEAR() (C_bit_set(cpustate, 0))
+void C_bit_set(dsp56156_core* cpustate, uint8_t value);
+
+// TODO: Maybe some functions for Interrupt Mask and Scaling Mode go here?
+
+
+/* 1-28 OPERATING MODE REGISTER (OMR) BITS */
+//uint8_t CD_bit(const dsp56156_core* cpustate);
+//uint8_t SD_bit(const dsp56156_core* cpustate);
+//uint8_t R_bit(const dsp56156_core* cpustate);
+//uint8_t SA_bit(const dsp56156_core* cpustate);
+//uint8_t MC_bit(const dsp56156_core* cpustate);
+uint8_t MB_bit(const dsp56156_core* cpustate);
+uint8_t MA_bit(const dsp56156_core* cpustate);
+
+void CD_bit_set(dsp56156_core* cpustate, uint8_t value);
+void SD_bit_set(dsp56156_core* cpustate, uint8_t value);
+void R_bit_set(dsp56156_core* cpustate, uint8_t value);
+void SA_bit_set(dsp56156_core* cpustate, uint8_t value);
+void MC_bit_set(dsp56156_core* cpustate, uint8_t value);
+void MB_bit_set(dsp56156_core* cpustate, uint8_t value);
+void MA_bit_set(dsp56156_core* cpustate, uint8_t value);
+
+/* 1-27 STACK POINTER (SP) BITS */
+uint8_t UF_bit(const dsp56156_core* cpustate);
+uint8_t SE_bit(const dsp56156_core* cpustate);
+
+//void UF_bit_set(dsp56156_core* cpustate, uint8_t value) {};
+//void SE_bit_set(dsp56156_core* cpustate, uint8_t value) {};
+
+
+// HACK - Bootstrap modes
+#define BOOTSTRAP_OFF (0)
+#define BOOTSTRAP_SSIX (1)
+#define BOOTSTRAP_HI (2)
+
+
+/* PCU IRQ goodies */
+void pcu_service_interrupts(dsp56156_core* cpustate);
+
+void dsp56156_irq_table_init(void);
+void dsp56156_set_irq_source(uint8_t irq_num, uint16_t iv, const char* source);
+int dsp56156_get_irq_index_by_tag(const char* tag);
+
+void dsp56156_add_pending_interrupt(dsp56156_core* cpustate, const char* name); // Call me to add an interrupt to the queue
+
+void dsp56156_clear_pending_interrupts(dsp56156_core* cpustate);
+int dsp56156_count_pending_interrupts(dsp56156_core* cpustate);
+void dsp56156_sort_pending_interrupts(dsp56156_core* cpustate, int num);
+int8_t dsp56156_get_irq_priority(dsp56156_core* cpustate, int index);
+
+} // namespace DSP_56156
+
+#endif
diff --git a/src/devices/cpu/dsp56156/inst.cpp b/src/devices/cpu/dsp56156/inst.cpp
new file mode 100644
index 00000000000..339156aa35e
--- /dev/null
+++ b/src/devices/cpu/dsp56156/inst.cpp
@@ -0,0 +1,786 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#include "emu.h"
+#include "inst.h"
+#include "emu.h"
+
+namespace DSP_56156
+{
+// Factory
+std::unique_ptr<Instruction> Instruction::decodeInstruction(const Opcode* opc,
+ const uint16_t word0,
+ const uint16_t word1,
+ bool shifted)
+{
+ uint16_t w0 = word0;
+ uint16_t w1 = word1;
+
+ if (shifted)
+ {
+ w0 = w1;
+ w1 = 0x0000;
+ }
+
+ /**************************************************************************/
+ /* The very funky case of the XMemoryDataMoveWithShortDisplacement */
+ /**************************************************************************/
+ if ((w0 & 0xff00) == 0x0500)
+ {
+ // Avoid "05-- 05--" recursion
+ if (shifted) return nullptr;
+
+ std::unique_ptr<Instruction> op = decodeInstruction(opc, w0, w1, true);
+ if (op)
+ {
+ // This parallel move only works for certain trailing instructions.
+ if (dynamic_cast<Add*>(op.get()) ||
+ dynamic_cast<Asr*>(op.get()) ||
+ dynamic_cast<Eor*>(op.get()) ||
+ dynamic_cast<Mac*>(op.get()) ||
+ dynamic_cast<Macr*>(op.get()) ||
+ dynamic_cast<Mpy*>(op.get()) ||
+ dynamic_cast<Neg*>(op.get()) ||
+ dynamic_cast<Sub*>(op.get()) ||
+ dynamic_cast<Tfr*>(op.get()) ||
+ dynamic_cast<Tst*>(op.get())
+ /* TODO: More? */)
+ {
+ op->m_sizeIncrement = 1;
+ return op;
+ }
+ }
+ }
+
+
+ /**************************************************************************/
+ /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142 */
+ /* Quote: (MOVE, MAC(R), MPY(R), ADD, SUB, TFR) */
+ /**************************************************************************/
+ /* TFR : 011m mKKK 0rr1 F0DD : A-212 */
+ if ((w0 & 0xe094) == 0x6010)
+ {
+ return std::make_unique<Tfr_2>(opc, w0, w1);
+ }
+ /* MOVE : 011m mKKK 0rr1 0000 : A-128 */
+ if ((w0 & 0xe097) == 0x6017)
+ {
+ return std::make_unique<Move_2>(opc, w0, w1);
+ }
+ /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */
+ else if ((w0 & 0xe094) == 0x6084)
+ {
+ return std::make_unique<Mac_3>(opc, w0, w1);
+ }
+ /* MACR: 011m mKKK 1--1 F1QQ : A-124 */
+ else if ((w0 & 0xe094) == 0x6094)
+ {
+ return std::make_unique<Macr_2>(opc, w0, w1);
+ }
+ /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */
+ else if ((w0 & 0xe094) == 0x6080)
+ {
+ return std::make_unique<Mpy_2>(opc, w0, w1);
+ }
+ /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */
+ else if ((w0 & 0xe094) == 0x6090)
+ {
+ return std::make_unique<Mpyr_2>(opc, w0, w1);
+ }
+ /* ADD : 011m mKKK 0rru Fuuu : A-22 */
+ /* SUB : 011m mKKK 0rru Fuuu : A-202 */
+ else if ((w0 & 0xe080) == 0x6000)
+ {
+ return std::make_unique<Add_2>(opc, w0, w1);
+ }
+
+ /****************************************************************************/
+ /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+ /* Quote: (MPY or MAC) */
+ /****************************************************************************/
+ /* MPY : 0001 0110 RRDD FQQQ : A-160 */
+ else if ((w0 & 0xff00) == 0x1600)
+ {
+ return std::make_unique<Mpy_3>(opc, w0, w1);
+ }
+ /* MAC : 0001 0111 RRDD FQQQ : A-122 */
+ else if ((w0 & 0xff00) == 0x1700)
+ {
+ return std::make_unique<Mac_3>(opc, w0, w1);
+ }
+
+ /****************************************************************/
+ /* No Parallel Data Move : 0100 1010 .... .... : A-131 */
+ /* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+ /* Address Register Update : 0011 0zRR .... .... : A-135 */
+ /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+ /* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+ /* Quote: (32 General parallel move instructions) */
+ /****************************************************************/
+ else if (((w0 & 0xff00) == 0x4a00) ||
+ ((w0 & 0xf000) == 0x4000) ||
+ ((w0 & 0xf800) == 0x3000) ||
+ ((w0 & 0x8000) == 0x8000) ||
+ ((w0 & 0xf000) == 0x5000))
+ {
+ /* Note: There is much overlap down here, so certain ops must come before others */
+
+ /* CLR : .... .... 0000 F001 : A-60 */
+ if ((w0 & 0x00f7) == 0x0001)
+ {
+ return std::make_unique<Clr>(opc, w0, w1);
+ }
+ /* ADD : .... .... 0000 FJJJ : A-22 */
+ else if ((w0 & 0x00f0) == 0x0000)
+ {
+ return std::make_unique<Add>(opc, w0, w1);
+ }
+
+ /* MOVE : .... .... 0001 0001 : A-128 */
+ else if ((w0 & 0x00ff) == 0x0011 || (w0 & 0x00ff) == 0x0019)
+ // NEW // else if ((w0 & 0x00ff) == 0x0011)
+ {
+ return std::make_unique<Move>(opc, w0, w1);
+ }
+ /* TFR : .... .... 0001 FJJJ : A-212 */
+ else if ((w0 & 0x00f0) == 0x0010)
+ {
+ return std::make_unique<Tfr>(opc, w0, w1);
+ }
+
+ /* RND : .... .... 0010 F000 : A-188 */
+ else if ((w0 & 0x00f7) == 0x0020)
+ {
+ return std::make_unique<Rnd>(opc, w0, w1);
+ }
+ /* TST : .... .... 0010 F001 : A-218 */
+ else if ((w0 & 0x00f7) == 0x0021)
+ {
+ return std::make_unique<Tst>(opc, w0, w1);
+ }
+ /* INC : .... .... 0010 F010 : A-104 */
+ else if ((w0 & 0x00f7) == 0x0022)
+ {
+ return std::make_unique<Inc>(opc, w0, w1);
+ }
+ /* INC24 : .... .... 0010 F011 : A-106 */
+ else if ((w0 & 0x00f7) == 0x0023)
+ {
+ return std::make_unique<Inc24>(opc, w0, w1);
+ }
+ /* OR : .... .... 0010 F1JJ : A-176 */
+ else if ((w0 & 0x00f4) == 0x0024)
+ {
+ return std::make_unique<Or>(opc, w0, w1);
+ }
+
+ /* ASR : .... .... 0011 F000 : A-32 */
+ else if ((w0 & 0x00f7) == 0x0030)
+ {
+ return std::make_unique<Asr>(opc, w0, w1);
+ }
+ /* ASL : .... .... 0011 F001 : A-28 */
+ else if ((w0 & 0x00f7) == 0x0031)
+ {
+ return std::make_unique<Asl>(opc, w0, w1);
+ }
+ /* LSR : .... .... 0011 F010 : A-120 */
+ else if ((w0 & 0x00f7) == 0x0032)
+ {
+ return std::make_unique<Lsr>(opc, w0, w1);
+ }
+ /* LSL : .... .... 0011 F011 : A-118 */
+ else if ((w0 & 0x00f7) == 0x0033)
+ {
+ return std::make_unique<Lsl>(opc, w0, w1);
+ }
+ /* EOR : .... .... 0011 F1JJ : A-94 */
+ else if ((w0 & 0x00f4) == 0x0034)
+ {
+ return std::make_unique<Eor>(opc, w0, w1);
+ }
+
+ /* SUBL : .... .... 0100 F001 : A-204 */
+ else if ((w0 & 0x00f7) == 0x0041)
+ {
+ return std::make_unique<Subl>(opc, w0, w1);
+ }
+ /* SUB : .... .... 0100 FJJJ : A-202 */
+ else if ((w0 & 0x00f0) == 0x0040)
+ {
+ return std::make_unique<Sub>(opc, w0, w1);
+ }
+
+ /* CLR24 : .... .... 0101 F001 : A-62 */
+ else if ((w0 & 0x00f7) == 0x0051)
+ {
+ return std::make_unique<Clr24>(opc, w0, w1);
+ }
+ /* SBC : .... .... 0101 F01J : A-198 */
+ else if ((w0 & 0x00f6) == 0x0052)
+ {
+ return std::make_unique<Sbc>(opc, w0, w1);
+ }
+ /* CMP : .... .... 0101 FJJJ : A-64 */
+ else if ((w0 & 0x00f0) == 0x0050)
+ {
+ return std::make_unique<Cmp>(opc, w0, w1);
+ }
+
+ /* NEG : .... .... 0110 F000 : A-166 */
+ else if ((w0 & 0x00f7) == 0x0060)
+ {
+ return std::make_unique<Neg>(opc, w0, w1);
+ }
+ /* NOT : .... .... 0110 F001 : A-174 */
+ else if ((w0 & 0x00f7) == 0x0061)
+ {
+ return std::make_unique<Not>(opc, w0, w1);
+ }
+ /* DEC : .... .... 0110 F010 : A-72 */
+ else if ((w0 & 0x00f7) == 0x0062)
+ {
+ return std::make_unique<Dec>(opc, w0, w1);
+ }
+ /* DEC24 : .... .... 0110 F011 : A-74 */
+ else if ((w0 & 0x00f7) == 0x0063)
+ {
+ return std::make_unique<Dec24>(opc, w0, w1);
+ }
+ /* AND : .... .... 0110 F1JJ : A-24 */
+ else if ((w0 & 0x00f4) == 0x0064)
+ {
+ return std::make_unique<And>(opc, w0, w1);
+ }
+
+ /* ABS : .... .... 0111 F001 : A-18 */
+ if ((w0 & 0x00f7) == 0x0071)
+ {
+ return std::make_unique<Abs>(opc, w0, w1);
+ }
+ /* ROR : .... .... 0111 F010 : A-192 */
+ else if ((w0 & 0x00f7) == 0x0072)
+ {
+ return std::make_unique<Ror>(opc, w0, w1);
+ }
+ /* ROL : .... .... 0111 F011 : A-190 */
+ else if ((w0 & 0x00f7) == 0x0073)
+ {
+ return std::make_unique<Rol>(opc, w0, w1);
+ }
+ /* CMPM : .... .... 0111 FJJJ : A-66 */
+ else if ((w0 & 0x00f0) == 0x0070)
+ {
+ return std::make_unique<Cmpm>(opc, w0, w1);
+ }
+
+ /* MPY : .... .... 1k00 FQQQ : A-160 */
+ else if ((w0 & 0x00b0) == 0x0080)
+ {
+ return std::make_unique<Mpy>(opc, w0, w1);
+ }
+ /* MPYR : .... .... 1k01 FQQQ : A-162 */
+ else if ((w0 & 0x00b0) == 0x0090)
+ {
+ return std::make_unique<Mpyr>(opc, w0, w1);
+ }
+ /* MAC : .... .... 1k10 FQQQ : A-122 */
+ else if ((w0 & 0x00b0) == 0x00a0)
+ {
+ return std::make_unique<Mac>(opc, w0, w1);
+ }
+ /* MACR : .... .... 1k11 FQQQ : A-124 */
+ else if ((w0 & 0x00b0) == 0x00b0)
+ {
+ return std::make_unique<Macr>(opc, w0, w1);
+ }
+ }
+
+ /******************************/
+ /* Remaining non-parallel ops */
+ /******************************/
+ /* ADC : 0001 0101 0000 F01J : A-20 */
+ else if ((w0 & 0xfff6) == 0x1502)
+ {
+ return std::make_unique<Adc>(opc, w0, w1);
+ }
+ /* ANDI : 0001 1EE0 iiii iiii : A-26 */
+ /* Note: MoveP sneaks in here if you don't check 0x0600 */
+ else if (((w0 & 0xf900) == 0x1800) & ((w0 & 0x0600) != 0x0000))
+ {
+ return std::make_unique<Andi>(opc, w0, w1);
+ }
+ /* ASL4 : 0001 0101 0011 F001 : A-30 */
+ else if ((w0 & 0xfff7) == 0x1531)
+ {
+ return std::make_unique<Asl4>(opc, w0, w1);
+ }
+ /* ASR4 : 0001 0101 0011 F000 : A-34 */
+ else if ((w0 & 0xfff7) == 0x1530)
+ {
+ return std::make_unique<Asr4>(opc, w0, w1);
+ }
+ /* ASR16 : 0001 0101 0111 F000 : A-36 */
+ else if ((w0 & 0xfff7) == 0x1570)
+ {
+ return std::make_unique<Asr16>(opc, w0, w1);
+ }
+ /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+ else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x1200))
+ {
+ return std::make_unique<BfInstruction>(opc, w0, w1);
+ }
+ /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+ else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x1200))
+ // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x1200))
+ {
+ return std::make_unique<BfInstruction_2>(opc, w0, w1);
+ }
+ /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+ else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x1200))
+ {
+ return std::make_unique<BfInstruction_3>(opc, w0, w1);
+ }
+ /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+ else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x0400))
+ {
+ return std::make_unique<BfInstruction>(opc, w0, w1);
+ }
+ /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+ else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x0400))
+ // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x0400))
+ {
+ return std::make_unique<BfInstruction_2>(opc, w0, w1);
+ }
+ /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+ else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x0400))
+ {
+ return std::make_unique<BfInstruction_3>(opc, w0, w1);
+ }
+ /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+ else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x1800))
+ {
+ return std::make_unique<BfInstruction>(opc, w0, w1);
+ }
+ /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+ else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x1800))
+ // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x1800))
+ {
+ return std::make_unique<BfInstruction_2>(opc, w0, w1);
+ }
+ /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+ else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x1800))
+ {
+ return std::make_unique<BfInstruction_3>(opc, w0, w1);
+ }
+ /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+ else if (((w0 & 0xffc0) == 0x1440) && ((w1 & 0x1f00) == 0x1000))
+ {
+ return std::make_unique<BfInstruction>(opc, w0, w1);
+ }
+ /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+ else if (((w0 & 0xfff0) == 0x1430) && ((w1 & 0x1f00) == 0x1000))
+ // NEW // else if (((w0 & 0xffe0) == 0x1420) && ((w1 & 0x1f00) == 0x1000))
+ {
+ return std::make_unique<BfInstruction_2>(opc, w0, w1);
+ }
+ /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+ else if (((w0 & 0xffe0) == 0x1400) && ((w1 & 0x1f00) == 0x1000))
+ {
+ return std::make_unique<BfInstruction_3>(opc, w0, w1);
+ }
+ /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+ else if (((w0 & 0xffc0) == 0x1440) && ((w1 & 0x1f00) == 0x0000))
+ {
+ return std::make_unique<BfInstruction>(opc, w0, w1);
+ }
+ /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+ else if (((w0 & 0xfff0) == 0x1430) && ((w1 & 0x1f00) == 0x0000))
+ // NEW // else if (((w0 & 0xffe0) == 0x1420) && ((w1 & 0x1f00) == 0x0000))
+ {
+ return std::make_unique<BfInstruction_2>(opc, w0, w1);
+ }
+ /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+ else if (((w0 & 0xffe0) == 0x1400) && ((w1 & 0x1f00) == 0x0000))
+ {
+ return std::make_unique<BfInstruction_3>(opc, w0, w1);
+ }
+ /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */
+ else if (((w0 & 0xff30) == 0x0730) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Bcc>(opc, w0, w1);
+ }
+ /* Bcc : 0010 11cc ccee eeee : A-48 */
+ else if ((w0 & 0xfc00) == 0x2c00)
+ {
+ return std::make_unique<Bcc_2>(opc, w0, w1);
+ }
+ /* Bcc : 0000 0111 RR10 cccc : A-48 */
+ else if ((w0 & 0xff30) == 0x0720)
+ {
+ return std::make_unique<Bcc_3>(opc, w0, w1);
+ }
+ /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */
+ else if (((w0 & 0xfffc) == 0x013c) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Bra>(opc, w0, w1);
+ }
+ /* BRA : 0000 1011 aaaa aaaa : A-50 */
+ else if ((w0 & 0xff00) == 0x0b00)
+ {
+ return std::make_unique<Bra_2>(opc, w0, w1);
+ }
+ /* BRA : 0000 0001 0010 11RR : A-50 */
+ else if ((w0 & 0xfffc) == 0x012c)
+ {
+ return std::make_unique<Bra_3>(opc, w0, w1);
+ }
+ /* BRKc : 0000 0001 0001 cccc : A-52 */
+ else if ((w0 & 0xfff0) == 0x0110)
+ {
+ return std::make_unique<Brkcc>(opc, w0, w1);
+ }
+ /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */
+ else if (((w0 & 0xff30) == 0x0710) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Bscc>(opc, w0, w1);
+ }
+ /* BScc : 0000 0111 RR00 cccc : A-54 */
+ else if ((w0 & 0xff30) == 0x0700)
+ {
+ return std::make_unique<Bscc_2>(opc, w0, w1);
+ }
+ /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */
+ else if (((w0 & 0xfffc) == 0x0138) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Bsr>(opc, w0, w1);
+ }
+ /* BSR : 0000 0001 0010 10RR : A-56 */
+ else if ((w0 & 0xfffc) == 0x0128)
+ {
+ return std::make_unique<Bsr_2>(opc, w0, w1);
+ }
+ /* CHKAAU : 0000 0000 0000 0100 : A-58 */
+ else if ((w0 & 0xffff) == 0x0004)
+ {
+ return std::make_unique<Chkaau>(opc, w0, w1);
+ }
+ /* DEBUG : 0000 0000 0000 0001 : A-68 */
+ else if ((w0 & 0xffff) == 0x0001)
+ {
+ return std::make_unique<Debug>(opc, w0, w1);
+ }
+ /* DEBUGcc : 0000 0000 0101 cccc : A-70 */
+ else if ((w0 & 0xfff0) == 0x0050)
+ {
+ return std::make_unique<Debugcc>(opc, w0, w1);
+ }
+ /* DIV : 0001 0101 0--0 F1DD : A-76 */
+ else if ((w0 & 0xfff4) == 0x1504)
+ // NEW // else if ((w0 & 0xff94) == 0x1504)
+ {
+ return std::make_unique<Div>(opc, w0, w1);
+ }
+ /* DMAC : 0001 0101 10s1 FsQQ : A-80 */
+ else if ((w0 & 0xffd0) == 0x1590)
+ {
+ return std::make_unique<Dmac>(opc, w0, w1);
+ }
+ /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */
+ else if (((w0 & 0xffe0) == 0x00c0) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return std::make_unique<Do>(opc, w0, w1);
+ }
+ /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */
+ else if (((w0 & 0xff00) == 0x0e00) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return std::make_unique<Do_2>(opc, w0, w1);
+ }
+ /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */
+ else if (((w0 & 0xffe0) == 0x0400) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return std::make_unique<Do_3>(opc, w0, w1);
+ }
+ /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */
+ else if (((w0 & 0xffff) == 0x0002) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return std::make_unique<DoForever>(opc, w0, w1);
+ }
+ /* ENDDO : 0000 0000 0000 1001 : A-92 */
+ else if ((w0 & 0xffff) == 0x0009)
+ {
+ return std::make_unique<Enddo>(opc, w0, w1);
+ }
+ /* EXT : 0001 0101 0101 F010 : A-96 */
+ else if ((w0 & 0xfff7) == 0x1552)
+ {
+ return std::make_unique<Ext>(opc, w0, w1);
+ }
+ /* ILLEGAL : 0000 0000 0000 1111 : A-98 */
+ else if ((w0 & 0xffff) == 0x000f)
+ {
+ return std::make_unique<Illegal>(opc, w0, w1);
+ }
+ /* IMAC : 0001 0101 1010 FQQQ : A-100 */
+ else if ((w0 & 0xfff0) == 0x15a0)
+ {
+ return std::make_unique<Imac>(opc, w0, w1);
+ }
+ /* IMPY : 0001 0101 1000 FQQQ : A-102 */
+ else if ((w0 & 0xfff0) == 0x1580)
+ {
+ return std::make_unique<Impy>(opc, w0, w1);
+ }
+ /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */
+ else if (((w0 & 0xff30) == 0x0630) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Jcc>(opc, w0, w1);
+ }
+ /* Jcc : 0000 0110 RR10 cccc : A-108 */
+ else if ((w0 & 0xff30) == 0x0620 )
+ {
+ return std::make_unique<Jcc_2>(opc, w0, w1);
+ }
+ /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */
+ else if (((w0 & 0xfffc) == 0x0134) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Jmp>(opc, w0, w1);
+ }
+ /* JMP : 0000 0001 0010 01RR : A-110 */
+ else if ((w0 & 0xfffc) == 0x0124)
+ {
+ //JMP2->m_oco = opc;
+ //JMP2->decode(w0, w1);
+ //return JMP2;
+ return std::make_unique<Jmp_2>(opc, w0, w1);
+ }
+ /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */
+ else if (((w0 & 0xff30) == 0x0610) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Jscc>(opc, w0, w1);
+ }
+ /* JScc : 0000 0110 RR00 cccc : A-112 */
+ else if ((w0 & 0xff30) == 0x0600)
+ {
+ return std::make_unique<Jscc_2>(opc, w0, w1);
+ }
+ /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */
+ else if (((w0 & 0xfffc) == 0x0130) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Jsr>(opc, w0, w1);
+ }
+ /* JSR : 0000 1010 AAAA AAAA : A-114 */
+ else if ((w0 & 0xff00) == 0x0a00)
+ {
+ return std::make_unique<Jsr_2>(opc, w0, w1);
+ }
+ /* JSR : 0000 0001 0010 00RR : A-114 */
+ else if ((w0 & 0xfffc) == 0x0120)
+ {
+ return std::make_unique<Jsr_3>(opc, w0, w1);
+ }
+ /* LEA : 0000 0001 11TT MMRR : A-116 */
+ else if ((w0 & 0xffc0) == 0x01c0)
+ {
+ return std::make_unique<Lea>(opc, w0, w1);
+ }
+ /* LEA : 0000 0001 10NN MMRR : A-116 */
+ else if ((w0 & 0xffc0) == 0x0180)
+ {
+ return std::make_unique<Lea_2>(opc, w0, w1);
+ }
+ /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */
+ else if ((w0 & 0xfff0) == 0x15e0)
+ {
+ return std::make_unique<Macsuuu>(opc, w0, w1);
+ }
+ /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */
+// NEW // else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0x00ff) == 0x0011))
+// NEW // {
+// NEW // return std::make_unique<Move_3>(opc, w0, w1);
+// NEW // }
+ /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */
+ else if ((w0 & 0xf810) == 0x3800)
+ {
+ return std::make_unique<Movec>(opc, w0, w1);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */
+ else if ((w0 & 0xf814) == 0x3810)
+ {
+ return std::make_unique<Movec_2>(opc, w0, w1);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */
+ else if ((w0 & 0xf816) == 0x3816)
+ {
+ return std::make_unique<Movec_3>(opc, w0, w1);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */
+ else if (((w0 & 0xf816) == 0x3814) && ((w1 & 0x0000) == 0x0000))
+ {
+ return std::make_unique<Movec_4>(opc, w0, w1);
+ }
+ /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */
+ else if ((w0 & 0xfc00) == 0x2800)
+ {
+ return std::make_unique<Movec_5>(opc, w0, w1);
+ }
+ /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */
+ else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0xf810) == 0x3800))
+ {
+ return std::make_unique<Movec_6>(opc, w0, w1);
+ }
+ /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */
+ else if ((w0 & 0xfc00) == 0x2000)
+ {
+ return std::make_unique<Movei>(opc, w0, w1);
+ }
+ /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */
+ else if ((w0 & 0xfe20) == 0x0200)
+ {
+ return std::make_unique<Movem>(opc, w0, w1);
+ }
+ /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */
+ else if ((w0 & 0xfe30) == 0x0230)
+ {
+ return std::make_unique<Movem_2>(opc, w0, w1);
+ }
+ /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */
+ else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0xfe20) == 0x0200))
+ {
+ return std::make_unique<Movem_3>(opc, w0, w1);
+ }
+ /* MOVE(P) : 0001 100W HH1p pppp : A-156 */
+ else if ((w0 & 0xfe20) == 0x1820)
+ {
+ return std::make_unique<Movep>(opc, w0, w1);
+ }
+ /* MOVE(P) : 0000 110W RRmp pppp : A-156 */
+ else if ((w0 & 0xfe00) == 0x0c00)
+ {
+ return std::make_unique<Movep_2>(opc, w0, w1);
+ }
+ /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */
+ else if ((w0 & 0xfe20) == 0x1800)
+ {
+ return std::make_unique<Moves>(opc, w0, w1);
+ }
+ /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */
+ else if ((w0 & 0xfff0) == 0x15c0)
+ {
+ return std::make_unique<Mpysuuu>(opc, w0, w1);
+ }
+ /* NEGC : 0001 0101 0110 F000 : A-168 */
+ else if ((w0 & 0xfff7) == 0x1560)
+ {
+ return std::make_unique<Negc>(opc, w0, w1);
+ }
+ /* NOP : 0000 0000 0000 0000 : A-170 */
+ else if ((w0 & 0xffff) == 0x0000)
+ {
+ return std::make_unique<Nop>(opc, w0, w1);
+ }
+ /* NORM : 0001 0101 0010 F0RR : A-172 */
+ else if ((w0 & 0xfff4) == 0x1520)
+ {
+ return std::make_unique<Norm>(opc, w0, w1);
+ }
+ /* ORI : 0001 1EE1 iiii iiii : A-178 */
+ else if ((w0 & 0xf900) == 0x1900)
+ {
+ return std::make_unique<Ori>(opc, w0, w1);
+ }
+ /* REP : 0000 0000 111- --RR : A-180 */
+ else if ((w0 & 0xffe0) == 0x00e0)
+ {
+ return std::make_unique<Rep>(opc, w0, w1);
+ }
+ /* REP : 0000 1111 iiii iiii : A-180 */
+ else if ((w0 & 0xff00) == 0x0f00)
+ {
+ return std::make_unique<Rep_2>(opc, w0, w1);
+ }
+ /* REP : 0000 0100 001D DDDD : A-180 */
+ else if ((w0 & 0xffe0) == 0x0420)
+ {
+ return std::make_unique<Rep_3>(opc, w0, w1);
+ }
+ /* REPcc : 0000 0001 0101 cccc : A-184 */
+ else if ((w0 & 0xfff0) == 0x0150)
+ {
+ return std::make_unique<Repcc>(opc, w0, w1);
+ }
+ /* RESET : 0000 0000 0000 1000 : A-186 */
+ else if ((w0 & 0xffff) == 0x0008)
+ {
+ return std::make_unique<Reset>(opc, w0, w1);
+ }
+ /* RTI : 0000 0000 0000 0111 : A-194 */
+ else if ((w0 & 0xffff) == 0x0007)
+ {
+ return std::make_unique<Rti>(opc, w0, w1);
+ }
+ /* RTS : 0000 0000 0000 0110 : A-196 */
+ else if ((w0 & 0xffff) == 0x0006)
+ {
+ return std::make_unique<Rts>(opc, w0, w1);
+ }
+ /* STOP : 0000 0000 0000 1010 : A-200 */
+ else if ((w0 & 0xffff) == 0x000a)
+ {
+ return std::make_unique<Stop>(opc, w0, w1);
+ }
+ /* SWAP : 0001 0101 0111 F001 : A-206 */
+ else if ((w0 & 0xfff7) == 0x1571)
+ {
+ return std::make_unique<Swap>(opc, w0, w1);
+ }
+ /* SWI : 0000 0000 0000 0101 : A-208 */
+ else if ((w0 & 0xffff) == 0x0005)
+ {
+ return std::make_unique<Swi>(opc, w0, w1);
+ }
+ /* Tcc : 0001 00cc ccTT Fh0h : A-210 */
+ else if ((w0 & 0xfc02) == 0x1000)
+ {
+ return std::make_unique<Tcc>(opc, w0, w1);
+ }
+ /* TFR(2) : 0001 0101 0000 F00J : A-214 */
+ else if ((w0 & 0xfff6) == 0x1500)
+ {
+ return std::make_unique<Tfr2>(opc, w0, w1);
+ }
+ /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */
+ else if ((w0 & 0xfc00) == 0x2400)
+ {
+ return std::make_unique<Tfr3>(opc, w0, w1);
+ }
+ /* TST(2) : 0001 0101 0001 -1DD : A-220 */
+ else if ((w0 & 0xfffc) == 0x1514)
+ // NEW // else if ((w0 & 0xfff4) == 0x1514)
+ {
+ return std::make_unique<Tst2>(opc, w0, w1);
+ }
+ /* WAIT : 0000 0000 0000 1011 : A-222 */
+ else if ((w0 & 0xffff) == 0x000b)
+ {
+ return std::make_unique<Wait>(opc, w0, w1);
+ }
+ /* ZERO : 0001 0101 0101 F000 : A-224 */
+ else if ((w0 & 0xfff7) == 0x1550)
+ {
+ return std::make_unique<Zero>(opc, w0, w1);
+ }
+ /* SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! */
+ else if ((w0 & 0xfff0) == 0x15d0)
+ {
+ return std::make_unique<Shfl>(opc, w0, w1);
+ }
+ /* SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! */
+ else if ((w0 & 0xfff0) == 0x15f0)
+ {
+ return std::make_unique<Shfr>(opc, w0, w1);
+ }
+
+ return nullptr;
+}
+
+}
diff --git a/src/devices/cpu/dsp56156/inst.h b/src/devices/cpu/dsp56156/inst.h
new file mode 100644
index 00000000000..c471b492ecf
--- /dev/null
+++ b/src/devices/cpu/dsp56156/inst.h
@@ -0,0 +1,3774 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#ifndef DSP56156_INSTRUCTION_H
+#define DSP56156_INSTRUCTION_H
+
+#include "opcode.h"
+#include "tables.h"
+
+#include "dsp56156.h"
+#include "dsp56def.h"
+#include "dsp56pcu.h"
+
+//
+// An Instruction is the base class all regular ops inherit from.
+//
+namespace DSP_56156
+{
+#define UNIMPLEMENTED_OPCODE() osd_printf_error("Unimplemented opcode: PC=%04x | %s;\n", PC, __PRETTY_FUNCTION__);
+
+class Opcode;
+
+class Instruction
+{
+public:
+ Instruction(const Opcode* oco) : m_valid(false),
+ m_oco(oco),
+ m_sizeIncrement(0),
+ m_source(iINVALID),
+ m_destination(iINVALID) { }
+ virtual ~Instruction() {}
+
+ virtual bool decode(const uint16_t word0, const uint16_t word1) = 0;
+ virtual void disassemble(std::string& retString) const = 0;
+ virtual void evaluate(dsp56156_core* cpustate) = 0;
+
+ virtual size_t size() const = 0;
+ virtual size_t evalSize() const { return size(); }
+ virtual size_t accumulatorBitsModified() const = 0; // Potentially make this always return ALL (like flags)
+ virtual size_t flags() const { return 0; }
+
+ static std::unique_ptr<Instruction> decodeInstruction(const Opcode* opc,
+ const uint16_t word0,
+ const uint16_t word1,
+ bool shifted=false);
+
+ bool valid() const { return m_valid; }
+
+ const reg_id& source() const { return m_source; }
+ const reg_id& destination() const { return m_destination; }
+
+ size_t sizeIncrement() const { return m_sizeIncrement; }
+
+protected:
+ bool m_valid;
+ const Opcode* m_oco;
+ size_t m_sizeIncrement;
+
+ // Parameters nearly everyone has
+ reg_id m_source;
+ reg_id m_destination;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// OPS ////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+// ABS : .... .... 0111 F001 : A-18 ////////////////////////////////////////////
+class Abs: public Instruction
+{
+public:
+ Abs(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "abs " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ADC : 0001 0101 0000 F01J : A-20 ////////////////////////////////////////////
+class Adc: public Instruction
+{
+public:
+ Adc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JF_table(BITSn(word0,0x0001), BITSn(word0,0x0008),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "adc " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ADD : .... .... 0000 FJJJ : A-22 ////////////////////////////////////////////
+class Add: public Instruction
+{
+public:
+ Add(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "add " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ??? Odd that i should put the 011m mKKK everywhere ??? TODO
+// ADD : 011m mKKK 0rru Fuuu : A-22 ////////////////////////////////////////////
+class Add_2: public Instruction
+{
+public:
+ Add_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_arg = "";
+ m_opcode = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_uuuuF_table(BITSn(word0,0x17), BITSn(word0,0x08),
+ m_opcode, m_source, m_destination);
+ // TODO: m_opcode = "add";
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = m_opcode + " " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ std::string m_opcode;
+ std::string m_arg; // TODO: get rid of this Add|Sub thing.
+};
+
+// AND : .... .... 0110 F1JJ : A-24 ////////////////////////////////////////////
+class And: public Instruction
+{
+public:
+ And(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "and " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// ANDI : 0001 1EE0 iiii iiii : A-26 ///////////////////////////////////////////
+class Andi: public Instruction
+{
+public:
+ Andi(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ decode_EE_table(BITSn(word0,0x0600), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "#$%x,%s", m_immediate, regIdAsString(m_destination).c_str());
+ retString = "andi " + std::string(temp);
+ // NEW // sprintf(opcode_str, "and(i)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint8_t m_immediate;
+};
+
+// ASL : .... .... 0011 F001 : A-28 ////////////////////////////////////////////
+class Asl: public Instruction
+{
+public:
+ Asl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "asl " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASL4 : 0001 0101 0011 F001 : A-30 ///////////////////////////////////////////
+class Asl4: public Instruction
+{
+public:
+ Asl4(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "asl4 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASR : .... .... 0011 F000 : A-32 ////////////////////////////////////////////
+class Asr: public Instruction
+{
+public:
+ Asr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "asr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASR4 : 0001 0101 0011 F000 : A-34 ///////////////////////////////////////////
+class Asr4: public Instruction
+{
+public:
+ Asr4(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "asr4 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASR16 : 0001 0101 0111 F000 : A-36 //////////////////////////////////////////
+class Asr16: public Instruction
+{
+public:
+ Asr16(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "asr16 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+/* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+class BfInstruction: public Instruction
+{
+public:
+ BfInstruction(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ dString = "";
+ m_opcode = "";
+ m_iVal = 0x0000;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* Decode the common parts */
+ m_iVal = BITSn(word1,0x00ff);
+
+ bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000));
+ switch(upperMiddleLower)
+ {
+ case BBB_UPPER: m_iVal <<= 8; break;
+ case BBB_MIDDLE: m_iVal <<= 4; break;
+ case BBB_LOWER: m_iVal <<= 0; break;
+
+ case BBB_INVALID: return false;
+ }
+
+ assemble_D_from_P_table(BITSn(word0,0x0020), BITSn(word0,0x001f), dString);
+
+ if (dString.compare("!!") == 0)
+ return false;
+
+ switch(BITSn(word1,0x1f00))
+ {
+ case 0x12: m_opcode = "bfchg"; break;
+ case 0x04: m_opcode = "bfclr"; break;
+ case 0x18: m_opcode = "bfset"; break;
+ case 0x10: m_opcode = "bftsth"; break;
+ case 0x00: m_opcode = "bftstl"; break;
+ }
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_iVal);
+ retString = m_opcode + " " + std::string(temp) + "," + dString;
+ // NEW // sprintf(temp, "#$%04x", iVal);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+private:
+ uint16_t m_iVal;
+ std::string m_opcode;
+ std::string dString;
+};
+
+/* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+class BfInstruction_2: public Instruction
+{
+public:
+ BfInstruction_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_opcode = "";
+ m_r = iINVALID;
+ m_iVal = 0x0000;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* Decode the common parts */
+ m_iVal = BITSn(word1,0x00ff);
+
+ bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000));
+ switch(upperMiddleLower)
+ {
+ case BBB_UPPER: m_iVal <<= 8; break;
+ case BBB_MIDDLE: m_iVal <<= 4; break;
+ case BBB_LOWER: m_iVal <<= 0; break;
+
+ case BBB_INVALID: return false;
+ }
+
+ decode_RR_table(BITSn(word0,0x0003), m_r);
+
+ if (m_r == iINVALID)
+ return false;
+
+ switch(BITSn(word1,0x1f00))
+ {
+ case 0x12: m_opcode = "bfchg"; break;
+ case 0x04: m_opcode = "bfclr"; break;
+ case 0x18: m_opcode = "bfset"; break;
+ case 0x10: m_opcode = "bftsth"; break;
+ case 0x00: m_opcode = "bftstl"; break;
+ }
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_iVal);
+ std::string source = temp;
+
+ sprintf(temp, "X:(%s)", regIdAsString(m_r).c_str());
+ std::string destination = temp;
+
+ retString = m_opcode + " " + source + "," + destination;
+ // NEW // sprintf(temp, "#$%04x", m_iVal);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_r;
+ uint16_t m_iVal;
+ std::string m_opcode;
+};
+
+/* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+class BfInstruction_3: public Instruction
+{
+public:
+ BfInstruction_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_opcode = "";
+ m_iVal = 0x0000;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* Decode the common parts */
+ m_iVal = BITSn(word1,0x00ff);
+
+ bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000));
+ switch(upperMiddleLower)
+ {
+ case BBB_UPPER: m_iVal <<= 8; break;
+ case BBB_MIDDLE: m_iVal <<= 4; break;
+ case BBB_LOWER: m_iVal <<= 0; break;
+
+ case BBB_INVALID: return false;
+ }
+
+ decode_DDDDD_table(BITSn(word0,0x001f), m_destination);
+
+ if (m_destination == iINVALID)
+ return false;
+
+ switch(BITSn(word1,0x1f00))
+ {
+ case 0x12: m_opcode = "bfchg"; break;
+ case 0x04: m_opcode = "bfclr"; break;
+ case 0x18: m_opcode = "bfset"; break;
+ case 0x10: m_opcode = "bftsth"; break;
+ case 0x00: m_opcode = "bftstl"; break;
+ }
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_iVal);
+ std::string source = temp;
+
+ retString = m_opcode + " " + source + "," + regIdAsString(m_destination);
+ // NEW // sprintf(temp, "#$%04x", m_iVal);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint16_t m_iVal;
+ std::string m_opcode;
+};
+
+// Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 ////////////////////////
+class Bcc: public Instruction
+{
+public:
+ Bcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = (int16_t)word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "b" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "b.%s", M);
+
+ char temp[32];
+ sprintf(temp, ">*+$%x", 2 + m_immediate);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (int16_t)word1, (int16_t)word1);
+ retString = opcode + " " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ int16_t m_immediate;
+};
+
+// Bcc : 0010 11cc ccee eeee : A-48 ////////////////////////////////////////////
+class Bcc_2: public Instruction
+{
+public:
+ Bcc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_cccc_table(BITSn(word0,0x3c0), m_mnem);
+ m_immediate = get_6_bit_signed_value(BITSn(word0,0x003f));
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "b" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "b.%s", M);
+
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, "<*+$%x", m_immediate + 1);
+ else sprintf(temp, "<*-$%x", 1 - m_immediate - 2);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 1 + relativeInt, relativeInt);
+
+ retString = opcode + " " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ int8_t m_immediate;
+};
+
+// Bcc : 0000 0111 RR10 cccc : A-48 ////////////////////////////////////////////
+class Bcc_3: public Instruction
+{
+public:
+ Bcc_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "b" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "b.%s", M);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 ////////////////////////
+class Bra: public Instruction
+{
+public:
+ Bra(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = (int16_t)word1;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, ">*+$%x", 2 + m_immediate);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + word1, (int16_t)word1);
+ retString = "bra " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int16_t m_immediate;
+};
+
+// BRA : 0000 1011 aaaa aaaa : A-50 ////////////////////////////////////////////
+class Bra_2: public Instruction
+{
+public:
+ Bra_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = (int8_t)BITSn(word0,0x00ff);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, "<*+$%x", 1 + m_immediate);
+ else sprintf(temp, "<*-$%x", 1 - m_immediate - 2);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 1 + iVal, iVal);
+ retString = "bra " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_immediate;
+};
+
+// BRA : 0000 0001 0010 11RR : A-50 ////////////////////////////////////////////
+class Bra_3: public Instruction
+{
+public:
+ Bra_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "bra " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// BRKcc : 0000 0001 0001 cccc : A-52 //////////////////////////////////////////
+class Brkcc: public Instruction
+{
+public:
+ Brkcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "brk" + opMnemonicAsString(m_mnem);
+ retString = opcode;
+ // NEW // sprintf(opcode_str, "brk.%s", M);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 ///////////////////////
+class Bscc: public Instruction
+{
+public:
+ Bscc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = (int16_t)word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "bs" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "bs.%s", M);
+
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, ">*+$%x", 2 + m_immediate);
+ else sprintf(temp, ">*-$%x", 1 - m_immediate - 1 - 2);
+ //sprintf(temp, ">*+$%x", 2 + m_immediate);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (int16_t)word1, (int16_t)word1);
+ retString = opcode + " " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+ int16_t m_immediate;
+};
+
+// BScc : 0000 0111 RR00 cccc : A-54 ///////////////////////////////////////////
+class Bscc_2: public Instruction
+{
+public:
+ Bscc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "bs" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "bs.%s", M);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 ////////////////////////
+class Bsr: public Instruction
+{
+public:
+ Bsr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = (int16_t)word1;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, ">*+$%x", 2 + m_immediate);
+ else sprintf(temp, ">*-$%x", 1 - m_immediate - 1 - 2);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (int16_t)word1, (int16_t)word1);
+ retString = "bsr " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+
+private:
+ int16_t m_immediate;
+};
+
+// BSR : 0000 0001 0010 10RR : A-56 ////////////////////////////////////////////
+class Bsr_2: public Instruction
+{
+public:
+ Bsr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "bsr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+};
+
+// CHKAAU : 0000 0000 0000 0100 : A-58 /////////////////////////////////////////
+class Chkaau: public Instruction
+{
+public:
+ Chkaau(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "chkaau";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// CLR : .... .... 0000 F001 : A-60 ////////////////////////////////////////////
+class Clr: public Instruction
+{
+public:
+ Clr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "clr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// CLR24 : .... .... 0101 F001 : A-62 //////////////////////////////////////////
+class Clr24: public Instruction
+{
+public:
+ Clr24(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "clr24 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// CMP : .... .... 0101 FJJJ : A-64 ////////////////////////////////////////////
+class Cmp: public Instruction
+{
+public:
+ Cmp(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* Note: This is a JJJF limited in the docs, but other opcodes sneak
+ in before cmp, so the same decode function can be used. */
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "cmp " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_NONE; }
+};
+
+// CMPM : .... .... 0111 FJJJ : A-66 ///////////////////////////////////////////
+class Cmpm: public Instruction
+{
+public:
+ Cmpm(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* Note: This is a JJJF limited in the docs, but other opcodes sneak
+ in before cmp, so the same decode function can be used. */
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "cmpm " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_NONE; }
+};
+
+// DEBUG : 0000 0000 0000 0001 : A-68 //////////////////////////////////////////
+class Debug: public Instruction
+{
+public:
+ Debug(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "debug";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// DEBUGcc : 0000 0000 0101 cccc : A-70 ////////////////////////////////////////
+class Debugcc: public Instruction
+{
+public:
+ Debugcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "debug" + opMnemonicAsString(m_mnem);
+ retString = opcode;
+ // NEW // sprintf(opcode_str, "debug.%s", M);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// DEC : .... .... 0110 F010 : A-72 ////////////////////////////////////////////
+class Dec: public Instruction
+{
+public:
+ Dec(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "dec " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// DEC24 : .... .... 0110 F011 : A-74 //////////////////////////////////////////
+class Dec24: public Instruction
+{
+public:
+ Dec24(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "dec24 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// DIV : 0001 0101 0--0 F1DD : A-76 ////////////////////////////////////////////
+class Div: public Instruction
+{
+public:
+ Div(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_DDF_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "div " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// DMAC : 0001 0101 10s1 FsQQ : A-80 ///////////////////////////////////////////
+class Dmac: public Instruction
+{
+public:
+ Dmac(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ decode_ss_table(BITSn(word0,0x0024), m_mnem);
+ if (m_mnem == oINVALID) return false;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "dmac" + opMnemonicAsString(m_mnem);
+
+ retString = opcode + " " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "dmac(%s)", A);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_source2;
+};
+
+// DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 /////////////////////////
+class Do: public Instruction
+{
+public:
+ Do(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = word1;
+ decode_RR_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "*+$%x", 2 + m_immediate);
+ std::string destination = temp;
+ // NEW // sprintf(temp, "X:(R%d),$%02x", Rnum, pc + 2 + word1);
+
+ sprintf(temp, "X:(%s)", regIdAsString(m_source).c_str());
+ std::string source = temp;
+
+ retString = "do " + source + "," + destination;
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint16_t m_immediate;
+};
+
+// DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 /////////////////////////
+class Do_2: public Instruction
+{
+public:
+ Do_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "#<$%x,*+$%x", m_immediate, 2 + m_displacement);
+ // NEW // sprintf(temp, "#$%02x,$%04x", BITSn(word0,0x00ff), pc + 2 + word1);
+ retString = "do " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint8_t m_immediate;
+ uint16_t m_displacement;
+};
+
+// DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 /////////////////////////
+class Do_3: public Instruction
+{
+public:
+ Do_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_displacement = word1;
+
+ decode_DDDDD_table(BITSn(word0,0x001f), m_source);
+ if (m_source == iSSH) return false;
+ if (m_source == iINVALID) return false;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "*+$%x", 2 + m_displacement);
+ // NEW // sprintf(temp, "%s,$%04x", S1, pc + 2 + word1);
+ retString = "do " + regIdAsString(m_source) + "," + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint16_t m_displacement;
+};
+
+// DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 /////////////////
+class DoForever: public Instruction
+{
+public:
+ DoForever(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "*+$%x", m_displacement + 2);
+ // NEW // sprintf(temp, "*+$%x", pc + word1);
+ // NEW // sprintf(temp, "$%04x", pc + 2 + word1);
+ retString = "do forever, " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint16_t m_displacement;
+};
+
+// ENDDO : 0000 0000 0000 1001 : A-92 //////////////////////////////////////////
+class Enddo: public Instruction
+{
+public:
+ Enddo(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "enddo";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// EOR : .... .... 0011 F1JJ : A-94 ////////////////////////////////////////////
+class Eor: public Instruction
+{
+public:
+ Eor(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "eor " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// EXT : 0001 0101 0101 F010 : A-96 ////////////////////////////////////////////
+class Ext: public Instruction
+{
+public:
+ Ext(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "ext " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ILLEGAL : 0000 0000 0000 1111 : A-98 ////////////////////////////////////////
+class Illegal: public Instruction
+{
+public:
+ Illegal(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "illegal";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// IMAC : 0001 0101 1010 FQQQ : A-100 //////////////////////////////////////////
+class Imac: public Instruction
+{
+public:
+ Imac(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "imac " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// IMPY : 0001 0101 1000 FQQQ : A-102 //////////////////////////////////////////
+class Impy: public Instruction
+{
+public:
+ Impy(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "impy " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// INC : .... .... 0010 F010 : A-104 ///////////////////////////////////////////
+class Inc: public Instruction
+{
+public:
+ Inc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "inc " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// INC24 : .... .... 0010 F011 : A-106 /////////////////////////////////////////
+class Inc24: public Instruction
+{
+public:
+ Inc24(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "inc24 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 ///////////////////////
+class Jcc: public Instruction
+{
+public:
+ Jcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_displacement = word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "j" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "j.%s", M);
+
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = opcode + " " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ uint16_t m_displacement;
+};
+
+// Jcc : 0000 0110 RR10 cccc : A-108 ///////////////////////////////////////////
+class Jcc_2: public Instruction
+{
+public:
+ Jcc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "j" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "j.%s", M);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 ///////////////////////
+class Jmp: public Instruction
+{
+public:
+ Jmp(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = "jmp " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override
+ {
+ PC = m_displacement;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ }
+ size_t size() const override { return 2; }
+ size_t evalSize() const override { return 0; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint16_t m_displacement;
+};
+
+// JMP : 0000 0001 0010 01RR : A-110 ///////////////////////////////////////////
+class Jmp_2: public Instruction
+{
+public:
+ Jmp_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "jmp " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override
+ {
+ PC = regValue16(cpustate, m_destination);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ }
+ size_t size() const override { return 1; }
+ size_t evalSize() const override { return 0; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+//static Jmp_2* JMP2 = new Jmp_2(nullptr, 0x0000, 0x0000);
+
+// JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 //////////////////////
+class Jscc: public Instruction
+{
+public:
+ Jscc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_displacement = word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "js" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "js.%s", M);
+
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = opcode + " " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+ uint16_t m_displacement;
+};
+
+// JScc : 0000 0110 RR00 cccc : A-112 //////////////////////////////////////////
+class Jscc_2: public Instruction
+{
+public:
+ Jscc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "js" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "js.%s", M);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 ///////////////////////
+class Jsr: public Instruction
+{
+public:
+ Jsr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = "jsr " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+
+private:
+ uint16_t m_displacement;
+};
+
+// JSR : 0000 1010 AAAA AAAA : A-114 ///////////////////////////////////////////
+class Jsr_2: public Instruction
+{
+public:
+ Jsr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_bAddr = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_bAddr = BITSn(word0,0x00ff);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "<$%x", m_bAddr);
+ // NEW // sprintf(temp, "#$%02x", BITSn(word0,0x00ff));
+ retString = "jsr " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+
+private:
+ uint8_t m_bAddr;
+};
+
+// JSR : 0000 0001 0010 00RR : A-114 ///////////////////////////////////////////
+class Jsr_3: public Instruction
+{
+public:
+ Jsr_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "jsr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OVER; }
+};
+
+// LEA : 0000 0001 11TT MMRR : A-116 ///////////////////////////////////////////
+class Lea: public Instruction
+{
+public:
+ Lea(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_ea = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ if ((word0 & 0x000c) == 0) return false; // NEW TODO //
+
+ decode_TT_table(BITSn(word0,0x0030), m_destination);
+
+ int8_t rNum = BITSn(word0,0x0003);
+ assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea);
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ // HACK
+ retString = "lea " + m_ea + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ std::string m_ea;
+};
+
+// LEA : 0000 0001 10NN MMRR : A-116 ///////////////////////////////////////////
+class Lea_2: public Instruction
+{
+public:
+ Lea_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ if ((word0 & 0x000c) == 0) return false; // NEW TODO //
+
+ decode_NN_table(BITSn(word0,0x0030), m_destination);
+
+ int8_t rNum = BITSn(word0,0x0003);
+ assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea);
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ // HACK
+ retString = "lea " + m_ea + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ std::string m_ea;
+};
+
+// LSL : .... .... 0011 F011 : A-118 ///////////////////////////////////////////
+class Lsl: public Instruction
+{
+public:
+ Lsl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "lsl " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// LSR : .... .... 0011 F010 : A-120 ///////////////////////////////////////////
+class Lsr: public Instruction
+{
+public:
+ Lsr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "lsr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// MAC : .... .... 1k10 FQQQ : A-122 ///////////////////////////////////////////
+class Mac: public Instruction
+{
+public:
+ Mac(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_sign = "";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string ts = m_sign;
+ if (ts.compare("-") != 0) ts = "";
+ retString = "mac " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+ std::string m_sign;
+};
+
+// MAC : 011m mKKK 1xx0 F1QQ : A-122 ///////////////////////////////////////////
+class Mac_2: public Instruction
+{
+public:
+ Mac_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "mac " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MAC : 0001 0111 RRDD FQQQ : A-122 ///////////////////////////////////////////
+class Mac_3: public Instruction
+{
+public:
+ Mac_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "mac " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MACR : .... .... 1k11 FQQQ : A-124 //////////////////////////////////////////
+class Macr: public Instruction
+{
+public:
+ Macr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_sign = "";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string ts = m_sign;
+ if (ts.compare("-") != 0) ts = "";
+ retString = "macr " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ std::string m_sign;
+ reg_id m_source2;
+};
+
+// MACR : 011m mKKK 1--1 F1QQ : A-124 //////////////////////////////////////////
+class Macr_2: public Instruction
+{
+public:
+ Macr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "macr " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 ////////////////////////////////////
+class Macsuuu: public Instruction
+{
+public:
+ Macsuuu(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ // Special QQF
+ decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ decode_s_table(BITSn(word0,0x0004), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "mac" + opMnemonicAsString(m_mnem);
+
+ retString = opcode + " " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "mac(%s)", A);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_source2;
+};
+
+// MOVE : .... .... 0001 0001 : A-128 //////////////////////////////////////////
+class Move: public Instruction
+{
+public:
+ Move(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_isNop = false;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ // Equivalent to a NOP (+ parallel move)
+
+ // This insures the debugger matches the reference disassembler
+ // for the undocumented .... .... 0001 1001 Instruction.
+ if(BITSn(word0, 0x000f) == 0x0001)
+ m_destination = iA;
+ else
+ m_destination = iB;
+
+ // Hack to match reference disassembler
+ uint8_t BITSn = (word0 & 0xff00) >> 8;
+ if (BITSn == 0x4a || BITSn == 0x4b)
+ m_isNop = true;
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ if (m_isNop)
+ retString = "nop";
+ else
+ retString = "move";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_NONE; }
+
+private:
+ bool m_isNop;
+};
+
+// MOVE : 011m mKKK 0rr1 0000 : A-128 //////////////////////////////////////////
+class Move_2: public Instruction
+{
+public:
+ Move_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ // Amounts to a nop with two parallel moves.
+ // This insures the debugger matches the reference disassembler
+ if((word0 & 0x0008) == 0x0008)
+ m_destination = iB;
+ else
+ m_destination = iA;
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "move";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 //////////////////////
+class Move_3: public Instruction
+{
+public:
+ Move_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_b = 0;
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_b = BITSn(word0,0x00ff);
+ m_W = BITSn(word1,0x0100);
+ decode_HHH_table(BITSn(word1,0x0e00), m_SD);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_reg_from_W_table(m_W, 'X', m_SD, m_b, source, destination);
+ retString = "move " + source + "," + destination;
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_b;
+ uint8_t m_W;
+ reg_id m_SD;
+};
+
+// MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 ///////////////////////////////////////
+class Movec: public Instruction
+{
+public:
+ Movec(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ int8_t rNum = BITSn(word0,0x0003);
+ assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea);
+
+ m_W = BITSn(word0,0x0400);
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_SD);
+ if (m_SD == iINVALID) return false;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ reg_id m_SD;
+ std::string m_ea;
+};
+
+// MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 ///////////////////////////////////////
+class Movec_2: public Instruction
+{
+public:
+ Movec_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ int8_t rNum = BITSn(word0,0x0003);
+ assemble_ea_from_q_table(BITSn(word0,0x0008), rNum, m_ea);
+
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_SD);
+ m_W = BITSn(word0,0x0400);
+ if (m_SD == iINVALID) return false;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ reg_id m_SD;
+ std::string m_ea;
+};
+
+// MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 ///////////////////////////////////////
+class Movec_3: public Instruction
+{
+public:
+ Movec_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_Z_table(BITSn(word0,0x0008), m_ea);
+
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_SD);
+ m_W = BITSn(word0,0x0400);
+ if (m_SD == iINVALID) return false;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ reg_id m_SD;
+ std::string m_ea;
+};
+
+// MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 ///////////////////
+class Movec_4: public Instruction
+{
+public:
+ Movec_4(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_t = 0;
+ m_W = 0;
+ m_sd = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_value = word1;
+ m_t = BITSn(word0,0x0008);
+ m_W = BITSn(word0,0x0400);
+
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_sd);
+ if (m_sd == iINVALID) return false;
+
+ // TODO: Figure out what this means, exactly.
+ if ((word0 & 0x000c) == 0x000c && (word0 & 0x0400) == 0x0000)
+ return false;
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string ea;
+ assemble_ea_from_t_table(m_t, m_value, ea);
+
+ retString = "move ";
+ if (m_W) retString += ea + "," + regIdAsString(m_sd);
+ else retString += regIdAsString(m_sd) + "," + ea;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56156_core* cpustate) override
+ {
+ if (m_W)
+ {
+ if (m_t)
+ {
+ setReg16(cpustate, m_value, m_sd);
+ }
+ else
+ {
+ //uint16_t memValue = memory_read_word_16le(cpustate->data, ADDRESS(m_value));
+ //setReg16(cpustate, memValue, m_sd);
+ }
+ }
+ else
+ {
+ if (m_t)
+ {
+ osd_printf_error("DSP561xx|Movec_4: This sure seems like it can't happen.");
+ }
+ else
+ {
+ //uint16_t regValue = regValue16(cpustate, m_sd);
+ //memory_write_word_16le(cpustate->data, m_value, regValue);
+ }
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ // All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ // bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ // limiting occurred. All ? bits are not affected otherwise.
+ }
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint8_t m_t;
+ uint8_t m_W;
+ uint16_t m_value;
+ reg_id m_sd;
+};
+
+// MOVE(C) : 0010 10dd dddD DDDD : A-144 ///////////////////////////////////////
+class Movec_5: public Instruction
+{
+public:
+ Movec_5(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_source);
+ decode_DDDDD_table(BITSn(word0,0x001f), m_destination);
+
+ if (m_source == iINVALID || m_destination == iINVALID) return false;
+ if (m_source == iSSH && m_destination == iSSH) return false;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "move " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 ///////////////////
+class Movec_6: public Instruction
+{
+public:
+ Movec_6(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_b = 0;
+ m_SD = iINVALID;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_b = BITSn(word0,0x00ff);
+ m_W = BITSn(word1,0x0400);
+ decode_DDDDD_table(BITSn(word1,0x03e0), m_SD);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_reg_from_W_table(m_W, 'X', m_SD, m_b, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // opcode = "move(c)";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_b;
+ uint8_t m_W;
+ reg_id m_SD;
+ op_mnem m_mnem;
+};
+
+// MOVE(I) : 0010 00DD BBBB BBBB : A-150 ///////////////////////////////////////
+class Movei: public Instruction
+{
+public:
+ Movei(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = (int8_t)BITSn(word0,0x00ff);
+ decode_DD_table(BITSn(word0,0x0300), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, "#<+$%x", m_immediate);
+ else sprintf(temp, "#<-$%x", 1 - m_immediate - 1);
+ // NEW // sprintf(temp, "#$%02x,%s", BITSn(word0,0x00ff), D1);
+
+ retString = "move " +
+ std::string(temp) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "move(i)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_immediate;
+};
+
+// MOVE(M) : 0000 001W RR0M MHHH : A-152 ///////////////////////////////////////
+class Movem: public Instruction
+{
+public:
+ Movem(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ int8_t rNum = BITSn(word0,0x00c0);
+
+ decode_HHH_table(BITSn(word0,0x0007), m_SD);
+ assemble_ea_from_MM_table(BITSn(word0,0x0018), rNum, m_ea);
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_arguments_from_W_table(m_W, 'P', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(m)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ reg_id m_SD;
+ std::string m_ea;
+};
+
+// MOVE(M) : 0000 001W RR11 mmRR : A-152 ///////////////////////////////////////
+class Movem_2: public Instruction
+{
+public:
+ Movem_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_ea2 = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_W = BITSn(word0,0x0100);
+ assemble_eas_from_mm_table(BITSn(word0,0x000c), BITSn(word0,0x00c0), BITSn(word0,0x0003), m_ea, m_ea2);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ if (m_W)
+ {
+ source = "X:" + m_ea;
+ destination = "P:" + m_ea2;
+ }
+ else
+ {
+ source = "P:" + m_ea;
+ destination = "X:" + m_ea2;
+ }
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(m)*");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint8_t m_W;
+ std::string m_ea;
+ std::string m_ea2;
+};
+
+// MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 ///////////////////
+class Movem_3: public Instruction
+{
+public:
+ Movem_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_b = 0;
+ m_SD = iINVALID;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_b = BITSn(word0,0x00ff);
+ m_W = BITSn(word1,0x0100);
+ decode_HHH_table(BITSn(word1,0x0007), m_SD);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_reg_from_W_table(m_W, 'P', m_SD, m_b, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // opcode = "move(m)";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 2; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_b;
+ uint8_t m_W;
+ reg_id m_SD;
+ op_mnem m_mnem;
+};
+
+// MOVE(P) : 0001 100W HH1p pppp : A-156 ///////////////////////////////////////
+class Movep: public Instruction
+{
+public:
+ Movep(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_HH_table(BITSn(word0,0x00c0), m_SD);
+
+ assemble_address_from_IO_short_address(BITSn(word0,0x001f), m_ea);
+ m_ea = "<<$" + m_ea;
+
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "movep " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(p)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ reg_id m_SD;
+ std::string m_ea;
+};
+
+// MOVE(P) : 0000 110W RRmp pppp : A-156 ///////////////////////////////////////
+class Movep_2: public Instruction
+{
+public:
+ Movep_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ int8_t rNum = BITSn(word0,0x00c0);
+
+ assemble_ea_from_m_table(BITSn(word0,0x0020), rNum, m_ea);
+
+ std::string fullAddy; /* Convert Short Absolute Address to full 16-bit */
+ assemble_address_from_IO_short_address(BITSn(word0,0x001f), fullAddy);
+
+ m_W = BITSn(word0,0x0100);
+ m_SD = "X:<<$" + fullAddy;
+ // NEW // sprintf(SD, "X:$%s", fullAddy);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "movep " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(p)*");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ std::string m_SD;
+ std::string m_ea;
+};
+
+// MOVE(S) : 0001 100W HH0a aaaa : A-158 ///////////////////////////////////////
+class Moves: public Instruction
+{
+public:
+ Moves(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_HH_table(BITSn(word0,0x00c0), m_SD);
+
+ char temp[32];
+ sprintf(temp, "<$%x", BITSn(word0,0x001f));
+ m_ea = temp;
+
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source;
+ std::string destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "moves " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(s)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ reg_id m_SD;
+ std::string m_ea;
+};
+
+// MPY : .... .... 1k00 FQQQ : A-160 ///////////////////////////////////////////
+class Mpy: public Instruction
+{
+public:
+ Mpy(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_sign = "";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* There are inconsistencies with the S1 & S2 operand ordering in the docs,
+ but since it's a multiply it doesn't matter */
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string ts = m_sign;
+ if (ts.compare("-")!=0) ts = "";
+ retString = "mpy " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ std::string m_sign;
+ reg_id m_source2;
+};
+
+// MPY : 011m mKKK 1xx0 F0QQ : A-160 ///////////////////////////////////////////
+class Mpy_2: public Instruction
+{
+public:
+ Mpy_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "mpy " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MPY : 0001 0110 RRDD FQQQ : A-160 ///////////////////////////////////////////
+class Mpy_3: public Instruction
+{
+public:
+ Mpy_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "mpy " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MPYR : .... .... 1k01 FQQQ : A-162 //////////////////////////////////////////
+class Mpyr: public Instruction
+{
+public:
+ Mpyr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_sign = "-";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* There are inconsistencies with the S1 & S2 operand ordering in the docs,
+ but since it's a multiply it doesn't matter */
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string ts = m_sign;
+ if (ts.compare("-") != 0) ts = "";
+ retString = "mpyr " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ std::string m_sign;
+ reg_id m_source2;
+};
+
+// MPYR : 011m mKKK 1--1 F0QQ : A-162 //////////////////////////////////////////
+class Mpyr_2: public Instruction
+{
+public:
+ Mpyr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "mpyr " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 ////////////////////////////////////
+class Mpysuuu: public Instruction
+{
+public:
+ Mpysuuu(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ decode_s_table(BITSn(word0,0x0004), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "mpy" + opMnemonicAsString(m_mnem);
+
+ retString = opcode + " " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "mpy(%s)", A);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_source2;
+};
+
+// NEG : .... .... 0110 F000 : A-166 ///////////////////////////////////////////
+class Neg: public Instruction
+{
+public:
+ Neg(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "neg " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NEGC : 0001 0101 0110 F000 : A-168 //////////////////////////////////////////
+class Negc: public Instruction
+{
+public:
+ Negc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "negc " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NOP : 0000 0000 0000 0000 : A-170 ///////////////////////////////////////////
+class Nop: public Instruction
+{
+public:
+ Nop(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "nop";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NORM : 0001 0101 0010 F0RR : A-172 //////////////////////////////////////////
+class Norm: public Instruction
+{
+public:
+ Norm(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+
+ decode_RR_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "norm " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NOT : .... .... 0110 F001 : A-174 ///////////////////////////////////////////
+class Not: public Instruction
+{
+public:
+ Not(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "not " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// OR : .... .... 0010 F1JJ : A-176 ////////////////////////////////////////////
+class Or: public Instruction
+{
+public:
+ Or(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "or " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// ORI : 0001 1EE1 iiii iiii : A-178 ///////////////////////////////////////////
+class Ori: public Instruction
+{
+public:
+ Ori(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ decode_EE_table(BITSn(word0,0x0600), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_immediate);
+ // NEW // sprintf(temp, "#$%02x", BITSn(word0,0x00ff));
+ retString = "ori " + std::string(temp) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "or(i)");
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint8_t m_immediate;
+};
+
+// REP : 0000 0000 111- --RR : A-180 ///////////////////////////////////////////
+class Rep: public Instruction
+{
+public:
+ Rep(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "X:(%s)", regIdAsString(m_source).c_str());
+ retString = "rep " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// REP : 0000 1111 iiii iiii : A-180 ///////////////////////////////////////////
+class Rep_2: public Instruction
+{
+public:
+ Rep_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_immediate);
+ // NEW // sprintf(temp, "#$%02x (%d)", BITSn(word0,0x00ff), BITSn(word0,0x00ff));
+ retString = "rep " + std::string(temp);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ uint8_t m_immediate;
+};
+
+// REP : 0000 0100 001D DDDD : A-180 ///////////////////////////////////////////
+class Rep_3: public Instruction
+{
+public:
+ Rep_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_DDDDD_table(BITSn(word0,0x001f), m_source);
+ if (m_source == iINVALID) return false;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "rep " + regIdAsString(m_source);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// REPcc : 0000 0001 0101 cccc : A-184 /////////////////////////////////////////
+class Repcc: public Instruction
+{
+public:
+ Repcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "rep" + opMnemonicAsString(m_mnem);
+ retString = opcode;
+ // NEW // sprintf(opcode_str, "rep.%s", M);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// RESET : 0000 0000 0000 1000 : A-186 /////////////////////////////////////////
+class Reset: public Instruction
+{
+public:
+ Reset(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "reset";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// RND : .... .... 0010 F000 : A-188 ///////////////////////////////////////////
+class Rnd: public Instruction
+{
+public:
+ Rnd(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "rnd " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ROL : .... .... 0111 F011 : A-190 ///////////////////////////////////////////
+class Rol: public Instruction
+{
+public:
+ Rol(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "rol " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// ROR : .... .... 0111 F010 : A-192 ///////////////////////////////////////////
+class Ror: public Instruction
+{
+public:
+ Ror(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "ror " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; }
+};
+
+// RTI : 0000 0000 0000 0111 : A-194 ///////////////////////////////////////////
+class Rti: public Instruction
+{
+public:
+ Rti(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "rti";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OUT; }
+};
+
+// RTS : 0000 0000 0000 0110 : A-196 ///////////////////////////////////////////
+class Rts: public Instruction
+{
+public:
+ Rts(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "rts";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const override { return util::disasm_interface::STEP_OUT; }
+};
+
+// SBC : .... .... 0101 F01J : A-198 ///////////////////////////////////////////
+class Sbc: public Instruction
+{
+public:
+ Sbc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JF_table(BITSn(word0,0x01), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "sbc " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// STOP : 0000 0000 0000 1010 : A-200 //////////////////////////////////////////
+class Stop: public Instruction
+{
+public:
+ Stop(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "stop";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SUB : .... .... 0100 FJJJ : A-202 ///////////////////////////////////////////
+class Sub: public Instruction
+{
+public:
+ Sub(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "sub " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SUB : 011m mKKK 0rru Fuuu : A-202 ///////////////////////////////////////////
+class Sub_2: public Instruction
+{
+public:
+ Sub_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_opcode = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_uuuuF_table(BITSn(word0,0x17), BITSn(word0,0x08),
+ m_opcode, m_source, m_destination);
+
+ // TODO // m_opcode = "sub";
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = m_opcode + " " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ std::string m_opcode;
+};
+
+// SUBL : .... .... 0100 F001 : A-204 //////////////////////////////////////////
+class Subl: public Instruction
+{
+public:
+ Subl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ /* There is only one option for the F table. This is a very strange opcode. */
+ if (!BITSn(word0,0x0008))
+ {
+ m_source = iB;
+ m_destination = iA;
+ }
+ else
+ {
+ m_source = iA;
+ m_destination = iB;
+ }
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "subl " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SWAP : 0001 0101 0111 F001 : A-206 //////////////////////////////////////////
+class Swap: public Instruction
+{
+public:
+ Swap(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "swap " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SWI : 0000 0000 0000 0101 : A-208 ///////////////////////////////////////////
+class Swi: public Instruction
+{
+public:
+ Swi(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "swi";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// Tcc : 0001 00cc ccTT Fh0h : A-210 ///////////////////////////////////////////
+class Tcc: public Instruction
+{
+public:
+ Tcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_destination2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_h0hF_table(BITSn(word0,0x0007),BITSn(word0,0x0008),
+ m_source, m_destination);
+
+ decode_RR_table(BITSn(word0,0x0030), m_destination2);
+
+ decode_cccc_table(BITSn(word0,0x03c0), m_mnem);
+ if (m_source != m_destination)
+ return true;
+ if (m_destination2 != iR0)
+ return true;
+
+ return false;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string opcode = "t" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "t.%s", M);
+
+ retString = opcode;
+ if (m_source != m_destination)
+ retString += std::string(" ") + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+
+ if (m_destination2 != iR0)
+ retString += std::string(" R0,") + regIdAsString(m_destination2);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_destination2;
+};
+
+// TFR : .... .... 0001 FJJJ : A-212 ///////////////////////////////////////////
+class Tfr: public Instruction
+{
+public:
+ Tfr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "tfr " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// TFR : 011m mKKK 0rr1 F0DD : A-212 ///////////////////////////////////////////
+class Tfr_2: public Instruction
+{
+public:
+ Tfr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_DDF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "tfr " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// TFR(2) : 0001 0101 0000 F00J : A-214 ////////////////////////////////////////
+class Tfr2: public Instruction
+{
+public:
+ Tfr2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_JF_table(BITSn(word0,0x0001),BITSn(word0,0x0008),
+ m_destination, m_source);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "tfr2 " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// TFR(3) : 0010 01mW RRDD FHHH : A-216 ////////////////////////////////////////
+class Tfr3: public Instruction
+{
+public:
+ Tfr3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_source2 = iINVALID;
+ m_destination2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_DDF_table(BITSn(word0,0x0030), BITSn(word0,0x0008),
+ m_destination, m_source);
+
+ decode_HHH_table(BITSn(word0,0x0007), m_SD);
+ // If the destination of the second move is the same as the first, you're invalid
+ if (m_SD == m_destination && BITSn(word0,0x0100)) return false;
+
+ int8_t rNum = BITSn(word0,0x00c0);
+ assemble_ea_from_m_table(BITSn(word0,0x0200), rNum, m_ea);
+
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ std::string source2;
+ std::string destination2;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source2, destination2);
+ retString = "tfr3 " +
+ regIdAsString(m_source) + "," + regIdAsString(m_destination) + " " +
+ source2 + "," + destination2;
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ int8_t m_W;
+ reg_id m_SD;
+ std::string m_ea;
+ reg_id m_source2;
+ reg_id m_destination2;
+};
+
+// TST : .... .... 0010 F001 : A-218 ///////////////////////////////////////////
+class Tst: public Instruction
+{
+public:
+ Tst(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "tst " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_NONE; }
+};
+
+// TST(2) : 0001 0101 0001 -1DD : A-220 ////////////////////////////////////////
+class Tst2: public Instruction
+{
+public:
+ Tst2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_DD_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "tst2 " + regIdAsString(m_source);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// WAIT : 0000 0000 0000 1011 : A-222 //////////////////////////////////////////
+class Wait: public Instruction
+{
+public:
+ Wait(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "wait";
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ZERO : 0001 0101 0101 F000 : A-224 //////////////////////////////////////////
+class Zero: public Instruction
+{
+public:
+ Zero(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "zero " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! ///////////////////////////////
+class Shfl: public Instruction
+{
+public:
+ Shfl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ // This hackery amounts to a very strange QQQF table...
+ if (m_source == iX0 && m_source2 == iX0) return false;
+ if (m_source == iX1 && m_source2 == iX0) return false;
+
+ if (m_source == iY0 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY0;
+ }
+ if (m_source == iY1 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY1;
+ }
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "shfl " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! ///////////////////////////////
+class Shfr: public Instruction
+{
+public:
+ Shfr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ // This hackery amounts to a very strange QQQF table...
+ if (m_source == iX0 && m_source2 == iX0) return false;
+ if (m_source == iX1 && m_source2 == iX0) return false;
+
+ if (m_source == iY0 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY0;
+ }
+ if (m_source == iY1 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY1;
+ }
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = "shfr " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56156_core* cpustate) override {}
+ size_t size() const override { return 1; }
+ size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+}
+#endif
diff --git a/src/devices/cpu/dsp56156/opcode.cpp b/src/devices/cpu/dsp56156/opcode.cpp
new file mode 100644
index 00000000000..15b305fa09e
--- /dev/null
+++ b/src/devices/cpu/dsp56156/opcode.cpp
@@ -0,0 +1,81 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#include "emu.h"
+#include <stdio.h>
+
+#include "opcode.h"
+
+namespace DSP_56156
+{
+Opcode::Opcode(uint16_t w0, uint16_t w1) : m_word0(w0)/*, m_word1(w1)*/
+{
+ m_instruction = Instruction::decodeInstruction(this, w0, w1);
+ m_parallelMove = ParallelMove::decodeParallelMove(this, w0, w1);
+}
+
+
+Opcode::~Opcode()
+{
+}
+
+
+std::string Opcode::disassemble() const
+{
+ // Duck out early if there isn't a valid op
+ if (!m_instruction)
+ return dcString();
+
+ // Duck out if either has had an explicit error.
+ if (m_instruction && !m_instruction->valid())
+ return dcString();
+ if (m_parallelMove && !m_parallelMove->valid())
+ return dcString();
+
+ // Disassemble what you can.
+ std::string opString = "";
+ std::string pmString = "";
+ if (m_instruction) m_instruction->disassemble(opString);
+ if (m_parallelMove) m_parallelMove->disassemble(pmString);
+
+ return opString + " " + pmString;
+}
+
+
+void Opcode::evaluate(dsp56156_core* cpustate) const
+{
+ if (m_instruction) m_instruction->evaluate(cpustate);
+ if (m_parallelMove) m_parallelMove->evaluate();
+}
+
+
+size_t Opcode::size() const
+{
+ if (m_instruction && m_instruction->valid())
+ return m_instruction->size() + m_instruction->sizeIncrement();
+
+ // Opcode failed to decode, so push it past dc
+ return 1;
+}
+
+size_t Opcode::evalSize() const
+{
+ if (m_instruction && m_instruction->valid())
+ return m_instruction->evalSize(); // Probably doesn't matter : + m_instruction->sizeIncrement();
+
+ // Opcode failed to decode, so push it past dc
+ return 1;
+}
+
+
+const reg_id& Opcode::instSource() const { return m_instruction->source(); }
+const reg_id& Opcode::instDestination() const { return m_instruction->destination(); }
+size_t Opcode::instAccumulatorBitsModified() const { return m_instruction->accumulatorBitsModified(); }
+
+std::string Opcode::dcString() const
+{
+ char tempStr[1024];
+ sprintf(tempStr, "dc $%x", m_word0);
+ return std::string(tempStr);
+}
+
+}
diff --git a/src/devices/cpu/dsp56156/opcode.h b/src/devices/cpu/dsp56156/opcode.h
new file mode 100644
index 00000000000..1044af8f188
--- /dev/null
+++ b/src/devices/cpu/dsp56156/opcode.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#ifndef DSP56156_OPCODE_H
+#define DSP56156_OPCODE_H
+
+#include "inst.h"
+#include "pmove.h"
+
+#include "dsp56156.h"
+
+//
+// An Opcode contains an instruction and a parallel move operation.
+//
+namespace DSP_56156
+{
+class Instruction;
+class ParallelMove;
+
+class Opcode
+{
+public:
+ Opcode(uint16_t w0, uint16_t w1);
+ virtual ~Opcode();
+
+ std::string disassemble() const;
+ void evaluate(dsp56156_core* cpustate) const;
+ size_t size() const;
+ size_t evalSize() const;
+
+ // Peek through to the instruction
+ const reg_id& instSource() const;
+ const reg_id& instDestination() const;
+ size_t instAccumulatorBitsModified() const;
+
+private:
+ std::unique_ptr<Instruction> m_instruction;
+ std::unique_ptr<ParallelMove> m_parallelMove;
+
+ uint16_t m_word0;
+ //uint16_t m_word1;
+
+ std::string dcString() const;
+};
+
+}
+#endif
diff --git a/src/devices/cpu/dsp56156/pmove.cpp b/src/devices/cpu/dsp56156/pmove.cpp
new file mode 100644
index 00000000000..514ed2de972
--- /dev/null
+++ b/src/devices/cpu/dsp56156/pmove.cpp
@@ -0,0 +1,80 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#include "emu.h"
+#include "pmove.h"
+
+namespace DSP_56156
+{
+const reg_id& ParallelMove::opSource() const { return m_oco->instSource(); }
+const reg_id& ParallelMove::opDestination() const { return m_oco->instDestination(); }
+size_t ParallelMove::opAccumulatorBitsModified() const { return m_oco->instAccumulatorBitsModified(); }
+
+
+std::unique_ptr<ParallelMove> ParallelMove::decodeParallelMove(const Opcode* opc, const uint16_t word0, const uint16_t word1)
+{
+ const uint16_t w0 = word0;
+ const uint16_t w1 = word1;
+
+ /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+ if ((w0 & 0xe000) == 0x6000)
+ {
+ return std::make_unique<DualXMemoryDataRead>(opc, w0, w1);
+ }
+ /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+ else if ((w0 & 0xfe00) == 0x1600)
+ {
+ return std::make_unique<XMemoryDataWriteAndRegisterDataMove>(opc, w0, w1);
+ }
+ else
+ {
+ /* 32 General parallel move operations */
+ /* Note: It's important that NPDM comes before RtRDM */
+
+ /* No Parallel Data Move : 0100 1010 .... .... : A-131 */
+ if ((w0 & 0xff00) == 0x4a00)
+ {
+ return nullptr;
+ }
+ /* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+ else if ((w0 & 0xf000) == 0x4000)
+ {
+ return std::make_unique<RegisterToRegisterDataMove>(opc, w0, w1);
+ }
+ /* Address Register Update : 0011 0zRR .... .... : A-135 */
+ else if ((w0 & 0xf800) == 0x3000)
+ {
+ return std::make_unique<AddressRegisterUpdate>(opc, w0, w1);
+ }
+ /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+ else if ((w0 & 0x8000) == 0x8000)
+ {
+ return std::make_unique<XMemoryDataMove>(opc, w0, w1);
+ }
+ /* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+ else if ((w0 & 0xf000) == 0x5000)
+ {
+ return std::make_unique<XMemoryDataMove_2>(opc, w0, w1);
+ }
+ /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+ else if ((w0 & 0xff00) == 0x0500)
+ {
+ // Now check it against all potential double-ups.
+ // These operations can't have an additional parallel move.
+ //
+ // MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152
+ // MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144
+ // MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128
+ //
+ if (((w1 & 0xfe20) != 0x0200) &&
+ ((w1 & 0xf810) != 0x3800) &&
+ ((w1 & 0x00ff) != 0x0011))
+ {
+ return std::make_unique<XMemoryDataMoveWithShortDisplacement>(opc, w0, w1);
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+}
diff --git a/src/devices/cpu/dsp56156/pmove.h b/src/devices/cpu/dsp56156/pmove.h
new file mode 100644
index 00000000000..bf5cb2ec34a
--- /dev/null
+++ b/src/devices/cpu/dsp56156/pmove.h
@@ -0,0 +1,335 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#ifndef DSP56156_PMOVE_H
+#define DSP56156_PMOVE_H
+
+#include "opcode.h"
+#include "tables.h"
+
+//
+// A ParallelMove Object is what all parallel move classes inherit from.
+//
+namespace DSP_56156
+{
+class Opcode;
+
+class ParallelMove
+{
+public:
+ ParallelMove(const Opcode* oco) : m_valid(false), m_oco(oco) { }
+ virtual ~ParallelMove() {}
+
+ virtual bool decode(const uint16_t word0, const uint16_t word1) = 0;
+ virtual void disassemble(std::string& retString) const = 0;
+ virtual void evaluate() = 0;
+
+ static std::unique_ptr<ParallelMove> decodeParallelMove(const Opcode* opc, const uint16_t word0, const uint16_t word1);
+
+ bool valid() const { return m_valid; }
+
+ // Peek through the opcode to see the instruction
+ const reg_id& opSource() const;
+ const reg_id& opDestination() const;
+ size_t opAccumulatorBitsModified() const;
+
+protected:
+ bool m_valid;
+ const Opcode* m_oco;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// PARALLEL MOVES ////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+/* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+class XMemoryDataMove: public ParallelMove
+{
+public:
+ XMemoryDataMove(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ reg_id r;
+ decode_RR_table(BITSn(word0,0x3000), r);
+
+ reg_id SD;
+ decode_HHH_table(BITSn(word0,0x0e00), SD);
+
+ std::string ea;
+ assemble_ea_from_m_table(BITSn(word0,0x4000), regIDAsNum(r), ea);
+
+ assemble_arguments_from_W_table(BITSn(word0,0x0100), 'X', SD, ea,
+ m_source, m_destination);
+
+ // If the destination of the instruction overlaps with our destination, abort.
+ if (registerOverlap(opDestination(), opAccumulatorBitsModified(), stringAsRegID(m_destination)))
+ return false;
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = m_source + "," + m_destination;
+ }
+ void evaluate() override {}
+
+private:
+ std::string m_source;
+ std::string m_destination;
+};
+
+
+/* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+class XMemoryDataMove_2: public ParallelMove
+{
+public:
+ XMemoryDataMove_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ std::string ea;
+ if (opDestination() == iB)
+ ea = "(A1)";
+ else if (opDestination() == iA)
+ ea = "(B1)";
+ else
+ ea = "(A1)";
+
+ reg_id SD;
+ decode_HHH_table(BITSn(word0,0x0e00), SD);
+
+ assemble_arguments_from_W_table(BITSn(word0,0x0100), 'X', SD, ea,
+ m_source, m_destination);
+
+ // If the destination of the instruction overlaps with our destination, abort.
+ if (registerOverlap(opDestination(), opAccumulatorBitsModified(), stringAsRegID(m_destination)))
+ return false;
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = m_source + "," + m_destination;
+ }
+ void evaluate() override {}
+
+private:
+ std::string m_source;
+ std::string m_destination;
+};
+
+
+/* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+class DualXMemoryDataRead: public ParallelMove
+{
+public:
+ DualXMemoryDataRead(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ reg_id r;
+ reg_id D1;
+ reg_id D2;
+ std::string ea1 = "";
+ std::string ea2 = "";
+
+ decode_rr_table(BITSn(word0,0x0060), r);
+ decode_KKK_table(BITSn(word0,0x0700), D1, D2);
+ assemble_eas_from_mm_table(BITSn(word0,0x1800), regIDAsNum(r), 3, ea1, ea2);
+
+ /* Not documented, but extrapolated from docs on page A-133 */
+ if (D1 == iFHAT)
+ {
+ if (opDestination() == iB)
+ D1 = iA;
+ else if (opDestination() == iA)
+ D1 = iB;
+ else
+ D1 = iA; /* In the case of no data ALU instruction */
+ }
+
+ /* D1 and D2 may not specify the same register : A-142 */
+ if (r == iR3) return false;
+
+ char temp[32];
+ sprintf(temp, "X:%s,%s", ea1.c_str(), regIdAsString(D1).c_str());
+ parallelMove = temp;
+ sprintf(temp, "X:%s,%s", ea2.c_str(), regIdAsString(D2).c_str());
+ parallelMove2 = temp;
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = parallelMove + " " + parallelMove2;
+ }
+ void evaluate() override {}
+
+private:
+ std::string parallelMove;
+ std::string parallelMove2;
+};
+
+
+/* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+class RegisterToRegisterDataMove: public ParallelMove
+{
+public:
+ RegisterToRegisterDataMove(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ decode_IIIIx_table(BITSn(word0,0x0f00), BITSn(word0,0x0008),
+ m_source, m_destination);
+
+ if (m_source == iINVALID)
+ return false;
+
+ if (m_source == iF)
+ m_source = opDestination();
+
+ if (m_destination == iFHAT)
+ {
+ if (opDestination() == iB)
+ m_destination = iA;
+ else if (opDestination() == iA)
+ m_destination = iB;
+ else
+ m_destination = iA; /* In the case of no data ALU instruction */
+ }
+
+ // Don't return a failure, just let everything fall through (nop).
+ //if (m_source == "?" && m_destination == "?")
+ // return false;
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ // (?,?) is a parallel nop
+ if (m_source == iWEIRD && m_destination == iWEIRD)
+ retString = "";
+ else
+ retString = regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate() override {}
+
+private:
+ reg_id m_source;
+ reg_id m_destination;
+};
+
+
+/* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+class XMemoryDataWriteAndRegisterDataMove: public ParallelMove
+{
+public:
+ XMemoryDataWriteAndRegisterDataMove(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco)
+ {
+ pms = "";
+ pms2 = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ reg_id r;
+ reg_id S;
+ reg_id Dnot;
+ char parallel_move_str[128];
+ char parallel_move_str2[128];
+
+ if (opDestination() == iA) Dnot = iB;
+ else Dnot = iA;
+
+ // NEW // decode_k_table(BITSn(word0,0x0100), Dnot);
+ decode_RR_table(BITSn(word0,0x00c0), r);
+ decode_DD_table(BITSn(word0,0x0030), S);
+
+ sprintf(parallel_move_str, "%s,X:(R%d)+N%d", regIdAsString(Dnot).c_str(), regIDAsNum(r), regIDAsNum(r));
+ sprintf(parallel_move_str2, "%s,%s", regIdAsString(S).c_str(), regIdAsString(Dnot).c_str());
+ pms = parallel_move_str;
+ pms2 = parallel_move_str2;
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = pms + " " + pms2;
+ }
+ void evaluate() override {}
+
+private:
+ std::string pms; // TODO
+ std::string pms2;
+};
+
+
+/* Address Register Update : 0011 0zRR .... .... : A-135 */
+class AddressRegisterUpdate: public ParallelMove
+{
+public:
+ AddressRegisterUpdate(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco)
+ {
+ m_ea = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ reg_id r;
+ decode_RR_table(BITSn(word0,0x0300), r);
+ assemble_ea_from_z_table(BITSn(word0,0x0400), regIDAsNum(r), m_ea);
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = m_ea;
+ }
+ void evaluate() override {}
+
+private:
+ std::string m_ea;
+};
+
+
+/* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+class XMemoryDataMoveWithShortDisplacement: public ParallelMove
+{
+public:
+ XMemoryDataMoveWithShortDisplacement(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco)
+ {
+ m_source = "";
+ m_destination = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const uint16_t word0, const uint16_t word1) override
+ {
+ int8_t b;
+ reg_id SD;
+ b = (char)(word0 & 0x00ff);
+ decode_HHH_table(BITSn(word1,0x0e00), SD);
+ assemble_reg_from_W_table(BITSn(word1,0x0100), 'X', SD, b, m_source, m_destination);
+
+ return true;
+ }
+ void disassemble(std::string& retString) const override
+ {
+ retString = m_source + "," + m_destination;
+ }
+ void evaluate() override {}
+
+private:
+ std::string m_source;
+ std::string m_destination;
+};
+
+}
+#endif
diff --git a/src/devices/cpu/dsp56156/tables.cpp b/src/devices/cpu/dsp56156/tables.cpp
new file mode 100644
index 00000000000..93f591b3a5c
--- /dev/null
+++ b/src/devices/cpu/dsp56156/tables.cpp
@@ -0,0 +1,900 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#include "emu.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tables.h"
+#include "dsp56def.h"
+
+namespace DSP_56156
+{
+/******************/
+/* Table decoding */
+/******************/
+bfShift decode_BBB_table(uint16_t BBB)
+{
+ switch(BBB)
+ {
+ case 0x4: return BBB_UPPER;
+ case 0x2: return BBB_MIDDLE;
+ case 0x1: return BBB_LOWER;
+ }
+
+ return BBB_INVALID;
+}
+
+void decode_cccc_table(const uint16_t cccc, op_mnem& mnemonic)
+{
+ switch (cccc)
+ {
+ case 0x0: mnemonic = oCC; break;
+ case 0x1: mnemonic = oGE; break;
+ case 0x2: mnemonic = oNE; break;
+ case 0x3: mnemonic = oPL; break;
+ case 0x4: mnemonic = oNN; break;
+ case 0x5: mnemonic = oEC; break;
+ case 0x6: mnemonic = oLC; break;
+ case 0x7: mnemonic = oGT; break;
+ case 0x8: mnemonic = oCS; break;
+ case 0x9: mnemonic = oLT; break;
+ case 0xa: mnemonic = oEQ; break;
+ case 0xb: mnemonic = oMI; break;
+ case 0xc: mnemonic = oNR; break;
+ case 0xd: mnemonic = oES; break;
+ case 0xe: mnemonic = oLS; break;
+ case 0xf: mnemonic = oLE; break;
+ }
+
+// NEW // switch (cccc)
+// NEW // {
+// NEW // case 0x0: sprintf(mnemonic, "cc(hs)"); break;
+// NEW // case 0x1: sprintf(mnemonic, "ge "); break;
+// NEW // case 0x2: sprintf(mnemonic, "ne "); break;
+// NEW // case 0x3: sprintf(mnemonic, "pl "); break;
+// NEW // case 0x4: sprintf(mnemonic, "nn "); break;
+// NEW // case 0x5: sprintf(mnemonic, "ec "); break;
+// NEW // case 0x6: sprintf(mnemonic, "lc "); break;
+// NEW // case 0x7: sprintf(mnemonic, "gt "); break;
+// NEW // case 0x8: sprintf(mnemonic, "cs(lo)"); break;
+// NEW // case 0x9: sprintf(mnemonic, "lt "); break;
+// NEW // case 0xa: sprintf(mnemonic, "eq "); break;
+// NEW // case 0xb: sprintf(mnemonic, "mi "); break;
+// NEW // case 0xc: sprintf(mnemonic, "nr "); break;
+// NEW // case 0xd: sprintf(mnemonic, "es "); break;
+// NEW // case 0xe: sprintf(mnemonic, "ls "); break;
+// NEW // case 0xf: sprintf(mnemonic, "le "); break;
+// NEW // }
+}
+
+void decode_DDDDD_table(const uint16_t DDDDD, reg_id& SD)
+{
+ switch(DDDDD)
+ {
+ case 0x00: SD = iX0; break;
+ case 0x01: SD = iY0; break;
+ case 0x02: SD = iX1; break;
+ case 0x03: SD = iY1; break;
+ case 0x04: SD = iA; break;
+ case 0x05: SD = iB; break;
+ case 0x06: SD = iA0; break;
+ case 0x07: SD = iB0; break;
+ case 0x08: SD = iLC; break;
+ case 0x09: SD = iSR; break;
+ case 0x0a: SD = iOMR; break;
+ case 0x0b: SD = iSP; break;
+ case 0x0c: SD = iA1; break;
+ case 0x0d: SD = iB1; break;
+ case 0x0e: SD = iA2; break;
+ case 0x0f: SD = iB2; break;
+
+ case 0x10: SD = iR0; break;
+ case 0x11: SD = iR1; break;
+ case 0x12: SD = iR2; break;
+ case 0x13: SD = iR3; break;
+ case 0x14: SD = iM0; break;
+ case 0x15: SD = iM1; break;
+ case 0x16: SD = iM2; break;
+ case 0x17: SD = iM3; break;
+ case 0x18: SD = iSSH; break;
+ case 0x19: SD = iSSL; break;
+ case 0x1a: SD = iLA; break;
+ case 0x1b: SD = iINVALID; break; /* no 0x1b */
+ case 0x1c: SD = iN0; break;
+ case 0x1d: SD = iN1; break;
+ case 0x1e: SD = iN2; break;
+ case 0x1f: SD = iN3; break;
+ }
+}
+
+void decode_DD_table(const uint16_t DD, reg_id& SD)
+{
+ switch (DD)
+ {
+ case 0x0: SD = iX0; break;
+ case 0x1: SD = iY0; break;
+ case 0x2: SD = iX1; break;
+ case 0x3: SD = iY1; break;
+ }
+}
+
+void decode_DDF_table(const uint16_t DD, const uint16_t F, reg_id& S, reg_id& D)
+{
+ const uint16_t switchVal = (DD << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x0: S = iX0; D = iA; break;
+ case 0x1: S = iX0; D = iB; break;
+ case 0x2: S = iY0; D = iA; break;
+ case 0x3: S = iY0; D = iB; break;
+ case 0x4: S = iX1; D = iA; break;
+ case 0x5: S = iX1; D = iB; break;
+ case 0x6: S = iY1; D = iA; break;
+ case 0x7: S = iY1; D = iB; break;
+ }
+}
+
+void decode_EE_table(const uint16_t EE, reg_id& D)
+{
+ switch(EE)
+ {
+ case 0x1: D = iMR; break;
+ case 0x3: D = iCCR; break;
+ case 0x2: D = iOMR; break;
+ }
+}
+
+void decode_F_table(const uint16_t F, reg_id& SD)
+{
+ switch(F)
+ {
+ case 0x0: SD = iA; break;
+ case 0x1: SD = iB; break;
+ }
+}
+
+void decode_h0hF_table(const uint16_t h0h, uint16_t F, reg_id& S, reg_id& D)
+{
+ const uint16_t switchVal = (h0h << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x8: S = iX0; D = iA; break;
+ case 0x9: S = iX0; D = iB; break;
+ case 0xa: S = iY0; D = iA; break;
+ case 0xb: S = iY0; D = iB; break;
+ case 0x2: S = iA; D = iA; break;
+ case 0x1: S = iA; D = iB; break;
+ case 0x0: S = iB; D = iA; break;
+ case 0x3: S = iB; D = iB; break;
+ }
+}
+
+void decode_HH_table(const uint16_t HH, reg_id& SD)
+{
+ switch(HH)
+ {
+ case 0x0: SD = iX0; break;
+ case 0x1: SD = iY0; break;
+ case 0x2: SD = iA; break;
+ case 0x3: SD = iB; break;
+ }
+}
+
+void decode_HHH_table(const uint16_t HHH, reg_id& SD)
+{
+ switch(HHH)
+ {
+ case 0x0: SD = iX0; break;
+ case 0x1: SD = iY0; break;
+ case 0x2: SD = iX1; break;
+ case 0x3: SD = iY1; break;
+ case 0x4: SD = iA; break;
+ case 0x5: SD = iB; break;
+ case 0x6: SD = iA0; break;
+ case 0x7: SD = iB0; break;
+ }
+}
+
+void decode_IIIIx_table(const uint16_t IIII, const uint16_t x, reg_id& S, reg_id& D)
+{
+ S = D = iINVALID;
+ switch(IIII)
+ {
+ case 0x0: S = iX0; D = iFHAT; break;
+ case 0x1: S = iY0; D = iFHAT; break;
+ case 0x2: S = iX1; D = iFHAT; break;
+ case 0x3: S = iY1; D = iFHAT; break;
+ case 0x4: S = iA; D = iX0; break;
+ case 0x5: S = iB; D = iY0; break;
+ case 0x6: S = iA0; D = iX0; break;
+ case 0x7: S = iB0; D = iY0; break;
+ case 0x8: if ( x) S = iF; D = iFHAT; break;
+ case 0x9: if (!x) S = iF; D = iFHAT; break;
+ case 0xa: S = iWEIRD; D = iWEIRD; break;
+ case 0xb: S = iWEIRD; D = iWEIRD; break;
+ case 0xc: S = iA; D = iX1; break;
+ case 0xd: S = iB; D = iY1; break;
+ case 0xe: S = iA0; D = iX1; break;
+ case 0xf: S = iB0; D = iY1; break;
+ }
+}
+
+void decode_JJJF_table(const uint16_t JJJ, const uint16_t F, reg_id& S, reg_id& D)
+{
+ const uint16_t switchVal = (JJJ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S = iB; D = iA; break;
+ case 0x1: S = iA; D = iB; break;
+ case 0x2: S = iINVALID; D = iINVALID; break;
+ case 0x3: S = iINVALID; D = iINVALID; break;
+ case 0x4: S = iX; D = iA; break;
+ case 0x5: S = iX; D = iB; break;
+ case 0x6: S = iY; D = iA; break;
+ case 0x7: S = iY; D = iB; break;
+ case 0x8: S = iX0; D = iA; break;
+ case 0x9: S = iX0; D = iB; break;
+ case 0xa: S = iY0; D = iA; break;
+ case 0xb: S = iY0; D = iB; break;
+ case 0xc: S = iX1; D = iA; break;
+ case 0xd: S = iX1; D = iB; break;
+ case 0xe: S = iY1; D = iA; break;
+ case 0xf: S = iY1; D = iB; break;
+ }
+}
+
+void decode_JJF_table(const uint16_t JJ, const uint16_t F, reg_id& S, reg_id& D)
+{
+ const uint16_t switchVal = (JJ << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x0: S = iX0; D = iA; break;
+ case 0x1: S = iX0; D = iB; break;
+ case 0x2: S = iY0; D = iA; break;
+ case 0x3: S = iY0; D = iB; break;
+ case 0x4: S = iX1; D = iA; break;
+ case 0x5: S = iX1; D = iB; break;
+ case 0x6: S = iY1; D = iA; break;
+ case 0x7: S = iY1; D = iB; break;
+ }
+}
+
+void decode_JF_table(const uint16_t J, const uint16_t F, reg_id& S, reg_id& D)
+{
+ const uint16_t switchVal = (J << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S = iX; D = iA; break;
+ case 0x1: S = iX; D = iB; break;
+ case 0x2: S = iY; D = iA; break;
+ case 0x3: S = iY; D = iB; break;
+ }
+}
+
+// NEW // void decode_k_table(uint16_t k, char *Dnot)
+// NEW // {
+// NEW // switch(k)
+// NEW // {
+// NEW // case 0x0: sprintf(Dnot, "B"); break;
+// NEW // case 0x1: sprintf(Dnot, "A"); break;
+// NEW // }
+// NEW // }
+
+void decode_kSign_table(const uint16_t k, std::string& plusMinus)
+{
+ switch(k)
+ {
+ case 0x0: plusMinus = "+"; break;
+ case 0x1: plusMinus = "-"; break;
+ }
+}
+
+void decode_KKK_table(const uint16_t KKK, reg_id& D1, reg_id& D2)
+{
+ switch(KKK)
+ {
+ case 0x0: D1 = iFHAT; D2 = iX0; break;
+ case 0x1: D1 = iY0; D2 = iX0; break;
+ case 0x2: D1 = iX1; D2 = iX0; break;
+ case 0x3: D1 = iY1; D2 = iX0; break;
+ case 0x4: D1 = iX0; D2 = iX1; break;
+ case 0x5: D1 = iY0; D2 = iX1; break;
+ case 0x6: D1 = iFHAT; D2 = iY0; break;
+ case 0x7: D1 = iY1; D2 = iX1; break;
+ }
+}
+
+void decode_NN_table(uint16_t NN, reg_id& ret)
+{
+ switch(NN)
+ {
+ case 0x0: ret = iN0; break;
+ case 0x1: ret = iN1; break;
+ case 0x2: ret = iN2; break;
+ case 0x3: ret = iN3; break;
+ }
+}
+
+void decode_TT_table(uint16_t TT, reg_id& ret)
+{
+ switch(TT)
+ {
+ case 0x0: ret = iR0; break;
+ case 0x1: ret = iR1; break;
+ case 0x2: ret = iR2; break;
+ case 0x3: ret = iR3; break;
+ }
+}
+
+void decode_QQF_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D)
+{
+ const uint16_t switchVal = (QQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S1 = iY0; S2 = iX0; D = iA; break;
+ case 0x1: S1 = iY0; S2 = iX0; D = iB; break;
+ case 0x2: S1 = iY1; S2 = iX0; D = iA; break;
+ case 0x3: S1 = iY1; S2 = iX0; D = iB; break;
+ case 0x4: S1 = iY0; S2 = iX1; D = iA; break;
+ case 0x5: S1 = iY0; S2 = iX1; D = iB; break;
+ case 0x6: S1 = iY1; S2 = iX1; D = iA; break;
+ case 0x7: S1 = iY1; S2 = iX1; D = iB; break;
+ }
+}
+
+void decode_QQF_special_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D)
+{
+ const uint16_t switchVal = (QQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S1 = iY0; S2 = iX0; D = iA; break;
+ case 0x1: S1 = iY0; S2 = iX0; D = iB; break;
+ case 0x2: S1 = iY1; S2 = iX0; D = iA; break;
+ case 0x3: S1 = iY1; S2 = iX0; D = iB; break;
+ case 0x4: S1 = iX1; S2 = iY0; D = iA; break;
+ case 0x5: S1 = iX1; S2 = iY0; D = iB; break;
+ case 0x6: S1 = iX1; S2 = iY1; D = iA; break;
+ case 0x7: S1 = iX1; S2 = iY1; D = iB; break;
+ }
+}
+
+void decode_QQQF_table(const uint16_t QQQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D)
+{
+ const uint16_t switchVal = (QQQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S1 = iX0; S2 = iX0; D = iA; break;
+ case 0x1: S1 = iX0; S2 = iX0; D = iB; break;
+ case 0x2: S1 = iX1; S2 = iX0; D = iA; break;
+ case 0x3: S1 = iX1; S2 = iX0; D = iB; break;
+ case 0x4: S1 = iA1; S2 = iY0; D = iA; break;
+ case 0x5: S1 = iA1; S2 = iY0; D = iB; break;
+ case 0x6: S1 = iB1; S2 = iX0; D = iA; break;
+ case 0x7: S1 = iB1; S2 = iX0; D = iB; break;
+ case 0x8: S1 = iY0; S2 = iX0; D = iA; break;
+ case 0x9: S1 = iY0; S2 = iX0; D = iB; break;
+ case 0xa: S1 = iY1; S2 = iX0; D = iA; break;
+ case 0xb: S1 = iY1; S2 = iX0; D = iB; break;
+ case 0xc: S1 = iY0; S2 = iX1; D = iA; break;
+ case 0xd: S1 = iY0; S2 = iX1; D = iB; break;
+ case 0xe: S1 = iY1; S2 = iX1; D = iA; break;
+ case 0xf: S1 = iY1; S2 = iX1; D = iB; break;
+ }
+}
+
+void decode_RR_table(uint16_t RR, reg_id& ret)
+{
+ switch(RR)
+ {
+ case 0x0: ret = iR0; break;
+ case 0x1: ret = iR1; break;
+ case 0x2: ret = iR2; break;
+ case 0x3: ret = iR3; break;
+ }
+}
+
+void decode_rr_table(uint16_t rr, reg_id& ret)
+{
+ switch(rr)
+ {
+ case 0x0: ret = iR0; break;
+ case 0x1: ret = iR1; break;
+ case 0x2: ret = iR2; break;
+ case 0x3: ret = iR3; break;
+ }
+}
+
+void decode_s_table(const uint16_t s, op_mnem& arithmetic)
+{
+ switch(s)
+ {
+ case 0x0: arithmetic = oSU; break;
+ case 0x1: arithmetic = oUU; break;
+ }
+}
+
+void decode_ss_table(const uint16_t ss, op_mnem& arithmetic)
+{
+ switch(ss)
+ {
+ case 0x0: arithmetic = oSS; break;
+ case 0x1: arithmetic = oINVALID; break;
+ // NEW // case 0x1: arithmetic = "ss"; break;
+ case 0x2: arithmetic = oSU; break;
+ case 0x3: arithmetic = oUU; break;
+ }
+}
+
+void decode_uuuuF_table(const uint16_t uuuu, const uint16_t F, std::string& arg, reg_id& S, reg_id& D)
+{
+ const uint16_t switchVal = (uuuu << 1) | F;
+
+ //D = "sub?";
+ //S = "add";
+ arg = "invalid";
+
+ switch(switchVal)
+ {
+ case 0x00: arg = "add"; S = iX0; D = iA; break;
+ case 0x01: arg = "add"; S = iX0; D = iB; break;
+ case 0x02: arg = "add"; S = iY0; D = iA; break;
+ case 0x03: arg = "add"; S = iY0; D = iB; break;
+ case 0x04: arg = "add"; S = iX1; D = iA; break;
+ case 0x05: arg = "add"; S = iX1; D = iB; break;
+ case 0x06: arg = "add"; S = iY1; D = iA; break;
+ case 0x07: arg = "add"; S = iY1; D = iB; break;
+
+ case 0x08: arg = "sub"; S = iX0; D = iA; break;
+ case 0x09: arg = "sub"; S = iX0; D = iB; break;
+ case 0x0a: arg = "sub"; S = iY0; D = iA; break;
+ case 0x0b: arg = "sub"; S = iY0; D = iB; break;
+ case 0x0c: arg = "sub"; S = iX1; D = iA; break;
+ case 0x0d: arg = "sub"; S = iX1; D = iB; break;
+ case 0x0e: arg = "sub"; S = iY1; D = iA; break;
+ case 0x0f: arg = "sub"; S = iY1; D = iB; break;
+
+ case 0x18: arg = "add"; S = iB; D = iA; break;
+ case 0x19: arg = "add"; S = iA; D = iB; break;
+
+ case 0x1a: arg = "sub"; S = iB; D = iA; break;
+ case 0x1b: arg = "sub"; S = iA; D = iB; break;
+
+ case 0x1c: arg = "tfr"; S = iB; D = iA; break;
+ case 0x1d: arg = "tfr"; S = iA; D = iB; break;
+
+ case 0x1e: arg = "move"; S = iINVALID; D = iINVALID; break;
+ case 0x1f: arg = "move"; S = iINVALID; D = iINVALID; break;
+ }
+}
+
+void decode_Z_table(const uint16_t Z, std::string& ea)
+{
+ /* This is fixed as per the Family Manual errata addendum */
+ switch(Z)
+ {
+ case 0x1: ea = "(A1)"; break;
+ case 0x0: ea = "(B1)"; break;
+ }
+}
+
+void assemble_ea_from_m_table(const uint16_t m, const int n, std::string& ea)
+{
+ char temp[32];
+ switch(m)
+ {
+ case 0x0: sprintf(temp, "(R%d)+",n) ; break;
+ case 0x1: sprintf(temp, "(R%d)+N%d", n, n); break;
+ }
+ ea = temp;
+}
+
+void assemble_eas_from_mm_table(uint16_t mm, int n1, int n2, std::string& ea1, std::string& ea2)
+{
+ char temp1[32];
+ char temp2[32];
+ switch(mm)
+ {
+ case 0x0: sprintf(temp1, "(R%d)+", n1) ;
+ sprintf(temp2, "(R%d)+", n2) ; break;
+ case 0x1: sprintf(temp1, "(R%d)+", n1) ;
+ sprintf(temp2, "(R%d)+N%d", n2, n2); break;
+ case 0x2: sprintf(temp1, "(R%d)+N%d", n1, n1);
+ sprintf(temp2, "(R%d)+", n2) ; break;
+ case 0x3: sprintf(temp1, "(R%d)+N%d", n1, n1);
+ sprintf(temp2, "(R%d)+N%d", n2, n2); break;
+ }
+ ea1 = temp1;
+ ea2 = temp2;
+}
+
+void assemble_ea_from_MM_table(uint16_t MM, int n, std::string& ea)
+{
+ char temp[32];
+ switch(MM)
+ {
+ case 0x0: sprintf(temp, "(R%d)", n) ; break;
+ case 0x1: sprintf(temp, "(R%d)+", n) ; break;
+ case 0x2: sprintf(temp, "(R%d)-", n) ; break;
+ case 0x3: sprintf(temp, "(R%d)+N%d", n, n); break;
+ }
+ ea = temp;
+}
+
+void assemble_ea_from_q_table(uint16_t q, int n, std::string& ea)
+{
+ char temp[32];
+ switch(q)
+ {
+ case 0x0: sprintf(temp, "(R%d+N%d)", n, n); break;
+ case 0x1: sprintf(temp, "-(R%d)", n) ; break;
+ }
+ ea = temp;
+}
+
+void assemble_ea_from_t_table(uint16_t t, uint16_t val, std::string& ea)
+{
+ char temp[32];
+ switch(t)
+ {
+ case 0x0: sprintf(temp, "X:>$%x", val); break;
+ case 0x1: sprintf(temp, "#>$%x", val); break;
+ // NEW // case 0x0: sprintf(ea, "X:$%04x", val); break;
+ // NEW // case 0x1: sprintf(ea, "#$%04x", val); break;
+ }
+ ea = temp;
+}
+
+void assemble_ea_from_z_table(uint16_t z, int n, std::string& ea)
+{
+ char temp[32];
+ switch(z)
+ {
+ case 0x0: sprintf(temp, "(R%d)-", n) ; break;
+ case 0x1: sprintf(temp, "(R%d)+N%d", n, n); break;
+ }
+ ea = temp;
+}
+
+void assemble_D_from_P_table(uint16_t P, uint16_t ppppp, std::string& D)
+{
+ char temp[32];
+ std::string fullAddy; /* Convert Short Absolute Address to full 16-bit */
+
+ switch(P)
+ {
+ case 0x0:
+ sprintf(temp, "X:<$%x", ppppp);
+ // NEW // sprintf(temp, "X:$%02x", ppppp);
+ break;
+ case 0x1:
+ assemble_address_from_IO_short_address(ppppp, fullAddy);
+ sprintf(temp, "X:<<$%s", fullAddy.c_str());
+ // NEW // sprintf(temp, "X:$%s", fullAddy.c_str());
+ break;
+ }
+ D = temp;
+}
+
+void assemble_arguments_from_W_table(uint16_t W, char ma, const reg_id& SD, const std::string& ea,
+ std::string& source, std::string& destination)
+{
+ char temp[32];
+ sprintf(temp, "%c:%s", ma, ea.c_str());
+ switch(W)
+ {
+ case 0x0: source = regIdAsString(SD); destination = temp; break;
+ case 0x1: source = temp; destination = regIdAsString(SD); break;
+ }
+}
+
+void assemble_arguments_from_W_table(uint16_t W, char ma, const std::string& SD, const std::string& ea,
+ std::string& source, std::string& destination)
+{
+ char temp[32];
+ sprintf(temp, "%c:%s", ma, ea.c_str());
+ switch(W)
+ {
+ case 0x0: source = SD; destination = temp; break;
+ case 0x1: source = temp; destination = SD; break;
+ }
+}
+
+void assemble_reg_from_W_table(uint16_t W, char ma, const reg_id& SD, const int8_t xx, std::string& S, std::string& D)
+{
+ uint8_t abs_xx;
+ char temp[32];
+ char operation[32];
+
+ if(xx < 0)
+ sprintf(operation,"-");
+ else
+ sprintf(operation,"+");
+
+ abs_xx = abs(xx);
+
+ sprintf(temp, "%c:(R2%s$%x)", ma, operation, abs_xx);
+ // NEW // sprintf(temp, "%c:(R2%s$%02x)", ma, operation, abs_xx);
+ switch(W)
+ {
+ case 0x0: S = regIdAsString(SD); D = temp; break;
+ case 0x1: S = temp; D = regIdAsString(SD); break;
+ }
+}
+
+void assemble_address_from_IO_short_address(uint16_t pp, std::string& ea)
+{
+ char temp[32];
+
+ uint16_t fullAddy = 0xffe0;
+ fullAddy |= pp;
+
+ sprintf(temp, "%.04x", fullAddy);
+ ea = temp;
+}
+
+int8_t get_6_bit_signed_value(uint16_t bits)
+{
+ uint16_t fullAddy = bits;
+ if (fullAddy & 0x0020)
+ fullAddy |= 0xffc0;
+
+ return (int8_t)fullAddy;
+}
+
+
+/********************/
+/* HELPER FUNCTIONS */
+/********************/
+
+uint16_t dsp56156_op_maskn(uint16_t cur, uint16_t mask)
+{
+ int i;
+
+ uint16_t retVal = (cur & mask);
+ uint16_t temp = 0x0000;
+ int offsetCount = 0;
+
+ /* Shift everything right, eliminating 'whitespace'... */
+ for (i = 0; i < 16; i++)
+ {
+ if (mask & (0x1<<i)) /* If mask bit is non-zero */
+ {
+ temp |= (((retVal >> i) & 0x1) << offsetCount);
+ offsetCount++;
+ }
+ }
+
+ return temp;
+}
+
+bool registerOverlap(const reg_id& r0, const size_t bmd, const reg_id& r1)
+{
+ if (bmd == BM_NONE)
+ return false;
+
+ if (r0 == r1)
+ return true;
+
+ if (r0 == iA && (bmd & BM_LOW) && r1 == iA0) return true;
+ if (r0 == iA && (bmd & BM_MIDDLE) && r1 == iA1) return true;
+ if (r0 == iA && (bmd & BM_HIGH) && r1 == iA2) return true;
+
+ if (r0 == iB && (bmd & BM_LOW) && r1 == iB0) return true;
+ if (r0 == iB && (bmd & BM_MIDDLE) && r1 == iB1) return true;
+ if (r0 == iB && (bmd & BM_HIGH) && r1 == iB2) return true;
+
+ return false;
+}
+
+uint16_t regValue16(dsp56156_core* cpustate, const reg_id& reg)
+{
+ if (reg == iX0) return X0;
+ if (reg == iX1) return X1;
+ if (reg == iY0) return Y0;
+ if (reg == iY1) return Y1;
+
+ if (reg == iA0) return A0;
+ if (reg == iA1) return A1;
+ if (reg == iB0) return B0;
+ if (reg == iB1) return B1;
+
+ if (reg == iR0) return R0;
+ if (reg == iR1) return R1;
+ if (reg == iR2) return R2;
+ if (reg == iR3) return R3;
+
+ if (reg == iN0) return N0;
+ if (reg == iN1) return N1;
+ if (reg == iN2) return N2;
+ if (reg == iN3) return N3;
+
+ if (reg == iM0) return M0;
+ if (reg == iM1) return M1;
+ if (reg == iM2) return M2;
+ if (reg == iM3) return M3;
+
+ osd_printf_debug("The dsp561xx core is requesting a 16 bit value from non-16 bit register!");
+ return 0xdead;
+}
+
+void setReg16(dsp56156_core* cpustate, const uint16_t& value, const reg_id& reg)
+{
+ if (reg == iX0) X0 = value;
+ if (reg == iX1) X1 = value;
+ if (reg == iY0) Y0 = value;
+ if (reg == iY1) Y1 = value;
+
+ if (reg == iA0) A0 = value;
+ if (reg == iA1) A1 = value;
+ if (reg == iB0) B0 = value;
+ if (reg == iB1) B1 = value;
+
+ if (reg == iR0) R0 = value;
+ if (reg == iR1) R1 = value;
+ if (reg == iR2) R2 = value;
+ if (reg == iR3) R3 = value;
+
+ if (reg == iN0) N0 = value;
+ if (reg == iN1) N1 = value;
+ if (reg == iN2) N2 = value;
+ if (reg == iN3) N3 = value;
+
+ if (reg == iM0) M0 = value;
+ if (reg == iM1) M1 = value;
+ if (reg == iM2) M2 = value;
+ if (reg == iM3) M3 = value;
+}
+
+std::string regIdAsString(const reg_id& regId)
+{
+ switch(regId)
+ {
+ case iX: return "X";
+ case iX0: return "X0";
+ case iX1: return "X1";
+ case iY: return "Y";
+ case iY0: return "Y0";
+ case iY1: return "Y1";
+ case iA: return "A";
+ case iA0: return "A0";
+ case iA1: return "A1";
+ case iA2: return "A2";
+ case iB: return "B";
+ case iB0: return "B0";
+ case iB1: return "B1";
+ case iB2: return "B2";
+ case iR0: return "R0";
+ case iR1: return "R1";
+ case iR2: return "R2";
+ case iR3: return "R3";
+ case iN0: return "N0";
+ case iN1: return "N1";
+ case iN2: return "N2";
+ case iN3: return "N3";
+ case iM0: return "M0";
+ case iM1: return "M1";
+ case iM2: return "M2";
+ case iM3: return "M3";
+ case iLC: return "LC";
+ case iSR: return "SR";
+ case iOMR: return "OMR";
+ case iSP: return "SP";
+ case iSSH: return "SSH";
+ case iSSL: return "SSL";
+ case iLA: return "LA";
+ case iMR: return "MR";
+ case iCCR: return "CCR";
+ case iF: return "F";
+ case iFHAT: return "^F";
+ case iINVALID: return "!!";
+ case iWEIRD: return "?";
+ }
+
+ return "INVALID_REG_ID";
+}
+
+std::string opMnemonicAsString(const op_mnem& mnem)
+{
+ switch(mnem)
+ {
+ case oCC: return "cc";
+ case oGE: return "ge";
+ case oNE: return "ne";
+ case oPL: return "pl";
+ case oNN: return "nn";
+ case oEC: return "ec";
+ case oLC: return "lc";
+ case oGT: return "gt";
+ case oCS: return "cs";
+ case oLT: return "lt";
+ case oEQ: return "eq";
+ case oMI: return "mi";
+ case oNR: return "nr";
+ case oES: return "es";
+ case oLS: return "ls";
+ case oLE: return "le";
+
+ case oSS: return "ss";
+ case oSU: return "su";
+ case oUU: return "uu";
+ case oINVALID: return "!!";
+ }
+
+ return "INVALID_OPCODE_MNEMONIC";
+}
+
+reg_id stringAsRegID(const std::string& str)
+{
+ if (str.compare("X")==0) return iX;
+ if (str.compare("X0") == 0) return iX0;
+ if (str.compare("X1") == 0) return iX1;
+ if (str.compare("Y") == 0) return iY;
+ if (str.compare("Y0") == 0) return iY0;
+ if (str.compare("Y1") == 0) return iY1;
+ if (str.compare("A") == 0) return iA;
+ if (str.compare("A0") == 0) return iA0;
+ if (str.compare("A1") == 0) return iA1;
+ if (str.compare("A2") == 0) return iA2;
+ if (str.compare("B") == 0) return iB;
+ if (str.compare("B0") == 0) return iB0;
+ if (str.compare("B1") == 0) return iB1;
+ if (str.compare("B2") == 0) return iB2;
+ if (str.compare("R0") == 0) return iR0;
+ if (str.compare("R1") == 0) return iR1;
+ if (str.compare("R2") == 0) return iR2;
+ if (str.compare("R3") == 0) return iR3;
+ if (str.compare("N0") == 0) return iN0;
+ if (str.compare("N1") == 0) return iN1;
+ if (str.compare("N2") == 0) return iN2;
+ if (str.compare("N3") == 0) return iN3;
+ if (str.compare("M0") == 0) return iM0;
+ if (str.compare("M1") == 0) return iM1;
+ if (str.compare("M2") == 0) return iM2;
+ if (str.compare("M3") == 0) return iM3;
+ if (str.compare("LC") == 0) return iLC;
+ if (str.compare("SR") == 0) return iSR;
+ if (str.compare("OMR") == 0) return iOMR;
+ if (str.compare("SP") == 0) return iSP;
+ if (str.compare("SSH") == 0) return iSSH;
+ if (str.compare("SSL") == 0) return iSSL;
+ if (str.compare("LA") == 0) return iLA;
+ if (str.compare("MR") == 0) return iMR;
+ if (str.compare("CCR") == 0) return iCCR;
+ if (str.compare("F") == 0) return iF;
+ if (str.compare("^F") == 0) return iFHAT;
+ if (str.compare("!!") == 0) return iINVALID;
+ if (str.compare("?") == 0)return iWEIRD;
+
+ return iINVALID;
+}
+
+uint8_t regIDAsNum(const reg_id& regId)
+{
+ if (regId == iR0) return 0;
+ if (regId == iR1) return 1;
+ if (regId == iR2) return 2;
+ if (regId == iR3) return 3;
+
+ if (regId == iN0) return 0;
+ if (regId == iN1) return 1;
+ if (regId == iN2) return 2;
+ if (regId == iN3) return 3;
+
+ if (regId == iM0) return 0;
+ if (regId == iM1) return 1;
+ if (regId == iM2) return 2;
+ if (regId == iM3) return 3;
+
+ return 255;
+}
+
+}
diff --git a/src/devices/cpu/dsp56156/tables.h b/src/devices/cpu/dsp56156/tables.h
new file mode 100644
index 00000000000..9ef1dc76b32
--- /dev/null
+++ b/src/devices/cpu/dsp56156/tables.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+#ifndef DSP56156_TABLES_H
+#define DSP56156_TABLES_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dsp56156.h"
+
+namespace DSP_56156
+{
+#define BITSn(CUR,MASK) (dsp56156_op_maskn(CUR,MASK))
+
+enum bitsModified {BM_NONE = 0x0, BM_LOW = 0x1, BM_MIDDLE = 0x2, BM_HIGH = 0x4};
+
+enum bfShift {BBB_UPPER, BBB_MIDDLE, BBB_LOWER, BBB_INVALID};
+enum reg_id {iX, iX0, iX1,
+ iY, iY0, iY1,
+ iA, iA0, iA1, iA2,
+ iB, iB0, iB1, iB2,
+ iR0, iR1, iR2, iR3,
+ iN0, iN1, iN2, iN3,
+ iM0, iM1, iM2, iM3,
+ iLC, iSR, iOMR, iSP, iSSH, iSSL, iLA, iMR, iCCR,
+ iF, iFHAT,
+ iINVALID, iWEIRD};
+
+enum op_mnem {oCC, oGE, oNE, oPL,
+ oNN, oEC, oLC, oGT,
+ oCS, oLT, oEQ, oMI,
+ oNR, oES, oLS, oLE,
+ oSS, oSU, oUU, oINVALID};
+
+
+bfShift decode_BBB_table(uint16_t BBB);
+void decode_cccc_table(const uint16_t cccc, op_mnem& mnemonic);
+void decode_DDDDD_table(const uint16_t DDDDD, reg_id& SD);
+void decode_DD_table(const uint16_t DD, reg_id& SD);
+void decode_DDF_table(const uint16_t DD, const uint16_t F, reg_id& S, reg_id& D);
+void decode_EE_table(const uint16_t EE, reg_id& D);
+void decode_F_table(const uint16_t F, reg_id& SD);
+void decode_h0hF_table(const uint16_t h0h, uint16_t F, reg_id& S, reg_id& D);
+void decode_HH_table(const uint16_t HH, reg_id& SD);
+void decode_HHH_table(const uint16_t HHH, reg_id& SD);
+void decode_IIIIx_table(const uint16_t IIII, const uint16_t x, reg_id& S, reg_id& D);
+void decode_JJJF_table(const uint16_t JJJ, const uint16_t F, reg_id& S, reg_id& D);
+void decode_JJF_table(const uint16_t JJ, const uint16_t F, reg_id& S, reg_id& D);
+void decode_JF_table(const uint16_t J, const uint16_t F, reg_id& S, reg_id& D);
+void decode_kSign_table(const uint16_t k, std::string& plusMinus);
+void decode_KKK_table(const uint16_t KKK, reg_id& D1, reg_id& D2);
+void decode_NN_table(uint16_t NN, reg_id& ret);
+void decode_TT_table(uint16_t TT, reg_id& ret);
+void decode_QQF_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D);
+void decode_QQF_special_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D);
+void decode_QQQF_table(const uint16_t QQQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D);
+void decode_RR_table(uint16_t RR, reg_id& ret);
+void decode_rr_table(uint16_t rr, reg_id& ret);
+void decode_s_table(const uint16_t s, op_mnem& arithmetic);
+void decode_ss_table(const uint16_t ss, op_mnem& arithmetic);
+void decode_uuuuF_table(const uint16_t uuuu, const uint16_t F, std::string& arg, reg_id& S, reg_id& D);
+void decode_Z_table(const uint16_t Z, std::string& ea);
+
+void assemble_ea_from_m_table(const uint16_t m, const int n, std::string& ea);
+void assemble_eas_from_mm_table(uint16_t mm, int n1, int n2, std::string& ea1, std::string& ea2);
+void assemble_ea_from_MM_table(uint16_t MM, int n, std::string& ea);
+void assemble_ea_from_q_table(uint16_t q, int n, std::string& ea);
+void assemble_ea_from_t_table(uint16_t t, uint16_t val, std::string& ea);
+void assemble_ea_from_z_table(uint16_t z, int n, std::string& ea);
+void assemble_D_from_P_table(uint16_t P, uint16_t ppppp, std::string& D);
+void assemble_arguments_from_W_table(uint16_t W, char ma, const reg_id& SD, const std::string& ea, std::string& S, std::string& D);
+void assemble_arguments_from_W_table(uint16_t W, char ma, const std::string& SD, const std::string& ea, std::string& S, std::string& D);
+void assemble_reg_from_W_table(uint16_t W, char ma, const reg_id& SD, const int8_t xx, std::string& S, std::string& D);
+void assemble_address_from_IO_short_address(uint16_t pp, std::string& ea);
+
+int8_t get_6_bit_signed_value(uint16_t bits);
+
+// Helpers
+uint16_t dsp56156_op_maskn(uint16_t cur, uint16_t mask);
+
+bool registerOverlap(const reg_id& r0, const size_t bmd, const reg_id& r1);
+
+uint16_t regValue16(dsp56156_core* cpustate, const reg_id& reg);
+void setReg16(dsp56156_core* cpustate, const uint16_t& value, const reg_id& reg);
+
+std::string regIdAsString(const reg_id& regId);
+std::string opMnemonicAsString(const op_mnem& mnem);
+reg_id stringAsRegID(const std::string& str);
+uint8_t regIDAsNum(const reg_id& regId);
+
+
+}
+#endif