From 450a57568e16822d625c3e0cd390e9c9e6a08718 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Mon, 19 Aug 2019 15:53:47 +0200 Subject: -dsp56k: Renamed relevant classes, files and namespaces to indicate that it is a DSP56156 core, not a DSP5600x core. [Ryan Holtz] --- scripts/src/cpu.lua | 40 +- src/devices/cpu/dsp56156/dsp56156.cpp | 515 ++++ src/devices/cpu/dsp56156/dsp56156.h | 259 ++ src/devices/cpu/dsp56156/dsp56def.h | 56 + src/devices/cpu/dsp56156/dsp56dsm.cpp | 34 + src/devices/cpu/dsp56156/dsp56dsm.h | 26 + src/devices/cpu/dsp56156/dsp56mem.cpp | 949 +++++++ src/devices/cpu/dsp56156/dsp56mem.h | 241 ++ src/devices/cpu/dsp56156/dsp56ops.hxx | 4903 +++++++++++++++++++++++++++++++++ src/devices/cpu/dsp56156/dsp56pcu.cpp | 488 ++++ src/devices/cpu/dsp56156/dsp56pcu.h | 150 + src/devices/cpu/dsp56156/inst.cpp | 786 ++++++ src/devices/cpu/dsp56156/inst.h | 3774 +++++++++++++++++++++++++ src/devices/cpu/dsp56156/opcode.cpp | 81 + src/devices/cpu/dsp56156/opcode.h | 46 + src/devices/cpu/dsp56156/pmove.cpp | 80 + src/devices/cpu/dsp56156/pmove.h | 335 +++ src/devices/cpu/dsp56156/tables.cpp | 900 ++++++ src/devices/cpu/dsp56156/tables.h | 93 + src/devices/cpu/dsp56k/dsp56def.h | 56 - src/devices/cpu/dsp56k/dsp56dsm.cpp | 34 - src/devices/cpu/dsp56k/dsp56dsm.h | 26 - src/devices/cpu/dsp56k/dsp56k.cpp | 515 ---- src/devices/cpu/dsp56k/dsp56k.h | 259 -- src/devices/cpu/dsp56k/dsp56mem.cpp | 949 ------- src/devices/cpu/dsp56k/dsp56mem.h | 241 -- src/devices/cpu/dsp56k/dsp56ops.hxx | 4903 --------------------------------- src/devices/cpu/dsp56k/dsp56pcu.cpp | 488 ---- src/devices/cpu/dsp56k/dsp56pcu.h | 150 - src/devices/cpu/dsp56k/inst.cpp | 786 ------ src/devices/cpu/dsp56k/inst.h | 3774 ------------------------- src/devices/cpu/dsp56k/opcode.cpp | 81 - src/devices/cpu/dsp56k/opcode.h | 46 - src/devices/cpu/dsp56k/pmove.cpp | 80 - src/devices/cpu/dsp56k/pmove.h | 335 --- src/devices/cpu/dsp56k/tables.cpp | 900 ------ src/devices/cpu/dsp56k/tables.h | 93 - src/mame/drivers/indigo.cpp | 2 +- src/mame/drivers/plygonet.cpp | 178 +- src/mame/includes/plygonet.h | 54 +- 40 files changed, 13853 insertions(+), 13853 deletions(-) create mode 100644 src/devices/cpu/dsp56156/dsp56156.cpp create mode 100644 src/devices/cpu/dsp56156/dsp56156.h create mode 100644 src/devices/cpu/dsp56156/dsp56def.h create mode 100644 src/devices/cpu/dsp56156/dsp56dsm.cpp create mode 100644 src/devices/cpu/dsp56156/dsp56dsm.h create mode 100644 src/devices/cpu/dsp56156/dsp56mem.cpp create mode 100644 src/devices/cpu/dsp56156/dsp56mem.h create mode 100644 src/devices/cpu/dsp56156/dsp56ops.hxx create mode 100644 src/devices/cpu/dsp56156/dsp56pcu.cpp create mode 100644 src/devices/cpu/dsp56156/dsp56pcu.h create mode 100644 src/devices/cpu/dsp56156/inst.cpp create mode 100644 src/devices/cpu/dsp56156/inst.h create mode 100644 src/devices/cpu/dsp56156/opcode.cpp create mode 100644 src/devices/cpu/dsp56156/opcode.h create mode 100644 src/devices/cpu/dsp56156/pmove.cpp create mode 100644 src/devices/cpu/dsp56156/pmove.h create mode 100644 src/devices/cpu/dsp56156/tables.cpp create mode 100644 src/devices/cpu/dsp56156/tables.h delete mode 100644 src/devices/cpu/dsp56k/dsp56def.h delete mode 100644 src/devices/cpu/dsp56k/dsp56dsm.cpp delete mode 100644 src/devices/cpu/dsp56k/dsp56dsm.h delete mode 100644 src/devices/cpu/dsp56k/dsp56k.cpp delete mode 100644 src/devices/cpu/dsp56k/dsp56k.h delete mode 100644 src/devices/cpu/dsp56k/dsp56mem.cpp delete mode 100644 src/devices/cpu/dsp56k/dsp56mem.h delete mode 100644 src/devices/cpu/dsp56k/dsp56ops.hxx delete mode 100644 src/devices/cpu/dsp56k/dsp56pcu.cpp delete mode 100644 src/devices/cpu/dsp56k/dsp56pcu.h delete mode 100644 src/devices/cpu/dsp56k/inst.cpp delete mode 100644 src/devices/cpu/dsp56k/inst.h delete mode 100644 src/devices/cpu/dsp56k/opcode.cpp delete mode 100644 src/devices/cpu/dsp56k/opcode.h delete mode 100644 src/devices/cpu/dsp56k/pmove.cpp delete mode 100644 src/devices/cpu/dsp56k/pmove.h delete mode 100644 src/devices/cpu/dsp56k/tables.cpp delete mode 100644 src/devices/cpu/dsp56k/tables.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 359fb71be9d..788e2cd3eb6 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1675,34 +1675,34 @@ if (CPUS["M680X0"]~=null or _OPTIONS["with-tools"]) then end -------------------------------------------------- --- Motorola/Freescale dsp56k ---@src/devices/cpu/dsp56k/dsp56k.h,CPUS["DSP56156"] = true +-- Motorola/Freescale DSP56156 +--@src/devices/cpu/dsp56156/dsp56156.h,CPUS["DSP56156"] = true -------------------------------------------------- if (CPUS["DSP56156"]~=null) then files { - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56k.cpp", - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56k.h", - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56mem.cpp", - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56mem.h", - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56pcu.cpp", - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56pcu.h", - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56def.h", - MAME_DIR .. "src/devices/cpu/dsp56k/dsp56ops.hxx", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56156.cpp", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56156.h", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56mem.cpp", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56mem.h", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56pcu.cpp", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56pcu.h", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56def.h", + MAME_DIR .. "src/devices/cpu/dsp56156/dsp56ops.hxx", } end if (CPUS["DSP56156"]~=null or _OPTIONS["with-tools"]) then - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/dsp56dsm.cpp") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/dsp56dsm.h") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/opcode.cpp") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/opcode.h") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/inst.cpp") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/inst.h") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/pmove.cpp") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/pmove.h") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/tables.cpp") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56k/tables.h") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/dsp56dsm.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/dsp56dsm.h") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/opcode.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/opcode.h") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/inst.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/inst.h") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/pmove.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/pmove.h") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/tables.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/dsp56156/tables.h") end -------------------------------------------------- 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 dsp56156_device::create_disassembler() +{ + return std::make_unique(); +} + +} // 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 create_disassembler() override; + +private: + address_space_config m_program_config; + address_space_config m_data_config; + required_shared_ptr 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 ¶ms) +{ + 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 ¶ms) 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: and X: */ + 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: 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: */ + /* 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) & 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::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 op = decodeInstruction(opc, w0, w1, true); + if (op) + { + // This parallel move only works for certain trailing instructions. + if (dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(op.get()) || + dynamic_cast(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(opc, w0, w1); + } + /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ + if ((w0 & 0xe097) == 0x6017) + { + return std::make_unique(opc, w0, w1); + } + /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ + else if ((w0 & 0xe094) == 0x6084) + { + return std::make_unique(opc, w0, w1); + } + /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ + else if ((w0 & 0xe094) == 0x6094) + { + return std::make_unique(opc, w0, w1); + } + /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ + else if ((w0 & 0xe094) == 0x6080) + { + return std::make_unique(opc, w0, w1); + } + /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ + else if ((w0 & 0xe094) == 0x6090) + { + return std::make_unique(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(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(opc, w0, w1); + } + /* MAC : 0001 0111 RRDD FQQQ : A-122 */ + else if ((w0 & 0xff00) == 0x1700) + { + return std::make_unique(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(opc, w0, w1); + } + /* ADD : .... .... 0000 FJJJ : A-22 */ + else if ((w0 & 0x00f0) == 0x0000) + { + return std::make_unique(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(opc, w0, w1); + } + /* TFR : .... .... 0001 FJJJ : A-212 */ + else if ((w0 & 0x00f0) == 0x0010) + { + return std::make_unique(opc, w0, w1); + } + + /* RND : .... .... 0010 F000 : A-188 */ + else if ((w0 & 0x00f7) == 0x0020) + { + return std::make_unique(opc, w0, w1); + } + /* TST : .... .... 0010 F001 : A-218 */ + else if ((w0 & 0x00f7) == 0x0021) + { + return std::make_unique(opc, w0, w1); + } + /* INC : .... .... 0010 F010 : A-104 */ + else if ((w0 & 0x00f7) == 0x0022) + { + return std::make_unique(opc, w0, w1); + } + /* INC24 : .... .... 0010 F011 : A-106 */ + else if ((w0 & 0x00f7) == 0x0023) + { + return std::make_unique(opc, w0, w1); + } + /* OR : .... .... 0010 F1JJ : A-176 */ + else if ((w0 & 0x00f4) == 0x0024) + { + return std::make_unique(opc, w0, w1); + } + + /* ASR : .... .... 0011 F000 : A-32 */ + else if ((w0 & 0x00f7) == 0x0030) + { + return std::make_unique(opc, w0, w1); + } + /* ASL : .... .... 0011 F001 : A-28 */ + else if ((w0 & 0x00f7) == 0x0031) + { + return std::make_unique(opc, w0, w1); + } + /* LSR : .... .... 0011 F010 : A-120 */ + else if ((w0 & 0x00f7) == 0x0032) + { + return std::make_unique(opc, w0, w1); + } + /* LSL : .... .... 0011 F011 : A-118 */ + else if ((w0 & 0x00f7) == 0x0033) + { + return std::make_unique(opc, w0, w1); + } + /* EOR : .... .... 0011 F1JJ : A-94 */ + else if ((w0 & 0x00f4) == 0x0034) + { + return std::make_unique(opc, w0, w1); + } + + /* SUBL : .... .... 0100 F001 : A-204 */ + else if ((w0 & 0x00f7) == 0x0041) + { + return std::make_unique(opc, w0, w1); + } + /* SUB : .... .... 0100 FJJJ : A-202 */ + else if ((w0 & 0x00f0) == 0x0040) + { + return std::make_unique(opc, w0, w1); + } + + /* CLR24 : .... .... 0101 F001 : A-62 */ + else if ((w0 & 0x00f7) == 0x0051) + { + return std::make_unique(opc, w0, w1); + } + /* SBC : .... .... 0101 F01J : A-198 */ + else if ((w0 & 0x00f6) == 0x0052) + { + return std::make_unique(opc, w0, w1); + } + /* CMP : .... .... 0101 FJJJ : A-64 */ + else if ((w0 & 0x00f0) == 0x0050) + { + return std::make_unique(opc, w0, w1); + } + + /* NEG : .... .... 0110 F000 : A-166 */ + else if ((w0 & 0x00f7) == 0x0060) + { + return std::make_unique(opc, w0, w1); + } + /* NOT : .... .... 0110 F001 : A-174 */ + else if ((w0 & 0x00f7) == 0x0061) + { + return std::make_unique(opc, w0, w1); + } + /* DEC : .... .... 0110 F010 : A-72 */ + else if ((w0 & 0x00f7) == 0x0062) + { + return std::make_unique(opc, w0, w1); + } + /* DEC24 : .... .... 0110 F011 : A-74 */ + else if ((w0 & 0x00f7) == 0x0063) + { + return std::make_unique(opc, w0, w1); + } + /* AND : .... .... 0110 F1JJ : A-24 */ + else if ((w0 & 0x00f4) == 0x0064) + { + return std::make_unique(opc, w0, w1); + } + + /* ABS : .... .... 0111 F001 : A-18 */ + if ((w0 & 0x00f7) == 0x0071) + { + return std::make_unique(opc, w0, w1); + } + /* ROR : .... .... 0111 F010 : A-192 */ + else if ((w0 & 0x00f7) == 0x0072) + { + return std::make_unique(opc, w0, w1); + } + /* ROL : .... .... 0111 F011 : A-190 */ + else if ((w0 & 0x00f7) == 0x0073) + { + return std::make_unique(opc, w0, w1); + } + /* CMPM : .... .... 0111 FJJJ : A-66 */ + else if ((w0 & 0x00f0) == 0x0070) + { + return std::make_unique(opc, w0, w1); + } + + /* MPY : .... .... 1k00 FQQQ : A-160 */ + else if ((w0 & 0x00b0) == 0x0080) + { + return std::make_unique(opc, w0, w1); + } + /* MPYR : .... .... 1k01 FQQQ : A-162 */ + else if ((w0 & 0x00b0) == 0x0090) + { + return std::make_unique(opc, w0, w1); + } + /* MAC : .... .... 1k10 FQQQ : A-122 */ + else if ((w0 & 0x00b0) == 0x00a0) + { + return std::make_unique(opc, w0, w1); + } + /* MACR : .... .... 1k11 FQQQ : A-124 */ + else if ((w0 & 0x00b0) == 0x00b0) + { + return std::make_unique(opc, w0, w1); + } + } + + /******************************/ + /* Remaining non-parallel ops */ + /******************************/ + /* ADC : 0001 0101 0000 F01J : A-20 */ + else if ((w0 & 0xfff6) == 0x1502) + { + return std::make_unique(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(opc, w0, w1); + } + /* ASL4 : 0001 0101 0011 F001 : A-30 */ + else if ((w0 & 0xfff7) == 0x1531) + { + return std::make_unique(opc, w0, w1); + } + /* ASR4 : 0001 0101 0011 F000 : A-34 */ + else if ((w0 & 0xfff7) == 0x1530) + { + return std::make_unique(opc, w0, w1); + } + /* ASR16 : 0001 0101 0111 F000 : A-36 */ + else if ((w0 & 0xfff7) == 0x1570) + { + return std::make_unique(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(opc, w0, w1); + } + /* Bcc : 0010 11cc ccee eeee : A-48 */ + else if ((w0 & 0xfc00) == 0x2c00) + { + return std::make_unique(opc, w0, w1); + } + /* Bcc : 0000 0111 RR10 cccc : A-48 */ + else if ((w0 & 0xff30) == 0x0720) + { + return std::make_unique(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(opc, w0, w1); + } + /* BRA : 0000 1011 aaaa aaaa : A-50 */ + else if ((w0 & 0xff00) == 0x0b00) + { + return std::make_unique(opc, w0, w1); + } + /* BRA : 0000 0001 0010 11RR : A-50 */ + else if ((w0 & 0xfffc) == 0x012c) + { + return std::make_unique(opc, w0, w1); + } + /* BRKc : 0000 0001 0001 cccc : A-52 */ + else if ((w0 & 0xfff0) == 0x0110) + { + return std::make_unique(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(opc, w0, w1); + } + /* BScc : 0000 0111 RR00 cccc : A-54 */ + else if ((w0 & 0xff30) == 0x0700) + { + return std::make_unique(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(opc, w0, w1); + } + /* BSR : 0000 0001 0010 10RR : A-56 */ + else if ((w0 & 0xfffc) == 0x0128) + { + return std::make_unique(opc, w0, w1); + } + /* CHKAAU : 0000 0000 0000 0100 : A-58 */ + else if ((w0 & 0xffff) == 0x0004) + { + return std::make_unique(opc, w0, w1); + } + /* DEBUG : 0000 0000 0000 0001 : A-68 */ + else if ((w0 & 0xffff) == 0x0001) + { + return std::make_unique(opc, w0, w1); + } + /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ + else if ((w0 & 0xfff0) == 0x0050) + { + return std::make_unique(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
(opc, w0, w1); + } + /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ + else if ((w0 & 0xffd0) == 0x1590) + { + return std::make_unique(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(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(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(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(opc, w0, w1); + } + /* ENDDO : 0000 0000 0000 1001 : A-92 */ + else if ((w0 & 0xffff) == 0x0009) + { + return std::make_unique(opc, w0, w1); + } + /* EXT : 0001 0101 0101 F010 : A-96 */ + else if ((w0 & 0xfff7) == 0x1552) + { + return std::make_unique(opc, w0, w1); + } + /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ + else if ((w0 & 0xffff) == 0x000f) + { + return std::make_unique(opc, w0, w1); + } + /* IMAC : 0001 0101 1010 FQQQ : A-100 */ + else if ((w0 & 0xfff0) == 0x15a0) + { + return std::make_unique(opc, w0, w1); + } + /* IMPY : 0001 0101 1000 FQQQ : A-102 */ + else if ((w0 & 0xfff0) == 0x1580) + { + return std::make_unique(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(opc, w0, w1); + } + /* Jcc : 0000 0110 RR10 cccc : A-108 */ + else if ((w0 & 0xff30) == 0x0620 ) + { + return std::make_unique(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(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(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(opc, w0, w1); + } + /* JScc : 0000 0110 RR00 cccc : A-112 */ + else if ((w0 & 0xff30) == 0x0600) + { + return std::make_unique(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(opc, w0, w1); + } + /* JSR : 0000 1010 AAAA AAAA : A-114 */ + else if ((w0 & 0xff00) == 0x0a00) + { + return std::make_unique(opc, w0, w1); + } + /* JSR : 0000 0001 0010 00RR : A-114 */ + else if ((w0 & 0xfffc) == 0x0120) + { + return std::make_unique(opc, w0, w1); + } + /* LEA : 0000 0001 11TT MMRR : A-116 */ + else if ((w0 & 0xffc0) == 0x01c0) + { + return std::make_unique(opc, w0, w1); + } + /* LEA : 0000 0001 10NN MMRR : A-116 */ + else if ((w0 & 0xffc0) == 0x0180) + { + return std::make_unique(opc, w0, w1); + } + /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ + else if ((w0 & 0xfff0) == 0x15e0) + { + return std::make_unique(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(opc, w0, w1); +// NEW // } + /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ + else if ((w0 & 0xf810) == 0x3800) + { + return std::make_unique(opc, w0, w1); + } + /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ + else if ((w0 & 0xf814) == 0x3810) + { + return std::make_unique(opc, w0, w1); + } + /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ + else if ((w0 & 0xf816) == 0x3816) + { + return std::make_unique(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(opc, w0, w1); + } + /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ + else if ((w0 & 0xfc00) == 0x2800) + { + return std::make_unique(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(opc, w0, w1); + } + /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ + else if ((w0 & 0xfc00) == 0x2000) + { + return std::make_unique(opc, w0, w1); + } + /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ + else if ((w0 & 0xfe20) == 0x0200) + { + return std::make_unique(opc, w0, w1); + } + /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ + else if ((w0 & 0xfe30) == 0x0230) + { + return std::make_unique(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(opc, w0, w1); + } + /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ + else if ((w0 & 0xfe20) == 0x1820) + { + return std::make_unique(opc, w0, w1); + } + /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ + else if ((w0 & 0xfe00) == 0x0c00) + { + return std::make_unique(opc, w0, w1); + } + /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ + else if ((w0 & 0xfe20) == 0x1800) + { + return std::make_unique(opc, w0, w1); + } + /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ + else if ((w0 & 0xfff0) == 0x15c0) + { + return std::make_unique(opc, w0, w1); + } + /* NEGC : 0001 0101 0110 F000 : A-168 */ + else if ((w0 & 0xfff7) == 0x1560) + { + return std::make_unique(opc, w0, w1); + } + /* NOP : 0000 0000 0000 0000 : A-170 */ + else if ((w0 & 0xffff) == 0x0000) + { + return std::make_unique(opc, w0, w1); + } + /* NORM : 0001 0101 0010 F0RR : A-172 */ + else if ((w0 & 0xfff4) == 0x1520) + { + return std::make_unique(opc, w0, w1); + } + /* ORI : 0001 1EE1 iiii iiii : A-178 */ + else if ((w0 & 0xf900) == 0x1900) + { + return std::make_unique(opc, w0, w1); + } + /* REP : 0000 0000 111- --RR : A-180 */ + else if ((w0 & 0xffe0) == 0x00e0) + { + return std::make_unique(opc, w0, w1); + } + /* REP : 0000 1111 iiii iiii : A-180 */ + else if ((w0 & 0xff00) == 0x0f00) + { + return std::make_unique(opc, w0, w1); + } + /* REP : 0000 0100 001D DDDD : A-180 */ + else if ((w0 & 0xffe0) == 0x0420) + { + return std::make_unique(opc, w0, w1); + } + /* REPcc : 0000 0001 0101 cccc : A-184 */ + else if ((w0 & 0xfff0) == 0x0150) + { + return std::make_unique(opc, w0, w1); + } + /* RESET : 0000 0000 0000 1000 : A-186 */ + else if ((w0 & 0xffff) == 0x0008) + { + return std::make_unique(opc, w0, w1); + } + /* RTI : 0000 0000 0000 0111 : A-194 */ + else if ((w0 & 0xffff) == 0x0007) + { + return std::make_unique(opc, w0, w1); + } + /* RTS : 0000 0000 0000 0110 : A-196 */ + else if ((w0 & 0xffff) == 0x0006) + { + return std::make_unique(opc, w0, w1); + } + /* STOP : 0000 0000 0000 1010 : A-200 */ + else if ((w0 & 0xffff) == 0x000a) + { + return std::make_unique(opc, w0, w1); + } + /* SWAP : 0001 0101 0111 F001 : A-206 */ + else if ((w0 & 0xfff7) == 0x1571) + { + return std::make_unique(opc, w0, w1); + } + /* SWI : 0000 0000 0000 0101 : A-208 */ + else if ((w0 & 0xffff) == 0x0005) + { + return std::make_unique(opc, w0, w1); + } + /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ + else if ((w0 & 0xfc02) == 0x1000) + { + return std::make_unique(opc, w0, w1); + } + /* TFR(2) : 0001 0101 0000 F00J : A-214 */ + else if ((w0 & 0xfff6) == 0x1500) + { + return std::make_unique(opc, w0, w1); + } + /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ + else if ((w0 & 0xfc00) == 0x2400) + { + return std::make_unique(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(opc, w0, w1); + } + /* WAIT : 0000 0000 0000 1011 : A-222 */ + else if ((w0 & 0xffff) == 0x000b) + { + return std::make_unique(opc, w0, w1); + } + /* ZERO : 0001 0101 0101 F000 : A-224 */ + else if ((w0 & 0xfff7) == 0x1550) + { + return std::make_unique(opc, w0, w1); + } + /* SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! */ + else if ((w0 & 0xfff0) == 0x15d0) + { + return std::make_unique(opc, w0, w1); + } + /* SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! */ + else if ((w0 & 0xfff0) == 0x15f0) + { + return std::make_unique(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 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 + +#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 m_instruction; + std::unique_ptr 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::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(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(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(opc, w0, w1); + } + /* Address Register Update : 0011 0zRR .... .... : A-135 */ + else if ((w0 & 0xf800) == 0x3000) + { + return std::make_unique(opc, w0, w1); + } + /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ + else if ((w0 & 0x8000) == 0x8000) + { + return std::make_unique(opc, w0, w1); + } + /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ + else if ((w0 & 0xf000) == 0x5000) + { + return std::make_unique(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(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 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 +#include +#include + +#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) & 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 +#include + +#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 diff --git a/src/devices/cpu/dsp56k/dsp56def.h b/src/devices/cpu/dsp56k/dsp56def.h deleted file mode 100644 index 14fe208dbb8..00000000000 --- a/src/devices/cpu/dsp56k/dsp56def.h +++ /dev/null @@ -1,56 +0,0 @@ -// 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 "dsp56k.h" - -namespace DSP56K -{ -/*************************************************************************** - 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 DSP56K - -#endif diff --git a/src/devices/cpu/dsp56k/dsp56dsm.cpp b/src/devices/cpu/dsp56k/dsp56dsm.cpp deleted file mode 100644 index 847a4bda6a0..00000000000 --- a/src/devices/cpu/dsp56k/dsp56dsm.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -/*************************************************************************** - - dsp56dsm.c - Disassembler for the portable Motorola/Freescale dsp56k emulator. - Written by Andrew Gardner - -***************************************************************************/ - -#include "emu.h" -#include "opcode.h" -#include "dsp56dsm.h" - -u32 dsp56k_disassembler::opcode_alignment() const -{ - return 1; -} - -/*****************************/ -/* Main disassembly function */ -/*****************************/ -offs_t dsp56k_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) -{ - const uint16_t w0 = opcodes.r16(pc); - const uint16_t w1 = opcodes.r16(pc+1); - - // Decode and disassemble. - DSP56K::Opcode op(w0, w1); - stream << op.disassemble(); - - const unsigned size = op.size(); - return (size | SUPPORTED); -} diff --git a/src/devices/cpu/dsp56k/dsp56dsm.h b/src/devices/cpu/dsp56k/dsp56dsm.h deleted file mode 100644 index 3e0f7cb87ff..00000000000 --- a/src/devices/cpu/dsp56k/dsp56dsm.h +++ /dev/null @@ -1,26 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -/*************************************************************************** - - dsp56dsm.c - Disassembler for the portable Motorola/Freescale dsp56k emulator. - Written by Andrew Gardner - -***************************************************************************/ - -#ifndef MAME_CPU_DSP56K_DSP56DSM_H -#define MAME_CPU_DSP56K_DSP56DSM_H - -#pragma once - -class dsp56k_disassembler : public util::disasm_interface -{ -public: - dsp56k_disassembler() = default; - virtual ~dsp56k_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 ¶ms) override; -}; - -#endif diff --git a/src/devices/cpu/dsp56k/dsp56k.cpp b/src/devices/cpu/dsp56k/dsp56k.cpp deleted file mode 100644 index c4da3de678a..00000000000 --- a/src/devices/cpu/dsp56k/dsp56k.cpp +++ /dev/null @@ -1,515 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -/*************************************************************************** - - dsp56k.c - Core implementation for the portable DSP56k 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 "dsp56k.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, DSP56K, dsp56k_device, "dsp56156", "Motorola DSP56156") - - -namespace DSP56K { - -enum -{ - // PCU - DSP56K_PC=1, - DSP56K_SR, - DSP56K_LC, - DSP56K_LA, - DSP56K_SP, - DSP56K_OMR, - - // ALU - DSP56K_X, DSP56K_Y, - DSP56K_A, DSP56K_B, - - // AGU - DSP56K_R0,DSP56K_R1,DSP56K_R2,DSP56K_R3, - DSP56K_N0,DSP56K_N1,DSP56K_N2,DSP56K_N3, - DSP56K_M0,DSP56K_M1,DSP56K_M2,DSP56K_M3, - DSP56K_TEMP, - DSP56K_STATUS, - - // CPU STACK - DSP56K_ST0, - DSP56K_ST1, - DSP56K_ST2, - DSP56K_ST3, - DSP56K_ST4, - DSP56K_ST5, - DSP56K_ST6, - DSP56K_ST7, - DSP56K_ST8, - DSP56K_ST9, - DSP56K_ST10, - DSP56K_ST11, - DSP56K_ST12, - DSP56K_ST13, - DSP56K_ST14, - DSP56K_ST15 -}; - - -/**************************************************************************** - * Internal Memory Maps - ****************************************************************************/ -void dsp56k_device::dsp56156_program_map(address_map &map) -{ - map(0x0000, 0x07ff).ram().share("dsk56k_program_ram"); /* 1-5 */ -// AM_RANGE(0x2f00,0x2fff) AM_ROM /* 1-5 PROM reserved memory. Is this the right spot for it? */ -} - -void dsp56k_device::dsp56156_x_data_map(address_map &map) -{ - map(0x0000, 0x07ff).ram(); /* 1-5 */ - map(0xffc0, 0xffff).rw(FUNC(dsp56k_device::peripheral_register_r), FUNC(dsp56k_device::peripheral_register_w)); /* 1-5 On-chip peripheral registers memory mapped in data space */ -} - - -dsp56k_device::dsp56k_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(dsp56k_device::dsp56156_program_map), this)) - , m_data_config("data", ENDIANNESS_LITTLE, 16, 16, -1, address_map_constructor(FUNC(dsp56k_device::dsp56156_x_data_map), this)) - , m_program_ram(*this, "dsk56k_program_ram") -{ -} - -device_memory_interface::space_config_vector dsp56k_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 dsp56k_device::execute_set_input(int irqline, int state) -{ - //logerror("DSP56k set irq line %d %d\n", irqline, state); - - switch(irqline) - { - case DSP56K_IRQ_MODA: - // TODO: 1-12 Get this triggering right - if (irqa_trigger(&m_dsp56k_core)) - logerror("DSP56k IRQA is set to fire on the \"Negative Edge\".\n"); - - if (state != CLEAR_LINE) - m_dsp56k_core.modA_state = true; - else - m_dsp56k_core.modA_state = false; - - if (m_dsp56k_core.reset_state != true) - dsp56k_add_pending_interrupt(&m_dsp56k_core, "IRQA"); - break; - - case DSP56K_IRQ_MODB: - // TODO: 1-12 Get this triggering right - if (irqb_trigger(&m_dsp56k_core)) - logerror("DSP56k IRQB is set to fire on the \"Negative Edge\".\n"); - - if (state != CLEAR_LINE) - m_dsp56k_core.modB_state = true; - else - m_dsp56k_core.modB_state = false; - - if (m_dsp56k_core.reset_state != true) - dsp56k_add_pending_interrupt(&m_dsp56k_core, "IRQB"); - break; - - case DSP56K_IRQ_MODC: - if (state != CLEAR_LINE) - m_dsp56k_core.modC_state = true; - else - m_dsp56k_core.modC_state = false; - - // TODO : Set bus mode or whatever - break; - - case DSP56K_IRQ_RESET: - if (state != CLEAR_LINE) - m_dsp56k_core.reset_state = true; - else - { - /* If it changes state from asserted to cleared. Call the reset function. */ - if (m_dsp56k_core.reset_state == true) - device_reset(); - - m_dsp56k_core.reset_state = false; - } - - // dsp56k_add_pending_interrupt("Hardware RESET"); - break; - - default: - logerror("DSP56k 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 dsp56k_device::agu_init() -{ - /* save states - dsp56k_agu members */ - save_item(NAME(m_dsp56k_core.AGU.r0)); - save_item(NAME(m_dsp56k_core.AGU.r1)); - save_item(NAME(m_dsp56k_core.AGU.r2)); - save_item(NAME(m_dsp56k_core.AGU.r3)); - save_item(NAME(m_dsp56k_core.AGU.n0)); - save_item(NAME(m_dsp56k_core.AGU.n1)); - save_item(NAME(m_dsp56k_core.AGU.n2)); - save_item(NAME(m_dsp56k_core.AGU.n3)); - save_item(NAME(m_dsp56k_core.AGU.m0)); - save_item(NAME(m_dsp56k_core.AGU.m1)); - save_item(NAME(m_dsp56k_core.AGU.m2)); - save_item(NAME(m_dsp56k_core.AGU.m3)); - save_item(NAME(m_dsp56k_core.AGU.temp)); -} - -void dsp56k_device::alu_init() -{ - /* save states - dsp56k_alu members */ - save_item(NAME(m_dsp56k_core.ALU.x)); - save_item(NAME(m_dsp56k_core.ALU.y)); - save_item(NAME(m_dsp56k_core.ALU.a)); - save_item(NAME(m_dsp56k_core.ALU.b)); -} - -void dsp56k_device::device_start() -{ - memset(&m_dsp56k_core, 0, sizeof(m_dsp56k_core)); - - m_dsp56k_core.device = this; - m_dsp56k_core.program_ram = m_program_ram; - - /* Call specific module inits */ - pcu_init(&m_dsp56k_core, this); - agu_init(); - alu_init(); - - /* HACK - You're not in bootstrap mode upon bootup */ - m_dsp56k_core.bootstrap_mode = BOOTSTRAP_OFF; - - /* Clear the irq states */ - m_dsp56k_core.modA_state = false; - m_dsp56k_core.modB_state = false; - m_dsp56k_core.modC_state = false; - m_dsp56k_core.reset_state = false; - - /* save states - dsp56k_core members */ - save_item(NAME(m_dsp56k_core.modA_state)); - save_item(NAME(m_dsp56k_core.modB_state)); - save_item(NAME(m_dsp56k_core.modC_state)); - save_item(NAME(m_dsp56k_core.reset_state)); - save_item(NAME(m_dsp56k_core.bootstrap_mode)); - save_item(NAME(m_dsp56k_core.repFlag)); - save_item(NAME(m_dsp56k_core.repAddr)); - save_item(NAME(m_dsp56k_core.ppc)); - save_item(NAME(m_dsp56k_core.op)); - save_item(NAME(m_dsp56k_core.interrupt_cycles)); - - /* save states - dsp56k_host_interface members */ - save_item(NAME(m_dsp56k_core.HI.icr)); - save_item(NAME(m_dsp56k_core.HI.cvr)); - save_item(NAME(m_dsp56k_core.HI.isr)); - save_item(NAME(m_dsp56k_core.HI.ivr)); - save_item(NAME(m_dsp56k_core.HI.trxh)); - save_item(NAME(m_dsp56k_core.HI.trxl)); - save_item(NAME(m_dsp56k_core.HI.bootstrap_offset)); - - save_item(NAME(m_dsp56k_core.peripheral_ram)); - - m_dsp56k_core.program = &space(AS_PROGRAM); - m_dsp56k_core.cache = m_dsp56k_core.program->cache<1, -1, ENDIANNESS_LITTLE>(); - m_dsp56k_core.data = &space(AS_DATA); - - state_add(DSP56K_PC, "PC", m_dsp56k_core.PCU.pc).formatstr("%04X"); - state_add(DSP56K_SR, "SR", m_dsp56k_core.PCU.sr).formatstr("%04X"); - state_add(DSP56K_LC, "LC", m_dsp56k_core.PCU.lc).formatstr("%04X"); - state_add(DSP56K_LA, "LA", m_dsp56k_core.PCU.la).formatstr("%04X"); - state_add(DSP56K_SP, "SP", m_dsp56k_core.PCU.sp).formatstr("%02X"); - state_add(DSP56K_OMR, "OMR", m_dsp56k_core.PCU.omr).formatstr("%02X"); - - state_add(DSP56K_X, "X", m_dsp56k_core.ALU.x.d).mask(0xffffffff).formatstr("%9s"); - state_add(DSP56K_Y, "Y", m_dsp56k_core.ALU.y.d).mask(0xffffffff).formatstr("%9s"); - - state_add(DSP56K_A, "A", m_dsp56k_core.ALU.a.q).mask(u64(0xffffffffffffffffU)).formatstr("%12s"); /* could benefit from a better mask? */ - state_add(DSP56K_B, "B", m_dsp56k_core.ALU.b.q).mask(u64(0xffffffffffffffffU)).formatstr("%12s"); /* could benefit from a better mask? */ - - state_add(DSP56K_R0, "R0", m_dsp56k_core.AGU.r0).formatstr("%04X"); - state_add(DSP56K_R1, "R1", m_dsp56k_core.AGU.r1).formatstr("%04X"); - state_add(DSP56K_R2, "R2", m_dsp56k_core.AGU.r2).formatstr("%04X"); - state_add(DSP56K_R3, "R3", m_dsp56k_core.AGU.r3).formatstr("%04X"); - - state_add(DSP56K_N0, "N0", m_dsp56k_core.AGU.n0).formatstr("%04X"); - state_add(DSP56K_N1, "N1", m_dsp56k_core.AGU.n1).formatstr("%04X"); - state_add(DSP56K_N2, "N2", m_dsp56k_core.AGU.n2).formatstr("%04X"); - state_add(DSP56K_N3, "N3", m_dsp56k_core.AGU.n3).formatstr("%04X"); - - state_add(DSP56K_M0, "M0", m_dsp56k_core.AGU.m0).formatstr("%04X"); - state_add(DSP56K_M1, "M1", m_dsp56k_core.AGU.m1).formatstr("%04X"); - state_add(DSP56K_M2, "M2", m_dsp56k_core.AGU.m2).formatstr("%04X"); - state_add(DSP56K_M3, "M3", m_dsp56k_core.AGU.m3).formatstr("%04X"); - - state_add(DSP56K_TEMP, "TMP", m_dsp56k_core.AGU.temp).formatstr("%04X").noshow(); - //state_add(DSP56K_STATUS, "STS", STATUS).formatstr("%02X"); - - state_add(DSP56K_ST0, "ST0", m_dsp56k_core.PCU.ss[0].d).formatstr("%08X"); - state_add(DSP56K_ST1, "ST1", m_dsp56k_core.PCU.ss[1].d).formatstr("%08X"); - state_add(DSP56K_ST2, "ST2", m_dsp56k_core.PCU.ss[2].d).formatstr("%08X"); - state_add(DSP56K_ST3, "ST3", m_dsp56k_core.PCU.ss[3].d).formatstr("%08X"); - state_add(DSP56K_ST4, "ST4", m_dsp56k_core.PCU.ss[4].d).formatstr("%08X"); - state_add(DSP56K_ST5, "ST5", m_dsp56k_core.PCU.ss[5].d).formatstr("%08X"); - state_add(DSP56K_ST6, "ST6", m_dsp56k_core.PCU.ss[6].d).formatstr("%08X"); - state_add(DSP56K_ST7, "ST7", m_dsp56k_core.PCU.ss[7].d).formatstr("%08X"); - state_add(DSP56K_ST8, "ST8", m_dsp56k_core.PCU.ss[8].d).formatstr("%08X"); - state_add(DSP56K_ST9, "ST9", m_dsp56k_core.PCU.ss[9].d).formatstr("%08X"); - state_add(DSP56K_ST10, "ST10", m_dsp56k_core.PCU.ss[10].d).formatstr("%08X"); - state_add(DSP56K_ST11, "ST11", m_dsp56k_core.PCU.ss[11].d).formatstr("%08X"); - state_add(DSP56K_ST12, "ST12", m_dsp56k_core.PCU.ss[12].d).formatstr("%08X"); - state_add(DSP56K_ST13, "ST13", m_dsp56k_core.PCU.ss[13].d).formatstr("%08X"); - state_add(DSP56K_ST14, "ST14", m_dsp56k_core.PCU.ss[14].d).formatstr("%08X"); - state_add(DSP56K_ST15, "ST15", m_dsp56k_core.PCU.ss[15].d).formatstr("%08X"); - - state_add(STATE_GENPC, "GENPC", m_dsp56k_core.PCU.pc).noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_dsp56k_core.ppc).noshow(); - state_add(STATE_GENSP, "GENSP", m_dsp56k_core.PCU.sp).noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_dsp56k_core.PCU.sr).formatstr("%14s").noshow(); - - set_icountptr(m_dsp56k_core.icount); -} - - -void dsp56k_device::state_string_export(const device_state_entry &entry, std::string &str) const -{ - const dsp56k_core *cpustate = &m_dsp56k_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 DSP56K_X: - str = string_format("%04x %04x", X1, X0); - break; - - case DSP56K_Y: - str = string_format("%04x %04x", Y1, Y0); - break; - - case DSP56K_A: - str = string_format("%02x %04x %04x", A2, A1, A0); - break; - - case DSP56K_B: - str = string_format("%02x %04x %04x", B2, B1, B0); - break; - } -} - -/*************************************************************************** - RESET BEHAVIOR -***************************************************************************/ -static void agu_reset(dsp56k_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(dsp56k_core* cpustate) -{ - X = 0x00000000; - Y = 0x00000000; - A = 0x0000000000; - B = 0x0000000000; -} - -void dsp56k_device::device_reset() -{ - logerror("Dsp56k reset\n"); - - m_dsp56k_core.interrupt_cycles = 0; - - m_dsp56k_core.repFlag = 0; - m_dsp56k_core.repAddr = 0x0000; - - pcu_reset(&m_dsp56k_core); - mem_reset(&m_dsp56k_core); - agu_reset(&m_dsp56k_core); - alu_reset(&m_dsp56k_core); - - m_dsp56k_core.ppc = m_dsp56k_core.PCU.pc; - - /* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */ - m_dsp56k_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(dsp56k_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 dsp56k_device::execute_run() -{ - /* If reset line is asserted, do nothing */ - if (m_dsp56k_core.reset_state) - { - m_dsp56k_core.icount = 0; - return; - } - - /* HACK - if you're in bootstrap mode, simply pretend you ate up all your cycles waiting for data. */ - if (m_dsp56k_core.bootstrap_mode != BOOTSTRAP_OFF) - { - m_dsp56k_core.icount = 0; - return; - } - - //m_dsp56k_core.icount -= m_dsp56k_core.interrupt_cycles; - //m_dsp56k_core.interrupt_cycles = 0; - - while(m_dsp56k_core.icount > 0) - { - execute_one(&m_dsp56k_core); - if (0) m_dsp56k_core.icount -= execute_one_new(&m_dsp56k_core); - pcu_service_interrupts(&m_dsp56k_core); // TODO: Is it incorrect to service after each instruction? - } -} - - -std::unique_ptr dsp56k_device::create_disassembler() -{ - return std::make_unique(); -} - -} // namespace DSP56K diff --git a/src/devices/cpu/dsp56k/dsp56k.h b/src/devices/cpu/dsp56k/dsp56k.h deleted file mode 100644 index bee7c335b03..00000000000 --- a/src/devices/cpu/dsp56k/dsp56k.h +++ /dev/null @@ -1,259 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -/*************************************************************************** - - dsp56k.h - Interface file for the portable Motorola/Freescale DSP56k emulator. - Written by Andrew Gardner - -***************************************************************************/ - - -#ifndef MAME_CPU_DSP56K_DSP56K_H -#define MAME_CPU_DSP56K_DSP56K_H - -#pragma once - - - -// IRQ Lines -// MODA and MODB are also known as IRQA and IRQB -#define DSP56K_IRQ_MODA 0 -#define DSP56K_IRQ_MODB 1 -#define DSP56K_IRQ_MODC 2 -#define DSP56K_IRQ_RESET 3 /* Is this needed? */ - - -namespace DSP56K { - -/*************************************************************************** - STRUCTURES & TYPEDEFS -***************************************************************************/ -// 5-4 Host Interface -struct dsp56k_host_interface -{ - // **** Dsp56k 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 dsp56k_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 dsp56k_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 dsp56k_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 dsp56k_interrupt_sources array) - int8_t pending_interrupts[32]; - - // Basics - - // Other PCU internals - uint16_t reset_vector; - -}; - -// 1-8 The dsp56156 CORE -struct dsp56k_core -{ - // PROGRAM CONTROLLER - dsp56k_pcu PCU; - - // ADR ALU (AGU) - dsp56k_agu AGU; - - // CLOCK GEN - //static emu_timer *dsp56k_timer; // 1-5, 1-8 - Clock gen - - // DATA ALU - dsp56k_data_alu ALU; - - // OnCE - - // IBS and BITFIELD UNIT - - // Host Interface - dsp56k_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 dsp56k_device : public cpu_device -{ -public: - dsp56k_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 == DSP56K_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 create_disassembler() override; - -private: - address_space_config m_program_config; - address_space_config m_data_config; - required_shared_ptr m_program_ram; - - dsp56k_core m_dsp56k_core; - - void agu_init(); - void alu_init(); -}; - -} // namespace DSP56K - - -DECLARE_DEVICE_TYPE_NS(DSP56156, DSP56K, dsp56k_device) -using DSP56K::dsp56k_device; - -#endif // MAME_CPU_DSP56K_DSP56K_H diff --git a/src/devices/cpu/dsp56k/dsp56mem.cpp b/src/devices/cpu/dsp56k/dsp56mem.cpp deleted file mode 100644 index 257865cb325..00000000000 --- a/src/devices/cpu/dsp56k/dsp56mem.cpp +++ /dev/null @@ -1,949 +0,0 @@ -// 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 DSP56K { - -/* IPR Accessor Implementations */ -void IPR_set(dsp56k_core* cpustate, uint16_t value) -{ - /* TODO: Is there anything else? */ - IPR = value; -} - -int8_t irqa_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0003) >> 0) - 1; } -uint8_t irqa_trigger(dsp56k_core* cpustate){ return (IPR & 0x0004) >> 2; } -int8_t irqb_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0018) >> 3) - 1; } -uint8_t irqb_trigger(dsp56k_core* cpustate){ return (IPR & 0x0002) >> 5; } -int8_t codec_ipl(dsp56k_core* cpustate) { return ((IPR & 0x00c0) >> 6) - 1; } -int8_t host_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0300) >> 8) - 1; } -int8_t ssi0_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0c00) >> 10) - 1; } -int8_t ssi1_ipl(dsp56k_core* cpustate) { return ((IPR & 0x3000) >> 12) - 1; } -int8_t tm_ipl(dsp56k_core* cpustate) { return ((IPR & 0xc000) >> 14) - 1; } - -void mem_reset(dsp56k_core* cpustate) -{ - // Reset the HI registers - dsp56k_host_interface_reset(cpustate); - - // Reset the IO registers - dsp56k_io_reset(cpustate); -} - - -/*************************************************************************** - HOST INTERFACE -***************************************************************************/ -/***************/ -/* DSP56k SIDE */ -/***************/ -/************************************/ -/* Host Control Register (HCR) Bits */ -/************************************/ -void HCR_set(dsp56k_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(dsp56k_core* cpustate) { return ((HCR & 0x0010) != 0); } -//uint16_t HF2_bit(dsp56k_core* cpustate) { return ((HCR & 0x0008) != 0); } -uint16_t HCIE_bit(dsp56k_core* cpustate) { return ((HCR & 0x0004) != 0); } -uint16_t HTIE_bit(dsp56k_core* cpustate) { return ((HCR & 0x0002) != 0); } -uint16_t HRIE_bit(dsp56k_core* cpustate) { return ((HCR & 0x0001) != 0); } - -void HF3_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HCR &= ~(0x0010); - HCR |= (value << 4); - - HF3_bit_host_set(cpustate, value); -} -void HF2_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HCR &= ~(0x0008); - HCR |= (value << 3); - - HF2_bit_host_set(cpustate, value); -} -void HCIE_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HCR &= ~(0x0004); - HCR |= (value << 2); -} -void HTIE_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HCR &= ~(0x0002); - HCR |= (value << 1); -} -void HRIE_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HCR &= ~(0x0001); - HCR |= (value << 0); -} - -/***********************************/ -/* Host Status Register (HSR) Bits */ -/***********************************/ -//uint16_t DMA_bit(dsp56k_core* cpustate) { return ((HSR & 0x0080) != 0); } -//uint16_t HF1_bit(dsp56k_core* cpustate) { return ((HSR & 0x0010) != 0); } -//uint16_t HF0_bit(dsp56k_core* cpustate) { return ((HSR & 0x0008) != 0); } -//uint16_t HCP_bit(dsp56k_core* cpustate) { return ((HSR & 0x0004) != 0); } -uint16_t HTDE_bit(dsp56k_core* cpustate) { return ((HSR & 0x0002) != 0); } -uint16_t HRDF_bit(dsp56k_core* cpustate) { return ((HSR & 0x0001) != 0); } - -void DMA_bit_set(dsp56k_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(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HSR &= ~(0x0010); - HSR |= (value << 4); -} -void HF0_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HSR &= ~(0x0008); - HSR |= (value << 3); -} -void HCP_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x01; - HSR &= ~(0x0004); - HSR |= (value << 2); - - if (value && HCIE_bit(cpustate)) - dsp56k_add_pending_interrupt(cpustate, "Host Command"); -} -void HTDE_bit_set(dsp56k_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)) - dsp56k_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)) - dsp56k_host_interface_HTX_to_host(cpustate); -} -void HRDF_bit_set(dsp56k_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)) - dsp56k_add_pending_interrupt(cpustate, "Host Receive Data"); - - // 5-5 If both me and TXDE are cleared, transmit data to the dsp56k - if (!value && !TXDE_bit(cpustate)) - dsp56k_host_interface_host_to_HTX(cpustate); -} - - - -/*************/ -/* HOST SIDE */ -/*************/ -/*****************************************/ -/* Interrupt Control Register (ICR) Bits */ -/*****************************************/ -void ICR_set(dsp56k_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(dsp56k_core* cpustate); #define x_initBIT ((dsp56k.HI.ICR & 0x0080) != 0) -//uint8_t HM1_bit(dsp56k_core* cpustate); #define x_hm1BIT ((dsp56k.HI.ICR & 0x0040) != 0) -//uint8_t HM0_bit(dsp56k_core* cpustate); #define x_hm0BIT ((dsp56k.HI.ICR & 0x0020) != 0) -//uint8_t HF1_bit_host(dsp56k_core* cpustate); #define x_hf1BIT ((dsp56k.HI.ICR & 0x0010) != 0) -//uint8_t HF0_bit_host(dsp56k_core* cpustate); #define x_hf0BIT ((dsp56k.HI.ICR & 0x0008) != 0) -//uint8_t TREQ_bit(dsp56k_core* cpustate); #define x_treqBIT ((dsp56k.HI.ICR & 0x0002) != 0) -//uint8_t RREQ_bit(dsp56k_core* cpustate); #define x_rreqBIT ((dsp56k.HI.ICR & 0x0001) != 0) - -//void INIT_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_initBIT() (dsp56k.HI.ICR &= (~0x0080)) -//void HM1_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_hm1BIT() (dsp56k.HI.ICR &= (~0x0040)) -//void HM0_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_hm0BIT() (dsp56k.HI.ICR &= (~0x0020)) -void HF1_bit_host_set(dsp56k_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(dsp56k_core* cpustate, uint8_t value) -{ - value = value & 0x01; - ICR &= ~(0x08); - ICR |= (value << 3); - - HF0_bit_set(cpustate, value); // 5-13 -} -void TREQ_bit_set(dsp56k_core* cpustate, uint8_t value) -{ - value = value & 0x01; - ICR &= ~(0x02); - ICR |= (value << 1); -} -void RREQ_bit_set(dsp56k_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(dsp56k_core* cpustate) { return (CVR & 0x1f); } - -void CVR_set(dsp56k_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(dsp56k_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(dsp56k_core* cpustate, uint8_t value) -{ - value = value & 0x1f; - CVR &= ~(0x1f); - CVR |= (value << 0); -} - - -/****************************************/ -/* Interrupt Status Register (ISR) Bits */ -/****************************************/ -uint8_t TXDE_bit(dsp56k_core* cpustate) { return ((ISR & 0x0002) != 0); } -uint8_t RXDF_bit(dsp56k_core* cpustate) { return ((ISR & 0x0001) != 0); } - -void HF3_bit_host_set(dsp56k_core* cpustate, uint8_t value) -{ - value = value & 0x01; - ISR &= ~(0x0010); - ISR |= (value << 4); -} -void HF2_bit_host_set(dsp56k_core* cpustate, uint8_t value) -{ - value = value & 0x01; - ISR &= ~(0x0008); - ISR |= (value << 3); -} - -void TXDE_bit_set(dsp56k_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 dsp56k - if (!value && !HRDF_bit(cpustate)) - dsp56k_host_interface_host_to_HTX(cpustate); -} - -void RXDF_bit_set(dsp56k_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)) - dsp56k_host_interface_HTX_to_host(cpustate); -} - - -// TODO: 5-11 What is the host processor Initialize function? - -void dsp56k_host_interface_reset(dsp56k_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 dsp56k_host_interface_HTX_to_host(dsp56k_core* cpustate) -{ - RXH = ((HTX & 0xff00) >> 8); - RXL = ((HTX & 0x00ff)); - RXDF_bit_set(cpustate, 1); - HTDE_bit_set(cpustate, 1); -} - -void dsp56k_host_interface_host_to_HTX(dsp56k_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(dsp56k_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(dsp56k_core* cpustate); -//uint16_t BS_bit(dsp56k_core* cpustate); -//uint16_t external_x_wait_states(dsp56k_core* cpustate); -//uint16_t external_p_wait_states(dsp56k_core* cpustate); - -void RH_bit_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x0001; - BCR &= ~(0x8000); - BCR |= (value << 15); - - // TODO: 4-6 Assert BR pin? -} -void BS_bit_set(dsp56k_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(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x001f; - BCR &= ~(0x03e0); - BCR |= (value << 5); -} -void external_p_wait_states_set(dsp56k_core* cpustate, uint16_t value) -{ - value = value & 0x001f; - BCR &= ~(0x001f); - BCR |= (value << 0); -} - - -/* Port B Control Register PBC */ -void PBC_set(dsp56k_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(dsp56k_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(dsp56k_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 dsp56k io restrictions, etc. */ -} - -/* Port B Data Register (PBD) */ -void PBD_set(dsp56k_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 dsp56k io restrictions, etc. */ -} - -/* Port C Control Register (PCC) */ -void PCC_set(dsp56k_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 dsp56k timer and control glue */ -} - -/* Port C Data Direction Register (PCDDR) */ -void PCDDR_set(dsp56k_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 dsp56k io restrictions, etc. */ -} - -/* Port C Data Register (PCD) */ -void PCD_set(dsp56k_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 dsp56k_io_reset(dsp56k_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( dsp56k_device::peripheral_register_r ) -{ - dsp56k_core* cpustate = &m_dsp56k_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 (!DSP56K::HRDF_bit(cpustate)) - return 0xbeef; - else - { - uint16_t value = HRX; // TODO: Maybe not exactly right? Just being safe. - DSP56K::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( dsp56k_device::peripheral_register_w ) -{ - dsp56k_core* cpustate = &m_dsp56k_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: - DSP56K::PBC_set(cpustate, data); - break; - - // Port C Control Register (PCC) - case 0xffc1: - DSP56K::PCC_set(cpustate, data); - break; - - // Port B Data Direction Register (PBDDR) - case 0xffc2: - DSP56K::PBDDR_set(cpustate, data); - break; - - // Port C Data Direction Register (PCDDR) - case 0xffc3: - DSP56K::PCDDR_set(cpustate, data); - break; - - // HCR: Host Control Register - case 0xffc4: - DSP56K::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: - DSP56K::BCR_set(cpustate, data); - break; - - // IPR: Interrupt Priority Register - case 0xffdf: - DSP56K::IPR_set(cpustate, data); - break; - - // Port B Data Register (PBD) - case 0xffe2: - DSP56K::PBD_set(cpustate, data); - break; - - // Port C Data Register (PCD) - case 0xffe3: - DSP56K::PCD_set(cpustate, data); - break; - - // HSR: Host Status Register - case 0xffe4: break; - - // HTX/HRX: Host TX/RX Register - case 0xffe5: - HTX = data; - DSP56K::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 dsp56k's host interface */ -void dsp56k_device::host_interface_write(uint8_t offset, uint8_t data) -{ - dsp56k_core* cpustate = &m_dsp56k_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; - } - } - DSP56K::ICR_set(cpustate, data); - break; - - // Command Vector Register (CVR) - case 0x01: - DSP56K::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 (DSP56K::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 (DSP56K::TXDE_bit(cpustate)) // 5-5 - { - TXL = data; - DSP56K::TXDE_bit_set(cpustate, 0); - } - break; - - default: cpustate->device->logerror("DSP56k : dsp56k_host_interface_write called with invalid address 0x%02x.\n", offset); - } -} - -uint8_t dsp56k_device::host_interface_read(uint8_t offset) -{ - dsp56k_core* cpustate = &m_dsp56k_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 (!DSP56K::RXDF_bit(cpustate)) - return 0xbf; - else - return RXH; - - // Receive byte register - low byte (RXL) - case 0x07: - // 5-5 - if (!DSP56K::RXDF_bit(cpustate)) - return 0xbf; - else - { - uint8_t value = RXL; // TODO: Maybe not exactly right? I'm just being safe. - DSP56K::RXDF_bit_set(cpustate, 0); - return value; - } - - default: cpustate->device->logerror("DSP56k : dsp56k_host_interface_read called with invalid address 0x%02x.\n", offset); - } - - /* Shouldn't get here */ - return 0xff; -} - -/* MISC*/ -uint16_t dsp56k_device::get_peripheral_memory(uint16_t addr) -{ - dsp56k_core* cpustate = &m_dsp56k_core; - return cpustate->peripheral_ram[A2O(addr)]; -} - - -} // namespace DSP56K diff --git a/src/devices/cpu/dsp56k/dsp56mem.h b/src/devices/cpu/dsp56k/dsp56mem.h deleted file mode 100644 index 2ceabc31c1e..00000000000 --- a/src/devices/cpu/dsp56k/dsp56mem.h +++ /dev/null @@ -1,241 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#ifndef MAME_CPU_DSP56K_DSP56MEM_H -#define MAME_CPU_DSP56K_DSP56MEM_H - -#include "dsp56k.h" - -namespace DSP56K { - -/*************************************************************************** - MEMORY -***************************************************************************/ -void mem_reset(dsp56k_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(dsp56k_core* cpustate, uint16_t value); - -/* A return value of -1 means disabled */ -int8_t irqa_ipl(dsp56k_core* cpustate); -int8_t irqb_ipl(dsp56k_core* cpustate); -uint8_t irqa_trigger(dsp56k_core* cpustate); -uint8_t irqb_trigger(dsp56k_core* cpustate); - -int8_t codec_ipl(dsp56k_core* cpustate); -int8_t host_ipl(dsp56k_core* cpustate); -int8_t ssi0_ipl(dsp56k_core* cpustate); -int8_t ssi1_ipl(dsp56k_core* cpustate); -int8_t tm_ipl(dsp56k_core* cpustate); - - -/*************************************************************************** - HOST INTERFACE -***************************************************************************/ -void dsp56k_host_interface_reset(dsp56k_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) - -/***************/ -/* DSP56k SIDE */ -/***************/ -/* Host Control Register (HCR) Bits */ -void HCR_set(dsp56k_core* cpustate, uint16_t value); - -//uint16_t HF3_bit(dsp56k_core* cpustate); #define hf3BIT ((HCR & 0x0010) != 0) -//uint16_t HF2_bit(dsp56k_core* cpustate); #define hf2BIT ((HCR & 0x0008) != 0) -uint16_t HCIE_bit(dsp56k_core* cpustate); -uint16_t HTIE_bit(dsp56k_core* cpustate); -uint16_t HRIE_bit(dsp56k_core* cpustate); - -void HF3_bit_set(dsp56k_core* cpustate, uint16_t value); -void HF2_bit_set(dsp56k_core* cpustate, uint16_t value); -void HCIE_bit_set(dsp56k_core* cpustate, uint16_t value); -void HTIE_bit_set(dsp56k_core* cpustate, uint16_t value); -void HRIE_bit_set(dsp56k_core* cpustate, uint16_t value); - -/* Host Status Register (HSR) Bits */ -//void HSR_set(dsp56k_core* cpustate, uint16_t value); - -//uint16_t DMA_bit(dsp56k_core* cpustate); #define dmaBIT ((HSR & 0x0080) != 0) -//uint16_t HF1_bit(dsp56k_core* cpustate); #define hf1BIT ((HSR & 0x0010) != 0) -//uint16_t HF0_bit(dsp56k_core* cpustate); #define hf0BIT ((HSR & 0x0008) != 0) -//uint16_t HCP_bit(dsp56k_core* cpustate); #define hcpBIT ((HSR & 0x0004) != 0) -uint16_t HTDE_bit(dsp56k_core* cpustate); -uint16_t HRDF_bit(dsp56k_core* cpustate); - -void DMA_bit_set(dsp56k_core* cpustate, uint16_t value); -void HF1_bit_set(dsp56k_core* cpustate, uint16_t value); -void HF0_bit_set(dsp56k_core* cpustate, uint16_t value); -void HCP_bit_set(dsp56k_core* cpustate, uint16_t value); -void HTDE_bit_set(dsp56k_core* cpustate, uint16_t value); -void HRDF_bit_set(dsp56k_core* cpustate, uint16_t value); - -/*************/ -/* HOST SIDE */ -/*************/ -/* Interrupt Control Register (ICR) Bits */ -void ICR_set(dsp56k_core* cpustate, uint8_t value); - -//uint8_t INIT_bit(dsp56k_core* cpustate); #define x_initBIT ((dsp56k.HI.ICR & 0x0080) != 0) -//uint8_t HM1_bit(dsp56k_core* cpustate); #define x_hm1BIT ((dsp56k.HI.ICR & 0x0040) != 0) -//uint8_t HM0_bit(dsp56k_core* cpustate); #define x_hm0BIT ((dsp56k.HI.ICR & 0x0020) != 0) -//uint8_t HF1_bit_host(dsp56k_core* cpustate); #define x_hf1BIT ((dsp56k.HI.ICR & 0x0010) != 0) -//uint8_t HF0_bit_host(dsp56k_core* cpustate); #define x_hf0BIT ((dsp56k.HI.ICR & 0x0008) != 0) -//uint8_t TREQ_bit(dsp56k_core* cpustate); #define x_treqBIT ((dsp56k.HI.ICR & 0x0002) != 0) -//uint8_t RREQ_bit(dsp56k_core* cpustate); #define x_rreqBIT ((dsp56k.HI.ICR & 0x0001) != 0) - -//void INIT_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_initBIT() (dsp56k.HI.ICR &= (~0x0080)) -//void HM1_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_hm1BIT() (dsp56k.HI.ICR &= (~0x0040)) -//void HM0_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_hm0BIT() (dsp56k.HI.ICR &= (~0x0020)) -void HF1_bit_host_set(dsp56k_core* cpustate, uint8_t value); -void HF0_bit_host_set(dsp56k_core* cpustate, uint8_t value); -void TREQ_bit_set(dsp56k_core* cpustate, uint8_t value); -void RREQ_bit_set(dsp56k_core* cpustate, uint8_t value); - -/* Command Vector Register (CVR) Bits */ -void CVR_set(dsp56k_core* cpustate, uint8_t value); - -//uint8_t HC_bit(); -uint8_t HV_bits(dsp56k_core* cpustate); - -void HC_bit_set(dsp56k_core* cpustate, uint8_t value); -void HV_bits_set(dsp56k_core* cpustate, uint8_t value); - -/* Interrupt Status Register (ISR) Bits */ -// void ISR_set(dsp56k_core* cpustate, uint8_t value); - -//uint8_t HREQ_bit(dsp56k_core* cpustate); #define x_hreqBIT ((dsp56k.HI.ISR & 0x0080) != 0) -//uint8_t DMA_bit(dsp56k_core* cpustate); #define x_dmaBIT ((dsp56k.HI.ISR & 0x0040) != 0) -//uint8_t HF3_bit_host(dsp56k_core* cpustate); #define x_hf3BIT ((dsp56k.HI.ISR & 0x0010) != 0) -//uint8_t HF2_bit_host(dsp56k_core* cpustate); #define x_hf2BIT ((dsp56k.HI.ISR & 0x0008) != 0) -//uint8_t TRDY_bit(dsp56k_core* cpustate); #define x_trdyBIT ((dsp56k.HI.ISR & 0x0004) != 0) -uint8_t TXDE_bit(dsp56k_core* cpustate); -uint8_t RXDF_bit(dsp56k_core* cpustate); - -//void HREQ_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_hreqBIT() (dsp56k.HI.ISR &= (~0x0080)) -//void DMA_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_dmaBIT() (dsp56k.HI.ISR &= (~0x0040)) -void HF3_bit_host_set(dsp56k_core* cpustate, uint8_t value); -void HF2_bit_host_set(dsp56k_core* cpustate, uint8_t value); -//void TRDY_bit_set(dsp56k_core* cpustate, uint8_t value); #define CLEAR_x_trdyBIT() (dsp56k.HI.ISR &= (~0x0004)) -void TXDE_bit_set(dsp56k_core* cpustate, uint8_t value); -void RXDF_bit_set(dsp56k_core* cpustate, uint8_t value); - -/* Interrupt Vector Register (IVR) Bits */ -//void IVR_set(dsp56k_core* cpustate, uint8_t value); - -//uint8_t IV7_bit(dsp56k_core* cpustate); -//uint8_t IV6_bit(dsp56k_core* cpustate); -//uint8_t IV5_bit(dsp56k_core* cpustate); -//uint8_t IV4_bit(dsp56k_core* cpustate); -//uint8_t IV3_bit(dsp56k_core* cpustate); -//uint8_t IV2_bit(dsp56k_core* cpustate); -//uint8_t IV1_bit(dsp56k_core* cpustate); -//uint8_t IV0_bit(dsp56k_core* cpustate); - -//void IV7_bit_set(dsp56k_core* cpustate, uint8_t value); -//void IV6_bit_set(dsp56k_core* cpustate, uint8_t value); -//void IV5_bit_set(dsp56k_core* cpustate, uint8_t value); -//void IV4_bit_set(dsp56k_core* cpustate, uint8_t value); -//void IV3_bit_set(dsp56k_core* cpustate, uint8_t value); -//void IV2_bit_set(dsp56k_core* cpustate, uint8_t value); -//void IV1_bit_set(dsp56k_core* cpustate, uint8_t value); -//void IV0_bit_set(dsp56k_core* cpustate, uint8_t value); - - -/* PROTOTYPES */ -void dsp56k_host_interface_HTX_to_host(dsp56k_core* cpustate); -void dsp56k_host_interface_host_to_HTX(dsp56k_core* cpustate); - - -/*************************************************************************** - I/O INTERFACE -***************************************************************************/ -void dsp56k_io_reset(dsp56k_core* cpustate); - -/* Port A Bus Control Register (BCR) */ -void BCR_set(dsp56k_core* cpustate, uint16_t value); - -//uint16_t RH_bit(dsp56k_core* cpustate); -//uint16_t BS_bit(dsp56k_core* cpustate); -//uint16_t external_x_wait_states(dsp56k_core* cpustate); -//uint16_t external_p_wait_states(dsp56k_core* cpustate); - -void RH_bit_set(dsp56k_core* cpustate, uint16_t value); -void BS_bit_set(dsp56k_core* cpustate, uint16_t value); -void external_x_wait_states_set(dsp56k_core* cpustate, uint16_t value); -void external_p_wait_states_set(dsp56k_core* cpustate, uint16_t value); - -/* Port B Control Register (PBC) */ -void PBC_set(dsp56k_core* cpustate, uint16_t value); -//int host_interface_active(dsp56k_core* cpustate); - -/* Port B Data Direction Register (PBDDR) */ -void PBDDR_set(dsp56k_core* cpustate, uint16_t value); - -/* Port B Data Register (PBD) */ -void PBD_set(dsp56k_core* cpustate, uint16_t value); - -/* Port C Control Register (PCC) */ -void PCC_set(dsp56k_core* cpustate, uint16_t value); - -/* Port C Data Direction Register (PCDDR) */ -void PCDDR_set(dsp56k_core* cpustate, uint16_t value); - -/* Port C Dtaa Register (PCD) */ -void PCD_set(dsp56k_core* cpustate, uint16_t value); - -} // namespace DSP56K - -#endif // MAME_CPU_DSP56K_DSP56MEM_H diff --git a/src/devices/cpu/dsp56k/dsp56ops.hxx b/src/devices/cpu/dsp56k/dsp56ops.hxx deleted file mode 100644 index 7e52d1b2cd0..00000000000 --- a/src/devices/cpu/dsp56k/dsp56ops.hxx +++ /dev/null @@ -1,4903 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -/*************************************************************************** - - dsp56ops.inc - Core implementation for the portable Motorola/Freescale DSP56k 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) (Dsp56kOpMask(CUR,MASK)) - -/*********************/ -/* Opcode prototypes */ -/*********************/ -static size_t dsp56k_op_addsub_2 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles); -static size_t dsp56k_op_mac_1 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles); -static size_t dsp56k_op_macr_1 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles); -static size_t dsp56k_op_move_1 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles); -static size_t dsp56k_op_mpy_1 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles); -static size_t dsp56k_op_mpyr_1 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles); -static size_t dsp56k_op_tfr_2 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint8_t* cycles); -static size_t dsp56k_op_mpy_2 (dsp56k_core* cpustate, const uint16_t op_byte, uint8_t* cycles); -static size_t dsp56k_op_mac_2 (dsp56k_core* cpustate, const uint16_t op_byte, uint8_t* cycles); -static size_t dsp56k_op_clr (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_add (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_move (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_tfr (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_rnd (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_tst (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_inc (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_inc24 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_or (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_asr (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_asl (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_lsr (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_lsl (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_eor (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_subl (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_sub (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_clr24 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_sbc (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_cmp (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_neg (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_not (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_dec (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_dec24 (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_and (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_abs (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_ror (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_rol (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_cmpm (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_mpy (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_mpyr (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_mac (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_macr (dsp56k_core* cpustate, const uint16_t op_byte, typed_pointer* d_register, uint64_t* p_accum, uint8_t* cycles); -static size_t dsp56k_op_adc (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_andi (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_asl4 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_asr4 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_asr16 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_bfop (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_bfop_1 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_bfop_2 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_bcc (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_bcc_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_bcc_2 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_bra (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_bra_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_bra_2 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_brkcc (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_bscc (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_bscc_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_bsr (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_bsr_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_chkaau (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_debug (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_debugcc (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_div (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_dmac (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_do (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_do_1 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_do_2 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_doforever(dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_enddo (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_ext (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_illegal (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_imac (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_impy (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_jcc (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_jcc_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_jmp (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_jmp_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_jscc (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_jscc_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_jsr (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_jsr_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_jsr_2 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_lea (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_lea_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_macsuuu (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_move_2 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_movec (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movec_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movec_2 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movec_3 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_movec_4 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movec_5 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_movei (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movem (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movem_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movem_2 (dsp56k_core* cpustate, const uint16_t op, const uint16_t op2, uint8_t* cycles); -static size_t dsp56k_op_movep (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_movep_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_moves (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_mpysuuu (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_negc (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_nop (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_norm (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_ori (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_rep (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_rep_1 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_rep_2 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_repcc (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_reset (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_rti (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_rts (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_stop (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_swap (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_swi (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_tcc (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_tfr2 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_tfr3 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_tst2 (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_wait (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); -static size_t dsp56k_op_zero (dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles); - - -static void execute_register_to_register_data_move(dsp56k_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value); -static void execute_address_register_update(dsp56k_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value); -static void execute_x_memory_data_move (dsp56k_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value); -static void execute_x_memory_data_move2(dsp56k_core* cpustate, const uint16_t op, typed_pointer* d_register); -static void execute_dual_x_memory_data_read(dsp56k_core* cpustate, const uint16_t op, typed_pointer* d_register); -static void execute_x_memory_data_move_with_short_displacement(dsp56k_core* cpustate, const uint16_t op, const uint16_t op2); - -static uint16_t decode_BBB_bitmask(dsp56k_core* cpustate, uint16_t BBB, uint16_t *iVal); -static int decode_cccc_table(dsp56k_core* cpustate, uint16_t cccc); -static void decode_DDDDD_table(dsp56k_core* cpustate, uint16_t DDDDD, typed_pointer* ret); -static void decode_DD_table(dsp56k_core* cpustate, uint16_t DD, typed_pointer* ret); -static void decode_DDF_table(dsp56k_core* cpustate, uint16_t DD, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret); -static void decode_F_table(dsp56k_core* cpustate, uint16_t F, typed_pointer* ret); -static void decode_h0hF_table(dsp56k_core* cpustate, uint16_t h0h, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret); -static void decode_HH_table(dsp56k_core* cpustate, uint16_t HH, typed_pointer* ret); -static void decode_HHH_table(dsp56k_core* cpustate, uint16_t HHH, typed_pointer* ret); -static void decode_IIII_table(dsp56k_core* cpustate, uint16_t IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void* working); -static void decode_JJJF_table(dsp56k_core* cpustate, uint16_t JJJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret); -static void decode_JJF_table(dsp56k_core* cpustate, uint16_t JJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret); -static void decode_JF_table(dsp56k_core* cpustate, uint16_t JJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret); -static void decode_KKK_table(dsp56k_core* cpustate, uint16_t KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working); -static void decode_QQF_table(dsp56k_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D); -static void decode_QQF_special_table(dsp56k_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D); -static void decode_QQQF_table(dsp56k_core* cpustate, uint16_t QQQ, uint16_t F, void **S1, void **S2, void **D); -static void decode_RR_table(dsp56k_core* cpustate, uint16_t RR, typed_pointer* ret); -static void decode_TT_table(dsp56k_core* cpustate, uint16_t TT, typed_pointer* ret); -static void decode_uuuuF_table(dsp56k_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(dsp56k_core* cpustate, uint16_t Z, typed_pointer* ret); - -static void execute_m_table(dsp56k_core* cpustate, int x, uint16_t m); -static void execute_mm_table(dsp56k_core* cpustate, uint16_t rnum, uint16_t mm); -static void execute_MM_table(dsp56k_core* cpustate, uint16_t rnum, uint16_t MM); -static uint16_t execute_q_table(dsp56k_core* cpustate, int RR, uint16_t q); -static void execute_z_table(dsp56k_core* cpustate, int RR, uint16_t z); - -static uint16_t assemble_address_from_Pppppp_table(dsp56k_core* cpustate, uint16_t P, uint16_t ppppp); -static uint16_t assemble_address_from_IO_short_address(dsp56k_core* cpustate, uint16_t pp); -static uint16_t assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, uint16_t srs); - -static void dsp56k_process_loop(dsp56k_core* cpustate); -static void dsp56k_process_rep(dsp56k_core* cpustate, size_t repSize); - - - -/********************/ -/* Helper Functions */ -/********************/ -static uint16_t Dsp56kOpMask(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(dsp56k_core* cpustate, typed_pointer source, uint32_t destinationAddr); -static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, uint32_t destinationAddr); - - - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -static void execute_one(dsp56k_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 = dsp56k_op_addsub_2(cpustate, op_byte, &d_register, &cycle_count); - } - /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ - else if ((op & 0xe094) == 0x6084) - { - size = dsp56k_op_mac_1(cpustate, op_byte, &d_register, &cycle_count); - } - /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ - else if ((op & 0xe094) == 0x6094) - { - size = dsp56k_op_macr_1(cpustate, op_byte, &d_register, &cycle_count); - } - /* TFR : 011m mKKK 0rr1 F0DD : A-212 */ - else if ((op & 0xe094) == 0x6010) - { - size = dsp56k_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 = dsp56k_op_move_1(cpustate, op_byte, &d_register, &cycle_count); - } - /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ - else if ((op & 0xe094) == 0x6080) - { - size = dsp56k_op_mpy_1(cpustate, op_byte, &d_register, &cycle_count); - } - /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ - else if ((op & 0xe094) == 0x6090) - { - size = dsp56k_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 = dsp56k_op_mpy_2(cpustate, op_byte, &cycle_count); - } - /* MAC : 0001 0111 RRDD FQQQ : A-122 */ - else if ((op & 0xff00) == 0x1700) - { - size = dsp56k_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("DSP56k: 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 = dsp56k_op_clr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* ADD : .... .... 0000 FJJJ : A-22 */ - else if ((op_byte & 0x00f0) == 0x0000) - { - size = dsp56k_op_add(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - - - /* MOVE : .... .... 0001 0001 : A-128 */ - else if ((op_byte & 0x00ff) == 0x0011) - { - size = dsp56k_op_move(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* TFR : .... .... 0001 FJJJ : A-212 */ - else if ((op_byte & 0x00f0) == 0x0010) - { - size = dsp56k_op_tfr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - - - /* RND : .... .... 0010 F000 : A-188 */ - else if ((op_byte & 0x00f7) == 0x0020) - { - size = dsp56k_op_rnd(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* TST : .... .... 0010 F001 : A-218 */ - else if ((op_byte & 0x00f7) == 0x0021) - { - size = dsp56k_op_tst(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* INC : .... .... 0010 F010 : A-104 */ - else if ((op_byte & 0x00f7) == 0x0022) - { - size = dsp56k_op_inc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* INC24 : .... .... 0010 F011 : A-106 */ - else if ((op_byte & 0x00f7) == 0x0023) - { - size = dsp56k_op_inc24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* OR : .... .... 0010 F1JJ : A-176 */ - else if ((op_byte & 0x00f4) == 0x0024) - { - size = dsp56k_op_or(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - - - /* ASR : .... .... 0011 F000 : A-32 */ - else if ((op_byte & 0x00f7) == 0x0030) - { - size = dsp56k_op_asr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* ASL : .... .... 0011 F001 : A-28 */ - else if ((op_byte & 0x00f7) == 0x0031) - { - size = dsp56k_op_asl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* LSR : .... .... 0011 F010 : A-120 */ - else if ((op_byte & 0x00f7) == 0x0032) - { - size = dsp56k_op_lsr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* LSL : .... .... 0011 F011 : A-118 */ - else if ((op_byte & 0x00f7) == 0x0033) - { - size = dsp56k_op_lsl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* EOR : .... .... 0011 F1JJ : A-94 */ - else if ((op_byte & 0x00f4) == 0x0034) - { - size = dsp56k_op_eor(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - - - /* SUBL : .... .... 0100 F001 : A-204 */ - else if ((op_byte & 0x00f7) == 0x0041) - { - size = dsp56k_op_subl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* SUB : .... .... 0100 FJJJ : A-202 */ - else if ((op_byte & 0x00f0) == 0x0040) - { - size = dsp56k_op_sub(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - - - /* CLR24 : .... .... 0101 F001 : A-62 */ - else if ((op_byte & 0x00f7) == 0x0051) - { - size = dsp56k_op_clr24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* SBC : .... .... 0101 F01J : A-198 */ - else if ((op_byte & 0x00f6) == 0x0052) - { - size = dsp56k_op_sbc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* CMP : .... .... 0101 FJJJ : A-64 */ - else if ((op_byte & 0x00f0) == 0x0050) - { - size = dsp56k_op_cmp(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - - - /* NEG : .... .... 0110 F000 : A-166 */ - else if ((op_byte & 0x00f7) == 0x0060) - { - size = dsp56k_op_neg(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* NOT : .... .... 0110 F001 : A-174 */ - else if ((op_byte & 0x00f7) == 0x0061) - { - size = dsp56k_op_not(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* DEC : .... .... 0110 F010 : A-72 */ - else if ((op_byte & 0x00f7) == 0x0062) - { - size = dsp56k_op_dec(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* DEC24 : .... .... 0110 F011 : A-74 */ - else if ((op_byte & 0x00f7) == 0x0063) - { - size = dsp56k_op_dec24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* AND : .... .... 0110 F1JJ : A-24 */ - else if ((op_byte & 0x00f4) == 0x0064) - { - size = dsp56k_op_and(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - - - /* ABS : .... .... 0111 F001 : A-18 */ - if ((op_byte & 0x00f7) == 0x0071) - { - size = dsp56k_op_abs(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* ROR : .... .... 0111 F010 : A-192 */ - else if ((op_byte & 0x00f7) == 0x0072) - { - size = dsp56k_op_ror(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* ROL : .... .... 0111 F011 : A-190 */ - else if ((op_byte & 0x00f7) == 0x0073) - { - size = dsp56k_op_rol(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* CMPM : .... .... 0111 FJJJ : A-66 */ - else if ((op_byte & 0x00f0) == 0x0070) - { - size = dsp56k_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 = dsp56k_op_mpy(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* MPYR : .... .... 1k01 FQQQ : A-162 */ - else if ((op_byte & 0x00b0) == 0x0090) - { - size = dsp56k_op_mpyr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); - } - /* MAC : .... .... 1k10 FQQQ : A-122 */ - else if ((op_byte & 0x00b0) == 0x00a0) - { - size = dsp56k_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 = dsp56k_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; - - dsp56k_process_loop(cpustate); - dsp56k_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 = dsp56k_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 = dsp56k_op_andi(cpustate, op, &cycle_count); - } - /* ASL4 : 0001 0101 0011 F001 : A-30 */ - else if ((op & 0xfff7) == 0x1531) - { - size = dsp56k_op_asl4(cpustate, op, &cycle_count); - } - /* ASR4 : 0001 0101 0011 F000 : A-34 */ - else if ((op & 0xfff7) == 0x1530) - { - size = dsp56k_op_asr4(cpustate, op, &cycle_count); - } - /* ASR16 : 0001 0101 0111 F000 : A-36 */ - else if ((op & 0xfff7) == 0x1570) - { - size = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_op_bcc(cpustate, op, op2, &cycle_count); - } - /* Bcc : 0010 11cc ccee eeee : A-48 */ - else if ((op & 0xfc00) == 0x2c00) - { - size = dsp56k_op_bcc_1(cpustate, op, &cycle_count); - } - /* Bcc : 0000 0111 RR10 cccc : A-48 */ - else if ((op & 0xff30) == 0x0720) - { - size = dsp56k_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 = dsp56k_op_bra(cpustate, op, op2, &cycle_count); - } - /* BRA : 0000 1011 aaaa aaaa : A-50 */ - else if ((op & 0xff00) == 0x0b00) - { - size = dsp56k_op_bra_1(cpustate, op, &cycle_count); - } - /* BRA : 0000 0001 0010 11RR : A-50 */ - else if ((op & 0xfffc) == 0x012c) - { - size = dsp56k_op_bra_2(cpustate, op, &cycle_count); - } - /* BRKc : 0000 0001 0001 cccc : A-52 */ - else if ((op & 0xfff0) == 0x0110) - { - size = dsp56k_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 = dsp56k_op_bscc(cpustate, op, op2, &cycle_count); - } - /* BScc : 0000 0111 RR00 cccc : A-54 */ - else if ((op & 0xff30) == 0x0700) - { - size = dsp56k_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 = dsp56k_op_bsr(cpustate, op, op2, &cycle_count); - } - /* BSR : 0000 0001 0010 10RR : A-56 */ - else if ((op & 0xfffc) == 0x0128) - { - size = dsp56k_op_bsr_1(cpustate, op, &cycle_count); - } - /* CHKAAU : 0000 0000 0000 0100 : A-58 */ - else if ((op & 0xffff) == 0x0004) - { - size = dsp56k_op_chkaau(cpustate, op, &cycle_count); - } - /* DEBUG : 0000 0000 0000 0001 : A-68 */ - else if ((op & 0xffff) == 0x0001) - { - size = dsp56k_op_debug(cpustate, op, &cycle_count); - } - /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ - else if ((op & 0xfff0) == 0x0050) - { - size = dsp56k_op_debugcc(cpustate, op, &cycle_count); - } - /* DIV : 0001 0101 0--0 F1DD : A-76 */ - else if ((op & 0xff94) == 0x1504) - { - size = dsp56k_op_div(cpustate, op, &cycle_count); - } - /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ - else if ((op & 0xffd0) == 0x1590) - { - size = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_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 = dsp56k_op_doforever(cpustate, op, op2, &cycle_count); - } - /* ENDDO : 0000 0000 0000 1001 : A-92 */ - else if ((op & 0xffff) == 0x0009) - { - size = dsp56k_op_enddo(cpustate, op, &cycle_count); - } - /* EXT : 0001 0101 0101 F010 : A-96 */ - else if ((op & 0xfff7) == 0x1552) - { - size = dsp56k_op_ext(cpustate, op, &cycle_count); - } - /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ - else if ((op & 0xffff) == 0x000f) - { - size = dsp56k_op_illegal(cpustate, op, &cycle_count); - } - /* IMAC : 0001 0101 1010 FQQQ : A-100 */ - else if ((op & 0xfff0) == 0x15a0) - { - size = dsp56k_op_imac(cpustate, op, &cycle_count); - } - /* IMPY : 0001 0101 1000 FQQQ : A-102 */ - else if ((op & 0xfff0) == 0x1580) - { - size = dsp56k_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 = dsp56k_op_jcc(cpustate, op, op2, &cycle_count); - } - /* Jcc : 0000 0110 RR10 cccc : A-108 */ - else if ((op & 0xff30) == 0x0620 ) - { - size = dsp56k_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 = dsp56k_op_jmp(cpustate, op, op2, &cycle_count); - } - /* JMP : 0000 0001 0010 01RR : A-110 */ - else if ((op & 0xfffc) == 0x0124) - { - size = dsp56k_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 = dsp56k_op_jscc(cpustate, op, op2, &cycle_count); - } - /* JScc : 0000 0110 RR00 cccc : A-112 */ - else if ((op & 0xff30) == 0x0600) - { - size = dsp56k_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 = dsp56k_op_jsr(cpustate, op, op2, &cycle_count); - } - /* JSR : 0000 1010 AAAA AAAA : A-114 */ - else if ((op & 0xff00) == 0x0a00) - { - size = dsp56k_op_jsr_1(cpustate, op, &cycle_count); - } - /* JSR : 0000 0001 0010 00RR : A-114 */ - else if ((op & 0xfffc) == 0x0120) - { - size = dsp56k_op_jsr_2(cpustate, op, &cycle_count); - } - /* LEA : 0000 0001 11TT MMRR : A-116 */ - else if ((op & 0xffc0) == 0x01c0) - { - size = dsp56k_op_lea(cpustate, op, &cycle_count); - } - /* LEA : 0000 0001 10NN MMRR : A-116 */ - else if ((op & 0xffc0) == 0x0180) - { - size = dsp56k_op_lea_1(cpustate, op, &cycle_count); - } - /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ - else if ((op & 0xfff0) == 0x15e0) - { - size = dsp56k_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 = dsp56k_op_move_2(cpustate, op, op2, &cycle_count); - } - /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ - else if ((op & 0xf810) == 0x3800) - { - size = dsp56k_op_movec(cpustate, op, &cycle_count); - } - /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ - else if ((op & 0xf814) == 0x3810) - { - size = dsp56k_op_movec_1(cpustate, op, &cycle_count); - } - /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ - else if ((op & 0xf816) == 0x3816) - { - size = dsp56k_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 = dsp56k_op_movec_3(cpustate, op, op2, &cycle_count); - } - /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ - else if ((op & 0xfc00) == 0x2800) - { - size = dsp56k_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 = dsp56k_op_movec_5(cpustate, op, op2, &cycle_count); - } - /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ - else if ((op & 0xfc00) == 0x2000) - { - size = dsp56k_op_movei(cpustate, op, &cycle_count); - } - /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ - else if ((op & 0xfe20) == 0x0200) - { - size = dsp56k_op_movem(cpustate, op, &cycle_count); - } - /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ - else if ((op & 0xfe30) == 0x0230) - { - size = dsp56k_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 = dsp56k_op_movem_2(cpustate, op, op2, &cycle_count); - } - /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ - else if ((op & 0xfe20) == 0x1820) - { - size = dsp56k_op_movep(cpustate, op, &cycle_count); - } - /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ - else if ((op & 0xfe00) == 0x0c00) - { - size = dsp56k_op_movep_1(cpustate, op, &cycle_count); - } - /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ - else if ((op & 0xfe20) == 0x1800) - { - size = dsp56k_op_moves(cpustate, op, &cycle_count); - } - /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ - else if ((op & 0xfff0) == 0x15c0) - { - size = dsp56k_op_mpysuuu(cpustate, op, &cycle_count); - } - /* NEGC : 0001 0101 0110 F000 : A-168 */ - else if ((op & 0xfff7) == 0x1560) - { - size = dsp56k_op_negc(cpustate, op, &cycle_count); - } - /* NOP : 0000 0000 0000 0000 : A-170 */ - else if ((op & 0xffff) == 0x0000) - { - size = dsp56k_op_nop(cpustate, op, &cycle_count); - } - /* NORM : 0001 0101 0010 F0RR : A-172 */ - else if ((op & 0xfff4) == 0x1520) - { - size = dsp56k_op_norm(cpustate, op, &cycle_count); - } - /* ORI : 0001 1EE1 iiii iiii : A-178 */ - else if ((op & 0xf900) == 0x1900) - { - size = dsp56k_op_ori(cpustate, op, &cycle_count); - } - /* REP : 0000 0000 111- --RR : A-180 */ - else if ((op & 0xffe0) == 0x00e0) - { - size = dsp56k_op_rep(cpustate, op, &cycle_count); - } - /* REP : 0000 1111 iiii iiii : A-180 */ - else if ((op & 0xff00) == 0x0f00) - { - size = dsp56k_op_rep_1(cpustate, op, &cycle_count); - } - /* REP : 0000 0100 001D DDDD : A-180 */ - else if ((op & 0xffe0) == 0x0420) - { - size = dsp56k_op_rep_2(cpustate, op, &cycle_count); - } - /* REPcc : 0000 0001 0101 cccc : A-184 */ - else if ((op & 0xfff0) == 0x0150) - { - size = dsp56k_op_repcc(cpustate, op, &cycle_count); - } - /* RESET : 0000 0000 0000 1000 : A-186 */ - else if ((op & 0xffff) == 0x0008) - { - size = dsp56k_op_reset(cpustate, op, &cycle_count); - } - /* RTI : 0000 0000 0000 0111 : A-194 */ - else if ((op & 0xffff) == 0x0007) - { - size = dsp56k_op_rti(cpustate, op, &cycle_count); - } - /* RTS : 0000 0000 0000 0110 : A-196 */ - else if ((op & 0xffff) == 0x0006) - { - size = dsp56k_op_rts(cpustate, op, &cycle_count); - } - /* STOP : 0000 0000 0000 1010 : A-200 */ - else if ((op & 0xffff) == 0x000a) - { - size = dsp56k_op_stop(cpustate, op, &cycle_count); - } - /* SWAP : 0001 0101 0111 F001 : A-206 */ - else if ((op & 0xfff7) == 0x1571) - { - size = dsp56k_op_swap(cpustate, op, &cycle_count); - } - /* SWI : 0000 0000 0000 0101 : A-208 */ - else if ((op & 0xffff) == 0x0005) - { - size = dsp56k_op_swi(cpustate, op, &cycle_count); - } - /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ - else if ((op & 0xfc02) == 0x1000) - { - size = dsp56k_op_tcc(cpustate, op, &cycle_count); - } - /* TFR(2) : 0001 0101 0000 F00J : A-214 */ - else if ((op & 0xfff6) == 0x1500) - { - size = dsp56k_op_tfr2(cpustate, op, &cycle_count); - } - /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ - else if ((op & 0xfc00) == 0x2400) - { - size = dsp56k_op_tfr3(cpustate, op, &cycle_count); - } - /* TST(2) : 0001 0101 0001 -1DD : A-220 */ - else if ((op & 0xfff4) == 0x1514) - { - size = dsp56k_op_tst2(cpustate, op, &cycle_count); - } - /* WAIT : 0000 0000 0000 1011 : A-222 */ - else if ((op & 0xffff) == 0x000b) - { - size = dsp56k_op_wait(cpustate, op, &cycle_count); - } - /* ZERO : 0001 0101 0101 F000 : A-224 */ - else if ((op & 0xfff7) == 0x1550) - { - size = dsp56k_op_zero(cpustate, op, &cycle_count); - } - - - /* Not recognized? Nudge debugger onto the next word */ - if (size == 0x1337) - { - cpustate->device->logerror("DSP56k: 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; - - dsp56k_process_loop(cpustate); - dsp56k_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 dsp56k_op_addsub_2(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ -static size_t dsp56k_op_mac_1(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: +mv oscillator cycles */ - return 1; -} - -/* MACR: 011m mKKK 1--1 F1QQ : A-124 */ -static size_t dsp56k_op_macr_1(dsp56k_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 dsp56k_op_move_1(dsp56k_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 dsp56k_op_mpy_1(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: +mv oscillator cycles */ - return 1; -} - -/* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ -static size_t dsp56k_op_mpyr_1(dsp56k_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 dsp56k_op_tfr_2(dsp56k_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 dsp56k_op_mpy_2(dsp56k_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 dsp56k_op_mac_2(dsp56k_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 dsp56k_op_clr(dsp56k_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 */ - DSP56K_E_CLEAR(); - DSP56K_U_SET(); - DSP56K_N_CLEAR(); - DSP56K_Z_SET(); - DSP56K_V_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator clock cycles */ - return 1; -} - -/* ADD : .... .... 0000 FJJJ : A-22 */ -static size_t dsp56k_op_add(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* MOVE : .... .... 0001 0001 : A-128 */ -static size_t dsp56k_op_move(dsp56k_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 dsp56k_op_tfr(dsp56k_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 dsp56k_op_rnd(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator clock cycles */ - return 1; -} - -/* TST : .... .... 0010 F001 : A-218 */ -static size_t dsp56k_op_tst(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - DSP56K_C_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator clock cycles */ - return 1; -} - -/* INC : .... .... 0010 F010 : A-104 */ -static size_t dsp56k_op_inc(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - cycles += 2; /* TODO: +mv oscillator cycles */ - return 1; -} - -/* INC24 : .... .... 0010 F011 : A-106 */ -static size_t dsp56k_op_inc24(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - if ((workBits24 & 0xff000000) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); - if ((workBits24 & 0xff000000) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator clock cycles */ - return 1; -} - -/* OR : .... .... 0010 F1JJ : A-176 */ -static size_t dsp56k_op_or(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* ASR : .... .... 0011 F000 : A-32 */ -static size_t dsp56k_op_asr(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - if (*p_accum & 0x0000000000000001U) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* ASL : .... .... 0011 F001 : A-28 */ -static size_t dsp56k_op_asl(dsp56k_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 dsp56k_op_lsr(dsp56k_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 */ - DSP56K_N_CLEAR(); - if (((PAIR64*)D.addr)->w.h == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - if (*p_accum & 0x0000000000010000U) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* LSL : .... .... 0011 F011 : A-118 */ -static size_t dsp56k_op_lsl(dsp56k_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 dsp56k_op_eor(dsp56k_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 dsp56k_op_subl(dsp56k_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 dsp56k_op_sub(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ( *((uint64_t*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); - if ((*((uint64_t*)D.addr) & 0xffffff0000000000U) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* CLR24 : .... .... 0101 F001 : A-62 */ -static size_t dsp56k_op_clr24(dsp56k_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 dsp56k_op_sbc(dsp56k_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 dsp56k_op_cmp(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ( result == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - if ((result & 0xffffff0000000000U) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); - if ((result & 0xffffff0000000000U) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - - cycles += 2; /* TODO: + mv oscillator clock cycles */ - return 1; -} - -/* NEG : .... .... 0110 F000 : A-166 */ -static size_t dsp56k_op_neg(dsp56k_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 dsp56k_op_not(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* DEC : .... .... 0110 F010 : A-72 */ -static size_t dsp56k_op_dec(dsp56k_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 dsp56k_op_dec24(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffff0000U) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator clock cycles */ - return 1; -} - -/* AND : .... .... 0110 F1JJ : A-24 */ -static size_t dsp56k_op_and(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x00000000ffff0000U) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator cycles */ - return 1; -} - -/* ABS : .... .... 0111 F001 : A-18 */ -static size_t dsp56k_op_abs(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D.addr) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - if ((*p_accum) == 0x0000008000000000U) DSP56K_V_SET(); else DSP56K_V_CLEAR(); - - cycles += 2; /* TODO: + mv oscillator clock cycles */ - return 1; -} - -/* ROR : .... .... 0111 F010 : A-192 */ -static size_t dsp56k_op_ror(dsp56k_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 dsp56k_op_rol(dsp56k_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 dsp56k_op_cmpm(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if (((absResult) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - if ( (absResult & 0xffffff0000000000U) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); - if ( (absResult & 0xffffff0000000000U) != 0) DSP56K_C_SET(); else DSP56K_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 dsp56k_op_mpy(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: +mv oscillator cycles */ - return 1; -} - -/* MPYR : .... .... 1k01 FQQQ : A-162 */ -static size_t dsp56k_op_mpyr(dsp56k_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 dsp56k_op_mac(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: +mv oscillator cycles */ - return 1; -} - -/* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */ -static size_t dsp56k_op_macr(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; /* TODO: +mv oscillator cycles */ - return 1; -} - - -/******************************/ -/* Remaining non-parallel ops */ -/******************************/ - -/* ADC : 0001 0101 0000 F01J : A-20 */ -static size_t dsp56k_op_adc(dsp56k_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 dsp56k_op_andi(dsp56k_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("DSP56k - 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 dsp56k_op_asl4(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - if ( (*((uint64_t*)D.addr) & 0x000000ff00000000U) != (p_accum & 0x000000ff00000000U) ) DSP56K_V_SET(); else DSP56K_V_CLEAR(); - if (p_accum & 0x0000001000000000U) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - cycles += 2; - return 1; -} - -/* ASR4 : 0001 0101 0011 F000 : A-34 */ -static size_t dsp56k_op_asr4(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - if (p_accum & 0x0000000000000008U) DSP56K_C_SET(); else DSP56K_C_CLEAR(); - - cycles += 2; - return 1; -} - -/* ASR16 : 0001 0101 0111 F000 : A-36 */ -static size_t dsp56k_op_asr16(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if (*((uint64_t*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - if (backupVal & 0x0000000000008000U) DSP56K_C_SET(); else DSP56K_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 dsp56k_op_bfop(dsp56k_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) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x04: /* BFCLR */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x18: /* BFSET */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x10: /* BFTSTH */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x00: /* BFTSTL */ - if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_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 dsp56k_op_bfop_1(dsp56k_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) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x04: /* BFCLR */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x18: /* BFSET */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x10: /* BFTSTH */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x00: /* BFTSTL */ - if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_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 dsp56k_op_bfop_2(dsp56k_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) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x04: /* BFCLR */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x18: /* BFSET */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x10: /* BFTSTH */ - if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; - case 0x00: /* BFTSTL */ - if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_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 dsp56k_op_bcc(dsp56k_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 dsp56k_op_bcc_1(dsp56k_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 dsp56k_op_bcc_2(dsp56k_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 dsp56k_op_bra(dsp56k_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 dsp56k_op_bra_1(dsp56k_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 dsp56k_op_bra_2(dsp56k_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 dsp56k_op_brkcc(dsp56k_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 dsp56k_op_bscc(dsp56k_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 dsp56k_op_bscc_1(dsp56k_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 dsp56k_op_bsr(dsp56k_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 dsp56k_op_bsr_1(dsp56k_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 dsp56k_op_chkaau(dsp56k_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 dsp56k_op_debug(dsp56k_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 dsp56k_op_debugcc(dsp56k_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 dsp56k_op_div(dsp56k_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 dsp56k_op_dmac(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; - return 1; -} - -/* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */ -static size_t dsp56k_op_do(dsp56k_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 dsp56k_op_do_1(dsp56k_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 dsp56k_op_do_2(dsp56k_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("Dsp56k : 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("DSP56k: 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("DSP56k: 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 dsp56k_op_doforever(dsp56k_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 dsp56k_op_enddo(dsp56k_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 dsp56k_op_ext(dsp56k_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 dsp56k_op_illegal(dsp56k_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 dsp56k_op_imac(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffff0000U) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - DSP56K_V_CLEAR(); - - cycles += 2; - return 1; -} - -/* IMPY : 0001 0101 1000 FQQQ : A-102 */ -static size_t dsp56k_op_impy(dsp56k_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 dsp56k_op_jcc(dsp56k_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 dsp56k_op_jcc_1(dsp56k_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 dsp56k_op_jmp(dsp56k_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 dsp56k_op_jmp_1(dsp56k_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 dsp56k_op_jscc(dsp56k_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 dsp56k_op_jscc_1(dsp56k_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 dsp56k_op_jsr(dsp56k_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 dsp56k_op_jsr_1(dsp56k_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 dsp56k_op_jsr_2(dsp56k_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 dsp56k_op_lea(dsp56k_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 dsp56k_op_lea_1(dsp56k_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 dsp56k_op_macsuuu(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; - return 1; -} - -/* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */ -static size_t dsp56k_op_move_2(dsp56k_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 dsp56k_op_movec(dsp56k_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 dsp56k_op_movec_1(dsp56k_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 dsp56k_op_movec_2(dsp56k_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 dsp56k_op_movec_3(dsp56k_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("DSP56k: 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 dsp56k_op_movec_4(dsp56k_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 dsp56k_op_movec_5(dsp56k_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 dsp56k_op_movei(dsp56k_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 dsp56k_op_movem(dsp56k_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 dsp56k_op_movem_1(dsp56k_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 dsp56k_op_movem_2(dsp56k_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 dsp56k_op_movep(dsp56k_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 dsp56k_op_movep_1(dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles) -{ - /* X: and X: */ - 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("dsp56k : 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 dsp56k_op_moves(dsp56k_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 dsp56k_op_mpysuuu(dsp56k_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) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - - cycles += 2; - return 1; -} - -/* NEGC : 0001 0101 0110 F000 : A-168 */ -static size_t dsp56k_op_negc(dsp56k_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 dsp56k_op_nop(dsp56k_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 dsp56k_op_norm(dsp56k_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 dsp56k_op_ori(dsp56k_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 dsp56k_op_rep(dsp56k_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 dsp56k_op_rep_1(dsp56k_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 dsp56k_op_rep_2(dsp56k_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("DSP56k 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 dsp56k_op_repcc(dsp56k_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 dsp56k_op_reset(dsp56k_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 dsp56k_op_rti(dsp56k_core* cpustate, const uint16_t op, uint8_t* cycles) -{ - /* WARNING : THERE SHOULD BE A MORE GENERAL HANDLING OF STACK ERRORS. */ - if (SP == 0) - { - dsp56k_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 dsp56k_op_rts(dsp56k_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 dsp56k_op_stop(dsp56k_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 dsp56k_op_swap(dsp56k_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 dsp56k_op_swi(dsp56k_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 dsp56k_op_tcc(dsp56k_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 dsp56k_op_tfr2(dsp56k_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 dsp56k_op_tfr3(dsp56k_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 dsp56k_op_tst2(dsp56k_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) */ - DSP56K_L_CLEAR(); - DSP56K_E_CLEAR(); - /* U_CLEAR(); */ /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */ - if ((*((uint16_t*)D.addr)) & 0x8000) DSP56K_N_SET(); else DSP56K_N_CLEAR(); - if ((*((uint16_t*)D.addr)) == 0x0000) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); - /* DSP56K_V_CLEAR(); */ /* Unaffected */ - DSP56K_C_CLEAR(); - - cycles += 2; - return 1; -} - -/* WAIT : 0000 0000 0000 1011 : A-222 */ -static size_t dsp56k_op_wait(dsp56k_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 dsp56k_op_zero(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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("Dsp56k: 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(dsp56k_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(dsp56k_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("dsp56k: execute_q_table did something impossible!\n"); - return 0; -} - -static void execute_z_table(dsp56k_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(dsp56k_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(dsp56k_core* cpustate, uint16_t pp) -{ - uint16_t fullAddy = 0xffe0; - fullAddy |= pp; - return fullAddy; -} - -static uint16_t assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, uint16_t srs) -{ - uint16_t fullAddy = srs ; - if (fullAddy & 0x0020) - fullAddy |= 0xffc0 ; - - return fullAddy ; -} - -static void dsp56k_process_loop(dsp56k_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 dsp56k_process_rep(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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: 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: */ - /* 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(dsp56k_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(dsp56k_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(dsp56k_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("Dsp56k: 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("Dsp56k: 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 Dsp56kOpMask(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) & 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(dsp56k_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(dsp56k_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/dsp56k/dsp56pcu.cpp b/src/devices/cpu/dsp56k/dsp56pcu.cpp deleted file mode 100644 index 529c623a506..00000000000 --- a/src/devices/cpu/dsp56k/dsp56pcu.cpp +++ /dev/null @@ -1,488 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#include "emu.h" -#include "dsp56pcu.h" -#include "dsp56mem.h" - -namespace DSP56K -{ -/* ************************************************************************* */ -/* Status Register */ -/* ************************************************************************* */ -/* MR CCR */ -/* |-------------------------------------| |-------------------------------| */ -/* | LF | FV | * | * | S1 | S0 | I1 | I0 | | S | L | E | U | N | Z | V | C | */ -/* |-------------------------------------| |-------------------------------| */ -/* */ -/* ************************************************************************* */ -uint8_t LF_bit(const dsp56k_core* cpustate) { return (SR & 0x8000) >> 15; } -uint8_t FV_bit(const dsp56k_core* cpustate) { return (SR & 0x4000) >> 14; } -// uint8_t S_bits(const dsp56k_core* cpustate) { return (SR & 0x0c00) >> 10; } -uint8_t I_bits(const dsp56k_core* cpustate) { return (SR & 0x0300) >> 8; } -uint8_t S_bit (const dsp56k_core* cpustate) { return (SR & 0x0080) >> 7; } -uint8_t L_bit (const dsp56k_core* cpustate) { return (SR & 0x0040) >> 6; } -uint8_t E_bit (const dsp56k_core* cpustate) { return (SR & 0x0020) >> 5; } -uint8_t U_bit (const dsp56k_core* cpustate) { return (SR & 0x0010) >> 4; } -uint8_t N_bit (const dsp56k_core* cpustate) { return (SR & 0x0008) >> 3; } -uint8_t Z_bit (const dsp56k_core* cpustate) { return (SR & 0x0004) >> 2; } -uint8_t V_bit (const dsp56k_core* cpustate) { return (SR & 0x0002) >> 1; } -uint8_t C_bit (const dsp56k_core* cpustate) { return (SR & 0x0001) >> 0; } - -/* MR setters */ -void LF_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x8000); else (SR &= (~0x8000)); } -void FV_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x4000); else (SR &= (~0x4000)); } -void S_bits_set(dsp56k_core* cpustate, uint8_t value) { value = value & 0x03; SR &= ~(0x0c00); SR |= (value << 10); } -void I_bits_set(dsp56k_core* cpustate, uint8_t value) { value = value & 0x03; SR &= ~(0x0300); SR |= (value << 8); } - -/* CCR setters */ -void S_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x0080); else (SR &= (~0x0080)); } -void L_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x0040); else (SR &= (~0x0040)); } -void E_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x0020); else (SR &= (~0x0020)); } -void U_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x0010); else (SR &= (~0x0010)); } -void N_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x0008); else (SR &= (~0x0008)); } -void Z_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x0004); else (SR &= (~0x0004)); } -void V_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (SR |= 0x0002); else (SR &= (~0x0002)); } -void C_bit_set(dsp56k_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 dsp56k_core* cpustate) { return ((OMR & 0x0080) != 0); } -// uint8_t SD_bit(const dsp56k_core* cpustate) { return ((OMR & 0x0040) != 0); } -// uint8_t R_bit(const dsp56k_core* cpustate) { return ((OMR & 0x0020) != 0); } -// uint8_t SA_bit(const dsp56k_core* cpustate) { return ((OMR & 0x0010) != 0); } -// uint8_t MC_bit(const dsp56k_core* cpustate) { return ((OMR & 0x0004) != 0); } -uint8_t MB_bit(const dsp56k_core* cpustate) { return ((OMR & 0x0002) != 0); } -uint8_t MA_bit(const dsp56k_core* cpustate) { return ((OMR & 0x0001) != 0); } - -void CD_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0080); else (OMR &= (~0x0080)); } -void SD_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0040); else (OMR &= (~0x0040)); } -void R_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0020); else (OMR &= (~0x0020)); } -void SA_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0010); else (OMR &= (~0x0010)); } -void MC_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0004); else (OMR &= (~0x0004)); } -void MB_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0002); else (OMR &= (~0x0002)); } -void MA_bit_set(dsp56k_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0001); else (OMR &= (~0x0001)); } - -uint8_t dsp56k_operating_mode(const dsp56k_core* cpustate) -{ - return ((MB_bit(cpustate) << 1) | MA_bit(cpustate)); -} - - - -/* ************************************************************************* */ -/* Stack Pointer */ -/* ************************************************************************* */ -/* */ -/* |---------------------------------------------------------------------| */ -/* | * | * | * | * | * | * | * | * | * | * | UF | SE | P3 | P2 | P1 | P0 | */ -/* |---------------------------------------------------------------------| */ -/* */ -/* ************************************************************************* */ -uint8_t UF_bit(const dsp56k_core* cpustate) { return ((SP & 0x0020) != 0); } -uint8_t SE_bit(const dsp56k_core* cpustate) { return ((SP & 0x0010) != 0); } - -//void UF_bit_set(dsp56k_core* cpustate, uint8_t value) {}; -//void SE_bit_set(dsp56k_core* cpustate, uint8_t value) {}; - - - -/*************************************************************************** - INITIALIZATION AND RESET -***************************************************************************/ -void pcu_init(dsp56k_core* cpustate, device_t *device) -{ - /* Init the irq table */ - dsp56k_irq_table_init(); - - /* save states - dsp56k_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(dsp56k_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(dsp56k_operating_mode(cpustate)) - { - case 0x00: - cpustate->device->logerror("Dsp56k 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("Dsp56k 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("DSP56k : Currently in (hacked) bootstrap mode - reading from SSIx.\n"); - } - else - { - cpustate->bootstrap_mode = BOOTSTRAP_HI; - cpustate->device->logerror("DSP56k : 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("Dsp56k in Normal Expanded Mode\n"); - PC = 0xe000; - cpustate->PCU.reset_vector = 0xe000; - break; - - case 0x03: - cpustate->device->logerror("Dsp56k 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 */ - dsp56k_clear_pending_interrupts(cpustate); -} - -/*************************************************************************** - INTERRUPT HANDLING -***************************************************************************/ -struct dsp56k_irq_data -{ - uint16_t irq_vector; - char irq_source[128]; -}; - -dsp56k_irq_data dsp56k_interrupt_sources[32]; - -/* TODO: Figure out how to switch on level versus edge-triggered. */ -void pcu_service_interrupts(dsp56k_core* cpustate) -{ - int i; - - /* Count list of pending interrupts */ - int num_servicable = dsp56k_count_pending_interrupts(cpustate); - - if (num_servicable == 0) - return; - - /* Sort list according to priority */ - dsp56k_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 = dsp56k_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 = dsp56k_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); - } - } - } - - dsp56k_clear_pending_interrupts(cpustate); -} - - -/* Register an interrupt */ -void dsp56k_add_pending_interrupt(dsp56k_core* cpustate, const char* name) -{ - int i; - int irq_index = dsp56k_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 dsp56k_set_irq_source(uint8_t irq_num, uint16_t iv, const char* source) -{ - dsp56k_interrupt_sources[irq_num].irq_vector = iv; - strcpy(dsp56k_interrupt_sources[irq_num].irq_source, source); -} - -/* Construct a table containing pertient IRQ information */ -void dsp56k_irq_table_init(void) -{ - /* 1-14 + 1-18 */ - /* TODO: Cull host command stuff appropriately */ - /* array index . vector . token */ - dsp56k_set_irq_source(0, 0x0000, "Hardware RESET"); - dsp56k_set_irq_source(1, 0x0002, "Illegal Instruction"); - dsp56k_set_irq_source(2, 0x0004, "Stack Error"); - dsp56k_set_irq_source(3, 0x0006, "Reserved"); - dsp56k_set_irq_source(4, 0x0008, "SWI"); - dsp56k_set_irq_source(5, 0x000a, "IRQA"); - dsp56k_set_irq_source(6, 0x000c, "IRQB"); - dsp56k_set_irq_source(7, 0x000e, "Reserved"); - dsp56k_set_irq_source(8, 0x0010, "SSI0 Receive Data with Exception"); - dsp56k_set_irq_source(9, 0x0012, "SSI0 Receive Data"); - dsp56k_set_irq_source(10, 0x0014, "SSI0 Transmit Data with Exception"); - dsp56k_set_irq_source(11, 0x0016, "SSI0 Transmit Data"); - dsp56k_set_irq_source(12, 0x0018, "SSI1 Receive Data with Exception"); - dsp56k_set_irq_source(13, 0x001a, "SSI1 Receive Data"); - dsp56k_set_irq_source(14, 0x001c, "SSI1 Transmit Data with Exception"); - dsp56k_set_irq_source(15, 0x001e, "SSI1 Transmit Data"); - dsp56k_set_irq_source(16, 0x0020, "Timer Overflow"); - dsp56k_set_irq_source(17, 0x0022, "Timer Compare"); - dsp56k_set_irq_source(18, 0x0024, "Host DMA Receive Data"); - dsp56k_set_irq_source(19, 0x0026, "Host DMA Transmit Data"); - dsp56k_set_irq_source(20, 0x0028, "Host Receive Data"); - dsp56k_set_irq_source(21, 0x002a, "Host Transmit Data"); - dsp56k_set_irq_source(22, 0x002c, "Host Command"); /* Default vector for the host command */ - dsp56k_set_irq_source(23, 0x002e, "Codec Receive/Transmit"); - dsp56k_set_irq_source(24, 0x0030, "Host Command 1"); - dsp56k_set_irq_source(25, 0x0032, "Host Command 2"); - dsp56k_set_irq_source(26, 0x0034, "Host Command 3"); - dsp56k_set_irq_source(27, 0x0036, "Host Command 4"); - dsp56k_set_irq_source(28, 0x0038, "Host Command 5"); - dsp56k_set_irq_source(29, 0x003a, "Host Command 6"); - dsp56k_set_irq_source(30, 0x003c, "Host Command 7"); - dsp56k_set_irq_source(31, 0x003e, "Host Command 8"); -} - -/* Clear all entries from the pending table */ -void dsp56k_clear_pending_interrupts(dsp56k_core* cpustate) -{ - int i; - for (i = 0; i < 32; i++) - { - cpustate->PCU.pending_interrupts[i] = -1; - } -} - -/* Recover number of pending irqs */ -int dsp56k_count_pending_interrupts(dsp56k_core* cpustate) -{ - int numI = 0; - while (cpustate->PCU.pending_interrupts[numI] != -1) - { - numI++; - } - - return numI; -} - -/* Sort the pending irqs by priority */ -void dsp56k_sort_pending_interrupts(dsp56k_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] = dsp56k_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 dsp56k_get_irq_priority(dsp56k_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 dsp56k_get_irq_index_by_tag(const char* tag) -{ - int i; - for (i = 0; i < 32; i++) - { - if (strcmp(tag, dsp56k_interrupt_sources[i].irq_source) == 0) - { - return i; - } - } - - fatalerror("DSP56K ERROR : IRQ TAG specified incorrectly (get_vector_by_tag) : %s.\n", tag); - // never executed - //return -1; -} - -} // namespace DSP56K diff --git a/src/devices/cpu/dsp56k/dsp56pcu.h b/src/devices/cpu/dsp56k/dsp56pcu.h deleted file mode 100644 index 6e640af3839..00000000000 --- a/src/devices/cpu/dsp56k/dsp56pcu.h +++ /dev/null @@ -1,150 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#ifndef __DSP56_PCU_H__ -#define __DSP56_PCU_H__ - -#include "dsp56k.h" - -namespace DSP56K -{ -/*************************************************************************** - PCU -***************************************************************************/ -void pcu_reset(dsp56k_core* cpustate); -void pcu_init(dsp56k_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 dsp56k_core* cpustate); -uint8_t FV_bit(const dsp56k_core* cpustate); -//uint8_t S_bits(const dsp56k_core* cpustate); -uint8_t I_bits(const dsp56k_core* cpustate); - -/* CCR - with macros for easy access */ -#define S() (S_bit(cpustate)) -uint8_t S_bit(const dsp56k_core* cpustate); -#define L() (L_bit(cpustate)) -uint8_t L_bit(const dsp56k_core* cpustate); -#define E() (E_bit(cpustate)) -uint8_t E_bit(const dsp56k_core* cpustate); -#define U() (U_bit(cpustate)) -uint8_t U_bit(const dsp56k_core* cpustate); -#define N() (N_bit(cpustate)) -uint8_t N_bit(const dsp56k_core* cpustate); -#define Z() (Z_bit(cpustate)) -uint8_t Z_bit(const dsp56k_core* cpustate); -#define V() (V_bit(cpustate)) -uint8_t V_bit(const dsp56k_core* cpustate); -#define C() (C_bit(cpustate)) -uint8_t C_bit(const dsp56k_core* cpustate); - -/* MR setters */ -void LF_bit_set(dsp56k_core* cpustate, uint8_t value); -void FV_bit_set(dsp56k_core* cpustate, uint8_t value); -void S_bits_set(dsp56k_core* cpustate, uint8_t value); -void I_bits_set(dsp56k_core* cpustate, uint8_t value); - -/* CCR setters - with macros for easy access */ -#define DSP56K_S_SET() (S_bit_set(cpustate, 1)) -#define DSP56K_S_CLEAR() (S_bit_set(cpustate, 0)) -void S_bit_set(dsp56k_core* cpustate, uint8_t value); -#define DSP56K_L_SET() (L_bit_set(cpustate, 1)) -#define DSP56K_L_CLEAR() (L_bit_set(cpustate, 0)) -void L_bit_set(dsp56k_core* cpustate, uint8_t value); -#define DSP56K_E_SET() (E_bit_set(cpustate, 1)) -#define DSP56K_E_CLEAR() (E_bit_set(cpustate, 0)) -void E_bit_set(dsp56k_core* cpustate, uint8_t value); -#define DSP56K_U_SET() (U_bit_set(cpustate, 1)) -#define DSP56K_U_CLEAR() (U_bit_set(cpustate, 0)) -void U_bit_set(dsp56k_core* cpustate, uint8_t value); -#define DSP56K_N_SET() (N_bit_set(cpustate, 1)) -#define DSP56K_N_CLEAR() (N_bit_set(cpustate, 0)) -void N_bit_set(dsp56k_core* cpustate, uint8_t value); -#define DSP56K_Z_SET() (Z_bit_set(cpustate, 1)) -#define DSP56K_Z_CLEAR() (Z_bit_set(cpustate, 0)) -void Z_bit_set(dsp56k_core* cpustate, uint8_t value); -#define DSP56K_V_SET() (V_bit_set(cpustate, 1)) -#define DSP56K_V_CLEAR() (V_bit_set(cpustate, 0)) -void V_bit_set(dsp56k_core* cpustate, uint8_t value); -#define DSP56K_C_SET() (C_bit_set(cpustate, 1)) -#define DSP56K_C_CLEAR() (C_bit_set(cpustate, 0)) -void C_bit_set(dsp56k_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 dsp56k_core* cpustate); -//uint8_t SD_bit(const dsp56k_core* cpustate); -//uint8_t R_bit(const dsp56k_core* cpustate); -//uint8_t SA_bit(const dsp56k_core* cpustate); -//uint8_t MC_bit(const dsp56k_core* cpustate); -uint8_t MB_bit(const dsp56k_core* cpustate); -uint8_t MA_bit(const dsp56k_core* cpustate); - -void CD_bit_set(dsp56k_core* cpustate, uint8_t value); -void SD_bit_set(dsp56k_core* cpustate, uint8_t value); -void R_bit_set(dsp56k_core* cpustate, uint8_t value); -void SA_bit_set(dsp56k_core* cpustate, uint8_t value); -void MC_bit_set(dsp56k_core* cpustate, uint8_t value); -void MB_bit_set(dsp56k_core* cpustate, uint8_t value); -void MA_bit_set(dsp56k_core* cpustate, uint8_t value); - -/* 1-27 STACK POINTER (SP) BITS */ -uint8_t UF_bit(const dsp56k_core* cpustate); -uint8_t SE_bit(const dsp56k_core* cpustate); - -//void UF_bit_set(dsp56k_core* cpustate, uint8_t value) {}; -//void SE_bit_set(dsp56k_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(dsp56k_core* cpustate); - -void dsp56k_irq_table_init(void); -void dsp56k_set_irq_source(uint8_t irq_num, uint16_t iv, const char* source); -int dsp56k_get_irq_index_by_tag(const char* tag); - -void dsp56k_add_pending_interrupt(dsp56k_core* cpustate, const char* name); // Call me to add an interrupt to the queue - -void dsp56k_clear_pending_interrupts(dsp56k_core* cpustate); -int dsp56k_count_pending_interrupts(dsp56k_core* cpustate); -void dsp56k_sort_pending_interrupts(dsp56k_core* cpustate, int num); -int8_t dsp56k_get_irq_priority(dsp56k_core* cpustate, int index); - -} // namespace DSP56K - -#endif diff --git a/src/devices/cpu/dsp56k/inst.cpp b/src/devices/cpu/dsp56k/inst.cpp deleted file mode 100644 index d7c99777338..00000000000 --- a/src/devices/cpu/dsp56k/inst.cpp +++ /dev/null @@ -1,786 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#include "emu.h" -#include "inst.h" -#include "emu.h" - -namespace DSP56K -{ -// Factory -std::unique_ptr 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 op = decodeInstruction(opc, w0, w1, true); - if (op) - { - // This parallel move only works for certain trailing instructions. - if (dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(op.get()) || - dynamic_cast(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(opc, w0, w1); - } - /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ - if ((w0 & 0xe097) == 0x6017) - { - return std::make_unique(opc, w0, w1); - } - /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ - else if ((w0 & 0xe094) == 0x6084) - { - return std::make_unique(opc, w0, w1); - } - /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ - else if ((w0 & 0xe094) == 0x6094) - { - return std::make_unique(opc, w0, w1); - } - /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ - else if ((w0 & 0xe094) == 0x6080) - { - return std::make_unique(opc, w0, w1); - } - /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ - else if ((w0 & 0xe094) == 0x6090) - { - return std::make_unique(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(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(opc, w0, w1); - } - /* MAC : 0001 0111 RRDD FQQQ : A-122 */ - else if ((w0 & 0xff00) == 0x1700) - { - return std::make_unique(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(opc, w0, w1); - } - /* ADD : .... .... 0000 FJJJ : A-22 */ - else if ((w0 & 0x00f0) == 0x0000) - { - return std::make_unique(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(opc, w0, w1); - } - /* TFR : .... .... 0001 FJJJ : A-212 */ - else if ((w0 & 0x00f0) == 0x0010) - { - return std::make_unique(opc, w0, w1); - } - - /* RND : .... .... 0010 F000 : A-188 */ - else if ((w0 & 0x00f7) == 0x0020) - { - return std::make_unique(opc, w0, w1); - } - /* TST : .... .... 0010 F001 : A-218 */ - else if ((w0 & 0x00f7) == 0x0021) - { - return std::make_unique(opc, w0, w1); - } - /* INC : .... .... 0010 F010 : A-104 */ - else if ((w0 & 0x00f7) == 0x0022) - { - return std::make_unique(opc, w0, w1); - } - /* INC24 : .... .... 0010 F011 : A-106 */ - else if ((w0 & 0x00f7) == 0x0023) - { - return std::make_unique(opc, w0, w1); - } - /* OR : .... .... 0010 F1JJ : A-176 */ - else if ((w0 & 0x00f4) == 0x0024) - { - return std::make_unique(opc, w0, w1); - } - - /* ASR : .... .... 0011 F000 : A-32 */ - else if ((w0 & 0x00f7) == 0x0030) - { - return std::make_unique(opc, w0, w1); - } - /* ASL : .... .... 0011 F001 : A-28 */ - else if ((w0 & 0x00f7) == 0x0031) - { - return std::make_unique(opc, w0, w1); - } - /* LSR : .... .... 0011 F010 : A-120 */ - else if ((w0 & 0x00f7) == 0x0032) - { - return std::make_unique(opc, w0, w1); - } - /* LSL : .... .... 0011 F011 : A-118 */ - else if ((w0 & 0x00f7) == 0x0033) - { - return std::make_unique(opc, w0, w1); - } - /* EOR : .... .... 0011 F1JJ : A-94 */ - else if ((w0 & 0x00f4) == 0x0034) - { - return std::make_unique(opc, w0, w1); - } - - /* SUBL : .... .... 0100 F001 : A-204 */ - else if ((w0 & 0x00f7) == 0x0041) - { - return std::make_unique(opc, w0, w1); - } - /* SUB : .... .... 0100 FJJJ : A-202 */ - else if ((w0 & 0x00f0) == 0x0040) - { - return std::make_unique(opc, w0, w1); - } - - /* CLR24 : .... .... 0101 F001 : A-62 */ - else if ((w0 & 0x00f7) == 0x0051) - { - return std::make_unique(opc, w0, w1); - } - /* SBC : .... .... 0101 F01J : A-198 */ - else if ((w0 & 0x00f6) == 0x0052) - { - return std::make_unique(opc, w0, w1); - } - /* CMP : .... .... 0101 FJJJ : A-64 */ - else if ((w0 & 0x00f0) == 0x0050) - { - return std::make_unique(opc, w0, w1); - } - - /* NEG : .... .... 0110 F000 : A-166 */ - else if ((w0 & 0x00f7) == 0x0060) - { - return std::make_unique(opc, w0, w1); - } - /* NOT : .... .... 0110 F001 : A-174 */ - else if ((w0 & 0x00f7) == 0x0061) - { - return std::make_unique(opc, w0, w1); - } - /* DEC : .... .... 0110 F010 : A-72 */ - else if ((w0 & 0x00f7) == 0x0062) - { - return std::make_unique(opc, w0, w1); - } - /* DEC24 : .... .... 0110 F011 : A-74 */ - else if ((w0 & 0x00f7) == 0x0063) - { - return std::make_unique(opc, w0, w1); - } - /* AND : .... .... 0110 F1JJ : A-24 */ - else if ((w0 & 0x00f4) == 0x0064) - { - return std::make_unique(opc, w0, w1); - } - - /* ABS : .... .... 0111 F001 : A-18 */ - if ((w0 & 0x00f7) == 0x0071) - { - return std::make_unique(opc, w0, w1); - } - /* ROR : .... .... 0111 F010 : A-192 */ - else if ((w0 & 0x00f7) == 0x0072) - { - return std::make_unique(opc, w0, w1); - } - /* ROL : .... .... 0111 F011 : A-190 */ - else if ((w0 & 0x00f7) == 0x0073) - { - return std::make_unique(opc, w0, w1); - } - /* CMPM : .... .... 0111 FJJJ : A-66 */ - else if ((w0 & 0x00f0) == 0x0070) - { - return std::make_unique(opc, w0, w1); - } - - /* MPY : .... .... 1k00 FQQQ : A-160 */ - else if ((w0 & 0x00b0) == 0x0080) - { - return std::make_unique(opc, w0, w1); - } - /* MPYR : .... .... 1k01 FQQQ : A-162 */ - else if ((w0 & 0x00b0) == 0x0090) - { - return std::make_unique(opc, w0, w1); - } - /* MAC : .... .... 1k10 FQQQ : A-122 */ - else if ((w0 & 0x00b0) == 0x00a0) - { - return std::make_unique(opc, w0, w1); - } - /* MACR : .... .... 1k11 FQQQ : A-124 */ - else if ((w0 & 0x00b0) == 0x00b0) - { - return std::make_unique(opc, w0, w1); - } - } - - /******************************/ - /* Remaining non-parallel ops */ - /******************************/ - /* ADC : 0001 0101 0000 F01J : A-20 */ - else if ((w0 & 0xfff6) == 0x1502) - { - return std::make_unique(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(opc, w0, w1); - } - /* ASL4 : 0001 0101 0011 F001 : A-30 */ - else if ((w0 & 0xfff7) == 0x1531) - { - return std::make_unique(opc, w0, w1); - } - /* ASR4 : 0001 0101 0011 F000 : A-34 */ - else if ((w0 & 0xfff7) == 0x1530) - { - return std::make_unique(opc, w0, w1); - } - /* ASR16 : 0001 0101 0111 F000 : A-36 */ - else if ((w0 & 0xfff7) == 0x1570) - { - return std::make_unique(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(opc, w0, w1); - } - /* Bcc : 0010 11cc ccee eeee : A-48 */ - else if ((w0 & 0xfc00) == 0x2c00) - { - return std::make_unique(opc, w0, w1); - } - /* Bcc : 0000 0111 RR10 cccc : A-48 */ - else if ((w0 & 0xff30) == 0x0720) - { - return std::make_unique(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(opc, w0, w1); - } - /* BRA : 0000 1011 aaaa aaaa : A-50 */ - else if ((w0 & 0xff00) == 0x0b00) - { - return std::make_unique(opc, w0, w1); - } - /* BRA : 0000 0001 0010 11RR : A-50 */ - else if ((w0 & 0xfffc) == 0x012c) - { - return std::make_unique(opc, w0, w1); - } - /* BRKc : 0000 0001 0001 cccc : A-52 */ - else if ((w0 & 0xfff0) == 0x0110) - { - return std::make_unique(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(opc, w0, w1); - } - /* BScc : 0000 0111 RR00 cccc : A-54 */ - else if ((w0 & 0xff30) == 0x0700) - { - return std::make_unique(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(opc, w0, w1); - } - /* BSR : 0000 0001 0010 10RR : A-56 */ - else if ((w0 & 0xfffc) == 0x0128) - { - return std::make_unique(opc, w0, w1); - } - /* CHKAAU : 0000 0000 0000 0100 : A-58 */ - else if ((w0 & 0xffff) == 0x0004) - { - return std::make_unique(opc, w0, w1); - } - /* DEBUG : 0000 0000 0000 0001 : A-68 */ - else if ((w0 & 0xffff) == 0x0001) - { - return std::make_unique(opc, w0, w1); - } - /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ - else if ((w0 & 0xfff0) == 0x0050) - { - return std::make_unique(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
(opc, w0, w1); - } - /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ - else if ((w0 & 0xffd0) == 0x1590) - { - return std::make_unique(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(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(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(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(opc, w0, w1); - } - /* ENDDO : 0000 0000 0000 1001 : A-92 */ - else if ((w0 & 0xffff) == 0x0009) - { - return std::make_unique(opc, w0, w1); - } - /* EXT : 0001 0101 0101 F010 : A-96 */ - else if ((w0 & 0xfff7) == 0x1552) - { - return std::make_unique(opc, w0, w1); - } - /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ - else if ((w0 & 0xffff) == 0x000f) - { - return std::make_unique(opc, w0, w1); - } - /* IMAC : 0001 0101 1010 FQQQ : A-100 */ - else if ((w0 & 0xfff0) == 0x15a0) - { - return std::make_unique(opc, w0, w1); - } - /* IMPY : 0001 0101 1000 FQQQ : A-102 */ - else if ((w0 & 0xfff0) == 0x1580) - { - return std::make_unique(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(opc, w0, w1); - } - /* Jcc : 0000 0110 RR10 cccc : A-108 */ - else if ((w0 & 0xff30) == 0x0620 ) - { - return std::make_unique(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(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(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(opc, w0, w1); - } - /* JScc : 0000 0110 RR00 cccc : A-112 */ - else if ((w0 & 0xff30) == 0x0600) - { - return std::make_unique(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(opc, w0, w1); - } - /* JSR : 0000 1010 AAAA AAAA : A-114 */ - else if ((w0 & 0xff00) == 0x0a00) - { - return std::make_unique(opc, w0, w1); - } - /* JSR : 0000 0001 0010 00RR : A-114 */ - else if ((w0 & 0xfffc) == 0x0120) - { - return std::make_unique(opc, w0, w1); - } - /* LEA : 0000 0001 11TT MMRR : A-116 */ - else if ((w0 & 0xffc0) == 0x01c0) - { - return std::make_unique(opc, w0, w1); - } - /* LEA : 0000 0001 10NN MMRR : A-116 */ - else if ((w0 & 0xffc0) == 0x0180) - { - return std::make_unique(opc, w0, w1); - } - /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ - else if ((w0 & 0xfff0) == 0x15e0) - { - return std::make_unique(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(opc, w0, w1); -// NEW // } - /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ - else if ((w0 & 0xf810) == 0x3800) - { - return std::make_unique(opc, w0, w1); - } - /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ - else if ((w0 & 0xf814) == 0x3810) - { - return std::make_unique(opc, w0, w1); - } - /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ - else if ((w0 & 0xf816) == 0x3816) - { - return std::make_unique(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(opc, w0, w1); - } - /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ - else if ((w0 & 0xfc00) == 0x2800) - { - return std::make_unique(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(opc, w0, w1); - } - /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ - else if ((w0 & 0xfc00) == 0x2000) - { - return std::make_unique(opc, w0, w1); - } - /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ - else if ((w0 & 0xfe20) == 0x0200) - { - return std::make_unique(opc, w0, w1); - } - /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ - else if ((w0 & 0xfe30) == 0x0230) - { - return std::make_unique(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(opc, w0, w1); - } - /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ - else if ((w0 & 0xfe20) == 0x1820) - { - return std::make_unique(opc, w0, w1); - } - /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ - else if ((w0 & 0xfe00) == 0x0c00) - { - return std::make_unique(opc, w0, w1); - } - /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ - else if ((w0 & 0xfe20) == 0x1800) - { - return std::make_unique(opc, w0, w1); - } - /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ - else if ((w0 & 0xfff0) == 0x15c0) - { - return std::make_unique(opc, w0, w1); - } - /* NEGC : 0001 0101 0110 F000 : A-168 */ - else if ((w0 & 0xfff7) == 0x1560) - { - return std::make_unique(opc, w0, w1); - } - /* NOP : 0000 0000 0000 0000 : A-170 */ - else if ((w0 & 0xffff) == 0x0000) - { - return std::make_unique(opc, w0, w1); - } - /* NORM : 0001 0101 0010 F0RR : A-172 */ - else if ((w0 & 0xfff4) == 0x1520) - { - return std::make_unique(opc, w0, w1); - } - /* ORI : 0001 1EE1 iiii iiii : A-178 */ - else if ((w0 & 0xf900) == 0x1900) - { - return std::make_unique(opc, w0, w1); - } - /* REP : 0000 0000 111- --RR : A-180 */ - else if ((w0 & 0xffe0) == 0x00e0) - { - return std::make_unique(opc, w0, w1); - } - /* REP : 0000 1111 iiii iiii : A-180 */ - else if ((w0 & 0xff00) == 0x0f00) - { - return std::make_unique(opc, w0, w1); - } - /* REP : 0000 0100 001D DDDD : A-180 */ - else if ((w0 & 0xffe0) == 0x0420) - { - return std::make_unique(opc, w0, w1); - } - /* REPcc : 0000 0001 0101 cccc : A-184 */ - else if ((w0 & 0xfff0) == 0x0150) - { - return std::make_unique(opc, w0, w1); - } - /* RESET : 0000 0000 0000 1000 : A-186 */ - else if ((w0 & 0xffff) == 0x0008) - { - return std::make_unique(opc, w0, w1); - } - /* RTI : 0000 0000 0000 0111 : A-194 */ - else if ((w0 & 0xffff) == 0x0007) - { - return std::make_unique(opc, w0, w1); - } - /* RTS : 0000 0000 0000 0110 : A-196 */ - else if ((w0 & 0xffff) == 0x0006) - { - return std::make_unique(opc, w0, w1); - } - /* STOP : 0000 0000 0000 1010 : A-200 */ - else if ((w0 & 0xffff) == 0x000a) - { - return std::make_unique(opc, w0, w1); - } - /* SWAP : 0001 0101 0111 F001 : A-206 */ - else if ((w0 & 0xfff7) == 0x1571) - { - return std::make_unique(opc, w0, w1); - } - /* SWI : 0000 0000 0000 0101 : A-208 */ - else if ((w0 & 0xffff) == 0x0005) - { - return std::make_unique(opc, w0, w1); - } - /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ - else if ((w0 & 0xfc02) == 0x1000) - { - return std::make_unique(opc, w0, w1); - } - /* TFR(2) : 0001 0101 0000 F00J : A-214 */ - else if ((w0 & 0xfff6) == 0x1500) - { - return std::make_unique(opc, w0, w1); - } - /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ - else if ((w0 & 0xfc00) == 0x2400) - { - return std::make_unique(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(opc, w0, w1); - } - /* WAIT : 0000 0000 0000 1011 : A-222 */ - else if ((w0 & 0xffff) == 0x000b) - { - return std::make_unique(opc, w0, w1); - } - /* ZERO : 0001 0101 0101 F000 : A-224 */ - else if ((w0 & 0xfff7) == 0x1550) - { - return std::make_unique(opc, w0, w1); - } - /* SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! */ - else if ((w0 & 0xfff0) == 0x15d0) - { - return std::make_unique(opc, w0, w1); - } - /* SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! */ - else if ((w0 & 0xfff0) == 0x15f0) - { - return std::make_unique(opc, w0, w1); - } - - return nullptr; -} - -} diff --git a/src/devices/cpu/dsp56k/inst.h b/src/devices/cpu/dsp56k/inst.h deleted file mode 100644 index d2db2a013e9..00000000000 --- a/src/devices/cpu/dsp56k/inst.h +++ /dev/null @@ -1,3774 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#ifndef __DSP56K_INSTRUCTION_H__ -#define __DSP56K_INSTRUCTION_H__ - -#include "opcode.h" -#include "tables.h" - -#include "dsp56k.h" -#include "dsp56def.h" -#include "dsp56pcu.h" - -// -// An Instruction is the base class all regular ops inherit from. -// -namespace DSP56K -{ -#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(dsp56k_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 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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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(dsp56k_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/dsp56k/opcode.cpp b/src/devices/cpu/dsp56k/opcode.cpp deleted file mode 100644 index efd1ce6156e..00000000000 --- a/src/devices/cpu/dsp56k/opcode.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#include "emu.h" -#include - -#include "opcode.h" - -namespace DSP56K -{ -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(dsp56k_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/dsp56k/opcode.h b/src/devices/cpu/dsp56k/opcode.h deleted file mode 100644 index 704602d17f3..00000000000 --- a/src/devices/cpu/dsp56k/opcode.h +++ /dev/null @@ -1,46 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#ifndef __DSP56K_OPCODE_H__ -#define __DSP56K_OPCODE_H__ - -#include "inst.h" -#include "pmove.h" - -#include "dsp56k.h" - -// -// An Opcode contains an instruction and a parallel move operation. -// -namespace DSP56K -{ -class Instruction; -class ParallelMove; - -class Opcode -{ -public: - Opcode(uint16_t w0, uint16_t w1); - virtual ~Opcode(); - - std::string disassemble() const; - void evaluate(dsp56k_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 m_instruction; - std::unique_ptr m_parallelMove; - - uint16_t m_word0; - //uint16_t m_word1; - - std::string dcString() const; -}; - -} -#endif diff --git a/src/devices/cpu/dsp56k/pmove.cpp b/src/devices/cpu/dsp56k/pmove.cpp deleted file mode 100644 index 15a13eb9ecf..00000000000 --- a/src/devices/cpu/dsp56k/pmove.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#include "emu.h" -#include "pmove.h" - -namespace DSP56K -{ -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::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(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(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(opc, w0, w1); - } - /* Address Register Update : 0011 0zRR .... .... : A-135 */ - else if ((w0 & 0xf800) == 0x3000) - { - return std::make_unique(opc, w0, w1); - } - /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ - else if ((w0 & 0x8000) == 0x8000) - { - return std::make_unique(opc, w0, w1); - } - /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ - else if ((w0 & 0xf000) == 0x5000) - { - return std::make_unique(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(opc, w0, w1); - } - } - } - - return nullptr; -} - -} diff --git a/src/devices/cpu/dsp56k/pmove.h b/src/devices/cpu/dsp56k/pmove.h deleted file mode 100644 index 86d0932cf2f..00000000000 --- a/src/devices/cpu/dsp56k/pmove.h +++ /dev/null @@ -1,335 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#ifndef __DSP56K_PARALLEL_MOVE_H__ -#define __DSP56K_PARALLEL_MOVE_H__ - -#include "opcode.h" -#include "tables.h" - -// -// A ParallelMove Object is what all parallel move classes inherit from. -// -namespace DSP56K -{ -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 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/dsp56k/tables.cpp b/src/devices/cpu/dsp56k/tables.cpp deleted file mode 100644 index fac697f8fa8..00000000000 --- a/src/devices/cpu/dsp56k/tables.cpp +++ /dev/null @@ -1,900 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#include "emu.h" -#include -#include -#include - -#include "tables.h" -#include "dsp56def.h" - -namespace DSP56K -{ -/******************/ -/* 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 dsp56k_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) & 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(dsp56k_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(dsp56k_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/dsp56k/tables.h b/src/devices/cpu/dsp56k/tables.h deleted file mode 100644 index 05c11db908b..00000000000 --- a/src/devices/cpu/dsp56k/tables.h +++ /dev/null @@ -1,93 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Andrew Gardner -#ifndef __DSP56K_OPS_H__ -#define __DSP56K_OPS_H__ - -#include -#include - -#include "dsp56k.h" - -namespace DSP56K -{ -#define BITSn(CUR,MASK) (dsp56k_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 dsp56k_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(dsp56k_core* cpustate, const reg_id& reg); -void setReg16(dsp56k_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 diff --git a/src/mame/drivers/indigo.cpp b/src/mame/drivers/indigo.cpp index f5ceae47718..af32ece2422 100644 --- a/src/mame/drivers/indigo.cpp +++ b/src/mame/drivers/indigo.cpp @@ -16,7 +16,7 @@ **********************************************************************/ #include "emu.h" -//#include "cpu/dsp56k/dsp56k.h" +//#include "cpu/dsp56156/dsp56156.h" #include "cpu/mips/mips1.h" #include "cpu/mips/mips3.h" #include "machine/eepromser.h" diff --git a/src/mame/drivers/plygonet.cpp b/src/mame/drivers/plygonet.cpp index 5c86f066355..caba37690bf 100644 --- a/src/mame/drivers/plygonet.cpp +++ b/src/mame/drivers/plygonet.cpp @@ -186,16 +186,16 @@ WRITE32_MEMBER(polygonet_state::shared_ram_write) m_maincpu->pc()); } - /* write to the current dsp56k word */ + /* write to the current DSP word */ if (ACCESSING_BITS_16_31) { - m_dsp56k_shared_ram_16[(offset<<1)] = (m_shared_ram[offset] & 0xffff0000) >> 16 ; + m_dsp56156_shared_ram_16[(offset<<1)] = (m_shared_ram[offset] & 0xffff0000) >> 16 ; } - /* write to the next dsp56k word */ + /* write to the next DSP word */ if (ACCESSING_BITS_0_15) { - m_dsp56k_shared_ram_16[(offset<<1)+1] = (m_shared_ram[offset] & 0x0000ffff) ; + m_dsp56156_shared_ram_16[(offset<<1)+1] = (m_shared_ram[offset] & 0x0000ffff) ; } } @@ -207,12 +207,12 @@ WRITE32_MEMBER(polygonet_state::dsp_w_lines) if ((data >> 24) & 0x01) { // logerror("RESET CLEARED\n"); - m_dsp->set_input_line(DSP56K_IRQ_RESET, CLEAR_LINE); + m_dsp->set_input_line(DSP56156_IRQ_RESET, CLEAR_LINE); } else { // logerror("RESET ASSERTED\n"); - m_dsp->set_input_line(DSP56K_IRQ_RESET, ASSERT_LINE); + m_dsp->set_input_line(DSP56156_IRQ_RESET, ASSERT_LINE); } /* 0x04000000 is the COMBNK line - it switches who has access to the shared RAM - the dsp or the 68020 */ @@ -241,16 +241,16 @@ READ32_MEMBER(polygonet_state::network_r) /**********************************************************************************/ -/******* DSP56k maps *******/ +/******* DSP56156 maps *******/ /**********************************************************************************/ /* It's believed this is hard-wired to return (at least) bit 15 as 0 - causes a host interface bootup */ -READ16_MEMBER(polygonet_state::dsp56k_bootload_r) +READ16_MEMBER(polygonet_state::dsp56156_bootload_r) { return 0x7fff; } -/* The dsp56k's Port C Data register (0xffe3) : +/* The dsp56156's Port C Data register (0xffe3) : Program code (function 4e) configures it as general purpose output I/O pins (ffc1 = 0000 & ffc3 = 0fff). XXXX ---- ---- ---- . Reserved bits @@ -265,9 +265,9 @@ READ16_MEMBER(polygonet_state::dsp56k_bootload_r) bit 0002 turns on *just* before this happens. */ -static uint8_t dsp56k_bank_group(device_t* cpu) +static uint8_t dsp56156_bank_group(device_t* cpu) { - uint16_t portC = downcast(cpu)->get_peripheral_memory(0xffe3); + uint16_t portC = downcast(cpu)->get_peripheral_memory(0xffe3); /* If bank group B is on, it overrides bank group A */ if (portC & 0x0002) @@ -278,9 +278,9 @@ static uint8_t dsp56k_bank_group(device_t* cpu) return INVALID_BANK_GROUP; } -static uint8_t dsp56k_bank_num(device_t* cpu, uint8_t bank_group) +static uint8_t dsp56156_bank_num(device_t* cpu, uint8_t bank_group) { - uint16_t portC = downcast(cpu)->get_peripheral_memory(0xffe3); + uint16_t portC = downcast(cpu)->get_peripheral_memory(0xffe3); if (bank_group == BANK_GROUP_A) { @@ -296,7 +296,7 @@ static uint8_t dsp56k_bank_num(device_t* cpu, uint8_t bank_group) } else if (bank_group == INVALID_BANK_GROUP) { - fatalerror("Plygonet: dsp56k bank num invalid.\n"); + fatalerror("Plygonet: dsp56156 bank num invalid.\n"); } return 0; @@ -304,110 +304,110 @@ static uint8_t dsp56k_bank_num(device_t* cpu, uint8_t bank_group) /* BANK HANDLERS */ -READ16_MEMBER(polygonet_state::dsp56k_ram_bank00_read) +READ16_MEMBER(polygonet_state::dsp56156_ram_bank00_read) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank00_size * 8) + (bank_num * dsp56k_bank00_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank00_size * 8) + (bank_num * dsp56156_bank00_size); - return m_dsp56k_bank00_ram[driver_bank_offset + offset]; + return m_dsp56156_bank00_ram[driver_bank_offset + offset]; } -WRITE16_MEMBER(polygonet_state::dsp56k_ram_bank00_write) +WRITE16_MEMBER(polygonet_state::dsp56156_ram_bank00_write) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank00_size * 8) + (bank_num * dsp56k_bank00_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank00_size * 8) + (bank_num * dsp56156_bank00_size); - COMBINE_DATA(&m_dsp56k_bank00_ram[driver_bank_offset + offset]); + COMBINE_DATA(&m_dsp56156_bank00_ram[driver_bank_offset + offset]); } -READ16_MEMBER(polygonet_state::dsp56k_ram_bank01_read) +READ16_MEMBER(polygonet_state::dsp56156_ram_bank01_read) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank01_size * 8) + (bank_num * dsp56k_bank01_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank01_size * 8) + (bank_num * dsp56156_bank01_size); - return m_dsp56k_bank01_ram[driver_bank_offset + offset]; + return m_dsp56156_bank01_ram[driver_bank_offset + offset]; } -WRITE16_MEMBER(polygonet_state::dsp56k_ram_bank01_write) +WRITE16_MEMBER(polygonet_state::dsp56156_ram_bank01_write) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank01_size * 8) + (bank_num * dsp56k_bank01_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank01_size * 8) + (bank_num * dsp56156_bank01_size); - COMBINE_DATA(&m_dsp56k_bank01_ram[driver_bank_offset + offset]); + COMBINE_DATA(&m_dsp56156_bank01_ram[driver_bank_offset + offset]); /* For now, *always* combine P:0x7000-0x7fff with bank01 with no regard to the banking hardware. */ - m_dsp56k_p_mirror[offset] = data; + m_dsp56156_p_mirror[offset] = data; } -READ16_MEMBER(polygonet_state::dsp56k_ram_bank02_read) +READ16_MEMBER(polygonet_state::dsp56156_ram_bank02_read) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank02_size * 8) + (bank_num * dsp56k_bank02_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank02_size * 8) + (bank_num * dsp56156_bank02_size); - return m_dsp56k_bank02_ram[driver_bank_offset + offset]; + return m_dsp56156_bank02_ram[driver_bank_offset + offset]; } -WRITE16_MEMBER(polygonet_state::dsp56k_ram_bank02_write) +WRITE16_MEMBER(polygonet_state::dsp56156_ram_bank02_write) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank02_size * 8) + (bank_num * dsp56k_bank02_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank02_size * 8) + (bank_num * dsp56156_bank02_size); - COMBINE_DATA(&m_dsp56k_bank02_ram[driver_bank_offset + offset]); + COMBINE_DATA(&m_dsp56156_bank02_ram[driver_bank_offset + offset]); } -READ16_MEMBER(polygonet_state::dsp56k_shared_ram_read) +READ16_MEMBER(polygonet_state::dsp56156_shared_ram_read) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_shared_ram_16_size * 8) + (bank_num * dsp56k_shared_ram_16_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_shared_ram_16_size * 8) + (bank_num * dsp56156_shared_ram_16_size); - return m_dsp56k_shared_ram_16[driver_bank_offset + offset]; + return m_dsp56156_shared_ram_16[driver_bank_offset + offset]; } -WRITE16_MEMBER(polygonet_state::dsp56k_shared_ram_write) +WRITE16_MEMBER(polygonet_state::dsp56156_shared_ram_write) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_shared_ram_16_size * 8) + (bank_num * dsp56k_shared_ram_16_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_shared_ram_16_size * 8) + (bank_num * dsp56156_shared_ram_16_size); - COMBINE_DATA(&m_dsp56k_shared_ram_16[driver_bank_offset + offset]); + COMBINE_DATA(&m_dsp56156_shared_ram_16[driver_bank_offset + offset]); /* Bank group A with offset 0 is believed to be the shared region */ if (en_group == BANK_GROUP_A && bank_num == 0) { if (offset % 2) - m_shared_ram[offset>>1] = ((m_dsp56k_shared_ram_16[offset-1]) << 16) | m_dsp56k_shared_ram_16[offset]; + m_shared_ram[offset>>1] = ((m_dsp56156_shared_ram_16[offset-1]) << 16) | m_dsp56156_shared_ram_16[offset]; else - m_shared_ram[offset>>1] = ((m_dsp56k_shared_ram_16[offset]) << 16) | m_dsp56k_shared_ram_16[offset+1]; + m_shared_ram[offset>>1] = ((m_dsp56156_shared_ram_16[offset]) << 16) | m_dsp56156_shared_ram_16[offset+1]; } } -READ16_MEMBER(polygonet_state::dsp56k_ram_bank04_read) +READ16_MEMBER(polygonet_state::dsp56156_ram_bank04_read) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank04_size * 8) + (bank_num * dsp56k_bank04_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank04_size * 8) + (bank_num * dsp56156_bank04_size); - return m_dsp56k_bank04_ram[driver_bank_offset + offset]; + return m_dsp56156_bank04_ram[driver_bank_offset + offset]; } -WRITE16_MEMBER(polygonet_state::dsp56k_ram_bank04_write) +WRITE16_MEMBER(polygonet_state::dsp56156_ram_bank04_write) { - uint8_t en_group = dsp56k_bank_group(m_dsp.target()); - uint8_t bank_num = dsp56k_bank_num(m_dsp.target(), en_group); - uint32_t driver_bank_offset = (en_group * dsp56k_bank04_size * 8) + (bank_num * dsp56k_bank04_size); + uint8_t en_group = dsp56156_bank_group(m_dsp.target()); + uint8_t bank_num = dsp56156_bank_num(m_dsp.target(), en_group); + uint32_t driver_bank_offset = (en_group * dsp56156_bank04_size * 8) + (bank_num * dsp56156_bank04_size); - COMBINE_DATA(&m_dsp56k_bank04_ram[driver_bank_offset + offset]); + COMBINE_DATA(&m_dsp56156_bank04_ram[driver_bank_offset + offset]); } @@ -440,19 +440,19 @@ void polygonet_state::main_map(address_map &map) void polygonet_state::dsp_program_map(address_map &map) { - map(0x7000, 0x7fff).ram().share("dsp56k_p_mirror"); /* Unsure of size, but 0x1000 matches bank01 */ - map(0x8000, 0x87ff).ram().share("dsp56k_p_8000"); - map(0xc000, 0xc000).r(FUNC(polygonet_state::dsp56k_bootload_r)); + map(0x7000, 0x7fff).ram().share("dsp56156_p_mirror"); /* Unsure of size, but 0x1000 matches bank01 */ + map(0x8000, 0x87ff).ram().share("dsp56156_p_8000"); + map(0xc000, 0xc000).r(FUNC(polygonet_state::dsp56156_bootload_r)); } void polygonet_state::dsp_data_map(address_map &map) { map(0x0800, 0x5fff).ram(); /* Appears to not be affected by banking? */ - map(0x6000, 0x6fff).rw(FUNC(polygonet_state::dsp56k_ram_bank00_read), FUNC(polygonet_state::dsp56k_ram_bank00_write)); - map(0x7000, 0x7fff).rw(FUNC(polygonet_state::dsp56k_ram_bank01_read), FUNC(polygonet_state::dsp56k_ram_bank01_write)); /* Mirrored in program space @ 0x7000 */ - map(0x8000, 0xbfff).rw(FUNC(polygonet_state::dsp56k_ram_bank02_read), FUNC(polygonet_state::dsp56k_ram_bank02_write)); - map(0xc000, 0xdfff).rw(FUNC(polygonet_state::dsp56k_shared_ram_read), FUNC(polygonet_state::dsp56k_shared_ram_write)); - map(0xe000, 0xffbf).rw(FUNC(polygonet_state::dsp56k_ram_bank04_read), FUNC(polygonet_state::dsp56k_ram_bank04_write)); + map(0x6000, 0x6fff).rw(FUNC(polygonet_state::dsp56156_ram_bank00_read), FUNC(polygonet_state::dsp56156_ram_bank00_write)); + map(0x7000, 0x7fff).rw(FUNC(polygonet_state::dsp56156_ram_bank01_read), FUNC(polygonet_state::dsp56156_ram_bank01_write)); /* Mirrored in program space @ 0x7000 */ + map(0x8000, 0xbfff).rw(FUNC(polygonet_state::dsp56156_ram_bank02_read), FUNC(polygonet_state::dsp56156_ram_bank02_write)); + map(0xc000, 0xdfff).rw(FUNC(polygonet_state::dsp56156_shared_ram_read), FUNC(polygonet_state::dsp56156_shared_ram_write)); + map(0xe000, 0xffbf).rw(FUNC(polygonet_state::dsp56156_ram_bank04_read), FUNC(polygonet_state::dsp56156_ram_bank04_write)); } /**********************************************************************************/ @@ -519,9 +519,9 @@ void polygonet_state::machine_reset() m_sound_ctrl = 0; /* It's presumed the hardware has hard-wired operating mode 1 (MODA = 1, MODB = 0) */ - m_dsp->set_input_line(DSP56K_IRQ_RESET, ASSERT_LINE); - m_dsp->set_input_line(DSP56K_IRQ_MODA, ASSERT_LINE); - m_dsp->set_input_line(DSP56K_IRQ_MODB, CLEAR_LINE); + m_dsp->set_input_line(DSP56156_IRQ_RESET, ASSERT_LINE); + m_dsp->set_input_line(DSP56156_IRQ_MODA, ASSERT_LINE); + m_dsp->set_input_line(DSP56156_IRQ_MODB, CLEAR_LINE); } void polygonet_state::machine_start() @@ -532,11 +532,11 @@ void polygonet_state::machine_start() m_inputs[3] = ioport("IN3"); /* save states */ - save_item(NAME(m_dsp56k_bank00_ram)); - save_item(NAME(m_dsp56k_bank01_ram)); - save_item(NAME(m_dsp56k_bank02_ram)); - save_item(NAME(m_dsp56k_shared_ram_16)); - save_item(NAME(m_dsp56k_bank04_ram)); + save_item(NAME(m_dsp56156_bank00_ram)); + save_item(NAME(m_dsp56156_bank01_ram)); + save_item(NAME(m_dsp56156_bank02_ram)); + save_item(NAME(m_dsp56156_shared_ram_16)); + save_item(NAME(m_dsp56156_bank04_ram)); save_item(NAME(m_sys0)); save_item(NAME(m_sys1)); save_item(NAME(m_sound_ctrl)); @@ -667,12 +667,12 @@ void polygonet_state::init_polygonet() { membank("bank1")->configure_entries(0, 8, memregion("audiocpu")->base(), 0x4000); - /* Allocate space for the dsp56k banking */ - memset(m_dsp56k_bank00_ram, 0, sizeof(m_dsp56k_bank00_ram)); - memset(m_dsp56k_bank01_ram, 0, sizeof(m_dsp56k_bank01_ram)); - memset(m_dsp56k_bank02_ram, 0, sizeof(m_dsp56k_bank02_ram)); - memset(m_dsp56k_shared_ram_16, 0, sizeof(m_dsp56k_shared_ram_16)); - memset(m_dsp56k_bank04_ram, 0, sizeof(m_dsp56k_bank04_ram)); + /* Allocate space for the dsp56156 banking */ + memset(m_dsp56156_bank00_ram, 0, sizeof(m_dsp56156_bank00_ram)); + memset(m_dsp56156_bank01_ram, 0, sizeof(m_dsp56156_bank01_ram)); + memset(m_dsp56156_bank02_ram, 0, sizeof(m_dsp56156_bank02_ram)); + memset(m_dsp56156_shared_ram_16, 0, sizeof(m_dsp56156_shared_ram_16)); + memset(m_dsp56156_bank04_ram, 0, sizeof(m_dsp56156_bank04_ram)); } diff --git a/src/mame/includes/plygonet.h b/src/mame/includes/plygonet.h index 8c5685b0b99..566d6289d03 100644 --- a/src/mame/includes/plygonet.h +++ b/src/mame/includes/plygonet.h @@ -8,15 +8,15 @@ #include "machine/eepromser.h" #include "machine/k054321.h" #include "video/k053936.h" -#include "cpu/dsp56k/dsp56k.h" +#include "cpu/dsp56156/dsp56156.h" #include "emupal.h" -static const uint16_t dsp56k_bank00_size = 0x1000; -static const uint16_t dsp56k_bank01_size = 0x1000; -static const uint16_t dsp56k_bank02_size = 0x4000; -static const uint16_t dsp56k_shared_ram_16_size = 0x2000; -static const uint16_t dsp56k_bank04_size = 0x1fc0; +static const uint16_t dsp56156_bank00_size = 0x1000; +static const uint16_t dsp56156_bank01_size = 0x1000; +static const uint16_t dsp56156_bank02_size = 0x4000; +static const uint16_t dsp56156_shared_ram_16_size = 0x2000; +static const uint16_t dsp56156_bank04_size = 0x1fc0; class polygonet_state : public driver_device { @@ -32,8 +32,8 @@ public: m_palette(*this, "palette"), m_k054321(*this, "k054321"), m_shared_ram(*this, "shared_ram"), - m_dsp56k_p_mirror(*this, "dsp56k_p_mirror"), - m_dsp56k_p_8000(*this, "dsp56k_p_8000") + m_dsp56156_p_mirror(*this, "dsp56156_p_mirror"), + m_dsp56156_p_8000(*this, "dsp56156_p_8000") { } void plygonet(machine_config &config); @@ -43,7 +43,7 @@ public: private: required_device m_maincpu; required_device m_audiocpu; - required_device m_dsp; + required_device m_dsp; required_device m_eeprom; required_device m_k053936; required_device m_gfxdecode; @@ -53,8 +53,8 @@ private: /* 68k-side shared ram */ required_shared_ptr m_shared_ram; - required_shared_ptr m_dsp56k_p_mirror; - required_shared_ptr m_dsp56k_p_8000; + required_shared_ptr m_dsp56156_p_mirror; + required_shared_ptr m_dsp56156_p_8000; ioport_port *m_inputs[4]; uint8_t m_sys0; @@ -72,11 +72,11 @@ private: uint8_t m_sound_intck; /* memory buffers */ - uint16_t m_dsp56k_bank00_ram[2 * 8 * dsp56k_bank00_size]; /* 2 bank sets, 8 potential banks each */ - uint16_t m_dsp56k_bank01_ram[2 * 8 * dsp56k_bank01_size]; - uint16_t m_dsp56k_bank02_ram[2 * 8 * dsp56k_bank02_size]; - uint16_t m_dsp56k_shared_ram_16[2 * 8 * dsp56k_shared_ram_16_size]; - uint16_t m_dsp56k_bank04_ram[2 * 8 * dsp56k_bank04_size]; + uint16_t m_dsp56156_bank00_ram[2 * 8 * dsp56156_bank00_size]; /* 2 bank sets, 8 potential banks each */ + uint16_t m_dsp56156_bank01_ram[2 * 8 * dsp56156_bank01_size]; + uint16_t m_dsp56156_bank02_ram[2 * 8 * dsp56156_bank02_size]; + uint16_t m_dsp56156_shared_ram_16[2 * 8 * dsp56156_shared_ram_16_size]; + uint16_t m_dsp56156_bank04_ram[2 * 8 * dsp56156_bank04_size]; DECLARE_WRITE8_MEMBER(polygonet_sys_w); DECLARE_READ8_MEMBER(polygonet_inputs_r); @@ -86,17 +86,17 @@ private: DECLARE_WRITE32_MEMBER(dsp_w_lines); DECLARE_WRITE32_MEMBER(dsp_host_interface_w); DECLARE_READ32_MEMBER(network_r); - DECLARE_READ16_MEMBER(dsp56k_bootload_r); - DECLARE_READ16_MEMBER(dsp56k_ram_bank00_read); - DECLARE_WRITE16_MEMBER(dsp56k_ram_bank00_write); - DECLARE_READ16_MEMBER(dsp56k_ram_bank01_read); - DECLARE_WRITE16_MEMBER(dsp56k_ram_bank01_write); - DECLARE_READ16_MEMBER(dsp56k_ram_bank02_read); - DECLARE_WRITE16_MEMBER(dsp56k_ram_bank02_write); - DECLARE_READ16_MEMBER(dsp56k_shared_ram_read); - DECLARE_WRITE16_MEMBER(dsp56k_shared_ram_write); - DECLARE_READ16_MEMBER(dsp56k_ram_bank04_read); - DECLARE_WRITE16_MEMBER(dsp56k_ram_bank04_write); + DECLARE_READ16_MEMBER(dsp56156_bootload_r); + DECLARE_READ16_MEMBER(dsp56156_ram_bank00_read); + DECLARE_WRITE16_MEMBER(dsp56156_ram_bank00_write); + DECLARE_READ16_MEMBER(dsp56156_ram_bank01_read); + DECLARE_WRITE16_MEMBER(dsp56156_ram_bank01_write); + DECLARE_READ16_MEMBER(dsp56156_ram_bank02_read); + DECLARE_WRITE16_MEMBER(dsp56156_ram_bank02_write); + DECLARE_READ16_MEMBER(dsp56156_shared_ram_read); + DECLARE_WRITE16_MEMBER(dsp56156_shared_ram_write); + DECLARE_READ16_MEMBER(dsp56156_ram_bank04_read); + DECLARE_WRITE16_MEMBER(dsp56156_ram_bank04_write); DECLARE_WRITE8_MEMBER(sound_ctrl_w); DECLARE_READ32_MEMBER(polygonet_ttl_ram_r); DECLARE_WRITE32_MEMBER(polygonet_ttl_ram_w); -- cgit v1.2.3