diff options
author | 2019-08-19 15:53:47 +0200 | |
---|---|---|
committer | 2019-08-19 15:53:47 +0200 | |
commit | 450a57568e16822d625c3e0cd390e9c9e6a08718 (patch) | |
tree | 32d1157ef80d206fda7bfccbd5557828d1261570 /src/devices/cpu/dsp56156 | |
parent | 93726462006c604f1f6d728be6e7d18065e2d9e2 (diff) |
-dsp56k: Renamed relevant classes, files and namespaces to indicate that it is a DSP56156 core, not a DSP5600x core. [Ryan Holtz]
Diffstat (limited to 'src/devices/cpu/dsp56156')
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56156.cpp | 515 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56156.h | 259 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56def.h | 56 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56dsm.cpp | 34 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56dsm.h | 26 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56mem.cpp | 949 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56mem.h | 241 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56ops.hxx | 4903 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56pcu.cpp | 488 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/dsp56pcu.h | 150 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/inst.cpp | 786 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/inst.h | 3774 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/opcode.cpp | 81 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/opcode.h | 46 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/pmove.cpp | 80 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/pmove.h | 335 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/tables.cpp | 900 | ||||
-rw-r--r-- | src/devices/cpu/dsp56156/tables.h | 93 |
18 files changed, 13716 insertions, 0 deletions
diff --git a/src/devices/cpu/dsp56156/dsp56156.cpp b/src/devices/cpu/dsp56156/dsp56156.cpp new file mode 100644 index 00000000000..a308e5329bc --- /dev/null +++ b/src/devices/cpu/dsp56156/dsp56156.cpp @@ -0,0 +1,515 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +/*************************************************************************** + + dsp56156.cpp + Core implementation for the portable DSP56156 emulator. + Written by Andrew Gardner + +**************************************************************************** + + Note: + This CPU emulator is very much a work-in-progress. + + DONE: + 1: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, , , , , , ,18, , , + + TODO: + X 1-6 Explore CORE naming scheme. + - 1-9 paragraph 1 : memory access timings + - 1-9 Data ALU arithmetic operations generally use fractional two's complement arithmetic + (Unsigned numbers are only supported by the multiply and multiply-accumulate instruction) + - 1-9 For fractional arithmetic, the 31-bit product is added to the 40-bit contents of A or B. No pipeline! + - 1-10 Two types of rounding: convergent rounding and two's complement rounding. See status register bit R. + - 1-10 Logic unit is 16-bits wide and works on MSP portion of accum register + - 1-10 The AGU can implement three types of arithmetic: linear, modulo, and reverse carry. + - 1-12 "Two external interrupt pins!!!" + - 1-12 Take care of all interrupt priority (IPR) stuff! + - 1-19 Memory WAIT states + - 1-20 The timer's interesting! + - 1-21 Vectored exception requests on the Host Interface! +***************************************************************************/ + +#include "emu.h" +#include "dsp56156.h" +#include "dsp56dsm.h" + +#include "opcode.h" + +#include "debugger.h" + +#include "dsp56def.h" + +/*************************************************************************** + COMPONENT FUNCTIONALITY +***************************************************************************/ +/* 1-9 ALU */ +// #include "dsp56alu.h" + +/* 1-10 Address Generation Unit (AGU) */ +// #include "dsp56agu.h" + +/* 1-11 Program Control Unit (PCU) */ +#include "dsp56pcu.h" + +/* 5-1 Host Interface (HI) */ +//#include "dsp56hi.h" + +/* 4-8 Memory handlers for on-chip peripheral memory. */ +#include "dsp56mem.h" + + +DEFINE_DEVICE_TYPE_NS(DSP56156, DSP_56156, dsp56156_device, "dsp56156", "Motorola DSP56156") + + +namespace DSP_56156 { + +enum +{ + // PCU + DSP56156_PC=1, + DSP56156_SR, + DSP56156_LC, + DSP56156_LA, + DSP56156_SP, + DSP56156_OMR, + + // ALU + DSP56156_X, DSP56156_Y, + DSP56156_A, DSP56156_B, + + // AGU + DSP56156_R0,DSP56156_R1,DSP56156_R2,DSP56156_R3, + DSP56156_N0,DSP56156_N1,DSP56156_N2,DSP56156_N3, + DSP56156_M0,DSP56156_M1,DSP56156_M2,DSP56156_M3, + DSP56156_TEMP, + DSP56156_STATUS, + + // CPU STACK + DSP56156_ST0, + DSP56156_ST1, + DSP56156_ST2, + DSP56156_ST3, + DSP56156_ST4, + DSP56156_ST5, + DSP56156_ST6, + DSP56156_ST7, + DSP56156_ST8, + DSP56156_ST9, + DSP56156_ST10, + DSP56156_ST11, + DSP56156_ST12, + DSP56156_ST13, + DSP56156_ST14, + DSP56156_ST15 +}; + + +/**************************************************************************** + * Internal Memory Maps + ****************************************************************************/ +void dsp56156_device::dsp56156_program_map(address_map &map) +{ + map(0x0000, 0x07ff).ram().share("dsk56156_program_ram"); /* 1-5 */ +// AM_RANGE(0x2f00,0x2fff) AM_ROM /* 1-5 PROM reserved memory. Is this the right spot for it? */ +} + +void dsp56156_device::dsp56156_x_data_map(address_map &map) +{ + map(0x0000, 0x07ff).ram(); /* 1-5 */ + map(0xffc0, 0xffff).rw(FUNC(dsp56156_device::peripheral_register_r), FUNC(dsp56156_device::peripheral_register_w)); /* 1-5 On-chip peripheral registers memory mapped in data space */ +} + + +dsp56156_device::dsp56156_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : cpu_device(mconfig, DSP56156, tag, owner, clock) + , m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1, address_map_constructor(FUNC(dsp56156_device::dsp56156_program_map), this)) + , m_data_config("data", ENDIANNESS_LITTLE, 16, 16, -1, address_map_constructor(FUNC(dsp56156_device::dsp56156_x_data_map), this)) + , m_program_ram(*this, "dsk56156_program_ram") +{ +} + +device_memory_interface::space_config_vector dsp56156_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_DATA, &m_data_config) + }; +} + +/*************************************************************************** + MEMORY ACCESSORS +***************************************************************************/ +#define ROPCODE(pc) cpustate->cache->read_word(pc) + + +/*************************************************************************** + IRQ HANDLING +***************************************************************************/ +void dsp56156_device::execute_set_input(int irqline, int state) +{ + //logerror("DSP56156 set irq line %d %d\n", irqline, state); + + switch(irqline) + { + case DSP56156_IRQ_MODA: + // TODO: 1-12 Get this triggering right + if (irqa_trigger(&m_core)) + logerror("DSP56156 IRQA is set to fire on the \"Negative Edge\".\n"); + + if (state != CLEAR_LINE) + m_core.modA_state = true; + else + m_core.modA_state = false; + + if (m_core.reset_state != true) + dsp56156_add_pending_interrupt(&m_core, "IRQA"); + break; + + case DSP56156_IRQ_MODB: + // TODO: 1-12 Get this triggering right + if (irqb_trigger(&m_core)) + logerror("DSP56156 IRQB is set to fire on the \"Negative Edge\".\n"); + + if (state != CLEAR_LINE) + m_core.modB_state = true; + else + m_core.modB_state = false; + + if (m_core.reset_state != true) + dsp56156_add_pending_interrupt(&m_core, "IRQB"); + break; + + case DSP56156_IRQ_MODC: + if (state != CLEAR_LINE) + m_core.modC_state = true; + else + m_core.modC_state = false; + + // TODO : Set bus mode or whatever + break; + + case DSP56156_IRQ_RESET: + if (state != CLEAR_LINE) + m_core.reset_state = true; + else + { + /* If it changes state from asserted to cleared. Call the reset function. */ + if (m_core.reset_state == true) + device_reset(); + + m_core.reset_state = false; + } + + // dsp56156_add_pending_interrupt("Hardware RESET"); + break; + + default: + logerror("DSP56156 setting some weird irq line : %d", irqline); + break; + } + + /* If the reset line isn't asserted, service interrupts */ + // TODO: Is it right to immediately service interrupts? + //if (cpustate->reset_state != true) + // pcu_service_interrupts(); +} + + +/*************************************************************************** + INITIALIZATION AND SHUTDOWN +***************************************************************************/ +void dsp56156_device::agu_init() +{ + /* save states - dsp56156_agu members */ + save_item(NAME(m_core.AGU.r0)); + save_item(NAME(m_core.AGU.r1)); + save_item(NAME(m_core.AGU.r2)); + save_item(NAME(m_core.AGU.r3)); + save_item(NAME(m_core.AGU.n0)); + save_item(NAME(m_core.AGU.n1)); + save_item(NAME(m_core.AGU.n2)); + save_item(NAME(m_core.AGU.n3)); + save_item(NAME(m_core.AGU.m0)); + save_item(NAME(m_core.AGU.m1)); + save_item(NAME(m_core.AGU.m2)); + save_item(NAME(m_core.AGU.m3)); + save_item(NAME(m_core.AGU.temp)); +} + +void dsp56156_device::alu_init() +{ + /* save states - dsp56156_alu members */ + save_item(NAME(m_core.ALU.x)); + save_item(NAME(m_core.ALU.y)); + save_item(NAME(m_core.ALU.a)); + save_item(NAME(m_core.ALU.b)); +} + +void dsp56156_device::device_start() +{ + memset(&m_core, 0, sizeof(m_core)); + + m_core.device = this; + m_core.program_ram = m_program_ram; + + /* Call specific module inits */ + pcu_init(&m_core, this); + agu_init(); + alu_init(); + + /* HACK - You're not in bootstrap mode upon bootup */ + m_core.bootstrap_mode = BOOTSTRAP_OFF; + + /* Clear the irq states */ + m_core.modA_state = false; + m_core.modB_state = false; + m_core.modC_state = false; + m_core.reset_state = false; + + /* save states - dsp56156_core members */ + save_item(NAME(m_core.modA_state)); + save_item(NAME(m_core.modB_state)); + save_item(NAME(m_core.modC_state)); + save_item(NAME(m_core.reset_state)); + save_item(NAME(m_core.bootstrap_mode)); + save_item(NAME(m_core.repFlag)); + save_item(NAME(m_core.repAddr)); + save_item(NAME(m_core.ppc)); + save_item(NAME(m_core.op)); + save_item(NAME(m_core.interrupt_cycles)); + + /* save states - dsp56156_host_interface members */ + save_item(NAME(m_core.HI.icr)); + save_item(NAME(m_core.HI.cvr)); + save_item(NAME(m_core.HI.isr)); + save_item(NAME(m_core.HI.ivr)); + save_item(NAME(m_core.HI.trxh)); + save_item(NAME(m_core.HI.trxl)); + save_item(NAME(m_core.HI.bootstrap_offset)); + + save_item(NAME(m_core.peripheral_ram)); + + m_core.program = &space(AS_PROGRAM); + m_core.cache = m_core.program->cache<1, -1, ENDIANNESS_LITTLE>(); + m_core.data = &space(AS_DATA); + + state_add(DSP56156_PC, "PC", m_core.PCU.pc).formatstr("%04X"); + state_add(DSP56156_SR, "SR", m_core.PCU.sr).formatstr("%04X"); + state_add(DSP56156_LC, "LC", m_core.PCU.lc).formatstr("%04X"); + state_add(DSP56156_LA, "LA", m_core.PCU.la).formatstr("%04X"); + state_add(DSP56156_SP, "SP", m_core.PCU.sp).formatstr("%02X"); + state_add(DSP56156_OMR, "OMR", m_core.PCU.omr).formatstr("%02X"); + + state_add(DSP56156_X, "X", m_core.ALU.x.d).mask(0xffffffff).formatstr("%9s"); + state_add(DSP56156_Y, "Y", m_core.ALU.y.d).mask(0xffffffff).formatstr("%9s"); + + state_add(DSP56156_A, "A", m_core.ALU.a.q).mask(u64(0xffffffffffffffffU)).formatstr("%12s"); /* could benefit from a better mask? */ + state_add(DSP56156_B, "B", m_core.ALU.b.q).mask(u64(0xffffffffffffffffU)).formatstr("%12s"); /* could benefit from a better mask? */ + + state_add(DSP56156_R0, "R0", m_core.AGU.r0).formatstr("%04X"); + state_add(DSP56156_R1, "R1", m_core.AGU.r1).formatstr("%04X"); + state_add(DSP56156_R2, "R2", m_core.AGU.r2).formatstr("%04X"); + state_add(DSP56156_R3, "R3", m_core.AGU.r3).formatstr("%04X"); + + state_add(DSP56156_N0, "N0", m_core.AGU.n0).formatstr("%04X"); + state_add(DSP56156_N1, "N1", m_core.AGU.n1).formatstr("%04X"); + state_add(DSP56156_N2, "N2", m_core.AGU.n2).formatstr("%04X"); + state_add(DSP56156_N3, "N3", m_core.AGU.n3).formatstr("%04X"); + + state_add(DSP56156_M0, "M0", m_core.AGU.m0).formatstr("%04X"); + state_add(DSP56156_M1, "M1", m_core.AGU.m1).formatstr("%04X"); + state_add(DSP56156_M2, "M2", m_core.AGU.m2).formatstr("%04X"); + state_add(DSP56156_M3, "M3", m_core.AGU.m3).formatstr("%04X"); + + state_add(DSP56156_TEMP, "TMP", m_core.AGU.temp).formatstr("%04X").noshow(); + //state_add(DSP56156_STATUS, "STS", STATUS).formatstr("%02X"); + + state_add(DSP56156_ST0, "ST0", m_core.PCU.ss[0].d).formatstr("%08X"); + state_add(DSP56156_ST1, "ST1", m_core.PCU.ss[1].d).formatstr("%08X"); + state_add(DSP56156_ST2, "ST2", m_core.PCU.ss[2].d).formatstr("%08X"); + state_add(DSP56156_ST3, "ST3", m_core.PCU.ss[3].d).formatstr("%08X"); + state_add(DSP56156_ST4, "ST4", m_core.PCU.ss[4].d).formatstr("%08X"); + state_add(DSP56156_ST5, "ST5", m_core.PCU.ss[5].d).formatstr("%08X"); + state_add(DSP56156_ST6, "ST6", m_core.PCU.ss[6].d).formatstr("%08X"); + state_add(DSP56156_ST7, "ST7", m_core.PCU.ss[7].d).formatstr("%08X"); + state_add(DSP56156_ST8, "ST8", m_core.PCU.ss[8].d).formatstr("%08X"); + state_add(DSP56156_ST9, "ST9", m_core.PCU.ss[9].d).formatstr("%08X"); + state_add(DSP56156_ST10, "ST10", m_core.PCU.ss[10].d).formatstr("%08X"); + state_add(DSP56156_ST11, "ST11", m_core.PCU.ss[11].d).formatstr("%08X"); + state_add(DSP56156_ST12, "ST12", m_core.PCU.ss[12].d).formatstr("%08X"); + state_add(DSP56156_ST13, "ST13", m_core.PCU.ss[13].d).formatstr("%08X"); + state_add(DSP56156_ST14, "ST14", m_core.PCU.ss[14].d).formatstr("%08X"); + state_add(DSP56156_ST15, "ST15", m_core.PCU.ss[15].d).formatstr("%08X"); + + state_add(STATE_GENPC, "GENPC", m_core.PCU.pc).noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_core.ppc).noshow(); + state_add(STATE_GENSP, "GENSP", m_core.PCU.sp).noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_core.PCU.sr).formatstr("%14s").noshow(); + + set_icountptr(m_core.icount); +} + + +void dsp56156_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ + const dsp56156_core *cpustate = &m_core; + + switch (entry.index()) + { + case STATE_GENFLAGS: + str = string_format("%s%s %s%s%s%s%s%s%s%s %s%s", + /* Status Register */ + LF_bit(cpustate) ? "L" : ".", + FV_bit(cpustate) ? "F" : ".", + + S_bit(cpustate) ? "S" : ".", + L_bit(cpustate) ? "L" : ".", + E_bit(cpustate) ? "E" : ".", + U_bit(cpustate) ? "U" : ".", + N_bit(cpustate) ? "N" : ".", + Z_bit(cpustate) ? "Z" : ".", + V_bit(cpustate) ? "V" : ".", + C_bit(cpustate) ? "C" : ".", + + /* Stack Pointer */ + UF_bit(cpustate) ? "U" : ".", + SE_bit(cpustate) ? "S" : "."); + break; + + case DSP56156_X: + str = string_format("%04x %04x", X1, X0); + break; + + case DSP56156_Y: + str = string_format("%04x %04x", Y1, Y0); + break; + + case DSP56156_A: + str = string_format("%02x %04x %04x", A2, A1, A0); + break; + + case DSP56156_B: + str = string_format("%02x %04x %04x", B2, B1, B0); + break; + } +} + +/*************************************************************************** + RESET BEHAVIOR +***************************************************************************/ +static void agu_reset(dsp56156_core* cpustate) +{ + /* FM.4-3 */ + R0 = 0x0000; + R1 = 0x0000; + R2 = 0x0000; + R3 = 0x0000; + + N0 = 0x0000; + N1 = 0x0000; + N2 = 0x0000; + N3 = 0x0000; + + M0 = 0xffff; + M1 = 0xffff; + M2 = 0xffff; + M3 = 0xffff; + + TEMP = 0x0000; +} + +static void alu_reset(dsp56156_core* cpustate) +{ + X = 0x00000000; + Y = 0x00000000; + A = 0x0000000000; + B = 0x0000000000; +} + +void dsp56156_device::device_reset() +{ + logerror("DSP56156 reset\n"); + + m_core.interrupt_cycles = 0; + + m_core.repFlag = 0; + m_core.repAddr = 0x0000; + + pcu_reset(&m_core); + mem_reset(&m_core); + agu_reset(&m_core); + alu_reset(&m_core); + + m_core.ppc = m_core.PCU.pc; + + /* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */ + m_core.program->write_word(0x0000, 0x0124); +} + + + +/*************************************************************************** + CORE INCLUDE +***************************************************************************/ +#include "dsp56ops.hxx" + + +/*************************************************************************** + CORE EXECUTION LOOP +***************************************************************************/ +// Execute a single opcode and return how many cycles it took. +static size_t execute_one_new(dsp56156_core* cpustate) +{ + // For MAME + cpustate->ppc = PC; + if (cpustate->device->machine().debug_flags & DEBUG_FLAG_CALL_HOOK) // FIXME: if this was a member, the helper would work + cpustate->device->debug()->instruction_hook(PC); + + cpustate->op = ROPCODE(PC); + uint16_t w0 = ROPCODE(PC); + uint16_t w1 = ROPCODE(PC + 1); + + Opcode op(w0, w1); + op.evaluate(cpustate); + PC += op.evalSize(); // Special size function needed to handle jmps, etc. + + // TODO: Currently all operations take up 4 cycles (inst->cycles()). + return 4; +} + +void dsp56156_device::execute_run() +{ + /* If reset line is asserted, do nothing */ + if (m_core.reset_state) + { + m_core.icount = 0; + return; + } + + /* HACK - if you're in bootstrap mode, simply pretend you ate up all your cycles waiting for data. */ + if (m_core.bootstrap_mode != BOOTSTRAP_OFF) + { + m_core.icount = 0; + return; + } + + //m_core.icount -= m_core.interrupt_cycles; + //m_core.interrupt_cycles = 0; + + while(m_core.icount > 0) + { + execute_one(&m_core); + if (0) m_core.icount -= execute_one_new(&m_core); + pcu_service_interrupts(&m_core); // TODO: Is it incorrect to service after each instruction? + } +} + + +std::unique_ptr<util::disasm_interface> dsp56156_device::create_disassembler() +{ + return std::make_unique<dsp56156_disassembler>(); +} + +} // namespace DSP_56156 diff --git a/src/devices/cpu/dsp56156/dsp56156.h b/src/devices/cpu/dsp56156/dsp56156.h new file mode 100644 index 00000000000..9276e4e8702 --- /dev/null +++ b/src/devices/cpu/dsp56156/dsp56156.h @@ -0,0 +1,259 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +/*************************************************************************** + + dsp56156.h + Interface file for the portable Motorola/Freescale DSP56156 emulator. + Written by Andrew Gardner + +***************************************************************************/ + + +#ifndef MAME_CPU_DSP56156_DSP56156_H +#define MAME_CPU_DSP56156_DSP56156_H + +#pragma once + + + +// IRQ Lines +// MODA and MODB are also known as IRQA and IRQB +#define DSP56156_IRQ_MODA 0 +#define DSP56156_IRQ_MODB 1 +#define DSP56156_IRQ_MODC 2 +#define DSP56156_IRQ_RESET 3 /* Is this needed? */ + + +namespace DSP_56156 { + +/*************************************************************************** + STRUCTURES & TYPEDEFS +***************************************************************************/ +// 5-4 Host Interface +struct dsp56156_host_interface +{ + // **** DSP56156 side **** // + // Host Control Register + uint16_t* hcr; + + // Host Status Register + uint16_t* hsr; + + // Host Transmit/Receive Data + uint16_t* htrx; + + // **** Host CPU side **** // + // Interrupt Control Register + uint8_t icr; + + // Command Vector Register + uint8_t cvr; + + // Interrupt Status Register + uint8_t isr; + + // Interrupt Vector Register + uint8_t ivr; + + // Transmit / Receive Registers + uint8_t trxh; + uint8_t trxl; + + // HACK - Host interface bootstrap write offset + uint16_t bootstrap_offset; + +}; + +// 1-9 ALU +struct dsp56156_data_alu +{ + // Four 16-bit input registers (can be accessed as 2 32-bit registers) + PAIR x; + PAIR y; + + // Two 32-bit accumulator registers + 8-bit accumulator extension registers + PAIR64 a; + PAIR64 b; + + // An accumulation shifter + // One data bus shifter/limiter + // A parallel, single cycle, non-pipelined Multiply-Accumulator (MAC) unit + // Basics +}; + +// 1-10 Address Generation Unit (AGU) +struct dsp56156_agu +{ + // Four address registers + uint16_t r0; + uint16_t r1; + uint16_t r2; + uint16_t r3; + + // Four offset registers + uint16_t n0; + uint16_t n1; + uint16_t n2; + uint16_t n3; + + // Four modifier registers + uint16_t m0; + uint16_t m1; + uint16_t m2; + uint16_t m3; + + // Used in loop processing + uint16_t temp; + + // FM.4-5 - hmmm? + // uint8_t status; + + // Basics +}; + +// 1-11 Program Control Unit (PCU) +struct dsp56156_pcu +{ + // Program Counter + uint16_t pc; + + // Loop Address + uint16_t la; + + // Loop Counter + uint16_t lc; + + // Status Register + uint16_t sr; + + // Operating Mode Register + uint16_t omr; + + // Stack Pointer + uint16_t sp; + + // Stack (TODO: 15-level?) + PAIR ss[16]; + + // Controls IRQ processing + void (*service_interrupts)(void); + + // A list of pending interrupts (indices into dsp56156_interrupt_sources array) + int8_t pending_interrupts[32]; + + // Basics + + // Other PCU internals + uint16_t reset_vector; + +}; + +// 1-8 The dsp56156 CORE +struct dsp56156_core +{ + // PROGRAM CONTROLLER + dsp56156_pcu PCU; + + // ADR ALU (AGU) + dsp56156_agu AGU; + + // CLOCK GEN + //static emu_timer *dsp56156_timer; // 1-5, 1-8 - Clock gen + + // DATA ALU + dsp56156_data_alu ALU; + + // OnCE + + // IBS and BITFIELD UNIT + + // Host Interface + dsp56156_host_interface HI; + + // IRQ line states + bool modA_state; + bool modB_state; + bool modC_state; + bool reset_state; + + // HACK - Bootstrap mode state variable. + uint8_t bootstrap_mode; + + uint8_t repFlag; // Knowing if we're in a 'repeat' state (dunno how the processor does this) + uint32_t repAddr; // The address of the instruction to repeat... + + + /* MAME internal stuff */ + int icount; + + uint32_t ppc; + uint32_t op; + int interrupt_cycles; + void (*output_pins_changed)(uint32_t pins); + cpu_device *device; + address_space *program; + memory_access_cache<1, -1, ENDIANNESS_LITTLE> *cache; + address_space *data; + + uint16_t peripheral_ram[0x40]; + uint16_t *program_ram; +}; + + +class dsp56156_device : public cpu_device +{ +public: + dsp56156_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock); + + DECLARE_READ16_MEMBER( peripheral_register_r ); + DECLARE_WRITE16_MEMBER( peripheral_register_w ); + + void host_interface_write(uint8_t offset, uint8_t data); + uint8_t host_interface_read(uint8_t offset); + + uint16_t get_peripheral_memory(uint16_t addr); + + void dsp56156_program_map(address_map &map); + void dsp56156_x_data_map(address_map &map); +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const override { return (clocks + 2 - 1) / 2; } + virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const override { return (cycles * 2); } + virtual uint32_t execute_min_cycles() const override { return 1; } + virtual uint32_t execute_max_cycles() const override { return 8; } + virtual uint32_t execute_input_lines() const override { return 4; } + virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == DSP56156_IRQ_RESET; } + virtual void execute_run() override; + virtual void execute_set_input(int inputnum, int state) override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_state_interface overrides + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + // device_disasm_interface overrides + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; + +private: + address_space_config m_program_config; + address_space_config m_data_config; + required_shared_ptr<uint16_t> m_program_ram; + + dsp56156_core m_core; + + void agu_init(); + void alu_init(); +}; + +} // namespace DSP_56156 + + +DECLARE_DEVICE_TYPE_NS(DSP56156, DSP_56156, dsp56156_device) +using DSP_56156::dsp56156_device; + +#endif // MAME_CPU_DSP56156_DSP56156_H diff --git a/src/devices/cpu/dsp56156/dsp56def.h b/src/devices/cpu/dsp56156/dsp56def.h new file mode 100644 index 00000000000..3ae4dd414ec --- /dev/null +++ b/src/devices/cpu/dsp56156/dsp56def.h @@ -0,0 +1,56 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +/////////////////////////////////////////// +// All the macros that are fit to print. // +/////////////////////////////////////////// + +#ifndef __DSP56_DEF_H__ +#define __DSP56_DEF_H__ + +#include "dsp56156.h" + +namespace DSP_56156 +{ +/*************************************************************************** + ALU +***************************************************************************/ +#define X cpustate->ALU.x.d +#define X1 cpustate->ALU.x.w.h +#define X0 cpustate->ALU.x.w.l +#define Y cpustate->ALU.y.d +#define Y1 cpustate->ALU.y.w.h +#define Y0 cpustate->ALU.y.w.l + +#define A cpustate->ALU.a.q +#define A2 cpustate->ALU.a.b.h4 +#define A1 cpustate->ALU.a.w.h +#define A0 cpustate->ALU.a.w.l +#define B cpustate->ALU.b.q +#define B2 cpustate->ALU.b.b.h4 +#define B1 cpustate->ALU.b.w.h +#define B0 cpustate->ALU.b.w.l + + +/*************************************************************************** + AGU +***************************************************************************/ +#define R0 cpustate->AGU.r0 +#define R1 cpustate->AGU.r1 +#define R2 cpustate->AGU.r2 +#define R3 cpustate->AGU.r3 + +#define N0 cpustate->AGU.n0 +#define N1 cpustate->AGU.n1 +#define N2 cpustate->AGU.n2 +#define N3 cpustate->AGU.n3 + +#define M0 cpustate->AGU.m0 +#define M1 cpustate->AGU.m1 +#define M2 cpustate->AGU.m2 +#define M3 cpustate->AGU.m3 + +#define TEMP cpustate->AGU.temp + +} // namespace DSP_56156 + +#endif diff --git a/src/devices/cpu/dsp56156/dsp56dsm.cpp b/src/devices/cpu/dsp56156/dsp56dsm.cpp new file mode 100644 index 00000000000..58397c3284f --- /dev/null +++ b/src/devices/cpu/dsp56156/dsp56dsm.cpp @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +/*************************************************************************** + + dsp56dsm.cpp + Disassembler for the portable Motorola/Freescale DSP56156 emulator. + Written by Andrew Gardner + +***************************************************************************/ + +#include "emu.h" +#include "opcode.h" +#include "dsp56dsm.h" + +u32 dsp56156_disassembler::opcode_alignment() const +{ + return 1; +} + +/*****************************/ +/* Main disassembly function */ +/*****************************/ +offs_t dsp56156_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶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:<Rx> and X:<pp> */ + uint16_t W; + uint16_t pp; + + typed_pointer SD = {nullptr, DT_BYTE}; + decode_RR_table(cpustate, BITS(op,0x00c0), &SD); + + pp = op & 0x001f; + pp = assemble_address_from_IO_short_address(cpustate, pp); + + W = BITS(op,0x0100); + + /* A little different than most W if's - opposite read and write */ + if (W) + { + uint16_t data = cpustate->data->read_word(*((uint16_t*)SD.addr)); + + typed_pointer tempTP; + tempTP.addr = &data; + tempTP.data_type = DT_WORD; + + SetDataMemoryValue(cpustate, tempTP, pp); + } + else + { + /* TODO */ + fatalerror("dsp56156 : move(p) NOTHING HERE (yet)\n") ; + } + + /* Postincrement */ + execute_m_table(cpustate, BITS(op,0x00c0), BITS(op,0x0020)); + + /* S L E U N Z V C */ + /* * * - - - - - - */ + /* TODO: S, L */ + cycles += 4; /* TODO: + mvp oscillator cycles */ + return 1; +} + +/* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ +static size_t dsp56156_op_moves(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* * * - - - - - - */ + return 0; +} + +/* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ +static size_t dsp56156_op_mpysuuu(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + uint8_t s = 0; + int64_t result = 0; + + void* D = nullptr; + void* S1 = nullptr; + void* S2 = nullptr; + + decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); + + s = BITS(op,0x0004); + + /* Fixed-point 2's complement multiplication requires a shift */ + if (s) + { + /* Unsigned * Unsigned */ + uint32_t s1 = (uint32_t)(*((uint16_t*)S1)); + uint32_t s2 = (uint32_t)(*((uint16_t*)S2)); + result = ( s1 * s2 ) << 1; + } + else + { + /* Signed * Unsigned */ + /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ + int32_t s1 = ((int32_t)(*((uint16_t*)S1))); + int32_t s2 = (uint32_t)(*((uint16_t*)S2)); + result = ( s1 * s2 ) << 1; + } + + (*((uint64_t*)D)) = result; + + /* And out the bits that don't live in the register */ + (*((uint64_t*)D)) &= 0x000000ffffffffffU; + + /* S L E U N Z V C */ + /* - * * * * * * - */ + /* TODO: L, E, U, V */ + if ( *((uint64_t*)D) & 0x0000008000000000U) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint64_t*)D) & 0x000000ffffffffffU) == 0) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + + cycles += 2; + return 1; +} + +/* NEGC : 0001 0101 0110 F000 : A-168 */ +static size_t dsp56156_op_negc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - * * * * * * * */ + return 0; +} + +/* NOP : 0000 0000 0000 0000 : A-170 */ +static size_t dsp56156_op_nop(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - - - - - - - - */ + return 1; +} + +/* NORM : 0001 0101 0010 F0RR : A-172 */ +static size_t dsp56156_op_norm(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - * * * * * ? - */ + /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst + bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ + return 0; +} + +/* ORI : 0001 1EE1 iiii iiii : A-178 */ +static size_t dsp56156_op_ori(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - ? ? ? ? ? ? ? */ + /* All ? bits - Set if the corresponding bit in the immediate data is set and if the operand is the + CCR. Not affected otherwise. */ + return 0; +} + +/* REP : 0000 0000 111- --RR : A-180 */ +static size_t dsp56156_op_rep(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - * - - - - - - */ + return 0; +} + +/* REP : 0000 1111 iiii iiii : A-180 */ +static size_t dsp56156_op_rep_1(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* TODO: This is non-interruptable, probably have to turn off interrupts here */ + uint16_t iVal = op & 0x00ff; + + if (iVal != 0) + { + TEMP = LC; + LC = iVal; + + cpustate->repFlag = 1; + cpustate->repAddr = PC + 2; + + cycles += 4; /* TODO: + mv oscillator clock cycles */ + } + else + { + cycles += 6; /* TODO: + mv oscillator clock cycles */ + } + + + /* S L E U N Z V C */ + /* - * - - - - - - */ + /* TODO: L */ + return 1; +} + +/* REP : 0000 0100 001D DDDD : A-180 */ +static size_t dsp56156_op_rep_2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* TODO: This is non-interruptable, probably have to turn off interrupts here */ + uint16_t repValue; + typed_pointer D = {nullptr, DT_BYTE}; + decode_DDDDD_table(cpustate, BITS(op,0x001f), &D); + + /* TODO: handle special A&B source cases */ + if (D.addr == &A || D.addr == &B) + cpustate->device->logerror("DSP56156 ERROR : Rep with A or B instruction not implemented yet!\n"); + + repValue = *((uint16_t*)D.addr); + + if (repValue != 0) + { + TEMP = LC; + LC = repValue; + + cpustate->repFlag = 1; + cpustate->repAddr = PC + 2; + + cycles += 4; /* TODO: + mv oscillator clock cycles */ + } + else + { + cycles += 6; /* TODO: + mv oscillator clock cycles */ + } + + /* S L E U N Z V C */ + /* - * - - - - - - */ + /* TODO: L */ + return 1; +} + +/* REPcc : 0000 0001 0101 cccc : A-184 */ +static size_t dsp56156_op_repcc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - - - - - - - - */ + return 0; +} + +/* RESET : 0000 0000 0000 1000 : A-186 */ +static size_t dsp56156_op_reset(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - - - - - - - - */ + return 0; +} + +/* RTI : 0000 0000 0000 0111 : A-194 */ +static size_t dsp56156_op_rti(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* WARNING : THERE SHOULD BE A MORE GENERAL HANDLING OF STACK ERRORS. */ + if (SP == 0) + { + dsp56156_add_pending_interrupt(cpustate, "Stack Error"); + return 0; + } + + PC = SSH; + + SR = SSL; + SP = SP - 1; + + /* S L E U N Z V C */ + /* ? ? ? ? ? ? ? ? */ + /* All ? bits - Set according to value pulled from the stack. */ + cycles += 4; /* TODO: + rx oscillator clock cycles */ + return 0; +} + +/* RTS : 0000 0000 0000 0110 : A-196 */ +static size_t dsp56156_op_rts(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* Pop */ + PC = SSH; + + /* SR = SSL; The status register is not affected. */ + + SP--; + + /* S L E U N Z V C */ + /* - - - - - - - - */ + cycles += 4; /* TODO: + rx oscillator clock cycles */ + return 0; +} + +/* STOP : 0000 0000 0000 1010 : A-200 */ +static size_t dsp56156_op_stop(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - - - - - - - - */ + return 0; +} + +/* SWAP : 0001 0101 0111 F001 : A-206 */ +static size_t dsp56156_op_swap(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - - - - - - - - */ + return 0; +} + +/* SWI : 0000 0000 0000 0101 : A-208 */ +static size_t dsp56156_op_swi(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - - - - - - - - */ + return 0; +} + +/* Tcc : 0001 00cc ccTT Fh0h : A-210 */ +static size_t dsp56156_op_tcc(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + int shouldTransfer = decode_cccc_table(cpustate, BITS(op,0x03c0)); + + if (shouldTransfer) + { + typed_pointer S = {nullptr, DT_BYTE}; + typed_pointer D = {nullptr, DT_BYTE}; + typed_pointer S2 = {&R0, DT_WORD}; + typed_pointer D2 = {nullptr, DT_BYTE}; + + decode_h0hF_table(cpustate, BITS(op,0x0007),BITS(op,0x0008), &S, &D); + SetDestinationValue(S, D); + + /* TODO: What's up with that A,A* thing in the docs? Can you only ignore the R0->RX transfer if you do an A,A? */ + decode_RR_table(cpustate, BITS(op,0x0030), &D2); /* TT is the same as RR */ + SetDestinationValue(S2, D2); + } + + /* S L E U N Z V C */ + /* - - - - - - - - */ + cycles += 2; + return 1; +} + +/* TFR(2) : 0001 0101 0000 F00J : A-214 */ +static size_t dsp56156_op_tfr2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + typed_pointer S = {nullptr, DT_BYTE}; + typed_pointer D = {nullptr, DT_BYTE}; + + decode_JF_table(cpustate, BITS(op,0x0001), BITS(op,0x0008), &S, &D); + + SetDestinationValue(S, D); + + /* S L E U N Z V C */ + /* - * - - - - - - */ + /* TODO: L */ + cycles += 2; + return 1; +} + +/* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ +static size_t dsp56156_op_tfr3(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* * * - - - - - - */ + return 0; +} + +/* TST(2) : 0001 0101 0001 -1DD : A-220 */ +static size_t dsp56156_op_tst2(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + typed_pointer D = {nullptr, DT_BYTE}; + decode_DD_table(cpustate, BITS(op,0x0003), &D); + + /* S L E U N Z V C */ + /* - * * * * * 0 0 */ + /* (L,E,U should be set to 0) */ + DSP56156_L_CLEAR(); + DSP56156_E_CLEAR(); + /* U_CLEAR(); */ /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */ + if ((*((uint16_t*)D.addr)) & 0x8000) DSP56156_N_SET(); else DSP56156_N_CLEAR(); + if ((*((uint16_t*)D.addr)) == 0x0000) DSP56156_Z_SET(); else DSP56156_Z_CLEAR(); + /* DSP56156_V_CLEAR(); */ /* Unaffected */ + DSP56156_C_CLEAR(); + + cycles += 2; + return 1; +} + +/* WAIT : 0000 0000 0000 1011 : A-222 */ +static size_t dsp56156_op_wait(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - - - - - - - - */ + return 0; +} + +/* ZERO : 0001 0101 0101 F000 : A-224 */ +static size_t dsp56156_op_zero(dsp56156_core* cpustate, const uint16_t op, uint8_t* cycles) +{ + /* S L E U N Z V C */ + /* - * * * * * * - */ + return 0; +} + + + +/*************************************************************************** + Table decoding +***************************************************************************/ +static uint16_t decode_BBB_bitmask(dsp56156_core* cpustate, uint16_t BBB, uint16_t *iVal) +{ + uint16_t retVal = 0x0000; + + switch(BBB) + { + case 0x4: retVal = 0xff00; *iVal <<= 8; break; + case 0x2: retVal = 0x0ff0; *iVal <<= 4; break; + case 0x1: retVal = 0x00ff; *iVal <<= 0; break; + } + + return retVal; +} + +static int decode_cccc_table(dsp56156_core* cpustate, uint16_t cccc) +{ + int retVal = 0; + + /* Not fully tested */ + switch (cccc) + { + /* Arranged according to mnemonic table - not decoding table */ + case 0x0: if( C() == 0) retVal = 1; break; /* cc(hs) */ + case 0x8: if( C() == 1) retVal = 1; break; /* cs(lo) */ + case 0x5: if( E() == 0) retVal = 1; break; /* ec */ + case 0xa: if( Z() == 1) retVal = 1; break; /* eq */ + case 0xd: if( E() == 1) retVal = 1; break; /* es */ + case 0x1: if((N() ^ V()) == 0) retVal = 1; break; /* ge */ + case 0x7: if((Z() | (N() ^ V())) == 0) retVal = 1; break; /* gt */ + case 0x6: if( L() == 0) retVal = 1; break; /* lc */ + case 0xf: if((Z() | (N() ^ V())) == 1) retVal = 1; break; /* le */ + case 0xe: if( L() == 1) retVal = 1; break; /* ls */ + case 0x9: if((N() ^ V()) == 1) retVal = 1; break; /* lt */ + case 0xb: if( N() == 1) retVal = 1; break; /* mi */ + case 0x2: if( Z() == 0) retVal = 1; break; /* ne */ + case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; /* nr */ + case 0x3: if( N() == 0) retVal = 1; break; /* pl */ + case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; /* nn */ + } + + return retVal; +} + +static void decode_DDDDD_table(dsp56156_core* cpustate, uint16_t DDDDD, typed_pointer* ret) +{ + switch(DDDDD) + { + case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break; + case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break; + case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break; + case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break; + case 0x04: ret->addr = &A ; ret->data_type = DT_LONG_WORD; break; + case 0x05: ret->addr = &B ; ret->data_type = DT_LONG_WORD; break; + case 0x06: ret->addr = &A0; ret->data_type = DT_WORD; break; + case 0x07: ret->addr = &B0; ret->data_type = DT_WORD; break; + case 0x08: ret->addr = &LC; ret->data_type = DT_WORD; break; + case 0x09: ret->addr = &SR; ret->data_type = DT_WORD; break; + case 0x0a: ret->addr = &OMR; ret->data_type = DT_BYTE; break; + case 0x0b: ret->addr = &SP; ret->data_type = DT_BYTE; break; + case 0x0c: ret->addr = &A1; ret->data_type = DT_WORD; break; + case 0x0d: ret->addr = &B1; ret->data_type = DT_WORD; break; + case 0x0e: ret->addr = &A2; ret->data_type = DT_BYTE; break; + case 0x0f: ret->addr = &B2; ret->data_type = DT_BYTE; break; + + case 0x10: ret->addr = &R0; ret->data_type = DT_WORD; break; + case 0x11: ret->addr = &R1; ret->data_type = DT_WORD; break; + case 0x12: ret->addr = &R2; ret->data_type = DT_WORD; break; + case 0x13: ret->addr = &R3; ret->data_type = DT_WORD; break; + case 0x14: ret->addr = &M0; ret->data_type = DT_WORD; break; + case 0x15: ret->addr = &M1; ret->data_type = DT_WORD; break; + case 0x16: ret->addr = &M2; ret->data_type = DT_WORD; break; + case 0x17: ret->addr = &M3; ret->data_type = DT_WORD; break; + case 0x18: ret->addr = &SSH; ret->data_type = DT_WORD; break; + case 0x19: ret->addr = &SSL; ret->data_type = DT_WORD; break; + case 0x1a: ret->addr = &LA; ret->data_type = DT_WORD; break; + /*no 0x1b */ + case 0x1c: ret->addr = &N0; ret->data_type = DT_WORD; break; + case 0x1d: ret->addr = &N1; ret->data_type = DT_WORD; break; + case 0x1e: ret->addr = &N2; ret->data_type = DT_WORD; break; + case 0x1f: ret->addr = &N3; ret->data_type = DT_WORD; break; + } +} + +static void decode_DD_table(dsp56156_core* cpustate, uint16_t DD, typed_pointer* ret) +{ + switch(DD) + { + case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break; + case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break; + case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break; + case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break; + } +} + +static void decode_DDF_table(dsp56156_core* cpustate, uint16_t DD, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) +{ + uint16_t switchVal = (DD << 1) | F; + + switch (switchVal) + { + case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + } +} + +static void decode_F_table(dsp56156_core* cpustate, uint16_t F, typed_pointer* ret) +{ + switch(F) + { + case 0x0: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; + case 0x1: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; + } +} + +static void decode_h0hF_table(dsp56156_core* cpustate, uint16_t h0h, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) +{ + uint16_t switchVal = (h0h << 1) | F ; + + switch (switchVal) + { + case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + } +} + +static void decode_HH_table(dsp56156_core* cpustate, uint16_t HH, typed_pointer* ret) +{ + switch(HH) + { + case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break; + case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break; + case 0x2: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; + case 0x3: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; + } +} + +static void decode_HHH_table(dsp56156_core* cpustate, uint16_t HHH, typed_pointer* ret) +{ + switch(HHH) + { + case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break; + case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break; + case 0x2: ret->addr = &X1; ret->data_type = DT_WORD; break; + case 0x3: ret->addr = &Y1; ret->data_type = DT_WORD; break; + case 0x4: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; + case 0x5: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; + case 0x6: ret->addr = &A0; ret->data_type = DT_WORD; break; + case 0x7: ret->addr = &B0; ret->data_type = DT_WORD; break; + } +} + +static void decode_IIII_table(dsp56156_core* cpustate, uint16_t IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void *working) +{ + void *opposite = nullptr ; + + if (working == &A) opposite = &B ; + else opposite = &A ; + + switch(IIII) + { + case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0x1: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0x2: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0x3: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0x4: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; + case 0x5: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; + case 0x6: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; + case 0x7: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; + case 0x8: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0x9: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; + case 0xc: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; + case 0xd: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; + case 0xe: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; + case 0xf: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; + } +} + +static void decode_JJJF_table(dsp56156_core* cpustate, uint16_t JJJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) +{ + uint16_t switchVal = (JJJ << 1) | F ; + + switch(switchVal) + { + case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x4: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x5: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x6: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x7: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0xc: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0xd: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0xe: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0xf: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + } +} + +static void decode_JJF_table(dsp56156_core* cpustate, uint16_t JJ, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) +{ + uint16_t switchVal = (JJ << 1) | F ; + + switch (switchVal) + { + case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + } +} + +static void decode_JF_table(dsp56156_core* cpustate, uint16_t J, uint16_t F, typed_pointer* src_ret, typed_pointer* dst_ret) +{ + uint16_t switchVal = (J << 1) | F ; + + switch (switchVal) + { + case 0x0: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break; + case 0x1: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break; + case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break; + case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break; + } +} + +static void decode_KKK_table(dsp56156_core* cpustate, uint16_t KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working) +{ + void *opposite = nullptr ; + + if (working == &A) opposite = &B ; + else opposite = &A ; + + switch(KKK) + { + case 0x0: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; + case 0x1: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; + case 0x2: dst_ret1->addr = &X1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; + case 0x3: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; + case 0x4: dst_ret1->addr = &X0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; + case 0x5: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; + case 0x6: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &Y0; dst_ret2->data_type = DT_WORD; break; + case 0x7: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; + } +} + +static void decode_QQF_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D) +{ + uint16_t switchVal = (QQ << 1) | F ; + + switch(switchVal) + { + case 0x0: *S1 = &X0; *S2 = &Y0; *D = &A; break; + case 0x1: *S1 = &X0; *S2 = &Y0; *D = &B; break; + case 0x2: *S1 = &X0; *S2 = &Y1; *D = &A; break; + case 0x3: *S1 = &X0; *S2 = &Y1; *D = &B; break; + case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break; + case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break; + case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break; + case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break; + } +} + +static void decode_QQF_special_table(dsp56156_core* cpustate, uint16_t QQ, uint16_t F, void **S1, void **S2, void **D) +{ + uint16_t switchVal = (QQ << 1) | F ; + + switch(switchVal) + { + case 0x0: *S1 = &Y0; *S2 = &X0; *D = &A; break; + case 0x1: *S1 = &Y0; *S2 = &X0; *D = &B; break; + case 0x2: *S1 = &Y1; *S2 = &X0; *D = &A; break; + case 0x3: *S1 = &Y1; *S2 = &X0; *D = &B; break; + case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break; + case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break; + case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break; + case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break; + } +} + +static void decode_QQQF_table(dsp56156_core* cpustate, uint16_t QQQ, uint16_t F, void **S1, void **S2, void **D) +{ + uint16_t switchVal = (QQQ << 1) | F; + + switch(switchVal) + { + case 0x0: *S1 = &X0; *S2 = &X0; *D = &A; break; + case 0x1: *S1 = &X0; *S2 = &X0; *D = &B; break; + case 0x2: *S1 = &X1; *S2 = &X0; *D = &A; break; + case 0x3: *S1 = &X1; *S2 = &X0; *D = &B; break; + case 0x4: *S1 = &A1; *S2 = &Y0; *D = &A; break; + case 0x5: *S1 = &A1; *S2 = &Y0; *D = &B; break; + case 0x6: *S1 = &B1; *S2 = &X0; *D = &A; break; + case 0x7: *S1 = &B1; *S2 = &X0; *D = &B; break; + case 0x8: *S1 = &Y0; *S2 = &X0; *D = &A; break; + case 0x9: *S1 = &Y0; *S2 = &X0; *D = &B; break; + case 0xa: *S1 = &Y1; *S2 = &X0; *D = &A; break; + case 0xb: *S1 = &Y1; *S2 = &X0; *D = &B; break; + case 0xc: *S1 = &Y0; *S2 = &X1; *D = &A; break; + case 0xd: *S1 = &Y0; *S2 = &X1; *D = &B; break; + case 0xe: *S1 = &Y1; *S2 = &X1; *D = &A; break; + case 0xf: *S1 = &Y1; *S2 = &X1; *D = &B; break; + } +} + +static void decode_RR_table(dsp56156_core* cpustate, uint16_t RR, typed_pointer* ret) +{ + switch(RR) + { + case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break; + case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break; + case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break; + case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break; + } +} + +static void decode_TT_table(dsp56156_core* cpustate, uint16_t TT, typed_pointer* ret) +{ + switch(TT) + { + case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break; + case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break; + case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break; + case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break; + } +} + + +static void decode_uuuuF_table(dsp56156_core* cpustate, uint16_t uuuu, uint16_t F, uint8_t add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret) +{ + uint16_t switchVal = (uuuu << 1) | F; + + /* Unknown uuuuFs have been seen in the wild */ + add_sub_other = OP_OTHER; + src_ret->addr = nullptr; src_ret->data_type = DT_BYTE; + dst_ret->addr = nullptr; dst_ret->data_type = DT_BYTE; + + switch(switchVal) + { + case 0x00: add_sub_other = OP_ADD; + src_ret->addr = &X0; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x08: add_sub_other = OP_SUB; + src_ret->addr = &X0; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x01: add_sub_other = OP_ADD; + src_ret->addr = &X0; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x09: add_sub_other = OP_SUB; + src_ret->addr = &X0; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x02: add_sub_other = OP_ADD; + src_ret->addr = &Y0; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x0a: add_sub_other = OP_SUB; + src_ret->addr = &Y0; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x03: add_sub_other = OP_ADD; + src_ret->addr = &Y0; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x0b: add_sub_other = OP_SUB; + src_ret->addr = &Y0; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x04: add_sub_other = OP_ADD; + src_ret->addr = &X1; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x0c: add_sub_other = OP_SUB; + src_ret->addr = &X1; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x05: add_sub_other = OP_ADD; + src_ret->addr = &X1; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x0d: add_sub_other = OP_SUB; + src_ret->addr = &X1; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x06: add_sub_other = OP_ADD; + src_ret->addr = &Y1; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x0e: add_sub_other = OP_SUB; + src_ret->addr = &Y1; src_ret->data_type = DT_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x07: add_sub_other = OP_ADD; + src_ret->addr = &Y1; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x0f: add_sub_other = OP_SUB; + src_ret->addr = &Y1; src_ret->data_type = DT_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x18: add_sub_other = OP_ADD; + src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x1a: add_sub_other = OP_SUB; + src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; + dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; + case 0x19: add_sub_other = OP_ADD; + src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + case 0x1b: add_sub_other = OP_SUB; + src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; + dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; + } +} + +static void decode_Z_table(dsp56156_core* cpustate, uint16_t Z, typed_pointer* ret) +{ + switch(Z) + { + /* Fixed as per the Family Manual addendum */ + case 0x01: ret->addr = &A1; ret->data_type = DT_WORD; break; + case 0x00: ret->addr = &B1; ret->data_type = DT_WORD; break; + } +} + +static void execute_m_table(dsp56156_core* cpustate, int x, uint16_t m) +{ + uint16_t *rX = nullptr ; + uint16_t *nX = nullptr ; + + switch(x) + { + case 0x0: rX = &R0; nX = &N0; break; + case 0x1: rX = &R1; nX = &N1; break; + case 0x2: rX = &R2; nX = &N2; break; + case 0x3: rX = &R3; nX = &N3; break; + } + + switch(m) + { + case 0x0: (*rX)++; break; + case 0x1: (*rX) = (*rX)+(*nX); break; + } +} + +static void execute_mm_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t mm) +{ + uint16_t *rX = nullptr; + uint16_t *nX = nullptr; + + switch(rnum) + { + case 0x0: rX = &R0; nX = &N0; break; + case 0x1: rX = &R1; nX = &N1; break; + case 0x2: rX = &R2; nX = &N2; break; + case 0x3: fatalerror("Dsp56156: Error. execute_mm_table specified R3 as its first source!\n"); break; + } + + switch(mm) + { + case 0x0: (*rX)++; R3++; break; + case 0x1: (*rX)++; R3 = R3 + N3; break; + case 0x2: (*rX) = (*rX) + (*nX); R3++; break; + case 0x3: (*rX) = (*rX) + (*nX); R3 = R3 + N3; break; + } +} + +static void execute_MM_table(dsp56156_core* cpustate, uint16_t rnum, uint16_t MM) +{ + uint16_t *rX = nullptr ; + uint16_t *nX = nullptr ; + + switch(rnum) + { + case 0x0: rX = &R0; nX = &N0; break; + case 0x1: rX = &R1; nX = &N1; break; + case 0x2: rX = &R2; nX = &N2; break; + case 0x3: rX = &R3; nX = &N3; break; + } + + switch(MM) + { + case 0x0: /* do nothing */ break; + case 0x1: (*rX)++ ; break; + case 0x2: (*rX)-- ; break; + case 0x3: (*rX) = (*rX)+(*nX) ; break; + } +} + +/* Returns R value */ +static uint16_t execute_q_table(dsp56156_core* cpustate, int RR, uint16_t q) +{ + uint16_t *rX = nullptr; + uint16_t *nX = nullptr; + + switch(RR) + { + case 0x0: rX = &R0; nX = &N0; break; + case 0x1: rX = &R1; nX = &N1; break; + case 0x2: rX = &R2; nX = &N2; break; + case 0x3: rX = &R3; nX = &N3; break; + } + + switch(q) + { + case 0x0: /* No permanent changes */ ; return (*rX)+(*nX); + case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */ + } + + /* Should not get here */ + fatalerror("dsp56156: execute_q_table did something impossible!\n"); + return 0; +} + +static void execute_z_table(dsp56156_core* cpustate, int RR, uint16_t z) +{ + uint16_t *rX = nullptr; + uint16_t *nX = nullptr; + + switch(RR) + { + case 0x0: rX = &R0; nX = &N0; break; + case 0x1: rX = &R1; nX = &N1; break; + case 0x2: rX = &R2; nX = &N2; break; + case 0x3: rX = &R3; nX = &N3; break; + } + + switch(z) + { + case 0x0: (*rX)--; break; + case 0x1: (*rX) = (*rX) + (*nX); break; + } +} + +static uint16_t assemble_address_from_Pppppp_table(dsp56156_core* cpustate, uint16_t P, uint16_t ppppp) +{ + uint16_t destAddr = 0x00 ; + + switch (P) + { + case 0x0: destAddr = ppppp; break; /* TODO: Does this really only address up to 0x32? */ + case 0x1: destAddr = assemble_address_from_IO_short_address(cpustate, ppppp); break; + } + + return destAddr ; +} + +static uint16_t assemble_address_from_IO_short_address(dsp56156_core* cpustate, uint16_t pp) +{ + uint16_t fullAddy = 0xffe0; + fullAddy |= pp; + return fullAddy; +} + +static uint16_t assemble_address_from_6bit_signed_relative_short_address(dsp56156_core* cpustate, uint16_t srs) +{ + uint16_t fullAddy = srs ; + if (fullAddy & 0x0020) + fullAddy |= 0xffc0 ; + + return fullAddy ; +} + +static void dsp56156_process_loop(dsp56156_core* cpustate) +{ + /* TODO: This might not work for dos nested in doForevers */ + if (LF_bit(cpustate) && FV_bit(cpustate)) + { + /* Do Forever*/ + if (PC == LA) + { + LC--; + + PC = SSH; + } + } + else if (LF_bit(cpustate)) + { + /* Do */ + if (PC == LA) + { + if (LC == 1) + { + /* End of loop processing */ + SR = SSL; /* TODO: A-83. I believe only the Loop Flag comes back here. And maybe the do forever bit too. */ + SP--; + + LA = SSH; + LC = SSL; + SP--; + } + else + { + LC--; + PC = SSH; + } + } + } +} + +static void dsp56156_process_rep(dsp56156_core* cpustate, size_t repSize) +{ + if (cpustate->repFlag) + { + if (PC == cpustate->repAddr) + { + if (LC == 1) + { + /* End of rep processing */ + LC = TEMP; + cpustate->repFlag = 0; + cpustate->repAddr = 0x0000; + } + else + { + LC--; + PC -= repSize; /* A little strange - rewind by the size of the rep'd op */ + } + } + } +} + + +/*************************************************************************** + Parallel Memory Ops +***************************************************************************/ +/* Register to Register Data Move : 0100 IIII .... .... : A-132 */ +static void execute_register_to_register_data_move(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value) +{ + typed_pointer S = {nullptr, DT_BYTE}; + typed_pointer D = {nullptr, DT_BYTE}; + + decode_IIII_table(cpustate, BITS(op,0x0f00), &S, &D, d_register->addr); + + /* If the source is the same as the ALU destination, use the previous accumulator value */ + if (d_register->addr == S.addr) + { + typed_pointer tempTP; + tempTP.addr = prev_accum_value; + tempTP.data_type = DT_LONG_WORD; + SetDestinationValue(tempTP, D); + } + else + { + SetDestinationValue(S, D); + } +} + +/* Address Register Update : 0011 0zRR .... .... : A-135 */ +static void execute_address_register_update(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value) +{ + execute_z_table(cpustate, BITS(op,0x0300), BITS(op,0x0400)); +} + +/* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ +static void execute_x_memory_data_move(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register, uint64_t* prev_accum_value) +{ + uint16_t W; + typed_pointer R = {nullptr, DT_BYTE}; + typed_pointer SD = {nullptr, DT_BYTE}; + + W = BITS(op,0x0100); + decode_HHH_table(cpustate, BITS(op,0x0e00), &SD); + decode_RR_table(cpustate, BITS(op,0x3000),&R); + + if (W) + { + /* From X:<ea> to SD */ + uint16_t data = cpustate->data->read_word(*((uint16_t*)R.addr)); + + typed_pointer tempTP; + tempTP.addr = &data; + tempTP.data_type = DT_WORD; + + SetDestinationValue(tempTP, SD); + } + else + { + /* From SD to X:<ea> */ + /* If the source is the same as the ALU destination, use the previous accumulator value */ + if (d_register->addr == SD.addr) + { + typed_pointer tempTP; + tempTP.addr = prev_accum_value; + tempTP.data_type = DT_LONG_WORD; + + SetDataMemoryValue(cpustate, tempTP, *((uint16_t*)R.addr)) ; + } + else + { + SetDataMemoryValue(cpustate, SD, *((uint16_t*)R.addr)) ; + } + } + + execute_m_table(cpustate, BITS(op,0x3000), BITS(op,0x4000)); +} + +/* X Memory Data Move : 0101 HHHW .... .... : A-137 */ +/* NOTE: previous accumulator value is not needed since ^F1 is always the opposite accumulator */ +static void execute_x_memory_data_move2(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register) +{ + uint16_t W; + uint16_t* mem_offset = nullptr; + typed_pointer SD = {nullptr, DT_BYTE}; + + W = BITS(op,0x0100); + decode_HHH_table(cpustate, BITS(op,0x0e000), &SD); + + if (d_register->addr == &A) + mem_offset = &B1; + else + mem_offset = &A1; + + if (W) + { + /* Write D */ + uint16_t value = cpustate->data->read_word(*mem_offset); + typed_pointer tempV = {&value, DT_WORD}; + SetDestinationValue(tempV, SD); + } + else + { + /* Read S */ + SetDataMemoryValue(cpustate, SD, *mem_offset); + } +} + +/* X Memory Data Move With Short Displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ +static void execute_x_memory_data_move_with_short_displacement(dsp56156_core* cpustate, const uint16_t op, const uint16_t op2) +{ + int8_t xx; + uint8_t W; + uint16_t memOffset; + typed_pointer SD = { nullptr, DT_BYTE }; + + xx = (int8_t)(op & 0x00ff); + W = BITS(op2,0x0100); + decode_HHH_table(cpustate, BITS(op2,0x0e00), &SD); + + memOffset = R2 + (int16_t)xx; + + if (W) + { + /* Write D */ + uint16_t tempData = cpustate->data->read_word(memOffset); + typed_pointer temp_src = { (void*)&tempData, DT_WORD }; + SetDestinationValue(temp_src, SD); + } + else + { + /* Read S */ + uint16_t tempData = *((uint16_t*)SD.addr); + typed_pointer temp_src = { (void*)&tempData, DT_WORD }; + SetDataMemoryValue(cpustate, temp_src, memOffset); + } +} + +/* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ +static void execute_dual_x_memory_data_read(dsp56156_core* cpustate, const uint16_t op, typed_pointer* d_register) +{ + typed_pointer tempV; + uint16_t srcVal1 = 0x0000; + uint16_t srcVal2 = 0x0000; + typed_pointer R = {nullptr, DT_BYTE}; + typed_pointer D1 = {nullptr, DT_BYTE}; + typed_pointer D2 = {nullptr, DT_BYTE}; + + decode_RR_table(cpustate, BITS(op,0x0060), &R); + decode_KKK_table(cpustate, BITS(op,0x0700), &D1, &D2, d_register->addr); + + /* Can't do an R3 for S1 */ + if (R.addr == &R3) + fatalerror("Dsp56156: Error. Dual x memory data read specified R3 as its first source!\n"); + + /* The note on A-142 is very interesting. + You can effectively access external memory in the last 64 bytes of X data memory! */ + if (*((uint16_t*)D2.addr) >= 0xffc0) + fatalerror("Dsp56156: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read.\n"); + + /* First memmove */ + srcVal1 = cpustate->data->read_word(*((uint16_t*)R.addr)); + tempV.addr = &srcVal1; + tempV.data_type = DT_WORD; + SetDestinationValue(tempV, D1); + + /* Second memmove */ + srcVal2 = cpustate->data->read_word(R3); + tempV.addr = &srcVal2; + tempV.data_type = DT_WORD; + SetDestinationValue(tempV, D2); + + /* Touch up the R regs after all the moves */ + execute_mm_table(cpustate, BITS(op,0x0060), BITS(op,0x1800)); +} + +/*************************************************************************** + Helper Functions +***************************************************************************/ +static uint16_t Dsp56156OpMask(uint16_t cur, uint16_t mask) +{ + int i ; + + uint16_t retVal = (cur & mask) ; + uint16_t temp = 0x0000 ; + int offsetCount = 0 ; + + /* Shift everything right, eliminating 'whitespace' */ + for (i = 0; i < 16; i++) + { + if (mask & (0x1<<i)) /* If mask bit is non-zero */ + { + temp |= (((retVal >> i) & 0x1) << offsetCount) ; + offsetCount++ ; + } + } + + return temp ; +} + +static void SetDestinationValue(typed_pointer source, typed_pointer dest) +{ + uint64_t destinationValue = 0 ; + + switch(dest.data_type) + { + /* Copying to an 8-bit value */ + case DT_BYTE: + switch(source.data_type) + { + /* From a ? */ + case DT_BYTE: *((uint8_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break; + case DT_WORD: *((uint8_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0x00ff; break; + case DT_DOUBLE_WORD: *((uint8_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0x000000ff; break; + case DT_LONG_WORD: *((uint8_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000000000ffU; break; + } + break ; + + /* Copying to a 16-bit value */ + case DT_WORD: + switch(source.data_type) + { + case DT_BYTE: *((uint16_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break; + case DT_WORD: *((uint16_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0xffff; break; + case DT_DOUBLE_WORD: *((uint16_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0x0000ffff; break; + case DT_LONG_WORD: *((uint16_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000000000ffffU; break; /* TODO: Shift limiter action! A-147 */ + } + break ; + + /* Copying to a 32-bit value */ + case DT_DOUBLE_WORD: + switch(source.data_type) + { + case DT_BYTE: *((uint32_t*)dest.addr) = (*((uint8_t*) source.addr)) & 0xff; break; + case DT_WORD: *((uint32_t*)dest.addr) = (*((uint16_t*)source.addr)) & 0xffff; break; + case DT_DOUBLE_WORD: *((uint32_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0xffffffff; break; + case DT_LONG_WORD: *((uint32_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x00000000ffffffffU; break; + } + break ; + + /* Copying to a 64-bit value */ + case DT_LONG_WORD: + switch(source.data_type) + { + case DT_BYTE: *((uint64_t*)dest.addr) = (*((uint8_t*)source.addr)) & 0xff; break; + + case DT_WORD: destinationValue = (*((uint16_t*)source.addr)) << 16; + if (destinationValue & 0x0000000080000000U) + destinationValue |= 0x000000ff00000000U; + *((uint64_t*)dest.addr) = (uint64_t)destinationValue; break; /* Forget not, yon shift register */ + + case DT_DOUBLE_WORD: *((uint64_t*)dest.addr) = (*((uint32_t*)source.addr)) & 0xffffffff; break; + case DT_LONG_WORD: *((uint64_t*)dest.addr) = (*((uint64_t*)source.addr)) & 0x000000ffffffffffU; break; + } + break ; + } +} + +/* TODO: Wait-state timings! */ +static void SetDataMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr) +{ + switch(source.data_type) + { + case DT_BYTE: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff) ) ) ; break ; + case DT_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff) ) ) ; break ; + case DT_DOUBLE_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff) ) ) ; break ; + + /* !!! Is this universal ??? */ + /* !!! Forget not, yon shift-limiter !!! */ + case DT_LONG_WORD: cpustate->data->write_word(destinationAddr, (uint16_t)( ((*((uint64_t*)source.addr)) & 0x00000000ffff0000U) >> 16) ) ; break ; + } +} + +/* TODO: Wait-state timings! */ +static void SetProgramMemoryValue(dsp56156_core* cpustate, typed_pointer source, uint32_t destinationAddr) +{ + switch(source.data_type) + { + case DT_BYTE: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint8_t*) source.addr) & 0xff) ) ) ; break ; + case DT_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint16_t*)source.addr) & 0xffff) ) ) ; break ; + case DT_DOUBLE_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( (*((uint32_t*)source.addr) & 0x0000ffff) ) ) ; break ; + + /* !!! Is this universal ??? */ + /* !!! Forget not, yon shift-limiter !!! */ + case DT_LONG_WORD: cpustate->program->write_word(destinationAddr, (uint16_t)( ((*((uint64_t*)source.addr)) & 0x00000000ffff0000U) >> 16) ) ; break ; + } +} diff --git a/src/devices/cpu/dsp56156/dsp56pcu.cpp b/src/devices/cpu/dsp56156/dsp56pcu.cpp new file mode 100644 index 00000000000..94ca3b1caae --- /dev/null +++ b/src/devices/cpu/dsp56156/dsp56pcu.cpp @@ -0,0 +1,488 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#include "emu.h" +#include "dsp56pcu.h" +#include "dsp56mem.h" + +namespace DSP_56156 +{ +/* ************************************************************************* */ +/* Status Register */ +/* ************************************************************************* */ +/* MR CCR */ +/* |-------------------------------------| |-------------------------------| */ +/* | LF | FV | * | * | S1 | S0 | I1 | I0 | | S | L | E | U | N | Z | V | C | */ +/* |-------------------------------------| |-------------------------------| */ +/* */ +/* ************************************************************************* */ +uint8_t LF_bit(const dsp56156_core* cpustate) { return (SR & 0x8000) >> 15; } +uint8_t FV_bit(const dsp56156_core* cpustate) { return (SR & 0x4000) >> 14; } +// uint8_t S_bits(const dsp56156_core* cpustate) { return (SR & 0x0c00) >> 10; } +uint8_t I_bits(const dsp56156_core* cpustate) { return (SR & 0x0300) >> 8; } +uint8_t S_bit (const dsp56156_core* cpustate) { return (SR & 0x0080) >> 7; } +uint8_t L_bit (const dsp56156_core* cpustate) { return (SR & 0x0040) >> 6; } +uint8_t E_bit (const dsp56156_core* cpustate) { return (SR & 0x0020) >> 5; } +uint8_t U_bit (const dsp56156_core* cpustate) { return (SR & 0x0010) >> 4; } +uint8_t N_bit (const dsp56156_core* cpustate) { return (SR & 0x0008) >> 3; } +uint8_t Z_bit (const dsp56156_core* cpustate) { return (SR & 0x0004) >> 2; } +uint8_t V_bit (const dsp56156_core* cpustate) { return (SR & 0x0002) >> 1; } +uint8_t C_bit (const dsp56156_core* cpustate) { return (SR & 0x0001) >> 0; } + +/* MR setters */ +void LF_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x8000); else (SR &= (~0x8000)); } +void FV_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x4000); else (SR &= (~0x4000)); } +void S_bits_set(dsp56156_core* cpustate, uint8_t value) { value = value & 0x03; SR &= ~(0x0c00); SR |= (value << 10); } +void I_bits_set(dsp56156_core* cpustate, uint8_t value) { value = value & 0x03; SR &= ~(0x0300); SR |= (value << 8); } + +/* CCR setters */ +void S_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0080); else (SR &= (~0x0080)); } +void L_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0040); else (SR &= (~0x0040)); } +void E_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0020); else (SR &= (~0x0020)); } +void U_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0010); else (SR &= (~0x0010)); } +void N_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0008); else (SR &= (~0x0008)); } +void Z_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0004); else (SR &= (~0x0004)); } +void V_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0002); else (SR &= (~0x0002)); } +void C_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (SR |= 0x0001); else (SR &= (~0x0001)); } + + + +/* ************************************************************************* */ +/* Operating Mode Register */ +/* ************************************************************************* */ +/* */ +/* |---------------------------------------------------------------------| */ +/* | * | * | * | * | * | * | * | * | CD | SD | R | SA | * | MC | MB | MA | */ +/* |---------------------------------------------------------------------| */ +/* */ +/* ************************************************************************* */ +// uint8_t CD_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0080) != 0); } +// uint8_t SD_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0040) != 0); } +// uint8_t R_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0020) != 0); } +// uint8_t SA_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0010) != 0); } +// uint8_t MC_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0004) != 0); } +uint8_t MB_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0002) != 0); } +uint8_t MA_bit(const dsp56156_core* cpustate) { return ((OMR & 0x0001) != 0); } + +void CD_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0080); else (OMR &= (~0x0080)); } +void SD_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0040); else (OMR &= (~0x0040)); } +void R_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0020); else (OMR &= (~0x0020)); } +void SA_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0010); else (OMR &= (~0x0010)); } +void MC_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0004); else (OMR &= (~0x0004)); } +void MB_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0002); else (OMR &= (~0x0002)); } +void MA_bit_set(dsp56156_core* cpustate, uint8_t value) { if (value) (OMR |= 0x0001); else (OMR &= (~0x0001)); } + +uint8_t dsp56156_operating_mode(const dsp56156_core* cpustate) +{ + return ((MB_bit(cpustate) << 1) | MA_bit(cpustate)); +} + + + +/* ************************************************************************* */ +/* Stack Pointer */ +/* ************************************************************************* */ +/* */ +/* |---------------------------------------------------------------------| */ +/* | * | * | * | * | * | * | * | * | * | * | UF | SE | P3 | P2 | P1 | P0 | */ +/* |---------------------------------------------------------------------| */ +/* */ +/* ************************************************************************* */ +uint8_t UF_bit(const dsp56156_core* cpustate) { return ((SP & 0x0020) != 0); } +uint8_t SE_bit(const dsp56156_core* cpustate) { return ((SP & 0x0010) != 0); } + +//void UF_bit_set(dsp56156_core* cpustate, uint8_t value) {}; +//void SE_bit_set(dsp56156_core* cpustate, uint8_t value) {}; + + + +/*************************************************************************** + INITIALIZATION AND RESET +***************************************************************************/ +void pcu_init(dsp56156_core* cpustate, device_t *device) +{ + /* Init the irq table */ + dsp56156_irq_table_init(); + + /* save states - dsp56156_pcu members */ + device->save_item(NAME(cpustate->PCU.pc)); + device->save_item(NAME(cpustate->PCU.la)); + device->save_item(NAME(cpustate->PCU.lc)); + device->save_item(NAME(cpustate->PCU.sr)); + device->save_item(NAME(cpustate->PCU.omr)); + device->save_item(NAME(cpustate->PCU.sp)); + device->save_item(NAME(cpustate->PCU.ss)); + device->save_item(NAME(cpustate->PCU.pending_interrupts)); + device->save_item(NAME(cpustate->PCU.reset_vector)); +} + +void pcu_reset(dsp56156_core* cpustate) +{ + int i; + + /* When reset is deasserted, set MA, MB, and MC from MODA, MODB, and MODC lines. */ + MA_bit_set(cpustate, cpustate->modA_state); + MB_bit_set(cpustate, cpustate->modB_state); + MC_bit_set(cpustate, cpustate->modC_state); + + /* Reset based on the operating mode. */ + switch(dsp56156_operating_mode(cpustate)) + { + case 0x00: + cpustate->device->logerror("Dsp56156 in Special Bootstrap Mode 1\n"); + + /* HACK - We don't need to put the bootstrap mode on here since */ + /* we'll simulate it entirely in this function */ + cpustate->bootstrap_mode = BOOTSTRAP_OFF; + + /* HACK - Simply copy over 0x1000 bytes of data located at program memory 0xc000. */ + /* This, in actuality, is handled with the internal boot ROM. */ + for (i = 0; i < 0x800; i++) + { + uint32_t mem_offset = (0xc000<<1) + (i<<1); /* TODO: TEST */ + + /* TODO - DO I HAVE TO FLIP THIS WORD? */ + /* P:$c000 -> Internal P:$0000 low byte */ + /* P:$c001 -> Internal P:$0000 high byte */ + /* ... */ + /* P:$cffe -> Internal P:$07ff low byte */ + /* P:$cfff -> Internal P:$07ff high byte */ + uint8_t mem_value_low = cpustate->program->read_byte(mem_offset); /* TODO: IS THIS READING RIGHT? */ + uint8_t mem_value_high = cpustate->program->read_byte(mem_offset); + cpustate->program_ram[i] = (mem_value_high << 8) | mem_value_low; + } + + /* HACK - Set the PC to 0x0000 as per the boot ROM. */ + PC = 0x0000; + + /* HACK - All done! Set the Operating Mode to 2 as per the boot ROM. */ + MB_bit_set(cpustate, 1); + MA_bit_set(cpustate, 0); + cpustate->PCU.reset_vector = 0xe000; + break; + + case 0x01: + cpustate->device->logerror("Dsp56156 in Special Bootstrap Mode 2\n"); + + /* HACK - Turn bootstrap mode on. This hijacks the CPU execute loop and lets */ + /* Either the host interface or the SSIO interface suck in all the data */ + /* they need. Once they've had their fill, they turn bootstrap mode off */ + /* and the CPU begins execution at 0x0000; */ + /* HACK - Read bit 15 at 0xc000 to see if we're working with the SSIO or host interface. */ + if (cpustate->program->read_word(0xc000<<1) & 0x8000) + { + cpustate->bootstrap_mode = BOOTSTRAP_SSIX; + cpustate->device->logerror("DSP56156 : Currently in (hacked) bootstrap mode - reading from SSIx.\n"); + } + else + { + cpustate->bootstrap_mode = BOOTSTRAP_HI; + cpustate->device->logerror("DSP56156 : Currently in (hacked) bootstrap mode - reading from Host Interface.\n"); + } + + /* HACK - Set the PC to 0x0000 as per the boot ROM. */ + PC = 0x0000; + + /* HACK - Not done yet, but set the Operating Mode to 2 in preparation. */ + MB_bit_set(cpustate, 1); + MA_bit_set(cpustate, 0); + cpustate->PCU.reset_vector = 0xe000; + break; + + case 0x02: + cpustate->device->logerror("Dsp56156 in Normal Expanded Mode\n"); + PC = 0xe000; + cpustate->PCU.reset_vector = 0xe000; + break; + + case 0x03: + cpustate->device->logerror("Dsp56156 in Development Expanded Mode\n"); + /* TODO: Disable internal ROM, etc. Likely a tricky thing for MAME? */ + PC = 0x0000; + cpustate->PCU.reset_vector = 0x0000; + break; + } + + /* Set registers properly */ + /* 1-17 Clear Interrupt Priority Register (IPR) */ + IPR = 0x0000; + + /* FM.5-4 */ + I_bits_set(cpustate, 0x03); + S_bits_set(cpustate, 0); + L_bit_set(cpustate, 0); + S_bit_set(cpustate, 0); + FV_bit_set(cpustate, 0); + + /* FM.7-25 */ + E_bit_set(cpustate, 0); + U_bit_set(cpustate, 0); + N_bit_set(cpustate, 0); + V_bit_set(cpustate, 0); + Z_bit_set(cpustate, 0); + + /* FM.5-4+ */ + C_bit_set(cpustate, 0); + LF_bit_set(cpustate, 0); + SP = 0x0000; + + /* FM.5-14 (OMR) */ + SA_bit_set(cpustate, 0); + R_bit_set(cpustate, 0); + SD_bit_set(cpustate, 0); + CD_bit_set(cpustate, 0); + + /* Clear out the pending interrupt list */ + dsp56156_clear_pending_interrupts(cpustate); +} + +/*************************************************************************** + INTERRUPT HANDLING +***************************************************************************/ +struct dsp56156_irq_data +{ + uint16_t irq_vector; + char irq_source[128]; +}; + +dsp56156_irq_data dsp56156_interrupt_sources[32]; + +/* TODO: Figure out how to switch on level versus edge-triggered. */ +void pcu_service_interrupts(dsp56156_core* cpustate) +{ + int i; + + /* Count list of pending interrupts */ + int num_servicable = dsp56156_count_pending_interrupts(cpustate); + + if (num_servicable == 0) + return; + + /* Sort list according to priority */ + dsp56156_sort_pending_interrupts(cpustate, num_servicable); + + /* Service each interrupt in order */ + /* TODO: This just *can't* be right :) */ + for (i = 0; i < num_servicable; i++) + { + const int interrupt_index = cpustate->PCU.pending_interrupts[i]; + + /* Get the priority of the interrupt - a return value of -1 means disabled! */ + int8_t priority = dsp56156_get_irq_priority(cpustate, interrupt_index); + + /* 1-12 Make sure you're not masked out against the Interrupt Mask Bits (disabled is handled for free here) */ + if (priority >= I_bits(cpustate)) + { + /* TODO: Implement long interrupts & fast interrupts correctly! */ + /* Right now they are handled in the JSR & BSR ops. SupahLame. */ + + /* Are you anything but the Host Command interrupt? */ + if (interrupt_index != 22) + { + /* Execute a normal interrupt */ + PC = dsp56156_interrupt_sources[interrupt_index].irq_vector; + } + else + { + /* The host command input has a floating vector. */ + const uint16_t irq_vector = HV_bits(cpustate) << 1; + + PC = irq_vector; + + /* TODO: 5-9 5-11 Gotta' Clear HC (HCP gets it too) when taking this exception! */ + HC_bit_set(cpustate, 0); + } + } + } + + dsp56156_clear_pending_interrupts(cpustate); +} + + +/* Register an interrupt */ +void dsp56156_add_pending_interrupt(dsp56156_core* cpustate, const char* name) +{ + int i; + int irq_index = dsp56156_get_irq_index_by_tag(name); + + for (i = 0; i < 32; i++) + { + if (cpustate->PCU.pending_interrupts[i] == -1) + { + cpustate->PCU.pending_interrupts[i] = irq_index; + break; + } + } +} + +/* Utility function to construct IRQ table */ +void dsp56156_set_irq_source(uint8_t irq_num, uint16_t iv, const char* source) +{ + dsp56156_interrupt_sources[irq_num].irq_vector = iv; + strcpy(dsp56156_interrupt_sources[irq_num].irq_source, source); +} + +/* Construct a table containing pertient IRQ information */ +void dsp56156_irq_table_init(void) +{ + /* 1-14 + 1-18 */ + /* TODO: Cull host command stuff appropriately */ + /* array index . vector . token */ + dsp56156_set_irq_source(0, 0x0000, "Hardware RESET"); + dsp56156_set_irq_source(1, 0x0002, "Illegal Instruction"); + dsp56156_set_irq_source(2, 0x0004, "Stack Error"); + dsp56156_set_irq_source(3, 0x0006, "Reserved"); + dsp56156_set_irq_source(4, 0x0008, "SWI"); + dsp56156_set_irq_source(5, 0x000a, "IRQA"); + dsp56156_set_irq_source(6, 0x000c, "IRQB"); + dsp56156_set_irq_source(7, 0x000e, "Reserved"); + dsp56156_set_irq_source(8, 0x0010, "SSI0 Receive Data with Exception"); + dsp56156_set_irq_source(9, 0x0012, "SSI0 Receive Data"); + dsp56156_set_irq_source(10, 0x0014, "SSI0 Transmit Data with Exception"); + dsp56156_set_irq_source(11, 0x0016, "SSI0 Transmit Data"); + dsp56156_set_irq_source(12, 0x0018, "SSI1 Receive Data with Exception"); + dsp56156_set_irq_source(13, 0x001a, "SSI1 Receive Data"); + dsp56156_set_irq_source(14, 0x001c, "SSI1 Transmit Data with Exception"); + dsp56156_set_irq_source(15, 0x001e, "SSI1 Transmit Data"); + dsp56156_set_irq_source(16, 0x0020, "Timer Overflow"); + dsp56156_set_irq_source(17, 0x0022, "Timer Compare"); + dsp56156_set_irq_source(18, 0x0024, "Host DMA Receive Data"); + dsp56156_set_irq_source(19, 0x0026, "Host DMA Transmit Data"); + dsp56156_set_irq_source(20, 0x0028, "Host Receive Data"); + dsp56156_set_irq_source(21, 0x002a, "Host Transmit Data"); + dsp56156_set_irq_source(22, 0x002c, "Host Command"); /* Default vector for the host command */ + dsp56156_set_irq_source(23, 0x002e, "Codec Receive/Transmit"); + dsp56156_set_irq_source(24, 0x0030, "Host Command 1"); + dsp56156_set_irq_source(25, 0x0032, "Host Command 2"); + dsp56156_set_irq_source(26, 0x0034, "Host Command 3"); + dsp56156_set_irq_source(27, 0x0036, "Host Command 4"); + dsp56156_set_irq_source(28, 0x0038, "Host Command 5"); + dsp56156_set_irq_source(29, 0x003a, "Host Command 6"); + dsp56156_set_irq_source(30, 0x003c, "Host Command 7"); + dsp56156_set_irq_source(31, 0x003e, "Host Command 8"); +} + +/* Clear all entries from the pending table */ +void dsp56156_clear_pending_interrupts(dsp56156_core* cpustate) +{ + int i; + for (i = 0; i < 32; i++) + { + cpustate->PCU.pending_interrupts[i] = -1; + } +} + +/* Recover number of pending irqs */ +int dsp56156_count_pending_interrupts(dsp56156_core* cpustate) +{ + int numI = 0; + while (cpustate->PCU.pending_interrupts[numI] != -1) + { + numI++; + } + + return numI; +} + +/* Sort the pending irqs by priority */ +void dsp56156_sort_pending_interrupts(dsp56156_core* cpustate, int num) +{ + int i, j; + + /* We're going to be sorting the priorities */ + int priority_list[32]; + for (i = 0; i < num; i++) + { + priority_list[i] = dsp56156_get_irq_priority(cpustate, cpustate->PCU.pending_interrupts[i]); + } + + /* Bubble sort should be good enough for us */ + for (i = 0; i < num; i++) + { + for(j = 0; j < num-1; j++) + { + if (priority_list[j] > priority_list[j+1]) + { + int holder; + + /* Swap priorities */ + holder = priority_list[j+1]; + priority_list[j+1] = priority_list[j]; + priority_list[j] = holder; + + /* Swap irq indices. */ + holder = cpustate->PCU.pending_interrupts[j+1]; + cpustate->PCU.pending_interrupts[j+1] = cpustate->PCU.pending_interrupts[j]; + cpustate->PCU.pending_interrupts[j] = holder; + } + } + } + + /* TODO: 1-17 Now sort each of the priority levels within their categories. */ +} + +/* Given an index into the irq table, return the interrupt's current priority */ +int8_t dsp56156_get_irq_priority(dsp56156_core* cpustate, int index) +{ + /* 1-12 */ + switch (index) + { + /* Non-maskable */ + case 0: return 3; /* Hardware RESET */ + case 1: return 3; /* Illegal Instruction */ + case 2: return 3; /* Stack Error */ + case 3: return 3; /* Reserved */ + case 4: return 3; /* SWI */ + + /* Poll the IPR for these guys. */ + case 5: return irqa_ipl(cpustate); /* IRQA */ + case 6: return irqb_ipl(cpustate); /* IRQB */ + case 7: return -1; /* Reserved */ + case 8: return ssi0_ipl(cpustate); /* SSI0 Receive Data with Exception */ + case 9: return ssi0_ipl(cpustate); /* SSI0 Receive Data */ + case 10: return ssi0_ipl(cpustate); /* SSI0 Transmit Data with Exception */ + case 11: return ssi0_ipl(cpustate); /* SSI0 Transmit Data */ + case 12: return ssi1_ipl(cpustate); /* SSI1 Receive Data with Exception */ + case 13: return ssi1_ipl(cpustate); /* SSI1 Receive Data */ + case 14: return ssi1_ipl(cpustate); /* SSI1 Transmit Data with Exception */ + case 15: return ssi1_ipl(cpustate); /* SSI1 Transmit Data */ + case 16: return tm_ipl(cpustate); /* Timer Overflow */ + case 17: return tm_ipl(cpustate); /* Timer Compare */ + case 18: return host_ipl(cpustate); /* Host DMA Receive Data */ + case 19: return host_ipl(cpustate); /* Host DMA Transmit Data */ + case 20: return host_ipl(cpustate); /* Host Receive Data */ + case 21: return host_ipl(cpustate); /* Host Transmit Data */ + case 22: return host_ipl(cpustate); /* Host Command 0 (Default) */ + case 23: return codec_ipl(cpustate); /* Codec Receive/Transmit */ + case 24: return host_ipl(cpustate); /* Host Command 1 // TODO: Are all host ipl's the same? */ + case 25: return host_ipl(cpustate); /* Host Command 2 */ + case 26: return host_ipl(cpustate); /* Host Command 3 */ + case 27: return host_ipl(cpustate); /* Host Command 4 */ + case 28: return host_ipl(cpustate); /* Host Command 5 */ + case 29: return host_ipl(cpustate); /* Host Command 6 */ + case 30: return host_ipl(cpustate); /* Host Command 7 */ + case 31: return host_ipl(cpustate); /* Host Command 8 */ + + default: break; + } + + return -1; +} + +/* Given an IRQ name, return its index in the irq table */ +int dsp56156_get_irq_index_by_tag(const char* tag) +{ + int i; + for (i = 0; i < 32; i++) + { + if (strcmp(tag, dsp56156_interrupt_sources[i].irq_source) == 0) + { + return i; + } + } + + fatalerror("DSP56156 ERROR : IRQ TAG specified incorrectly (get_vector_by_tag) : %s.\n", tag); + // never executed + //return -1; +} + +} // namespace DSP_56156 diff --git a/src/devices/cpu/dsp56156/dsp56pcu.h b/src/devices/cpu/dsp56156/dsp56pcu.h new file mode 100644 index 00000000000..a04f7bf1f26 --- /dev/null +++ b/src/devices/cpu/dsp56156/dsp56pcu.h @@ -0,0 +1,150 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#ifndef DSP56156_PCU_H +#define DSP56156_PCU_H + +#include "dsp56156.h" + +namespace DSP_56156 +{ +/*************************************************************************** + PCU +***************************************************************************/ +void pcu_reset(dsp56156_core* cpustate); +void pcu_init(dsp56156_core* cpustate, device_t *device); +#define PC (cpustate->PCU.pc) +#define LA (cpustate->PCU.la) +#define LC (cpustate->PCU.lc) +#define SR (cpustate->PCU.sr) +#define OMR (cpustate->PCU.omr) +#define SP (cpustate->PCU.sp) +#define SS (cpustate->PCU.ss) + +#define SSH (SS[SP].w.h) +#define SSL (SS[SP].w.l) + +#define ST0 (SS[0].d) +#define ST1 (SS[1].d) +#define ST2 (SS[2].d) +#define ST3 (SS[3].d) +#define ST4 (SS[4].d) +#define ST5 (SS[5].d) +#define ST6 (SS[6].d) +#define ST7 (SS[7].d) +#define ST8 (SS[8].d) +#define ST9 (SS[9].d) +#define ST10 (SS[10].d) +#define ST11 (SS[11].d) +#define ST12 (SS[12].d) +#define ST13 (SS[13].d) +#define ST14 (SS[14].d) +#define ST15 (SS[15].d) + +/* STATUS REGISTER (SR) BITS (1-25) */ +/* MR */ +uint8_t LF_bit(const dsp56156_core* cpustate); +uint8_t FV_bit(const dsp56156_core* cpustate); +//uint8_t S_bits(const dsp56156_core* cpustate); +uint8_t I_bits(const dsp56156_core* cpustate); + +/* CCR - with macros for easy access */ +#define S() (S_bit(cpustate)) +uint8_t S_bit(const dsp56156_core* cpustate); +#define L() (L_bit(cpustate)) +uint8_t L_bit(const dsp56156_core* cpustate); +#define E() (E_bit(cpustate)) +uint8_t E_bit(const dsp56156_core* cpustate); +#define U() (U_bit(cpustate)) +uint8_t U_bit(const dsp56156_core* cpustate); +#define N() (N_bit(cpustate)) +uint8_t N_bit(const dsp56156_core* cpustate); +#define Z() (Z_bit(cpustate)) +uint8_t Z_bit(const dsp56156_core* cpustate); +#define V() (V_bit(cpustate)) +uint8_t V_bit(const dsp56156_core* cpustate); +#define C() (C_bit(cpustate)) +uint8_t C_bit(const dsp56156_core* cpustate); + +/* MR setters */ +void LF_bit_set(dsp56156_core* cpustate, uint8_t value); +void FV_bit_set(dsp56156_core* cpustate, uint8_t value); +void S_bits_set(dsp56156_core* cpustate, uint8_t value); +void I_bits_set(dsp56156_core* cpustate, uint8_t value); + +/* CCR setters - with macros for easy access */ +#define DSP56156_S_SET() (S_bit_set(cpustate, 1)) +#define DSP56156_S_CLEAR() (S_bit_set(cpustate, 0)) +void S_bit_set(dsp56156_core* cpustate, uint8_t value); +#define DSP56156_L_SET() (L_bit_set(cpustate, 1)) +#define DSP56156_L_CLEAR() (L_bit_set(cpustate, 0)) +void L_bit_set(dsp56156_core* cpustate, uint8_t value); +#define DSP56156_E_SET() (E_bit_set(cpustate, 1)) +#define DSP56156_E_CLEAR() (E_bit_set(cpustate, 0)) +void E_bit_set(dsp56156_core* cpustate, uint8_t value); +#define DSP56156_U_SET() (U_bit_set(cpustate, 1)) +#define DSP56156_U_CLEAR() (U_bit_set(cpustate, 0)) +void U_bit_set(dsp56156_core* cpustate, uint8_t value); +#define DSP56156_N_SET() (N_bit_set(cpustate, 1)) +#define DSP56156_N_CLEAR() (N_bit_set(cpustate, 0)) +void N_bit_set(dsp56156_core* cpustate, uint8_t value); +#define DSP56156_Z_SET() (Z_bit_set(cpustate, 1)) +#define DSP56156_Z_CLEAR() (Z_bit_set(cpustate, 0)) +void Z_bit_set(dsp56156_core* cpustate, uint8_t value); +#define DSP56156_V_SET() (V_bit_set(cpustate, 1)) +#define DSP56156_V_CLEAR() (V_bit_set(cpustate, 0)) +void V_bit_set(dsp56156_core* cpustate, uint8_t value); +#define DSP56156_C_SET() (C_bit_set(cpustate, 1)) +#define DSP56156_C_CLEAR() (C_bit_set(cpustate, 0)) +void C_bit_set(dsp56156_core* cpustate, uint8_t value); + +// TODO: Maybe some functions for Interrupt Mask and Scaling Mode go here? + + +/* 1-28 OPERATING MODE REGISTER (OMR) BITS */ +//uint8_t CD_bit(const dsp56156_core* cpustate); +//uint8_t SD_bit(const dsp56156_core* cpustate); +//uint8_t R_bit(const dsp56156_core* cpustate); +//uint8_t SA_bit(const dsp56156_core* cpustate); +//uint8_t MC_bit(const dsp56156_core* cpustate); +uint8_t MB_bit(const dsp56156_core* cpustate); +uint8_t MA_bit(const dsp56156_core* cpustate); + +void CD_bit_set(dsp56156_core* cpustate, uint8_t value); +void SD_bit_set(dsp56156_core* cpustate, uint8_t value); +void R_bit_set(dsp56156_core* cpustate, uint8_t value); +void SA_bit_set(dsp56156_core* cpustate, uint8_t value); +void MC_bit_set(dsp56156_core* cpustate, uint8_t value); +void MB_bit_set(dsp56156_core* cpustate, uint8_t value); +void MA_bit_set(dsp56156_core* cpustate, uint8_t value); + +/* 1-27 STACK POINTER (SP) BITS */ +uint8_t UF_bit(const dsp56156_core* cpustate); +uint8_t SE_bit(const dsp56156_core* cpustate); + +//void UF_bit_set(dsp56156_core* cpustate, uint8_t value) {}; +//void SE_bit_set(dsp56156_core* cpustate, uint8_t value) {}; + + +// HACK - Bootstrap modes +#define BOOTSTRAP_OFF (0) +#define BOOTSTRAP_SSIX (1) +#define BOOTSTRAP_HI (2) + + +/* PCU IRQ goodies */ +void pcu_service_interrupts(dsp56156_core* cpustate); + +void dsp56156_irq_table_init(void); +void dsp56156_set_irq_source(uint8_t irq_num, uint16_t iv, const char* source); +int dsp56156_get_irq_index_by_tag(const char* tag); + +void dsp56156_add_pending_interrupt(dsp56156_core* cpustate, const char* name); // Call me to add an interrupt to the queue + +void dsp56156_clear_pending_interrupts(dsp56156_core* cpustate); +int dsp56156_count_pending_interrupts(dsp56156_core* cpustate); +void dsp56156_sort_pending_interrupts(dsp56156_core* cpustate, int num); +int8_t dsp56156_get_irq_priority(dsp56156_core* cpustate, int index); + +} // namespace DSP_56156 + +#endif diff --git a/src/devices/cpu/dsp56156/inst.cpp b/src/devices/cpu/dsp56156/inst.cpp new file mode 100644 index 00000000000..339156aa35e --- /dev/null +++ b/src/devices/cpu/dsp56156/inst.cpp @@ -0,0 +1,786 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#include "emu.h" +#include "inst.h" +#include "emu.h" + +namespace DSP_56156 +{ +// Factory +std::unique_ptr<Instruction> Instruction::decodeInstruction(const Opcode* opc, + const uint16_t word0, + const uint16_t word1, + bool shifted) +{ + uint16_t w0 = word0; + uint16_t w1 = word1; + + if (shifted) + { + w0 = w1; + w1 = 0x0000; + } + + /**************************************************************************/ + /* The very funky case of the XMemoryDataMoveWithShortDisplacement */ + /**************************************************************************/ + if ((w0 & 0xff00) == 0x0500) + { + // Avoid "05-- 05--" recursion + if (shifted) return nullptr; + + std::unique_ptr<Instruction> op = decodeInstruction(opc, w0, w1, true); + if (op) + { + // This parallel move only works for certain trailing instructions. + if (dynamic_cast<Add*>(op.get()) || + dynamic_cast<Asr*>(op.get()) || + dynamic_cast<Eor*>(op.get()) || + dynamic_cast<Mac*>(op.get()) || + dynamic_cast<Macr*>(op.get()) || + dynamic_cast<Mpy*>(op.get()) || + dynamic_cast<Neg*>(op.get()) || + dynamic_cast<Sub*>(op.get()) || + dynamic_cast<Tfr*>(op.get()) || + dynamic_cast<Tst*>(op.get()) + /* TODO: More? */) + { + op->m_sizeIncrement = 1; + return op; + } + } + } + + + /**************************************************************************/ + /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142 */ + /* Quote: (MOVE, MAC(R), MPY(R), ADD, SUB, TFR) */ + /**************************************************************************/ + /* TFR : 011m mKKK 0rr1 F0DD : A-212 */ + if ((w0 & 0xe094) == 0x6010) + { + return std::make_unique<Tfr_2>(opc, w0, w1); + } + /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ + if ((w0 & 0xe097) == 0x6017) + { + return std::make_unique<Move_2>(opc, w0, w1); + } + /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ + else if ((w0 & 0xe094) == 0x6084) + { + return std::make_unique<Mac_3>(opc, w0, w1); + } + /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ + else if ((w0 & 0xe094) == 0x6094) + { + return std::make_unique<Macr_2>(opc, w0, w1); + } + /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ + else if ((w0 & 0xe094) == 0x6080) + { + return std::make_unique<Mpy_2>(opc, w0, w1); + } + /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ + else if ((w0 & 0xe094) == 0x6090) + { + return std::make_unique<Mpyr_2>(opc, w0, w1); + } + /* ADD : 011m mKKK 0rru Fuuu : A-22 */ + /* SUB : 011m mKKK 0rru Fuuu : A-202 */ + else if ((w0 & 0xe080) == 0x6000) + { + return std::make_unique<Add_2>(opc, w0, w1); + } + + /****************************************************************************/ + /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */ + /* Quote: (MPY or MAC) */ + /****************************************************************************/ + /* MPY : 0001 0110 RRDD FQQQ : A-160 */ + else if ((w0 & 0xff00) == 0x1600) + { + return std::make_unique<Mpy_3>(opc, w0, w1); + } + /* MAC : 0001 0111 RRDD FQQQ : A-122 */ + else if ((w0 & 0xff00) == 0x1700) + { + return std::make_unique<Mac_3>(opc, w0, w1); + } + + /****************************************************************/ + /* No Parallel Data Move : 0100 1010 .... .... : A-131 */ + /* Register to Register Data Move : 0100 IIII .... .... : A-133 */ + /* Address Register Update : 0011 0zRR .... .... : A-135 */ + /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ + /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ + /* Quote: (32 General parallel move instructions) */ + /****************************************************************/ + else if (((w0 & 0xff00) == 0x4a00) || + ((w0 & 0xf000) == 0x4000) || + ((w0 & 0xf800) == 0x3000) || + ((w0 & 0x8000) == 0x8000) || + ((w0 & 0xf000) == 0x5000)) + { + /* Note: There is much overlap down here, so certain ops must come before others */ + + /* CLR : .... .... 0000 F001 : A-60 */ + if ((w0 & 0x00f7) == 0x0001) + { + return std::make_unique<Clr>(opc, w0, w1); + } + /* ADD : .... .... 0000 FJJJ : A-22 */ + else if ((w0 & 0x00f0) == 0x0000) + { + return std::make_unique<Add>(opc, w0, w1); + } + + /* MOVE : .... .... 0001 0001 : A-128 */ + else if ((w0 & 0x00ff) == 0x0011 || (w0 & 0x00ff) == 0x0019) + // NEW // else if ((w0 & 0x00ff) == 0x0011) + { + return std::make_unique<Move>(opc, w0, w1); + } + /* TFR : .... .... 0001 FJJJ : A-212 */ + else if ((w0 & 0x00f0) == 0x0010) + { + return std::make_unique<Tfr>(opc, w0, w1); + } + + /* RND : .... .... 0010 F000 : A-188 */ + else if ((w0 & 0x00f7) == 0x0020) + { + return std::make_unique<Rnd>(opc, w0, w1); + } + /* TST : .... .... 0010 F001 : A-218 */ + else if ((w0 & 0x00f7) == 0x0021) + { + return std::make_unique<Tst>(opc, w0, w1); + } + /* INC : .... .... 0010 F010 : A-104 */ + else if ((w0 & 0x00f7) == 0x0022) + { + return std::make_unique<Inc>(opc, w0, w1); + } + /* INC24 : .... .... 0010 F011 : A-106 */ + else if ((w0 & 0x00f7) == 0x0023) + { + return std::make_unique<Inc24>(opc, w0, w1); + } + /* OR : .... .... 0010 F1JJ : A-176 */ + else if ((w0 & 0x00f4) == 0x0024) + { + return std::make_unique<Or>(opc, w0, w1); + } + + /* ASR : .... .... 0011 F000 : A-32 */ + else if ((w0 & 0x00f7) == 0x0030) + { + return std::make_unique<Asr>(opc, w0, w1); + } + /* ASL : .... .... 0011 F001 : A-28 */ + else if ((w0 & 0x00f7) == 0x0031) + { + return std::make_unique<Asl>(opc, w0, w1); + } + /* LSR : .... .... 0011 F010 : A-120 */ + else if ((w0 & 0x00f7) == 0x0032) + { + return std::make_unique<Lsr>(opc, w0, w1); + } + /* LSL : .... .... 0011 F011 : A-118 */ + else if ((w0 & 0x00f7) == 0x0033) + { + return std::make_unique<Lsl>(opc, w0, w1); + } + /* EOR : .... .... 0011 F1JJ : A-94 */ + else if ((w0 & 0x00f4) == 0x0034) + { + return std::make_unique<Eor>(opc, w0, w1); + } + + /* SUBL : .... .... 0100 F001 : A-204 */ + else if ((w0 & 0x00f7) == 0x0041) + { + return std::make_unique<Subl>(opc, w0, w1); + } + /* SUB : .... .... 0100 FJJJ : A-202 */ + else if ((w0 & 0x00f0) == 0x0040) + { + return std::make_unique<Sub>(opc, w0, w1); + } + + /* CLR24 : .... .... 0101 F001 : A-62 */ + else if ((w0 & 0x00f7) == 0x0051) + { + return std::make_unique<Clr24>(opc, w0, w1); + } + /* SBC : .... .... 0101 F01J : A-198 */ + else if ((w0 & 0x00f6) == 0x0052) + { + return std::make_unique<Sbc>(opc, w0, w1); + } + /* CMP : .... .... 0101 FJJJ : A-64 */ + else if ((w0 & 0x00f0) == 0x0050) + { + return std::make_unique<Cmp>(opc, w0, w1); + } + + /* NEG : .... .... 0110 F000 : A-166 */ + else if ((w0 & 0x00f7) == 0x0060) + { + return std::make_unique<Neg>(opc, w0, w1); + } + /* NOT : .... .... 0110 F001 : A-174 */ + else if ((w0 & 0x00f7) == 0x0061) + { + return std::make_unique<Not>(opc, w0, w1); + } + /* DEC : .... .... 0110 F010 : A-72 */ + else if ((w0 & 0x00f7) == 0x0062) + { + return std::make_unique<Dec>(opc, w0, w1); + } + /* DEC24 : .... .... 0110 F011 : A-74 */ + else if ((w0 & 0x00f7) == 0x0063) + { + return std::make_unique<Dec24>(opc, w0, w1); + } + /* AND : .... .... 0110 F1JJ : A-24 */ + else if ((w0 & 0x00f4) == 0x0064) + { + return std::make_unique<And>(opc, w0, w1); + } + + /* ABS : .... .... 0111 F001 : A-18 */ + if ((w0 & 0x00f7) == 0x0071) + { + return std::make_unique<Abs>(opc, w0, w1); + } + /* ROR : .... .... 0111 F010 : A-192 */ + else if ((w0 & 0x00f7) == 0x0072) + { + return std::make_unique<Ror>(opc, w0, w1); + } + /* ROL : .... .... 0111 F011 : A-190 */ + else if ((w0 & 0x00f7) == 0x0073) + { + return std::make_unique<Rol>(opc, w0, w1); + } + /* CMPM : .... .... 0111 FJJJ : A-66 */ + else if ((w0 & 0x00f0) == 0x0070) + { + return std::make_unique<Cmpm>(opc, w0, w1); + } + + /* MPY : .... .... 1k00 FQQQ : A-160 */ + else if ((w0 & 0x00b0) == 0x0080) + { + return std::make_unique<Mpy>(opc, w0, w1); + } + /* MPYR : .... .... 1k01 FQQQ : A-162 */ + else if ((w0 & 0x00b0) == 0x0090) + { + return std::make_unique<Mpyr>(opc, w0, w1); + } + /* MAC : .... .... 1k10 FQQQ : A-122 */ + else if ((w0 & 0x00b0) == 0x00a0) + { + return std::make_unique<Mac>(opc, w0, w1); + } + /* MACR : .... .... 1k11 FQQQ : A-124 */ + else if ((w0 & 0x00b0) == 0x00b0) + { + return std::make_unique<Macr>(opc, w0, w1); + } + } + + /******************************/ + /* Remaining non-parallel ops */ + /******************************/ + /* ADC : 0001 0101 0000 F01J : A-20 */ + else if ((w0 & 0xfff6) == 0x1502) + { + return std::make_unique<Adc>(opc, w0, w1); + } + /* ANDI : 0001 1EE0 iiii iiii : A-26 */ + /* Note: MoveP sneaks in here if you don't check 0x0600 */ + else if (((w0 & 0xf900) == 0x1800) & ((w0 & 0x0600) != 0x0000)) + { + return std::make_unique<Andi>(opc, w0, w1); + } + /* ASL4 : 0001 0101 0011 F001 : A-30 */ + else if ((w0 & 0xfff7) == 0x1531) + { + return std::make_unique<Asl4>(opc, w0, w1); + } + /* ASR4 : 0001 0101 0011 F000 : A-34 */ + else if ((w0 & 0xfff7) == 0x1530) + { + return std::make_unique<Asr4>(opc, w0, w1); + } + /* ASR16 : 0001 0101 0111 F000 : A-36 */ + else if ((w0 & 0xfff7) == 0x1570) + { + return std::make_unique<Asr16>(opc, w0, w1); + } + /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */ + else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x1200)) + { + return std::make_unique<BfInstruction>(opc, w0, w1); + } + /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */ + else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x1200)) + // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x1200)) + { + return std::make_unique<BfInstruction_2>(opc, w0, w1); + } + /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */ + else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x1200)) + { + return std::make_unique<BfInstruction_3>(opc, w0, w1); + } + /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */ + else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x0400)) + { + return std::make_unique<BfInstruction>(opc, w0, w1); + } + /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */ + else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x0400)) + // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x0400)) + { + return std::make_unique<BfInstruction_2>(opc, w0, w1); + } + /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */ + else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x0400)) + { + return std::make_unique<BfInstruction_3>(opc, w0, w1); + } + /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */ + else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x1800)) + { + return std::make_unique<BfInstruction>(opc, w0, w1); + } + /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */ + else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x1800)) + // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x1800)) + { + return std::make_unique<BfInstruction_2>(opc, w0, w1); + } + /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */ + else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x1800)) + { + return std::make_unique<BfInstruction_3>(opc, w0, w1); + } + /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */ + else if (((w0 & 0xffc0) == 0x1440) && ((w1 & 0x1f00) == 0x1000)) + { + return std::make_unique<BfInstruction>(opc, w0, w1); + } + /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */ + else if (((w0 & 0xfff0) == 0x1430) && ((w1 & 0x1f00) == 0x1000)) + // NEW // else if (((w0 & 0xffe0) == 0x1420) && ((w1 & 0x1f00) == 0x1000)) + { + return std::make_unique<BfInstruction_2>(opc, w0, w1); + } + /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */ + else if (((w0 & 0xffe0) == 0x1400) && ((w1 & 0x1f00) == 0x1000)) + { + return std::make_unique<BfInstruction_3>(opc, w0, w1); + } + /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */ + else if (((w0 & 0xffc0) == 0x1440) && ((w1 & 0x1f00) == 0x0000)) + { + return std::make_unique<BfInstruction>(opc, w0, w1); + } + /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */ + else if (((w0 & 0xfff0) == 0x1430) && ((w1 & 0x1f00) == 0x0000)) + // NEW // else if (((w0 & 0xffe0) == 0x1420) && ((w1 & 0x1f00) == 0x0000)) + { + return std::make_unique<BfInstruction_2>(opc, w0, w1); + } + /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ + else if (((w0 & 0xffe0) == 0x1400) && ((w1 & 0x1f00) == 0x0000)) + { + return std::make_unique<BfInstruction_3>(opc, w0, w1); + } + /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */ + else if (((w0 & 0xff30) == 0x0730) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Bcc>(opc, w0, w1); + } + /* Bcc : 0010 11cc ccee eeee : A-48 */ + else if ((w0 & 0xfc00) == 0x2c00) + { + return std::make_unique<Bcc_2>(opc, w0, w1); + } + /* Bcc : 0000 0111 RR10 cccc : A-48 */ + else if ((w0 & 0xff30) == 0x0720) + { + return std::make_unique<Bcc_3>(opc, w0, w1); + } + /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */ + else if (((w0 & 0xfffc) == 0x013c) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Bra>(opc, w0, w1); + } + /* BRA : 0000 1011 aaaa aaaa : A-50 */ + else if ((w0 & 0xff00) == 0x0b00) + { + return std::make_unique<Bra_2>(opc, w0, w1); + } + /* BRA : 0000 0001 0010 11RR : A-50 */ + else if ((w0 & 0xfffc) == 0x012c) + { + return std::make_unique<Bra_3>(opc, w0, w1); + } + /* BRKc : 0000 0001 0001 cccc : A-52 */ + else if ((w0 & 0xfff0) == 0x0110) + { + return std::make_unique<Brkcc>(opc, w0, w1); + } + /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */ + else if (((w0 & 0xff30) == 0x0710) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Bscc>(opc, w0, w1); + } + /* BScc : 0000 0111 RR00 cccc : A-54 */ + else if ((w0 & 0xff30) == 0x0700) + { + return std::make_unique<Bscc_2>(opc, w0, w1); + } + /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */ + else if (((w0 & 0xfffc) == 0x0138) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Bsr>(opc, w0, w1); + } + /* BSR : 0000 0001 0010 10RR : A-56 */ + else if ((w0 & 0xfffc) == 0x0128) + { + return std::make_unique<Bsr_2>(opc, w0, w1); + } + /* CHKAAU : 0000 0000 0000 0100 : A-58 */ + else if ((w0 & 0xffff) == 0x0004) + { + return std::make_unique<Chkaau>(opc, w0, w1); + } + /* DEBUG : 0000 0000 0000 0001 : A-68 */ + else if ((w0 & 0xffff) == 0x0001) + { + return std::make_unique<Debug>(opc, w0, w1); + } + /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ + else if ((w0 & 0xfff0) == 0x0050) + { + return std::make_unique<Debugcc>(opc, w0, w1); + } + /* DIV : 0001 0101 0--0 F1DD : A-76 */ + else if ((w0 & 0xfff4) == 0x1504) + // NEW // else if ((w0 & 0xff94) == 0x1504) + { + return std::make_unique<Div>(opc, w0, w1); + } + /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ + else if ((w0 & 0xffd0) == 0x1590) + { + return std::make_unique<Dmac>(opc, w0, w1); + } + /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */ + else if (((w0 & 0xffe0) == 0x00c0) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh? + { + return std::make_unique<Do>(opc, w0, w1); + } + /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */ + else if (((w0 & 0xff00) == 0x0e00) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh? + { + return std::make_unique<Do_2>(opc, w0, w1); + } + /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */ + else if (((w0 & 0xffe0) == 0x0400) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh? + { + return std::make_unique<Do_3>(opc, w0, w1); + } + /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */ + else if (((w0 & 0xffff) == 0x0002) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh? + { + return std::make_unique<DoForever>(opc, w0, w1); + } + /* ENDDO : 0000 0000 0000 1001 : A-92 */ + else if ((w0 & 0xffff) == 0x0009) + { + return std::make_unique<Enddo>(opc, w0, w1); + } + /* EXT : 0001 0101 0101 F010 : A-96 */ + else if ((w0 & 0xfff7) == 0x1552) + { + return std::make_unique<Ext>(opc, w0, w1); + } + /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ + else if ((w0 & 0xffff) == 0x000f) + { + return std::make_unique<Illegal>(opc, w0, w1); + } + /* IMAC : 0001 0101 1010 FQQQ : A-100 */ + else if ((w0 & 0xfff0) == 0x15a0) + { + return std::make_unique<Imac>(opc, w0, w1); + } + /* IMPY : 0001 0101 1000 FQQQ : A-102 */ + else if ((w0 & 0xfff0) == 0x1580) + { + return std::make_unique<Impy>(opc, w0, w1); + } + /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */ + else if (((w0 & 0xff30) == 0x0630) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Jcc>(opc, w0, w1); + } + /* Jcc : 0000 0110 RR10 cccc : A-108 */ + else if ((w0 & 0xff30) == 0x0620 ) + { + return std::make_unique<Jcc_2>(opc, w0, w1); + } + /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */ + else if (((w0 & 0xfffc) == 0x0134) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Jmp>(opc, w0, w1); + } + /* JMP : 0000 0001 0010 01RR : A-110 */ + else if ((w0 & 0xfffc) == 0x0124) + { + //JMP2->m_oco = opc; + //JMP2->decode(w0, w1); + //return JMP2; + return std::make_unique<Jmp_2>(opc, w0, w1); + } + /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */ + else if (((w0 & 0xff30) == 0x0610) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Jscc>(opc, w0, w1); + } + /* JScc : 0000 0110 RR00 cccc : A-112 */ + else if ((w0 & 0xff30) == 0x0600) + { + return std::make_unique<Jscc_2>(opc, w0, w1); + } + /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */ + else if (((w0 & 0xfffc) == 0x0130) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Jsr>(opc, w0, w1); + } + /* JSR : 0000 1010 AAAA AAAA : A-114 */ + else if ((w0 & 0xff00) == 0x0a00) + { + return std::make_unique<Jsr_2>(opc, w0, w1); + } + /* JSR : 0000 0001 0010 00RR : A-114 */ + else if ((w0 & 0xfffc) == 0x0120) + { + return std::make_unique<Jsr_3>(opc, w0, w1); + } + /* LEA : 0000 0001 11TT MMRR : A-116 */ + else if ((w0 & 0xffc0) == 0x01c0) + { + return std::make_unique<Lea>(opc, w0, w1); + } + /* LEA : 0000 0001 10NN MMRR : A-116 */ + else if ((w0 & 0xffc0) == 0x0180) + { + return std::make_unique<Lea_2>(opc, w0, w1); + } + /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ + else if ((w0 & 0xfff0) == 0x15e0) + { + return std::make_unique<Macsuuu>(opc, w0, w1); + } + /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */ +// NEW // else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0x00ff) == 0x0011)) +// NEW // { +// NEW // return std::make_unique<Move_3>(opc, w0, w1); +// NEW // } + /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ + else if ((w0 & 0xf810) == 0x3800) + { + return std::make_unique<Movec>(opc, w0, w1); + } + /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ + else if ((w0 & 0xf814) == 0x3810) + { + return std::make_unique<Movec_2>(opc, w0, w1); + } + /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ + else if ((w0 & 0xf816) == 0x3816) + { + return std::make_unique<Movec_3>(opc, w0, w1); + } + /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */ + else if (((w0 & 0xf816) == 0x3814) && ((w1 & 0x0000) == 0x0000)) + { + return std::make_unique<Movec_4>(opc, w0, w1); + } + /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ + else if ((w0 & 0xfc00) == 0x2800) + { + return std::make_unique<Movec_5>(opc, w0, w1); + } + /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */ + else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0xf810) == 0x3800)) + { + return std::make_unique<Movec_6>(opc, w0, w1); + } + /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ + else if ((w0 & 0xfc00) == 0x2000) + { + return std::make_unique<Movei>(opc, w0, w1); + } + /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ + else if ((w0 & 0xfe20) == 0x0200) + { + return std::make_unique<Movem>(opc, w0, w1); + } + /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ + else if ((w0 & 0xfe30) == 0x0230) + { + return std::make_unique<Movem_2>(opc, w0, w1); + } + /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */ + else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0xfe20) == 0x0200)) + { + return std::make_unique<Movem_3>(opc, w0, w1); + } + /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ + else if ((w0 & 0xfe20) == 0x1820) + { + return std::make_unique<Movep>(opc, w0, w1); + } + /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ + else if ((w0 & 0xfe00) == 0x0c00) + { + return std::make_unique<Movep_2>(opc, w0, w1); + } + /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ + else if ((w0 & 0xfe20) == 0x1800) + { + return std::make_unique<Moves>(opc, w0, w1); + } + /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ + else if ((w0 & 0xfff0) == 0x15c0) + { + return std::make_unique<Mpysuuu>(opc, w0, w1); + } + /* NEGC : 0001 0101 0110 F000 : A-168 */ + else if ((w0 & 0xfff7) == 0x1560) + { + return std::make_unique<Negc>(opc, w0, w1); + } + /* NOP : 0000 0000 0000 0000 : A-170 */ + else if ((w0 & 0xffff) == 0x0000) + { + return std::make_unique<Nop>(opc, w0, w1); + } + /* NORM : 0001 0101 0010 F0RR : A-172 */ + else if ((w0 & 0xfff4) == 0x1520) + { + return std::make_unique<Norm>(opc, w0, w1); + } + /* ORI : 0001 1EE1 iiii iiii : A-178 */ + else if ((w0 & 0xf900) == 0x1900) + { + return std::make_unique<Ori>(opc, w0, w1); + } + /* REP : 0000 0000 111- --RR : A-180 */ + else if ((w0 & 0xffe0) == 0x00e0) + { + return std::make_unique<Rep>(opc, w0, w1); + } + /* REP : 0000 1111 iiii iiii : A-180 */ + else if ((w0 & 0xff00) == 0x0f00) + { + return std::make_unique<Rep_2>(opc, w0, w1); + } + /* REP : 0000 0100 001D DDDD : A-180 */ + else if ((w0 & 0xffe0) == 0x0420) + { + return std::make_unique<Rep_3>(opc, w0, w1); + } + /* REPcc : 0000 0001 0101 cccc : A-184 */ + else if ((w0 & 0xfff0) == 0x0150) + { + return std::make_unique<Repcc>(opc, w0, w1); + } + /* RESET : 0000 0000 0000 1000 : A-186 */ + else if ((w0 & 0xffff) == 0x0008) + { + return std::make_unique<Reset>(opc, w0, w1); + } + /* RTI : 0000 0000 0000 0111 : A-194 */ + else if ((w0 & 0xffff) == 0x0007) + { + return std::make_unique<Rti>(opc, w0, w1); + } + /* RTS : 0000 0000 0000 0110 : A-196 */ + else if ((w0 & 0xffff) == 0x0006) + { + return std::make_unique<Rts>(opc, w0, w1); + } + /* STOP : 0000 0000 0000 1010 : A-200 */ + else if ((w0 & 0xffff) == 0x000a) + { + return std::make_unique<Stop>(opc, w0, w1); + } + /* SWAP : 0001 0101 0111 F001 : A-206 */ + else if ((w0 & 0xfff7) == 0x1571) + { + return std::make_unique<Swap>(opc, w0, w1); + } + /* SWI : 0000 0000 0000 0101 : A-208 */ + else if ((w0 & 0xffff) == 0x0005) + { + return std::make_unique<Swi>(opc, w0, w1); + } + /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ + else if ((w0 & 0xfc02) == 0x1000) + { + return std::make_unique<Tcc>(opc, w0, w1); + } + /* TFR(2) : 0001 0101 0000 F00J : A-214 */ + else if ((w0 & 0xfff6) == 0x1500) + { + return std::make_unique<Tfr2>(opc, w0, w1); + } + /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ + else if ((w0 & 0xfc00) == 0x2400) + { + return std::make_unique<Tfr3>(opc, w0, w1); + } + /* TST(2) : 0001 0101 0001 -1DD : A-220 */ + else if ((w0 & 0xfffc) == 0x1514) + // NEW // else if ((w0 & 0xfff4) == 0x1514) + { + return std::make_unique<Tst2>(opc, w0, w1); + } + /* WAIT : 0000 0000 0000 1011 : A-222 */ + else if ((w0 & 0xffff) == 0x000b) + { + return std::make_unique<Wait>(opc, w0, w1); + } + /* ZERO : 0001 0101 0101 F000 : A-224 */ + else if ((w0 & 0xfff7) == 0x1550) + { + return std::make_unique<Zero>(opc, w0, w1); + } + /* SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! */ + else if ((w0 & 0xfff0) == 0x15d0) + { + return std::make_unique<Shfl>(opc, w0, w1); + } + /* SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! */ + else if ((w0 & 0xfff0) == 0x15f0) + { + return std::make_unique<Shfr>(opc, w0, w1); + } + + return nullptr; +} + +} diff --git a/src/devices/cpu/dsp56156/inst.h b/src/devices/cpu/dsp56156/inst.h new file mode 100644 index 00000000000..c471b492ecf --- /dev/null +++ b/src/devices/cpu/dsp56156/inst.h @@ -0,0 +1,3774 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#ifndef DSP56156_INSTRUCTION_H +#define DSP56156_INSTRUCTION_H + +#include "opcode.h" +#include "tables.h" + +#include "dsp56156.h" +#include "dsp56def.h" +#include "dsp56pcu.h" + +// +// An Instruction is the base class all regular ops inherit from. +// +namespace DSP_56156 +{ +#define UNIMPLEMENTED_OPCODE() osd_printf_error("Unimplemented opcode: PC=%04x | %s;\n", PC, __PRETTY_FUNCTION__); + +class Opcode; + +class Instruction +{ +public: + Instruction(const Opcode* oco) : m_valid(false), + m_oco(oco), + m_sizeIncrement(0), + m_source(iINVALID), + m_destination(iINVALID) { } + virtual ~Instruction() {} + + virtual bool decode(const uint16_t word0, const uint16_t word1) = 0; + virtual void disassemble(std::string& retString) const = 0; + virtual void evaluate(dsp56156_core* cpustate) = 0; + + virtual size_t size() const = 0; + virtual size_t evalSize() const { return size(); } + virtual size_t accumulatorBitsModified() const = 0; // Potentially make this always return ALL (like flags) + virtual size_t flags() const { return 0; } + + static std::unique_ptr<Instruction> decodeInstruction(const Opcode* opc, + const uint16_t word0, + const uint16_t word1, + bool shifted=false); + + bool valid() const { return m_valid; } + + const reg_id& source() const { return m_source; } + const reg_id& destination() const { return m_destination; } + + size_t sizeIncrement() const { return m_sizeIncrement; } + +protected: + bool m_valid; + const Opcode* m_oco; + size_t m_sizeIncrement; + + // Parameters nearly everyone has + reg_id m_source; + reg_id m_destination; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// OPS //////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// ABS : .... .... 0111 F001 : A-18 //////////////////////////////////////////// +class Abs: public Instruction +{ +public: + Abs(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "abs " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ADC : 0001 0101 0000 F01J : A-20 //////////////////////////////////////////// +class Adc: public Instruction +{ +public: + Adc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JF_table(BITSn(word0,0x0001), BITSn(word0,0x0008), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "adc " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ADD : .... .... 0000 FJJJ : A-22 //////////////////////////////////////////// +class Add: public Instruction +{ +public: + Add(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "add " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ??? Odd that i should put the 011m mKKK everywhere ??? TODO +// ADD : 011m mKKK 0rru Fuuu : A-22 //////////////////////////////////////////// +class Add_2: public Instruction +{ +public: + Add_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_arg = ""; + m_opcode = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_uuuuF_table(BITSn(word0,0x17), BITSn(word0,0x08), + m_opcode, m_source, m_destination); + // TODO: m_opcode = "add"; + return true; + } + void disassemble(std::string& retString) const override + { + retString = m_opcode + " " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + std::string m_opcode; + std::string m_arg; // TODO: get rid of this Add|Sub thing. +}; + +// AND : .... .... 0110 F1JJ : A-24 //////////////////////////////////////////// +class And: public Instruction +{ +public: + And(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "and " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// ANDI : 0001 1EE0 iiii iiii : A-26 /////////////////////////////////////////// +class Andi: public Instruction +{ +public: + Andi(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = BITSn(word0,0x00ff); + decode_EE_table(BITSn(word0,0x0600), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "#$%x,%s", m_immediate, regIdAsString(m_destination).c_str()); + retString = "andi " + std::string(temp); + // NEW // sprintf(opcode_str, "and(i)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint8_t m_immediate; +}; + +// ASL : .... .... 0011 F001 : A-28 //////////////////////////////////////////// +class Asl: public Instruction +{ +public: + Asl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "asl " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ASL4 : 0001 0101 0011 F001 : A-30 /////////////////////////////////////////// +class Asl4: public Instruction +{ +public: + Asl4(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "asl4 " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ASR : .... .... 0011 F000 : A-32 //////////////////////////////////////////// +class Asr: public Instruction +{ +public: + Asr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "asr " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ASR4 : 0001 0101 0011 F000 : A-34 /////////////////////////////////////////// +class Asr4: public Instruction +{ +public: + Asr4(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "asr4 " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ASR16 : 0001 0101 0111 F000 : A-36 ////////////////////////////////////////// +class Asr16: public Instruction +{ +public: + Asr16(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "asr16 " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +/* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */ +/* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */ +/* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */ +/* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */ +/* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */ +class BfInstruction: public Instruction +{ +public: + BfInstruction(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + dString = ""; + m_opcode = ""; + m_iVal = 0x0000; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* Decode the common parts */ + m_iVal = BITSn(word1,0x00ff); + + bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000)); + switch(upperMiddleLower) + { + case BBB_UPPER: m_iVal <<= 8; break; + case BBB_MIDDLE: m_iVal <<= 4; break; + case BBB_LOWER: m_iVal <<= 0; break; + + case BBB_INVALID: return false; + } + + assemble_D_from_P_table(BITSn(word0,0x0020), BITSn(word0,0x001f), dString); + + if (dString.compare("!!") == 0) + return false; + + switch(BITSn(word1,0x1f00)) + { + case 0x12: m_opcode = "bfchg"; break; + case 0x04: m_opcode = "bfclr"; break; + case 0x18: m_opcode = "bfset"; break; + case 0x10: m_opcode = "bftsth"; break; + case 0x00: m_opcode = "bftstl"; break; + } + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "#$%x", m_iVal); + retString = m_opcode + " " + std::string(temp) + "," + dString; + // NEW // sprintf(temp, "#$%04x", iVal); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +private: + uint16_t m_iVal; + std::string m_opcode; + std::string dString; +}; + +/* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */ +/* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */ +/* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */ +/* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */ +/* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */ +class BfInstruction_2: public Instruction +{ +public: + BfInstruction_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_opcode = ""; + m_r = iINVALID; + m_iVal = 0x0000; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* Decode the common parts */ + m_iVal = BITSn(word1,0x00ff); + + bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000)); + switch(upperMiddleLower) + { + case BBB_UPPER: m_iVal <<= 8; break; + case BBB_MIDDLE: m_iVal <<= 4; break; + case BBB_LOWER: m_iVal <<= 0; break; + + case BBB_INVALID: return false; + } + + decode_RR_table(BITSn(word0,0x0003), m_r); + + if (m_r == iINVALID) + return false; + + switch(BITSn(word1,0x1f00)) + { + case 0x12: m_opcode = "bfchg"; break; + case 0x04: m_opcode = "bfclr"; break; + case 0x18: m_opcode = "bfset"; break; + case 0x10: m_opcode = "bftsth"; break; + case 0x00: m_opcode = "bftstl"; break; + } + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "#$%x", m_iVal); + std::string source = temp; + + sprintf(temp, "X:(%s)", regIdAsString(m_r).c_str()); + std::string destination = temp; + + retString = m_opcode + " " + source + "," + destination; + // NEW // sprintf(temp, "#$%04x", m_iVal); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_r; + uint16_t m_iVal; + std::string m_opcode; +}; + +/* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */ +/* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */ +/* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */ +/* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */ +/* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ +class BfInstruction_3: public Instruction +{ +public: + BfInstruction_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_opcode = ""; + m_iVal = 0x0000; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* Decode the common parts */ + m_iVal = BITSn(word1,0x00ff); + + bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000)); + switch(upperMiddleLower) + { + case BBB_UPPER: m_iVal <<= 8; break; + case BBB_MIDDLE: m_iVal <<= 4; break; + case BBB_LOWER: m_iVal <<= 0; break; + + case BBB_INVALID: return false; + } + + decode_DDDDD_table(BITSn(word0,0x001f), m_destination); + + if (m_destination == iINVALID) + return false; + + switch(BITSn(word1,0x1f00)) + { + case 0x12: m_opcode = "bfchg"; break; + case 0x04: m_opcode = "bfclr"; break; + case 0x18: m_opcode = "bfset"; break; + case 0x10: m_opcode = "bftsth"; break; + case 0x00: m_opcode = "bftstl"; break; + } + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "#$%x", m_iVal); + std::string source = temp; + + retString = m_opcode + " " + source + "," + regIdAsString(m_destination); + // NEW // sprintf(temp, "#$%04x", m_iVal); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint16_t m_iVal; + std::string m_opcode; +}; + +// Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 //////////////////////// +class Bcc: public Instruction +{ +public: + Bcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = (int16_t)word1; + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "b" + opMnemonicAsString(m_mnem); + // NEW // sprintf(opcode_str, "b.%s", M); + + char temp[32]; + sprintf(temp, ">*+$%x", 2 + m_immediate); + // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (int16_t)word1, (int16_t)word1); + retString = opcode + " " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; + int16_t m_immediate; +}; + +// Bcc : 0010 11cc ccee eeee : A-48 //////////////////////////////////////////// +class Bcc_2: public Instruction +{ +public: + Bcc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_cccc_table(BITSn(word0,0x3c0), m_mnem); + m_immediate = get_6_bit_signed_value(BITSn(word0,0x003f)); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "b" + opMnemonicAsString(m_mnem); + // NEW // sprintf(opcode_str, "b.%s", M); + + char temp[32]; + if (m_immediate >= 0) sprintf(temp, "<*+$%x", m_immediate + 1); + else sprintf(temp, "<*-$%x", 1 - m_immediate - 2); + // NEW // sprintf(temp, "$%04x (%d)", pc + 1 + relativeInt, relativeInt); + + retString = opcode + " " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; + int8_t m_immediate; +}; + +// Bcc : 0000 0111 RR10 cccc : A-48 //////////////////////////////////////////// +class Bcc_3: public Instruction +{ +public: + Bcc_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x00c0), m_destination); + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "b" + opMnemonicAsString(m_mnem); + retString = opcode + " " + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "b.%s", M); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; +}; + +// BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 //////////////////////// +class Bra: public Instruction +{ +public: + Bra(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = (int16_t)word1; + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, ">*+$%x", 2 + m_immediate); + // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + word1, (int16_t)word1); + retString = "bra " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int16_t m_immediate; +}; + +// BRA : 0000 1011 aaaa aaaa : A-50 //////////////////////////////////////////// +class Bra_2: public Instruction +{ +public: + Bra_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = (int8_t)BITSn(word0,0x00ff); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + if (m_immediate >= 0) sprintf(temp, "<*+$%x", 1 + m_immediate); + else sprintf(temp, "<*-$%x", 1 - m_immediate - 2); + // NEW // sprintf(temp, "$%04x (%d)", pc + 1 + iVal, iVal); + retString = "bra " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_immediate; +}; + +// BRA : 0000 0001 0010 11RR : A-50 //////////////////////////////////////////// +class Bra_3: public Instruction +{ +public: + Bra_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x0003), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "bra " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// BRKcc : 0000 0001 0001 cccc : A-52 ////////////////////////////////////////// +class Brkcc: public Instruction +{ +public: + Brkcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "brk" + opMnemonicAsString(m_mnem); + retString = opcode; + // NEW // sprintf(opcode_str, "brk.%s", M); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; +}; + +// BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 /////////////////////// +class Bscc: public Instruction +{ +public: + Bscc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = (int16_t)word1; + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "bs" + opMnemonicAsString(m_mnem); + // NEW // sprintf(opcode_str, "bs.%s", M); + + char temp[32]; + if (m_immediate >= 0) sprintf(temp, ">*+$%x", 2 + m_immediate); + else sprintf(temp, ">*-$%x", 1 - m_immediate - 1 - 2); + //sprintf(temp, ">*+$%x", 2 + m_immediate); + // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (int16_t)word1, (int16_t)word1); + retString = opcode + " " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } + +private: + op_mnem m_mnem; + int16_t m_immediate; +}; + +// BScc : 0000 0111 RR00 cccc : A-54 /////////////////////////////////////////// +class Bscc_2: public Instruction +{ +public: + Bscc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x00c0), m_destination); + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "bs" + opMnemonicAsString(m_mnem); + retString = opcode + " " + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "bs.%s", M); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } + +private: + op_mnem m_mnem; +}; + +// BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 //////////////////////// +class Bsr: public Instruction +{ +public: + Bsr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = (int16_t)word1; + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + if (m_immediate >= 0) sprintf(temp, ">*+$%x", 2 + m_immediate); + else sprintf(temp, ">*-$%x", 1 - m_immediate - 1 - 2); + // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (int16_t)word1, (int16_t)word1); + retString = "bsr " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } + +private: + int16_t m_immediate; +}; + +// BSR : 0000 0001 0010 10RR : A-56 //////////////////////////////////////////// +class Bsr_2: public Instruction +{ +public: + Bsr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x0003), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "bsr " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } +}; + +// CHKAAU : 0000 0000 0000 0100 : A-58 ///////////////////////////////////////// +class Chkaau: public Instruction +{ +public: + Chkaau(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "chkaau"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// CLR : .... .... 0000 F001 : A-60 //////////////////////////////////////////// +class Clr: public Instruction +{ +public: + Clr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "clr " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// CLR24 : .... .... 0101 F001 : A-62 ////////////////////////////////////////// +class Clr24: public Instruction +{ +public: + Clr24(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "clr24 " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// CMP : .... .... 0101 FJJJ : A-64 //////////////////////////////////////////// +class Cmp: public Instruction +{ +public: + Cmp(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* Note: This is a JJJF limited in the docs, but other opcodes sneak + in before cmp, so the same decode function can be used. */ + decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "cmp " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_NONE; } +}; + +// CMPM : .... .... 0111 FJJJ : A-66 /////////////////////////////////////////// +class Cmpm: public Instruction +{ +public: + Cmpm(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* Note: This is a JJJF limited in the docs, but other opcodes sneak + in before cmp, so the same decode function can be used. */ + decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "cmpm " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_NONE; } +}; + +// DEBUG : 0000 0000 0000 0001 : A-68 ////////////////////////////////////////// +class Debug: public Instruction +{ +public: + Debug(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "debug"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// DEBUGcc : 0000 0000 0101 cccc : A-70 //////////////////////////////////////// +class Debugcc: public Instruction +{ +public: + Debugcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "debug" + opMnemonicAsString(m_mnem); + retString = opcode; + // NEW // sprintf(opcode_str, "debug.%s", M); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; +}; + +// DEC : .... .... 0110 F010 : A-72 //////////////////////////////////////////// +class Dec: public Instruction +{ +public: + Dec(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "dec " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// DEC24 : .... .... 0110 F011 : A-74 ////////////////////////////////////////// +class Dec24: public Instruction +{ +public: + Dec24(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "dec24 " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// DIV : 0001 0101 0--0 F1DD : A-76 //////////////////////////////////////////// +class Div: public Instruction +{ +public: + Div(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_DDF_table(BITSn(word0,0x0003), BITSn(word0,0x0008), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "div " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// DMAC : 0001 0101 10s1 FsQQ : A-80 /////////////////////////////////////////// +class Dmac: public Instruction +{ +public: + Dmac(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + + decode_ss_table(BITSn(word0,0x0024), m_mnem); + if (m_mnem == oINVALID) return false; + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "dmac" + opMnemonicAsString(m_mnem); + + retString = opcode + " " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "dmac(%s)", A); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; + reg_id m_source2; +}; + +// DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 ///////////////////////// +class Do: public Instruction +{ +public: + Do(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = word1; + decode_RR_table(BITSn(word0,0x0003), m_source); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "*+$%x", 2 + m_immediate); + std::string destination = temp; + // NEW // sprintf(temp, "X:(R%d),$%02x", Rnum, pc + 2 + word1); + + sprintf(temp, "X:(%s)", regIdAsString(m_source).c_str()); + std::string source = temp; + + retString = "do " + source + "," + destination; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint16_t m_immediate; +}; + +// DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 ///////////////////////// +class Do_2: public Instruction +{ +public: + Do_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_displacement = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = BITSn(word0,0x00ff); + m_displacement = word1; + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "#<$%x,*+$%x", m_immediate, 2 + m_displacement); + // NEW // sprintf(temp, "#$%02x,$%04x", BITSn(word0,0x00ff), pc + 2 + word1); + retString = "do " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint8_t m_immediate; + uint16_t m_displacement; +}; + +// DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 ///////////////////////// +class Do_3: public Instruction +{ +public: + Do_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_displacement = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_displacement = word1; + + decode_DDDDD_table(BITSn(word0,0x001f), m_source); + if (m_source == iSSH) return false; + if (m_source == iINVALID) return false; + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "*+$%x", 2 + m_displacement); + // NEW // sprintf(temp, "%s,$%04x", S1, pc + 2 + word1); + retString = "do " + regIdAsString(m_source) + "," + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint16_t m_displacement; +}; + +// DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 ///////////////// +class DoForever: public Instruction +{ +public: + DoForever(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_displacement = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_displacement = word1; + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "*+$%x", m_displacement + 2); + // NEW // sprintf(temp, "*+$%x", pc + word1); + // NEW // sprintf(temp, "$%04x", pc + 2 + word1); + retString = "do forever, " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint16_t m_displacement; +}; + +// ENDDO : 0000 0000 0000 1001 : A-92 ////////////////////////////////////////// +class Enddo: public Instruction +{ +public: + Enddo(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "enddo"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// EOR : .... .... 0011 F1JJ : A-94 //////////////////////////////////////////// +class Eor: public Instruction +{ +public: + Eor(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "eor " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// EXT : 0001 0101 0101 F010 : A-96 //////////////////////////////////////////// +class Ext: public Instruction +{ +public: + Ext(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "ext " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ILLEGAL : 0000 0000 0000 1111 : A-98 //////////////////////////////////////// +class Illegal: public Instruction +{ +public: + Illegal(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "illegal"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// IMAC : 0001 0101 1010 FQQQ : A-100 ////////////////////////////////////////// +class Imac: public Instruction +{ +public: + Imac(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "imac " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// IMPY : 0001 0101 1000 FQQQ : A-102 ////////////////////////////////////////// +class Impy: public Instruction +{ +public: + Impy(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "impy " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// INC : .... .... 0010 F010 : A-104 /////////////////////////////////////////// +class Inc: public Instruction +{ +public: + Inc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "inc " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// INC24 : .... .... 0010 F011 : A-106 ///////////////////////////////////////// +class Inc24: public Instruction +{ +public: + Inc24(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "inc24 " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 /////////////////////// +class Jcc: public Instruction +{ +public: + Jcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_displacement = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_displacement = word1; + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "j" + opMnemonicAsString(m_mnem); + // NEW // sprintf(opcode_str, "j.%s", M); + + char temp[32]; + sprintf(temp, ">$%x", m_displacement); + // NEW // sprintf(temp, "$%04x", word1); + retString = opcode + " " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; + uint16_t m_displacement; +}; + +// Jcc : 0000 0110 RR10 cccc : A-108 /////////////////////////////////////////// +class Jcc_2: public Instruction +{ +public: + Jcc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x00c0), m_destination); + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "j" + opMnemonicAsString(m_mnem); + retString = opcode + " " + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "j.%s", M); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; +}; + +// JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 /////////////////////// +class Jmp: public Instruction +{ +public: + Jmp(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_displacement = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_displacement = word1; + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, ">$%x", m_displacement); + // NEW // sprintf(temp, "$%04x", word1); + retString = "jmp " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override + { + PC = m_displacement; + + /* S L E U N Z V C */ + /* - - - - - - - - */ + } + size_t size() const override { return 2; } + size_t evalSize() const override { return 0; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint16_t m_displacement; +}; + +// JMP : 0000 0001 0010 01RR : A-110 /////////////////////////////////////////// +class Jmp_2: public Instruction +{ +public: + Jmp_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x0003), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "jmp " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override + { + PC = regValue16(cpustate, m_destination); + + /* S L E U N Z V C */ + /* - - - - - - - - */ + } + size_t size() const override { return 1; } + size_t evalSize() const override { return 0; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +//static Jmp_2* JMP2 = new Jmp_2(nullptr, 0x0000, 0x0000); + +// JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 ////////////////////// +class Jscc: public Instruction +{ +public: + Jscc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_displacement = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_displacement = word1; + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "js" + opMnemonicAsString(m_mnem); + // NEW // sprintf(opcode_str, "js.%s", M); + + char temp[32]; + sprintf(temp, ">$%x", m_displacement); + // NEW // sprintf(temp, "$%04x", word1); + retString = opcode + " " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } + +private: + op_mnem m_mnem; + uint16_t m_displacement; +}; + +// JScc : 0000 0110 RR00 cccc : A-112 ////////////////////////////////////////// +class Jscc_2: public Instruction +{ +public: + Jscc_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x00c0), m_destination); + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "js" + opMnemonicAsString(m_mnem); + retString = opcode + " " + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "js.%s", M); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } + +private: + op_mnem m_mnem; +}; + +// JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 /////////////////////// +class Jsr: public Instruction +{ +public: + Jsr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_displacement = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_displacement = word1; + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, ">$%x", m_displacement); + // NEW // sprintf(temp, "$%04x", word1); + retString = "jsr " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } + +private: + uint16_t m_displacement; +}; + +// JSR : 0000 1010 AAAA AAAA : A-114 /////////////////////////////////////////// +class Jsr_2: public Instruction +{ +public: + Jsr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_bAddr = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_bAddr = BITSn(word0,0x00ff); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "<$%x", m_bAddr); + // NEW // sprintf(temp, "#$%02x", BITSn(word0,0x00ff)); + retString = "jsr " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } + +private: + uint8_t m_bAddr; +}; + +// JSR : 0000 0001 0010 00RR : A-114 /////////////////////////////////////////// +class Jsr_3: public Instruction +{ +public: + Jsr_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x0003), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "jsr " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OVER; } +}; + +// LEA : 0000 0001 11TT MMRR : A-116 /////////////////////////////////////////// +class Lea: public Instruction +{ +public: + Lea(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_ea = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + if ((word0 & 0x000c) == 0) return false; // NEW TODO // + + decode_TT_table(BITSn(word0,0x0030), m_destination); + + int8_t rNum = BITSn(word0,0x0003); + assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea); + + return true; + } + void disassemble(std::string& retString) const override + { + // HACK + retString = "lea " + m_ea + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + std::string m_ea; +}; + +// LEA : 0000 0001 10NN MMRR : A-116 /////////////////////////////////////////// +class Lea_2: public Instruction +{ +public: + Lea_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + if ((word0 & 0x000c) == 0) return false; // NEW TODO // + + decode_NN_table(BITSn(word0,0x0030), m_destination); + + int8_t rNum = BITSn(word0,0x0003); + assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea); + + return true; + } + void disassemble(std::string& retString) const override + { + // HACK + retString = "lea " + m_ea + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + std::string m_ea; +}; + +// LSL : .... .... 0011 F011 : A-118 /////////////////////////////////////////// +class Lsl: public Instruction +{ +public: + Lsl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "lsl " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// LSR : .... .... 0011 F010 : A-120 /////////////////////////////////////////// +class Lsr: public Instruction +{ +public: + Lsr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "lsr " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// MAC : .... .... 1k10 FQQQ : A-122 /////////////////////////////////////////// +class Mac: public Instruction +{ +public: + Mac(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_sign = ""; + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_source2, m_destination); + + decode_kSign_table(BITSn(word0,0x40), m_sign); + return true; + } + void disassemble(std::string& retString) const override + { + std::string ts = m_sign; + if (ts.compare("-") != 0) ts = ""; + retString = "mac " + + ts + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; + std::string m_sign; +}; + +// MAC : 011m mKKK 1xx0 F1QQ : A-122 /////////////////////////////////////////// +class Mac_2: public Instruction +{ +public: + Mac_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "mac " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// MAC : 0001 0111 RRDD FQQQ : A-122 /////////////////////////////////////////// +class Mac_3: public Instruction +{ +public: + Mac_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "mac " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// MACR : .... .... 1k11 FQQQ : A-124 ////////////////////////////////////////// +class Macr: public Instruction +{ +public: + Macr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_sign = ""; + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_source2, m_destination); + + decode_kSign_table(BITSn(word0,0x40), m_sign); + return true; + } + void disassemble(std::string& retString) const override + { + std::string ts = m_sign; + if (ts.compare("-") != 0) ts = ""; + retString = "macr " + + ts + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + std::string m_sign; + reg_id m_source2; +}; + +// MACR : 011m mKKK 1--1 F1QQ : A-124 ////////////////////////////////////////// +class Macr_2: public Instruction +{ +public: + Macr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "macr " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 //////////////////////////////////// +class Macsuuu: public Instruction +{ +public: + Macsuuu(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + // Special QQF + decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + + decode_s_table(BITSn(word0,0x0004), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "mac" + opMnemonicAsString(m_mnem); + + retString = opcode + " " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "mac(%s)", A); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; + reg_id m_source2; +}; + +// MOVE : .... .... 0001 0001 : A-128 ////////////////////////////////////////// +class Move: public Instruction +{ +public: + Move(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_isNop = false; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + // Equivalent to a NOP (+ parallel move) + + // This insures the debugger matches the reference disassembler + // for the undocumented .... .... 0001 1001 Instruction. + if(BITSn(word0, 0x000f) == 0x0001) + m_destination = iA; + else + m_destination = iB; + + // Hack to match reference disassembler + uint8_t BITSn = (word0 & 0xff00) >> 8; + if (BITSn == 0x4a || BITSn == 0x4b) + m_isNop = true; + + return true; + } + void disassemble(std::string& retString) const override + { + if (m_isNop) + retString = "nop"; + else + retString = "move"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_NONE; } + +private: + bool m_isNop; +}; + +// MOVE : 011m mKKK 0rr1 0000 : A-128 ////////////////////////////////////////// +class Move_2: public Instruction +{ +public: + Move_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + // Amounts to a nop with two parallel moves. + // This insures the debugger matches the reference disassembler + if((word0 & 0x0008) == 0x0008) + m_destination = iB; + else + m_destination = iA; + + return true; + } + void disassemble(std::string& retString) const override + { + retString = "move"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 ////////////////////// +class Move_3: public Instruction +{ +public: + Move_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_b = 0; + m_SD = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_b = BITSn(word0,0x00ff); + m_W = BITSn(word1,0x0100); + decode_HHH_table(BITSn(word1,0x0e00), m_SD); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_reg_from_W_table(m_W, 'X', m_SD, m_b, source, destination); + retString = "move " + source + "," + destination; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_b; + uint8_t m_W; + reg_id m_SD; +}; + +// MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 /////////////////////////////////////// +class Movec: public Instruction +{ +public: + Movec(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + int8_t rNum = BITSn(word0,0x0003); + assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea); + + m_W = BITSn(word0,0x0400); + decode_DDDDD_table(BITSn(word0,0x03e0), m_SD); + if (m_SD == iINVALID) return false; + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination); + retString = "move " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(c)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + reg_id m_SD; + std::string m_ea; +}; + +// MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 /////////////////////////////////////// +class Movec_2: public Instruction +{ +public: + Movec_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + int8_t rNum = BITSn(word0,0x0003); + assemble_ea_from_q_table(BITSn(word0,0x0008), rNum, m_ea); + + decode_DDDDD_table(BITSn(word0,0x03e0), m_SD); + m_W = BITSn(word0,0x0400); + if (m_SD == iINVALID) return false; + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination); + retString = "move " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(c)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + reg_id m_SD; + std::string m_ea; +}; + +// MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 /////////////////////////////////////// +class Movec_3: public Instruction +{ +public: + Movec_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_Z_table(BITSn(word0,0x0008), m_ea); + + decode_DDDDD_table(BITSn(word0,0x03e0), m_SD); + m_W = BITSn(word0,0x0400); + if (m_SD == iINVALID) return false; + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination); + retString = "move " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(c)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + reg_id m_SD; + std::string m_ea; +}; + +// MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 /////////////////// +class Movec_4: public Instruction +{ +public: + Movec_4(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_t = 0; + m_W = 0; + m_sd = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_value = word1; + m_t = BITSn(word0,0x0008); + m_W = BITSn(word0,0x0400); + + decode_DDDDD_table(BITSn(word0,0x03e0), m_sd); + if (m_sd == iINVALID) return false; + + // TODO: Figure out what this means, exactly. + if ((word0 & 0x000c) == 0x000c && (word0 & 0x0400) == 0x0000) + return false; + + return true; + } + void disassemble(std::string& retString) const override + { + std::string ea; + assemble_ea_from_t_table(m_t, m_value, ea); + + retString = "move "; + if (m_W) retString += ea + "," + regIdAsString(m_sd); + else retString += regIdAsString(m_sd) + "," + ea; + // NEW // sprintf(opcode_str, "move(c)"); + } + void evaluate(dsp56156_core* cpustate) override + { + if (m_W) + { + if (m_t) + { + setReg16(cpustate, m_value, m_sd); + } + else + { + //uint16_t memValue = memory_read_word_16le(cpustate->data, ADDRESS(m_value)); + //setReg16(cpustate, memValue, m_sd); + } + } + else + { + if (m_t) + { + osd_printf_error("DSP561xx|Movec_4: This sure seems like it can't happen."); + } + else + { + //uint16_t regValue = regValue16(cpustate, m_sd); + //memory_write_word_16le(cpustate->data, m_value, regValue); + } + } + + /* S L E U N Z V C */ + /* * ? ? ? ? ? ? ? */ + // All ? bits - If SR is specified as a destination operand, set according to the corresponding + // bit of the source operand. If SR is not specified as a destination operand, L is set if data + // limiting occurred. All ? bits are not affected otherwise. + } + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint8_t m_t; + uint8_t m_W; + uint16_t m_value; + reg_id m_sd; +}; + +// MOVE(C) : 0010 10dd dddD DDDD : A-144 /////////////////////////////////////// +class Movec_5: public Instruction +{ +public: + Movec_5(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_DDDDD_table(BITSn(word0,0x03e0), m_source); + decode_DDDDD_table(BITSn(word0,0x001f), m_destination); + + if (m_source == iINVALID || m_destination == iINVALID) return false; + if (m_source == iSSH && m_destination == iSSH) return false; + return true; + } + void disassemble(std::string& retString) const override + { + retString = "move " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "move(c)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 /////////////////// +class Movec_6: public Instruction +{ +public: + Movec_6(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_b = 0; + m_SD = iINVALID; + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_b = BITSn(word0,0x00ff); + m_W = BITSn(word1,0x0400); + decode_DDDDD_table(BITSn(word1,0x03e0), m_SD); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_reg_from_W_table(m_W, 'X', m_SD, m_b, source, destination); + retString = "move " + source + "," + destination; + // NEW // opcode = "move(c)"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_b; + uint8_t m_W; + reg_id m_SD; + op_mnem m_mnem; +}; + +// MOVE(I) : 0010 00DD BBBB BBBB : A-150 /////////////////////////////////////// +class Movei: public Instruction +{ +public: + Movei(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = (int8_t)BITSn(word0,0x00ff); + decode_DD_table(BITSn(word0,0x0300), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + if (m_immediate >= 0) sprintf(temp, "#<+$%x", m_immediate); + else sprintf(temp, "#<-$%x", 1 - m_immediate - 1); + // NEW // sprintf(temp, "#$%02x,%s", BITSn(word0,0x00ff), D1); + + retString = "move " + + std::string(temp) + "," + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "move(i)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_immediate; +}; + +// MOVE(M) : 0000 001W RR0M MHHH : A-152 /////////////////////////////////////// +class Movem: public Instruction +{ +public: + Movem(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + int8_t rNum = BITSn(word0,0x00c0); + + decode_HHH_table(BITSn(word0,0x0007), m_SD); + assemble_ea_from_MM_table(BITSn(word0,0x0018), rNum, m_ea); + m_W = BITSn(word0,0x0100); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_arguments_from_W_table(m_W, 'P', m_SD, m_ea, source, destination); + retString = "move " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(m)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + reg_id m_SD; + std::string m_ea; +}; + +// MOVE(M) : 0000 001W RR11 mmRR : A-152 /////////////////////////////////////// +class Movem_2: public Instruction +{ +public: + Movem_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_ea2 = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_W = BITSn(word0,0x0100); + assemble_eas_from_mm_table(BITSn(word0,0x000c), BITSn(word0,0x00c0), BITSn(word0,0x0003), m_ea, m_ea2); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + if (m_W) + { + source = "X:" + m_ea; + destination = "P:" + m_ea2; + } + else + { + source = "P:" + m_ea; + destination = "X:" + m_ea2; + } + retString = "move " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(m)*"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint8_t m_W; + std::string m_ea; + std::string m_ea2; +}; + +// MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 /////////////////// +class Movem_3: public Instruction +{ +public: + Movem_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_b = 0; + m_SD = iINVALID; + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_b = BITSn(word0,0x00ff); + m_W = BITSn(word1,0x0100); + decode_HHH_table(BITSn(word1,0x0007), m_SD); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_reg_from_W_table(m_W, 'P', m_SD, m_b, source, destination); + retString = "move " + source + "," + destination; + // NEW // opcode = "move(m)"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 2; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_b; + uint8_t m_W; + reg_id m_SD; + op_mnem m_mnem; +}; + +// MOVE(P) : 0001 100W HH1p pppp : A-156 /////////////////////////////////////// +class Movep: public Instruction +{ +public: + Movep(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_HH_table(BITSn(word0,0x00c0), m_SD); + + assemble_address_from_IO_short_address(BITSn(word0,0x001f), m_ea); + m_ea = "<<$" + m_ea; + + m_W = BITSn(word0,0x0100); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination); + retString = "movep " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(p)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + reg_id m_SD; + std::string m_ea; +}; + +// MOVE(P) : 0000 110W RRmp pppp : A-156 /////////////////////////////////////// +class Movep_2: public Instruction +{ +public: + Movep_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + int8_t rNum = BITSn(word0,0x00c0); + + assemble_ea_from_m_table(BITSn(word0,0x0020), rNum, m_ea); + + std::string fullAddy; /* Convert Short Absolute Address to full 16-bit */ + assemble_address_from_IO_short_address(BITSn(word0,0x001f), fullAddy); + + m_W = BITSn(word0,0x0100); + m_SD = "X:<<$" + fullAddy; + // NEW // sprintf(SD, "X:$%s", fullAddy); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination); + retString = "movep " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(p)*"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + std::string m_SD; + std::string m_ea; +}; + +// MOVE(S) : 0001 100W HH0a aaaa : A-158 /////////////////////////////////////// +class Moves: public Instruction +{ +public: + Moves(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_HH_table(BITSn(word0,0x00c0), m_SD); + + char temp[32]; + sprintf(temp, "<$%x", BITSn(word0,0x001f)); + m_ea = temp; + + m_W = BITSn(word0,0x0100); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source; + std::string destination; + assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination); + retString = "moves " + source + "," + destination; + // NEW // sprintf(opcode_str, "move(s)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + reg_id m_SD; + std::string m_ea; +}; + +// MPY : .... .... 1k00 FQQQ : A-160 /////////////////////////////////////////// +class Mpy: public Instruction +{ +public: + Mpy(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_sign = ""; + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* There are inconsistencies with the S1 & S2 operand ordering in the docs, + but since it's a multiply it doesn't matter */ + decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_source2, m_destination); + + decode_kSign_table(BITSn(word0,0x40), m_sign); + return true; + } + void disassemble(std::string& retString) const override + { + std::string ts = m_sign; + if (ts.compare("-")!=0) ts = ""; + retString = "mpy " + + ts + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + std::string m_sign; + reg_id m_source2; +}; + +// MPY : 011m mKKK 1xx0 F0QQ : A-160 /////////////////////////////////////////// +class Mpy_2: public Instruction +{ +public: + Mpy_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "mpy " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// MPY : 0001 0110 RRDD FQQQ : A-160 /////////////////////////////////////////// +class Mpy_3: public Instruction +{ +public: + Mpy_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "mpy " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// MPYR : .... .... 1k01 FQQQ : A-162 ////////////////////////////////////////// +class Mpyr: public Instruction +{ +public: + Mpyr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_sign = "-"; + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* There are inconsistencies with the S1 & S2 operand ordering in the docs, + but since it's a multiply it doesn't matter */ + decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_source2, m_destination); + + decode_kSign_table(BITSn(word0,0x40), m_sign); + return true; + } + void disassemble(std::string& retString) const override + { + std::string ts = m_sign; + if (ts.compare("-") != 0) ts = ""; + retString = "mpyr " + + ts + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + std::string m_sign; + reg_id m_source2; +}; + +// MPYR : 011m mKKK 1--1 F0QQ : A-162 ////////////////////////////////////////// +class Mpyr_2: public Instruction +{ +public: + Mpyr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08), + m_source, m_source2, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "mpyr " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 //////////////////////////////////// +class Mpysuuu: public Instruction +{ +public: + Mpysuuu(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + + decode_s_table(BITSn(word0,0x0004), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "mpy" + opMnemonicAsString(m_mnem); + + retString = opcode + " " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "mpy(%s)", A); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; + reg_id m_source2; +}; + +// NEG : .... .... 0110 F000 : A-166 /////////////////////////////////////////// +class Neg: public Instruction +{ +public: + Neg(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "neg " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// NEGC : 0001 0101 0110 F000 : A-168 ////////////////////////////////////////// +class Negc: public Instruction +{ +public: + Negc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "negc " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// NOP : 0000 0000 0000 0000 : A-170 /////////////////////////////////////////// +class Nop: public Instruction +{ +public: + Nop(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "nop"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// NORM : 0001 0101 0010 F0RR : A-172 ////////////////////////////////////////// +class Norm: public Instruction +{ +public: + Norm(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + + decode_RR_table(BITSn(word0,0x0003), m_source); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "norm " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// NOT : .... .... 0110 F001 : A-174 /////////////////////////////////////////// +class Not: public Instruction +{ +public: + Not(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "not " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// OR : .... .... 0010 F1JJ : A-176 //////////////////////////////////////////// +class Or: public Instruction +{ +public: + Or(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "or " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// ORI : 0001 1EE1 iiii iiii : A-178 /////////////////////////////////////////// +class Ori: public Instruction +{ +public: + Ori(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = BITSn(word0,0x00ff); + decode_EE_table(BITSn(word0,0x0600), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "#$%x", m_immediate); + // NEW // sprintf(temp, "#$%02x", BITSn(word0,0x00ff)); + retString = "ori " + std::string(temp) + "," + regIdAsString(m_destination); + // NEW // sprintf(opcode_str, "or(i)"); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint8_t m_immediate; +}; + +// REP : 0000 0000 111- --RR : A-180 /////////////////////////////////////////// +class Rep: public Instruction +{ +public: + Rep(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_RR_table(BITSn(word0,0x0003), m_source); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "X:(%s)", regIdAsString(m_source).c_str()); + retString = "rep " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// REP : 0000 1111 iiii iiii : A-180 /////////////////////////////////////////// +class Rep_2: public Instruction +{ +public: + Rep_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_immediate = 0; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + m_immediate = BITSn(word0,0x00ff); + return true; + } + void disassemble(std::string& retString) const override + { + char temp[32]; + sprintf(temp, "#$%x", m_immediate); + // NEW // sprintf(temp, "#$%02x (%d)", BITSn(word0,0x00ff), BITSn(word0,0x00ff)); + retString = "rep " + std::string(temp); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + uint8_t m_immediate; +}; + +// REP : 0000 0100 001D DDDD : A-180 /////////////////////////////////////////// +class Rep_3: public Instruction +{ +public: + Rep_3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_DDDDD_table(BITSn(word0,0x001f), m_source); + if (m_source == iINVALID) return false; + return true; + } + void disassemble(std::string& retString) const override + { + retString = "rep " + regIdAsString(m_source); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// REPcc : 0000 0001 0101 cccc : A-184 ///////////////////////////////////////// +class Repcc: public Instruction +{ +public: + Repcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_cccc_table(BITSn(word0,0x000f), m_mnem); + return true; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "rep" + opMnemonicAsString(m_mnem); + retString = opcode; + // NEW // sprintf(opcode_str, "rep.%s", M); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; +}; + +// RESET : 0000 0000 0000 1000 : A-186 ///////////////////////////////////////// +class Reset: public Instruction +{ +public: + Reset(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "reset"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// RND : .... .... 0010 F000 : A-188 /////////////////////////////////////////// +class Rnd: public Instruction +{ +public: + Rnd(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "rnd " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ROL : .... .... 0111 F011 : A-190 /////////////////////////////////////////// +class Rol: public Instruction +{ +public: + Rol(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "rol " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// ROR : .... .... 0111 F010 : A-192 /////////////////////////////////////////// +class Ror: public Instruction +{ +public: + Ror(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "ror " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE; } +}; + +// RTI : 0000 0000 0000 0111 : A-194 /////////////////////////////////////////// +class Rti: public Instruction +{ +public: + Rti(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "rti"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OUT; } +}; + +// RTS : 0000 0000 0000 0110 : A-196 /////////////////////////////////////////// +class Rts: public Instruction +{ +public: + Rts(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "rts"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + size_t flags() const override { return util::disasm_interface::STEP_OUT; } +}; + +// SBC : .... .... 0101 F01J : A-198 /////////////////////////////////////////// +class Sbc: public Instruction +{ +public: + Sbc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JF_table(BITSn(word0,0x01), BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "sbc " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// STOP : 0000 0000 0000 1010 : A-200 ////////////////////////////////////////// +class Stop: public Instruction +{ +public: + Stop(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "stop"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// SUB : .... .... 0100 FJJJ : A-202 /////////////////////////////////////////// +class Sub: public Instruction +{ +public: + Sub(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "sub " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// SUB : 011m mKKK 0rru Fuuu : A-202 /////////////////////////////////////////// +class Sub_2: public Instruction +{ +public: + Sub_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_opcode = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_uuuuF_table(BITSn(word0,0x17), BITSn(word0,0x08), + m_opcode, m_source, m_destination); + + // TODO // m_opcode = "sub"; + return true; + } + void disassemble(std::string& retString) const override + { + retString = m_opcode + " " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + std::string m_opcode; +}; + +// SUBL : .... .... 0100 F001 : A-204 ////////////////////////////////////////// +class Subl: public Instruction +{ +public: + Subl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + /* There is only one option for the F table. This is a very strange opcode. */ + if (!BITSn(word0,0x0008)) + { + m_source = iB; + m_destination = iA; + } + else + { + m_source = iA; + m_destination = iB; + } + return true; + } + void disassemble(std::string& retString) const override + { + retString = "subl " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// SWAP : 0001 0101 0111 F001 : A-206 ////////////////////////////////////////// +class Swap: public Instruction +{ +public: + Swap(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "swap " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// SWI : 0000 0000 0000 0101 : A-208 /////////////////////////////////////////// +class Swi: public Instruction +{ +public: + Swi(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "swi"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// Tcc : 0001 00cc ccTT Fh0h : A-210 /////////////////////////////////////////// +class Tcc: public Instruction +{ +public: + Tcc(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_mnem = oINVALID; + m_destination2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_h0hF_table(BITSn(word0,0x0007),BITSn(word0,0x0008), + m_source, m_destination); + + decode_RR_table(BITSn(word0,0x0030), m_destination2); + + decode_cccc_table(BITSn(word0,0x03c0), m_mnem); + if (m_source != m_destination) + return true; + if (m_destination2 != iR0) + return true; + + return false; + } + void disassemble(std::string& retString) const override + { + std::string opcode = "t" + opMnemonicAsString(m_mnem); + // NEW // sprintf(opcode_str, "t.%s", M); + + retString = opcode; + if (m_source != m_destination) + retString += std::string(" ") + regIdAsString(m_source) + "," + regIdAsString(m_destination); + + if (m_destination2 != iR0) + retString += std::string(" R0,") + regIdAsString(m_destination2); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + op_mnem m_mnem; + reg_id m_destination2; +}; + +// TFR : .... .... 0001 FJJJ : A-212 /////////////////////////////////////////// +class Tfr: public Instruction +{ +public: + Tfr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "tfr " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// TFR : 011m mKKK 0rr1 F0DD : A-212 /////////////////////////////////////////// +class Tfr_2: public Instruction +{ +public: + Tfr_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_DDF_table(BITSn(word0,0x03), BITSn(word0,0x08), + m_source, m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "tfr " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// TFR(2) : 0001 0101 0000 F00J : A-214 //////////////////////////////////////// +class Tfr2: public Instruction +{ +public: + Tfr2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_JF_table(BITSn(word0,0x0001),BITSn(word0,0x0008), + m_destination, m_source); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "tfr2 " + regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// TFR(3) : 0010 01mW RRDD FHHH : A-216 //////////////////////////////////////// +class Tfr3: public Instruction +{ +public: + Tfr3(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_W = 0; + m_ea = ""; + m_SD = iINVALID; + m_source2 = iINVALID; + m_destination2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_DDF_table(BITSn(word0,0x0030), BITSn(word0,0x0008), + m_destination, m_source); + + decode_HHH_table(BITSn(word0,0x0007), m_SD); + // If the destination of the second move is the same as the first, you're invalid + if (m_SD == m_destination && BITSn(word0,0x0100)) return false; + + int8_t rNum = BITSn(word0,0x00c0); + assemble_ea_from_m_table(BITSn(word0,0x0200), rNum, m_ea); + + m_W = BITSn(word0,0x0100); + return true; + } + void disassemble(std::string& retString) const override + { + std::string source2; + std::string destination2; + assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source2, destination2); + retString = "tfr3 " + + regIdAsString(m_source) + "," + regIdAsString(m_destination) + " " + + source2 + "," + destination2; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + int8_t m_W; + reg_id m_SD; + std::string m_ea; + reg_id m_source2; + reg_id m_destination2; +}; + +// TST : .... .... 0010 F001 : A-218 /////////////////////////////////////////// +class Tst: public Instruction +{ +public: + Tst(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x08), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "tst " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_NONE; } +}; + +// TST(2) : 0001 0101 0001 -1DD : A-220 //////////////////////////////////////// +class Tst2: public Instruction +{ +public: + Tst2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_DD_table(BITSn(word0,0x0003), m_source); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "tst2 " + regIdAsString(m_source); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// WAIT : 0000 0000 0000 1011 : A-222 ////////////////////////////////////////// +class Wait: public Instruction +{ +public: + Wait(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + return true; + } + void disassemble(std::string& retString) const override + { + retString = "wait"; + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// ZERO : 0001 0101 0101 F000 : A-224 ////////////////////////////////////////// +class Zero: public Instruction +{ +public: + Zero(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_F_table(BITSn(word0,0x0008), m_destination); + return true; + } + void disassemble(std::string& retString) const override + { + retString = "zero " + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } +}; + +// SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! /////////////////////////////// +class Shfl: public Instruction +{ +public: + Shfl(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + + // This hackery amounts to a very strange QQQF table... + if (m_source == iX0 && m_source2 == iX0) return false; + if (m_source == iX1 && m_source2 == iX0) return false; + + if (m_source == iY0 && m_source2 == iX1) + { + m_source = iX1; + m_source2 = iY0; + } + if (m_source == iY1 && m_source2 == iX1) + { + m_source = iX1; + m_source2 = iY1; + } + return true; + } + void disassemble(std::string& retString) const override + { + retString = "shfl " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +// SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! /////////////////////////////// +class Shfr: public Instruction +{ +public: + Shfr(const Opcode* oco, const uint16_t word0, const uint16_t word1) : Instruction(oco) + { + m_source2 = iINVALID; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008), + m_source, m_source2, m_destination); + + // This hackery amounts to a very strange QQQF table... + if (m_source == iX0 && m_source2 == iX0) return false; + if (m_source == iX1 && m_source2 == iX0) return false; + + if (m_source == iY0 && m_source2 == iX1) + { + m_source = iX1; + m_source2 = iY0; + } + if (m_source == iY1 && m_source2 == iX1) + { + m_source = iX1; + m_source2 = iY1; + } + return true; + } + void disassemble(std::string& retString) const override + { + retString = "shfr " + + regIdAsString(m_source) + "," + + regIdAsString(m_source2) + "," + regIdAsString(m_destination); + } + void evaluate(dsp56156_core* cpustate) override {} + size_t size() const override { return 1; } + size_t accumulatorBitsModified() const override { return BM_HIGH | BM_MIDDLE | BM_LOW; } + +private: + reg_id m_source2; +}; + +} +#endif diff --git a/src/devices/cpu/dsp56156/opcode.cpp b/src/devices/cpu/dsp56156/opcode.cpp new file mode 100644 index 00000000000..15b305fa09e --- /dev/null +++ b/src/devices/cpu/dsp56156/opcode.cpp @@ -0,0 +1,81 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#include "emu.h" +#include <stdio.h> + +#include "opcode.h" + +namespace DSP_56156 +{ +Opcode::Opcode(uint16_t w0, uint16_t w1) : m_word0(w0)/*, m_word1(w1)*/ +{ + m_instruction = Instruction::decodeInstruction(this, w0, w1); + m_parallelMove = ParallelMove::decodeParallelMove(this, w0, w1); +} + + +Opcode::~Opcode() +{ +} + + +std::string Opcode::disassemble() const +{ + // Duck out early if there isn't a valid op + if (!m_instruction) + return dcString(); + + // Duck out if either has had an explicit error. + if (m_instruction && !m_instruction->valid()) + return dcString(); + if (m_parallelMove && !m_parallelMove->valid()) + return dcString(); + + // Disassemble what you can. + std::string opString = ""; + std::string pmString = ""; + if (m_instruction) m_instruction->disassemble(opString); + if (m_parallelMove) m_parallelMove->disassemble(pmString); + + return opString + " " + pmString; +} + + +void Opcode::evaluate(dsp56156_core* cpustate) const +{ + if (m_instruction) m_instruction->evaluate(cpustate); + if (m_parallelMove) m_parallelMove->evaluate(); +} + + +size_t Opcode::size() const +{ + if (m_instruction && m_instruction->valid()) + return m_instruction->size() + m_instruction->sizeIncrement(); + + // Opcode failed to decode, so push it past dc + return 1; +} + +size_t Opcode::evalSize() const +{ + if (m_instruction && m_instruction->valid()) + return m_instruction->evalSize(); // Probably doesn't matter : + m_instruction->sizeIncrement(); + + // Opcode failed to decode, so push it past dc + return 1; +} + + +const reg_id& Opcode::instSource() const { return m_instruction->source(); } +const reg_id& Opcode::instDestination() const { return m_instruction->destination(); } +size_t Opcode::instAccumulatorBitsModified() const { return m_instruction->accumulatorBitsModified(); } + +std::string Opcode::dcString() const +{ + char tempStr[1024]; + sprintf(tempStr, "dc $%x", m_word0); + return std::string(tempStr); +} + +} diff --git a/src/devices/cpu/dsp56156/opcode.h b/src/devices/cpu/dsp56156/opcode.h new file mode 100644 index 00000000000..1044af8f188 --- /dev/null +++ b/src/devices/cpu/dsp56156/opcode.h @@ -0,0 +1,46 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#ifndef DSP56156_OPCODE_H +#define DSP56156_OPCODE_H + +#include "inst.h" +#include "pmove.h" + +#include "dsp56156.h" + +// +// An Opcode contains an instruction and a parallel move operation. +// +namespace DSP_56156 +{ +class Instruction; +class ParallelMove; + +class Opcode +{ +public: + Opcode(uint16_t w0, uint16_t w1); + virtual ~Opcode(); + + std::string disassemble() const; + void evaluate(dsp56156_core* cpustate) const; + size_t size() const; + size_t evalSize() const; + + // Peek through to the instruction + const reg_id& instSource() const; + const reg_id& instDestination() const; + size_t instAccumulatorBitsModified() const; + +private: + std::unique_ptr<Instruction> m_instruction; + std::unique_ptr<ParallelMove> m_parallelMove; + + uint16_t m_word0; + //uint16_t m_word1; + + std::string dcString() const; +}; + +} +#endif diff --git a/src/devices/cpu/dsp56156/pmove.cpp b/src/devices/cpu/dsp56156/pmove.cpp new file mode 100644 index 00000000000..514ed2de972 --- /dev/null +++ b/src/devices/cpu/dsp56156/pmove.cpp @@ -0,0 +1,80 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#include "emu.h" +#include "pmove.h" + +namespace DSP_56156 +{ +const reg_id& ParallelMove::opSource() const { return m_oco->instSource(); } +const reg_id& ParallelMove::opDestination() const { return m_oco->instDestination(); } +size_t ParallelMove::opAccumulatorBitsModified() const { return m_oco->instAccumulatorBitsModified(); } + + +std::unique_ptr<ParallelMove> ParallelMove::decodeParallelMove(const Opcode* opc, const uint16_t word0, const uint16_t word1) +{ + const uint16_t w0 = word0; + const uint16_t w1 = word1; + + /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ + if ((w0 & 0xe000) == 0x6000) + { + return std::make_unique<DualXMemoryDataRead>(opc, w0, w1); + } + /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */ + else if ((w0 & 0xfe00) == 0x1600) + { + return std::make_unique<XMemoryDataWriteAndRegisterDataMove>(opc, w0, w1); + } + else + { + /* 32 General parallel move operations */ + /* Note: It's important that NPDM comes before RtRDM */ + + /* No Parallel Data Move : 0100 1010 .... .... : A-131 */ + if ((w0 & 0xff00) == 0x4a00) + { + return nullptr; + } + /* Register to Register Data Move : 0100 IIII .... .... : A-133 */ + else if ((w0 & 0xf000) == 0x4000) + { + return std::make_unique<RegisterToRegisterDataMove>(opc, w0, w1); + } + /* Address Register Update : 0011 0zRR .... .... : A-135 */ + else if ((w0 & 0xf800) == 0x3000) + { + return std::make_unique<AddressRegisterUpdate>(opc, w0, w1); + } + /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ + else if ((w0 & 0x8000) == 0x8000) + { + return std::make_unique<XMemoryDataMove>(opc, w0, w1); + } + /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ + else if ((w0 & 0xf000) == 0x5000) + { + return std::make_unique<XMemoryDataMove_2>(opc, w0, w1); + } + /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ + else if ((w0 & 0xff00) == 0x0500) + { + // Now check it against all potential double-ups. + // These operations can't have an additional parallel move. + // + // MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 + // MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 + // MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 + // + if (((w1 & 0xfe20) != 0x0200) && + ((w1 & 0xf810) != 0x3800) && + ((w1 & 0x00ff) != 0x0011)) + { + return std::make_unique<XMemoryDataMoveWithShortDisplacement>(opc, w0, w1); + } + } + } + + return nullptr; +} + +} diff --git a/src/devices/cpu/dsp56156/pmove.h b/src/devices/cpu/dsp56156/pmove.h new file mode 100644 index 00000000000..bf5cb2ec34a --- /dev/null +++ b/src/devices/cpu/dsp56156/pmove.h @@ -0,0 +1,335 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#ifndef DSP56156_PMOVE_H +#define DSP56156_PMOVE_H + +#include "opcode.h" +#include "tables.h" + +// +// A ParallelMove Object is what all parallel move classes inherit from. +// +namespace DSP_56156 +{ +class Opcode; + +class ParallelMove +{ +public: + ParallelMove(const Opcode* oco) : m_valid(false), m_oco(oco) { } + virtual ~ParallelMove() {} + + virtual bool decode(const uint16_t word0, const uint16_t word1) = 0; + virtual void disassemble(std::string& retString) const = 0; + virtual void evaluate() = 0; + + static std::unique_ptr<ParallelMove> decodeParallelMove(const Opcode* opc, const uint16_t word0, const uint16_t word1); + + bool valid() const { return m_valid; } + + // Peek through the opcode to see the instruction + const reg_id& opSource() const; + const reg_id& opDestination() const; + size_t opAccumulatorBitsModified() const; + +protected: + bool m_valid; + const Opcode* m_oco; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// PARALLEL MOVES //////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ +class XMemoryDataMove: public ParallelMove +{ +public: + XMemoryDataMove(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + reg_id r; + decode_RR_table(BITSn(word0,0x3000), r); + + reg_id SD; + decode_HHH_table(BITSn(word0,0x0e00), SD); + + std::string ea; + assemble_ea_from_m_table(BITSn(word0,0x4000), regIDAsNum(r), ea); + + assemble_arguments_from_W_table(BITSn(word0,0x0100), 'X', SD, ea, + m_source, m_destination); + + // If the destination of the instruction overlaps with our destination, abort. + if (registerOverlap(opDestination(), opAccumulatorBitsModified(), stringAsRegID(m_destination))) + return false; + + return true; + } + void disassemble(std::string& retString) const override + { + retString = m_source + "," + m_destination; + } + void evaluate() override {} + +private: + std::string m_source; + std::string m_destination; +}; + + +/* X Memory Data Move : 0101 HHHW .... .... : A-137 */ +class XMemoryDataMove_2: public ParallelMove +{ +public: + XMemoryDataMove_2(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + std::string ea; + if (opDestination() == iB) + ea = "(A1)"; + else if (opDestination() == iA) + ea = "(B1)"; + else + ea = "(A1)"; + + reg_id SD; + decode_HHH_table(BITSn(word0,0x0e00), SD); + + assemble_arguments_from_W_table(BITSn(word0,0x0100), 'X', SD, ea, + m_source, m_destination); + + // If the destination of the instruction overlaps with our destination, abort. + if (registerOverlap(opDestination(), opAccumulatorBitsModified(), stringAsRegID(m_destination))) + return false; + + return true; + } + void disassemble(std::string& retString) const override + { + retString = m_source + "," + m_destination; + } + void evaluate() override {} + +private: + std::string m_source; + std::string m_destination; +}; + + +/* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ +class DualXMemoryDataRead: public ParallelMove +{ +public: + DualXMemoryDataRead(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + reg_id r; + reg_id D1; + reg_id D2; + std::string ea1 = ""; + std::string ea2 = ""; + + decode_rr_table(BITSn(word0,0x0060), r); + decode_KKK_table(BITSn(word0,0x0700), D1, D2); + assemble_eas_from_mm_table(BITSn(word0,0x1800), regIDAsNum(r), 3, ea1, ea2); + + /* Not documented, but extrapolated from docs on page A-133 */ + if (D1 == iFHAT) + { + if (opDestination() == iB) + D1 = iA; + else if (opDestination() == iA) + D1 = iB; + else + D1 = iA; /* In the case of no data ALU instruction */ + } + + /* D1 and D2 may not specify the same register : A-142 */ + if (r == iR3) return false; + + char temp[32]; + sprintf(temp, "X:%s,%s", ea1.c_str(), regIdAsString(D1).c_str()); + parallelMove = temp; + sprintf(temp, "X:%s,%s", ea2.c_str(), regIdAsString(D2).c_str()); + parallelMove2 = temp; + + return true; + } + void disassemble(std::string& retString) const override + { + retString = parallelMove + " " + parallelMove2; + } + void evaluate() override {} + +private: + std::string parallelMove; + std::string parallelMove2; +}; + + +/* Register to Register Data Move : 0100 IIII .... .... : A-133 */ +class RegisterToRegisterDataMove: public ParallelMove +{ +public: + RegisterToRegisterDataMove(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco) + { + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + decode_IIIIx_table(BITSn(word0,0x0f00), BITSn(word0,0x0008), + m_source, m_destination); + + if (m_source == iINVALID) + return false; + + if (m_source == iF) + m_source = opDestination(); + + if (m_destination == iFHAT) + { + if (opDestination() == iB) + m_destination = iA; + else if (opDestination() == iA) + m_destination = iB; + else + m_destination = iA; /* In the case of no data ALU instruction */ + } + + // Don't return a failure, just let everything fall through (nop). + //if (m_source == "?" && m_destination == "?") + // return false; + + return true; + } + void disassemble(std::string& retString) const override + { + // (?,?) is a parallel nop + if (m_source == iWEIRD && m_destination == iWEIRD) + retString = ""; + else + retString = regIdAsString(m_source) + "," + regIdAsString(m_destination); + } + void evaluate() override {} + +private: + reg_id m_source; + reg_id m_destination; +}; + + +/* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */ +class XMemoryDataWriteAndRegisterDataMove: public ParallelMove +{ +public: + XMemoryDataWriteAndRegisterDataMove(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco) + { + pms = ""; + pms2 = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + reg_id r; + reg_id S; + reg_id Dnot; + char parallel_move_str[128]; + char parallel_move_str2[128]; + + if (opDestination() == iA) Dnot = iB; + else Dnot = iA; + + // NEW // decode_k_table(BITSn(word0,0x0100), Dnot); + decode_RR_table(BITSn(word0,0x00c0), r); + decode_DD_table(BITSn(word0,0x0030), S); + + sprintf(parallel_move_str, "%s,X:(R%d)+N%d", regIdAsString(Dnot).c_str(), regIDAsNum(r), regIDAsNum(r)); + sprintf(parallel_move_str2, "%s,%s", regIdAsString(S).c_str(), regIdAsString(Dnot).c_str()); + pms = parallel_move_str; + pms2 = parallel_move_str2; + return true; + } + void disassemble(std::string& retString) const override + { + retString = pms + " " + pms2; + } + void evaluate() override {} + +private: + std::string pms; // TODO + std::string pms2; +}; + + +/* Address Register Update : 0011 0zRR .... .... : A-135 */ +class AddressRegisterUpdate: public ParallelMove +{ +public: + AddressRegisterUpdate(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco) + { + m_ea = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + reg_id r; + decode_RR_table(BITSn(word0,0x0300), r); + assemble_ea_from_z_table(BITSn(word0,0x0400), regIDAsNum(r), m_ea); + + return true; + } + void disassemble(std::string& retString) const override + { + retString = m_ea; + } + void evaluate() override {} + +private: + std::string m_ea; +}; + + +/* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ +class XMemoryDataMoveWithShortDisplacement: public ParallelMove +{ +public: + XMemoryDataMoveWithShortDisplacement(const Opcode* oco, const uint16_t word0, const uint16_t word1) : ParallelMove(oco) + { + m_source = ""; + m_destination = ""; + m_valid = decode(word0, word1); + } + bool decode(const uint16_t word0, const uint16_t word1) override + { + int8_t b; + reg_id SD; + b = (char)(word0 & 0x00ff); + decode_HHH_table(BITSn(word1,0x0e00), SD); + assemble_reg_from_W_table(BITSn(word1,0x0100), 'X', SD, b, m_source, m_destination); + + return true; + } + void disassemble(std::string& retString) const override + { + retString = m_source + "," + m_destination; + } + void evaluate() override {} + +private: + std::string m_source; + std::string m_destination; +}; + +} +#endif diff --git a/src/devices/cpu/dsp56156/tables.cpp b/src/devices/cpu/dsp56156/tables.cpp new file mode 100644 index 00000000000..93f591b3a5c --- /dev/null +++ b/src/devices/cpu/dsp56156/tables.cpp @@ -0,0 +1,900 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#include "emu.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "tables.h" +#include "dsp56def.h" + +namespace DSP_56156 +{ +/******************/ +/* Table decoding */ +/******************/ +bfShift decode_BBB_table(uint16_t BBB) +{ + switch(BBB) + { + case 0x4: return BBB_UPPER; + case 0x2: return BBB_MIDDLE; + case 0x1: return BBB_LOWER; + } + + return BBB_INVALID; +} + +void decode_cccc_table(const uint16_t cccc, op_mnem& mnemonic) +{ + switch (cccc) + { + case 0x0: mnemonic = oCC; break; + case 0x1: mnemonic = oGE; break; + case 0x2: mnemonic = oNE; break; + case 0x3: mnemonic = oPL; break; + case 0x4: mnemonic = oNN; break; + case 0x5: mnemonic = oEC; break; + case 0x6: mnemonic = oLC; break; + case 0x7: mnemonic = oGT; break; + case 0x8: mnemonic = oCS; break; + case 0x9: mnemonic = oLT; break; + case 0xa: mnemonic = oEQ; break; + case 0xb: mnemonic = oMI; break; + case 0xc: mnemonic = oNR; break; + case 0xd: mnemonic = oES; break; + case 0xe: mnemonic = oLS; break; + case 0xf: mnemonic = oLE; break; + } + +// NEW // switch (cccc) +// NEW // { +// NEW // case 0x0: sprintf(mnemonic, "cc(hs)"); break; +// NEW // case 0x1: sprintf(mnemonic, "ge "); break; +// NEW // case 0x2: sprintf(mnemonic, "ne "); break; +// NEW // case 0x3: sprintf(mnemonic, "pl "); break; +// NEW // case 0x4: sprintf(mnemonic, "nn "); break; +// NEW // case 0x5: sprintf(mnemonic, "ec "); break; +// NEW // case 0x6: sprintf(mnemonic, "lc "); break; +// NEW // case 0x7: sprintf(mnemonic, "gt "); break; +// NEW // case 0x8: sprintf(mnemonic, "cs(lo)"); break; +// NEW // case 0x9: sprintf(mnemonic, "lt "); break; +// NEW // case 0xa: sprintf(mnemonic, "eq "); break; +// NEW // case 0xb: sprintf(mnemonic, "mi "); break; +// NEW // case 0xc: sprintf(mnemonic, "nr "); break; +// NEW // case 0xd: sprintf(mnemonic, "es "); break; +// NEW // case 0xe: sprintf(mnemonic, "ls "); break; +// NEW // case 0xf: sprintf(mnemonic, "le "); break; +// NEW // } +} + +void decode_DDDDD_table(const uint16_t DDDDD, reg_id& SD) +{ + switch(DDDDD) + { + case 0x00: SD = iX0; break; + case 0x01: SD = iY0; break; + case 0x02: SD = iX1; break; + case 0x03: SD = iY1; break; + case 0x04: SD = iA; break; + case 0x05: SD = iB; break; + case 0x06: SD = iA0; break; + case 0x07: SD = iB0; break; + case 0x08: SD = iLC; break; + case 0x09: SD = iSR; break; + case 0x0a: SD = iOMR; break; + case 0x0b: SD = iSP; break; + case 0x0c: SD = iA1; break; + case 0x0d: SD = iB1; break; + case 0x0e: SD = iA2; break; + case 0x0f: SD = iB2; break; + + case 0x10: SD = iR0; break; + case 0x11: SD = iR1; break; + case 0x12: SD = iR2; break; + case 0x13: SD = iR3; break; + case 0x14: SD = iM0; break; + case 0x15: SD = iM1; break; + case 0x16: SD = iM2; break; + case 0x17: SD = iM3; break; + case 0x18: SD = iSSH; break; + case 0x19: SD = iSSL; break; + case 0x1a: SD = iLA; break; + case 0x1b: SD = iINVALID; break; /* no 0x1b */ + case 0x1c: SD = iN0; break; + case 0x1d: SD = iN1; break; + case 0x1e: SD = iN2; break; + case 0x1f: SD = iN3; break; + } +} + +void decode_DD_table(const uint16_t DD, reg_id& SD) +{ + switch (DD) + { + case 0x0: SD = iX0; break; + case 0x1: SD = iY0; break; + case 0x2: SD = iX1; break; + case 0x3: SD = iY1; break; + } +} + +void decode_DDF_table(const uint16_t DD, const uint16_t F, reg_id& S, reg_id& D) +{ + const uint16_t switchVal = (DD << 1) | F; + + switch (switchVal) + { + case 0x0: S = iX0; D = iA; break; + case 0x1: S = iX0; D = iB; break; + case 0x2: S = iY0; D = iA; break; + case 0x3: S = iY0; D = iB; break; + case 0x4: S = iX1; D = iA; break; + case 0x5: S = iX1; D = iB; break; + case 0x6: S = iY1; D = iA; break; + case 0x7: S = iY1; D = iB; break; + } +} + +void decode_EE_table(const uint16_t EE, reg_id& D) +{ + switch(EE) + { + case 0x1: D = iMR; break; + case 0x3: D = iCCR; break; + case 0x2: D = iOMR; break; + } +} + +void decode_F_table(const uint16_t F, reg_id& SD) +{ + switch(F) + { + case 0x0: SD = iA; break; + case 0x1: SD = iB; break; + } +} + +void decode_h0hF_table(const uint16_t h0h, uint16_t F, reg_id& S, reg_id& D) +{ + const uint16_t switchVal = (h0h << 1) | F; + + switch (switchVal) + { + case 0x8: S = iX0; D = iA; break; + case 0x9: S = iX0; D = iB; break; + case 0xa: S = iY0; D = iA; break; + case 0xb: S = iY0; D = iB; break; + case 0x2: S = iA; D = iA; break; + case 0x1: S = iA; D = iB; break; + case 0x0: S = iB; D = iA; break; + case 0x3: S = iB; D = iB; break; + } +} + +void decode_HH_table(const uint16_t HH, reg_id& SD) +{ + switch(HH) + { + case 0x0: SD = iX0; break; + case 0x1: SD = iY0; break; + case 0x2: SD = iA; break; + case 0x3: SD = iB; break; + } +} + +void decode_HHH_table(const uint16_t HHH, reg_id& SD) +{ + switch(HHH) + { + case 0x0: SD = iX0; break; + case 0x1: SD = iY0; break; + case 0x2: SD = iX1; break; + case 0x3: SD = iY1; break; + case 0x4: SD = iA; break; + case 0x5: SD = iB; break; + case 0x6: SD = iA0; break; + case 0x7: SD = iB0; break; + } +} + +void decode_IIIIx_table(const uint16_t IIII, const uint16_t x, reg_id& S, reg_id& D) +{ + S = D = iINVALID; + switch(IIII) + { + case 0x0: S = iX0; D = iFHAT; break; + case 0x1: S = iY0; D = iFHAT; break; + case 0x2: S = iX1; D = iFHAT; break; + case 0x3: S = iY1; D = iFHAT; break; + case 0x4: S = iA; D = iX0; break; + case 0x5: S = iB; D = iY0; break; + case 0x6: S = iA0; D = iX0; break; + case 0x7: S = iB0; D = iY0; break; + case 0x8: if ( x) S = iF; D = iFHAT; break; + case 0x9: if (!x) S = iF; D = iFHAT; break; + case 0xa: S = iWEIRD; D = iWEIRD; break; + case 0xb: S = iWEIRD; D = iWEIRD; break; + case 0xc: S = iA; D = iX1; break; + case 0xd: S = iB; D = iY1; break; + case 0xe: S = iA0; D = iX1; break; + case 0xf: S = iB0; D = iY1; break; + } +} + +void decode_JJJF_table(const uint16_t JJJ, const uint16_t F, reg_id& S, reg_id& D) +{ + const uint16_t switchVal = (JJJ << 1) | F; + + switch(switchVal) + { + case 0x0: S = iB; D = iA; break; + case 0x1: S = iA; D = iB; break; + case 0x2: S = iINVALID; D = iINVALID; break; + case 0x3: S = iINVALID; D = iINVALID; break; + case 0x4: S = iX; D = iA; break; + case 0x5: S = iX; D = iB; break; + case 0x6: S = iY; D = iA; break; + case 0x7: S = iY; D = iB; break; + case 0x8: S = iX0; D = iA; break; + case 0x9: S = iX0; D = iB; break; + case 0xa: S = iY0; D = iA; break; + case 0xb: S = iY0; D = iB; break; + case 0xc: S = iX1; D = iA; break; + case 0xd: S = iX1; D = iB; break; + case 0xe: S = iY1; D = iA; break; + case 0xf: S = iY1; D = iB; break; + } +} + +void decode_JJF_table(const uint16_t JJ, const uint16_t F, reg_id& S, reg_id& D) +{ + const uint16_t switchVal = (JJ << 1) | F; + + switch (switchVal) + { + case 0x0: S = iX0; D = iA; break; + case 0x1: S = iX0; D = iB; break; + case 0x2: S = iY0; D = iA; break; + case 0x3: S = iY0; D = iB; break; + case 0x4: S = iX1; D = iA; break; + case 0x5: S = iX1; D = iB; break; + case 0x6: S = iY1; D = iA; break; + case 0x7: S = iY1; D = iB; break; + } +} + +void decode_JF_table(const uint16_t J, const uint16_t F, reg_id& S, reg_id& D) +{ + const uint16_t switchVal = (J << 1) | F; + + switch(switchVal) + { + case 0x0: S = iX; D = iA; break; + case 0x1: S = iX; D = iB; break; + case 0x2: S = iY; D = iA; break; + case 0x3: S = iY; D = iB; break; + } +} + +// NEW // void decode_k_table(uint16_t k, char *Dnot) +// NEW // { +// NEW // switch(k) +// NEW // { +// NEW // case 0x0: sprintf(Dnot, "B"); break; +// NEW // case 0x1: sprintf(Dnot, "A"); break; +// NEW // } +// NEW // } + +void decode_kSign_table(const uint16_t k, std::string& plusMinus) +{ + switch(k) + { + case 0x0: plusMinus = "+"; break; + case 0x1: plusMinus = "-"; break; + } +} + +void decode_KKK_table(const uint16_t KKK, reg_id& D1, reg_id& D2) +{ + switch(KKK) + { + case 0x0: D1 = iFHAT; D2 = iX0; break; + case 0x1: D1 = iY0; D2 = iX0; break; + case 0x2: D1 = iX1; D2 = iX0; break; + case 0x3: D1 = iY1; D2 = iX0; break; + case 0x4: D1 = iX0; D2 = iX1; break; + case 0x5: D1 = iY0; D2 = iX1; break; + case 0x6: D1 = iFHAT; D2 = iY0; break; + case 0x7: D1 = iY1; D2 = iX1; break; + } +} + +void decode_NN_table(uint16_t NN, reg_id& ret) +{ + switch(NN) + { + case 0x0: ret = iN0; break; + case 0x1: ret = iN1; break; + case 0x2: ret = iN2; break; + case 0x3: ret = iN3; break; + } +} + +void decode_TT_table(uint16_t TT, reg_id& ret) +{ + switch(TT) + { + case 0x0: ret = iR0; break; + case 0x1: ret = iR1; break; + case 0x2: ret = iR2; break; + case 0x3: ret = iR3; break; + } +} + +void decode_QQF_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D) +{ + const uint16_t switchVal = (QQ << 1) | F; + + switch(switchVal) + { + case 0x0: S1 = iY0; S2 = iX0; D = iA; break; + case 0x1: S1 = iY0; S2 = iX0; D = iB; break; + case 0x2: S1 = iY1; S2 = iX0; D = iA; break; + case 0x3: S1 = iY1; S2 = iX0; D = iB; break; + case 0x4: S1 = iY0; S2 = iX1; D = iA; break; + case 0x5: S1 = iY0; S2 = iX1; D = iB; break; + case 0x6: S1 = iY1; S2 = iX1; D = iA; break; + case 0x7: S1 = iY1; S2 = iX1; D = iB; break; + } +} + +void decode_QQF_special_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D) +{ + const uint16_t switchVal = (QQ << 1) | F; + + switch(switchVal) + { + case 0x0: S1 = iY0; S2 = iX0; D = iA; break; + case 0x1: S1 = iY0; S2 = iX0; D = iB; break; + case 0x2: S1 = iY1; S2 = iX0; D = iA; break; + case 0x3: S1 = iY1; S2 = iX0; D = iB; break; + case 0x4: S1 = iX1; S2 = iY0; D = iA; break; + case 0x5: S1 = iX1; S2 = iY0; D = iB; break; + case 0x6: S1 = iX1; S2 = iY1; D = iA; break; + case 0x7: S1 = iX1; S2 = iY1; D = iB; break; + } +} + +void decode_QQQF_table(const uint16_t QQQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D) +{ + const uint16_t switchVal = (QQQ << 1) | F; + + switch(switchVal) + { + case 0x0: S1 = iX0; S2 = iX0; D = iA; break; + case 0x1: S1 = iX0; S2 = iX0; D = iB; break; + case 0x2: S1 = iX1; S2 = iX0; D = iA; break; + case 0x3: S1 = iX1; S2 = iX0; D = iB; break; + case 0x4: S1 = iA1; S2 = iY0; D = iA; break; + case 0x5: S1 = iA1; S2 = iY0; D = iB; break; + case 0x6: S1 = iB1; S2 = iX0; D = iA; break; + case 0x7: S1 = iB1; S2 = iX0; D = iB; break; + case 0x8: S1 = iY0; S2 = iX0; D = iA; break; + case 0x9: S1 = iY0; S2 = iX0; D = iB; break; + case 0xa: S1 = iY1; S2 = iX0; D = iA; break; + case 0xb: S1 = iY1; S2 = iX0; D = iB; break; + case 0xc: S1 = iY0; S2 = iX1; D = iA; break; + case 0xd: S1 = iY0; S2 = iX1; D = iB; break; + case 0xe: S1 = iY1; S2 = iX1; D = iA; break; + case 0xf: S1 = iY1; S2 = iX1; D = iB; break; + } +} + +void decode_RR_table(uint16_t RR, reg_id& ret) +{ + switch(RR) + { + case 0x0: ret = iR0; break; + case 0x1: ret = iR1; break; + case 0x2: ret = iR2; break; + case 0x3: ret = iR3; break; + } +} + +void decode_rr_table(uint16_t rr, reg_id& ret) +{ + switch(rr) + { + case 0x0: ret = iR0; break; + case 0x1: ret = iR1; break; + case 0x2: ret = iR2; break; + case 0x3: ret = iR3; break; + } +} + +void decode_s_table(const uint16_t s, op_mnem& arithmetic) +{ + switch(s) + { + case 0x0: arithmetic = oSU; break; + case 0x1: arithmetic = oUU; break; + } +} + +void decode_ss_table(const uint16_t ss, op_mnem& arithmetic) +{ + switch(ss) + { + case 0x0: arithmetic = oSS; break; + case 0x1: arithmetic = oINVALID; break; + // NEW // case 0x1: arithmetic = "ss"; break; + case 0x2: arithmetic = oSU; break; + case 0x3: arithmetic = oUU; break; + } +} + +void decode_uuuuF_table(const uint16_t uuuu, const uint16_t F, std::string& arg, reg_id& S, reg_id& D) +{ + const uint16_t switchVal = (uuuu << 1) | F; + + //D = "sub?"; + //S = "add"; + arg = "invalid"; + + switch(switchVal) + { + case 0x00: arg = "add"; S = iX0; D = iA; break; + case 0x01: arg = "add"; S = iX0; D = iB; break; + case 0x02: arg = "add"; S = iY0; D = iA; break; + case 0x03: arg = "add"; S = iY0; D = iB; break; + case 0x04: arg = "add"; S = iX1; D = iA; break; + case 0x05: arg = "add"; S = iX1; D = iB; break; + case 0x06: arg = "add"; S = iY1; D = iA; break; + case 0x07: arg = "add"; S = iY1; D = iB; break; + + case 0x08: arg = "sub"; S = iX0; D = iA; break; + case 0x09: arg = "sub"; S = iX0; D = iB; break; + case 0x0a: arg = "sub"; S = iY0; D = iA; break; + case 0x0b: arg = "sub"; S = iY0; D = iB; break; + case 0x0c: arg = "sub"; S = iX1; D = iA; break; + case 0x0d: arg = "sub"; S = iX1; D = iB; break; + case 0x0e: arg = "sub"; S = iY1; D = iA; break; + case 0x0f: arg = "sub"; S = iY1; D = iB; break; + + case 0x18: arg = "add"; S = iB; D = iA; break; + case 0x19: arg = "add"; S = iA; D = iB; break; + + case 0x1a: arg = "sub"; S = iB; D = iA; break; + case 0x1b: arg = "sub"; S = iA; D = iB; break; + + case 0x1c: arg = "tfr"; S = iB; D = iA; break; + case 0x1d: arg = "tfr"; S = iA; D = iB; break; + + case 0x1e: arg = "move"; S = iINVALID; D = iINVALID; break; + case 0x1f: arg = "move"; S = iINVALID; D = iINVALID; break; + } +} + +void decode_Z_table(const uint16_t Z, std::string& ea) +{ + /* This is fixed as per the Family Manual errata addendum */ + switch(Z) + { + case 0x1: ea = "(A1)"; break; + case 0x0: ea = "(B1)"; break; + } +} + +void assemble_ea_from_m_table(const uint16_t m, const int n, std::string& ea) +{ + char temp[32]; + switch(m) + { + case 0x0: sprintf(temp, "(R%d)+",n) ; break; + case 0x1: sprintf(temp, "(R%d)+N%d", n, n); break; + } + ea = temp; +} + +void assemble_eas_from_mm_table(uint16_t mm, int n1, int n2, std::string& ea1, std::string& ea2) +{ + char temp1[32]; + char temp2[32]; + switch(mm) + { + case 0x0: sprintf(temp1, "(R%d)+", n1) ; + sprintf(temp2, "(R%d)+", n2) ; break; + case 0x1: sprintf(temp1, "(R%d)+", n1) ; + sprintf(temp2, "(R%d)+N%d", n2, n2); break; + case 0x2: sprintf(temp1, "(R%d)+N%d", n1, n1); + sprintf(temp2, "(R%d)+", n2) ; break; + case 0x3: sprintf(temp1, "(R%d)+N%d", n1, n1); + sprintf(temp2, "(R%d)+N%d", n2, n2); break; + } + ea1 = temp1; + ea2 = temp2; +} + +void assemble_ea_from_MM_table(uint16_t MM, int n, std::string& ea) +{ + char temp[32]; + switch(MM) + { + case 0x0: sprintf(temp, "(R%d)", n) ; break; + case 0x1: sprintf(temp, "(R%d)+", n) ; break; + case 0x2: sprintf(temp, "(R%d)-", n) ; break; + case 0x3: sprintf(temp, "(R%d)+N%d", n, n); break; + } + ea = temp; +} + +void assemble_ea_from_q_table(uint16_t q, int n, std::string& ea) +{ + char temp[32]; + switch(q) + { + case 0x0: sprintf(temp, "(R%d+N%d)", n, n); break; + case 0x1: sprintf(temp, "-(R%d)", n) ; break; + } + ea = temp; +} + +void assemble_ea_from_t_table(uint16_t t, uint16_t val, std::string& ea) +{ + char temp[32]; + switch(t) + { + case 0x0: sprintf(temp, "X:>$%x", val); break; + case 0x1: sprintf(temp, "#>$%x", val); break; + // NEW // case 0x0: sprintf(ea, "X:$%04x", val); break; + // NEW // case 0x1: sprintf(ea, "#$%04x", val); break; + } + ea = temp; +} + +void assemble_ea_from_z_table(uint16_t z, int n, std::string& ea) +{ + char temp[32]; + switch(z) + { + case 0x0: sprintf(temp, "(R%d)-", n) ; break; + case 0x1: sprintf(temp, "(R%d)+N%d", n, n); break; + } + ea = temp; +} + +void assemble_D_from_P_table(uint16_t P, uint16_t ppppp, std::string& D) +{ + char temp[32]; + std::string fullAddy; /* Convert Short Absolute Address to full 16-bit */ + + switch(P) + { + case 0x0: + sprintf(temp, "X:<$%x", ppppp); + // NEW // sprintf(temp, "X:$%02x", ppppp); + break; + case 0x1: + assemble_address_from_IO_short_address(ppppp, fullAddy); + sprintf(temp, "X:<<$%s", fullAddy.c_str()); + // NEW // sprintf(temp, "X:$%s", fullAddy.c_str()); + break; + } + D = temp; +} + +void assemble_arguments_from_W_table(uint16_t W, char ma, const reg_id& SD, const std::string& ea, + std::string& source, std::string& destination) +{ + char temp[32]; + sprintf(temp, "%c:%s", ma, ea.c_str()); + switch(W) + { + case 0x0: source = regIdAsString(SD); destination = temp; break; + case 0x1: source = temp; destination = regIdAsString(SD); break; + } +} + +void assemble_arguments_from_W_table(uint16_t W, char ma, const std::string& SD, const std::string& ea, + std::string& source, std::string& destination) +{ + char temp[32]; + sprintf(temp, "%c:%s", ma, ea.c_str()); + switch(W) + { + case 0x0: source = SD; destination = temp; break; + case 0x1: source = temp; destination = SD; break; + } +} + +void assemble_reg_from_W_table(uint16_t W, char ma, const reg_id& SD, const int8_t xx, std::string& S, std::string& D) +{ + uint8_t abs_xx; + char temp[32]; + char operation[32]; + + if(xx < 0) + sprintf(operation,"-"); + else + sprintf(operation,"+"); + + abs_xx = abs(xx); + + sprintf(temp, "%c:(R2%s$%x)", ma, operation, abs_xx); + // NEW // sprintf(temp, "%c:(R2%s$%02x)", ma, operation, abs_xx); + switch(W) + { + case 0x0: S = regIdAsString(SD); D = temp; break; + case 0x1: S = temp; D = regIdAsString(SD); break; + } +} + +void assemble_address_from_IO_short_address(uint16_t pp, std::string& ea) +{ + char temp[32]; + + uint16_t fullAddy = 0xffe0; + fullAddy |= pp; + + sprintf(temp, "%.04x", fullAddy); + ea = temp; +} + +int8_t get_6_bit_signed_value(uint16_t bits) +{ + uint16_t fullAddy = bits; + if (fullAddy & 0x0020) + fullAddy |= 0xffc0; + + return (int8_t)fullAddy; +} + + +/********************/ +/* HELPER FUNCTIONS */ +/********************/ + +uint16_t dsp56156_op_maskn(uint16_t cur, uint16_t mask) +{ + int i; + + uint16_t retVal = (cur & mask); + uint16_t temp = 0x0000; + int offsetCount = 0; + + /* Shift everything right, eliminating 'whitespace'... */ + for (i = 0; i < 16; i++) + { + if (mask & (0x1<<i)) /* If mask bit is non-zero */ + { + temp |= (((retVal >> i) & 0x1) << offsetCount); + offsetCount++; + } + } + + return temp; +} + +bool registerOverlap(const reg_id& r0, const size_t bmd, const reg_id& r1) +{ + if (bmd == BM_NONE) + return false; + + if (r0 == r1) + return true; + + if (r0 == iA && (bmd & BM_LOW) && r1 == iA0) return true; + if (r0 == iA && (bmd & BM_MIDDLE) && r1 == iA1) return true; + if (r0 == iA && (bmd & BM_HIGH) && r1 == iA2) return true; + + if (r0 == iB && (bmd & BM_LOW) && r1 == iB0) return true; + if (r0 == iB && (bmd & BM_MIDDLE) && r1 == iB1) return true; + if (r0 == iB && (bmd & BM_HIGH) && r1 == iB2) return true; + + return false; +} + +uint16_t regValue16(dsp56156_core* cpustate, const reg_id& reg) +{ + if (reg == iX0) return X0; + if (reg == iX1) return X1; + if (reg == iY0) return Y0; + if (reg == iY1) return Y1; + + if (reg == iA0) return A0; + if (reg == iA1) return A1; + if (reg == iB0) return B0; + if (reg == iB1) return B1; + + if (reg == iR0) return R0; + if (reg == iR1) return R1; + if (reg == iR2) return R2; + if (reg == iR3) return R3; + + if (reg == iN0) return N0; + if (reg == iN1) return N1; + if (reg == iN2) return N2; + if (reg == iN3) return N3; + + if (reg == iM0) return M0; + if (reg == iM1) return M1; + if (reg == iM2) return M2; + if (reg == iM3) return M3; + + osd_printf_debug("The dsp561xx core is requesting a 16 bit value from non-16 bit register!"); + return 0xdead; +} + +void setReg16(dsp56156_core* cpustate, const uint16_t& value, const reg_id& reg) +{ + if (reg == iX0) X0 = value; + if (reg == iX1) X1 = value; + if (reg == iY0) Y0 = value; + if (reg == iY1) Y1 = value; + + if (reg == iA0) A0 = value; + if (reg == iA1) A1 = value; + if (reg == iB0) B0 = value; + if (reg == iB1) B1 = value; + + if (reg == iR0) R0 = value; + if (reg == iR1) R1 = value; + if (reg == iR2) R2 = value; + if (reg == iR3) R3 = value; + + if (reg == iN0) N0 = value; + if (reg == iN1) N1 = value; + if (reg == iN2) N2 = value; + if (reg == iN3) N3 = value; + + if (reg == iM0) M0 = value; + if (reg == iM1) M1 = value; + if (reg == iM2) M2 = value; + if (reg == iM3) M3 = value; +} + +std::string regIdAsString(const reg_id& regId) +{ + switch(regId) + { + case iX: return "X"; + case iX0: return "X0"; + case iX1: return "X1"; + case iY: return "Y"; + case iY0: return "Y0"; + case iY1: return "Y1"; + case iA: return "A"; + case iA0: return "A0"; + case iA1: return "A1"; + case iA2: return "A2"; + case iB: return "B"; + case iB0: return "B0"; + case iB1: return "B1"; + case iB2: return "B2"; + case iR0: return "R0"; + case iR1: return "R1"; + case iR2: return "R2"; + case iR3: return "R3"; + case iN0: return "N0"; + case iN1: return "N1"; + case iN2: return "N2"; + case iN3: return "N3"; + case iM0: return "M0"; + case iM1: return "M1"; + case iM2: return "M2"; + case iM3: return "M3"; + case iLC: return "LC"; + case iSR: return "SR"; + case iOMR: return "OMR"; + case iSP: return "SP"; + case iSSH: return "SSH"; + case iSSL: return "SSL"; + case iLA: return "LA"; + case iMR: return "MR"; + case iCCR: return "CCR"; + case iF: return "F"; + case iFHAT: return "^F"; + case iINVALID: return "!!"; + case iWEIRD: return "?"; + } + + return "INVALID_REG_ID"; +} + +std::string opMnemonicAsString(const op_mnem& mnem) +{ + switch(mnem) + { + case oCC: return "cc"; + case oGE: return "ge"; + case oNE: return "ne"; + case oPL: return "pl"; + case oNN: return "nn"; + case oEC: return "ec"; + case oLC: return "lc"; + case oGT: return "gt"; + case oCS: return "cs"; + case oLT: return "lt"; + case oEQ: return "eq"; + case oMI: return "mi"; + case oNR: return "nr"; + case oES: return "es"; + case oLS: return "ls"; + case oLE: return "le"; + + case oSS: return "ss"; + case oSU: return "su"; + case oUU: return "uu"; + case oINVALID: return "!!"; + } + + return "INVALID_OPCODE_MNEMONIC"; +} + +reg_id stringAsRegID(const std::string& str) +{ + if (str.compare("X")==0) return iX; + if (str.compare("X0") == 0) return iX0; + if (str.compare("X1") == 0) return iX1; + if (str.compare("Y") == 0) return iY; + if (str.compare("Y0") == 0) return iY0; + if (str.compare("Y1") == 0) return iY1; + if (str.compare("A") == 0) return iA; + if (str.compare("A0") == 0) return iA0; + if (str.compare("A1") == 0) return iA1; + if (str.compare("A2") == 0) return iA2; + if (str.compare("B") == 0) return iB; + if (str.compare("B0") == 0) return iB0; + if (str.compare("B1") == 0) return iB1; + if (str.compare("B2") == 0) return iB2; + if (str.compare("R0") == 0) return iR0; + if (str.compare("R1") == 0) return iR1; + if (str.compare("R2") == 0) return iR2; + if (str.compare("R3") == 0) return iR3; + if (str.compare("N0") == 0) return iN0; + if (str.compare("N1") == 0) return iN1; + if (str.compare("N2") == 0) return iN2; + if (str.compare("N3") == 0) return iN3; + if (str.compare("M0") == 0) return iM0; + if (str.compare("M1") == 0) return iM1; + if (str.compare("M2") == 0) return iM2; + if (str.compare("M3") == 0) return iM3; + if (str.compare("LC") == 0) return iLC; + if (str.compare("SR") == 0) return iSR; + if (str.compare("OMR") == 0) return iOMR; + if (str.compare("SP") == 0) return iSP; + if (str.compare("SSH") == 0) return iSSH; + if (str.compare("SSL") == 0) return iSSL; + if (str.compare("LA") == 0) return iLA; + if (str.compare("MR") == 0) return iMR; + if (str.compare("CCR") == 0) return iCCR; + if (str.compare("F") == 0) return iF; + if (str.compare("^F") == 0) return iFHAT; + if (str.compare("!!") == 0) return iINVALID; + if (str.compare("?") == 0)return iWEIRD; + + return iINVALID; +} + +uint8_t regIDAsNum(const reg_id& regId) +{ + if (regId == iR0) return 0; + if (regId == iR1) return 1; + if (regId == iR2) return 2; + if (regId == iR3) return 3; + + if (regId == iN0) return 0; + if (regId == iN1) return 1; + if (regId == iN2) return 2; + if (regId == iN3) return 3; + + if (regId == iM0) return 0; + if (regId == iM1) return 1; + if (regId == iM2) return 2; + if (regId == iM3) return 3; + + return 255; +} + +} diff --git a/src/devices/cpu/dsp56156/tables.h b/src/devices/cpu/dsp56156/tables.h new file mode 100644 index 00000000000..9ef1dc76b32 --- /dev/null +++ b/src/devices/cpu/dsp56156/tables.h @@ -0,0 +1,93 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner +#ifndef DSP56156_TABLES_H +#define DSP56156_TABLES_H + +#include <stdio.h> +#include <stdlib.h> + +#include "dsp56156.h" + +namespace DSP_56156 +{ +#define BITSn(CUR,MASK) (dsp56156_op_maskn(CUR,MASK)) + +enum bitsModified {BM_NONE = 0x0, BM_LOW = 0x1, BM_MIDDLE = 0x2, BM_HIGH = 0x4}; + +enum bfShift {BBB_UPPER, BBB_MIDDLE, BBB_LOWER, BBB_INVALID}; +enum reg_id {iX, iX0, iX1, + iY, iY0, iY1, + iA, iA0, iA1, iA2, + iB, iB0, iB1, iB2, + iR0, iR1, iR2, iR3, + iN0, iN1, iN2, iN3, + iM0, iM1, iM2, iM3, + iLC, iSR, iOMR, iSP, iSSH, iSSL, iLA, iMR, iCCR, + iF, iFHAT, + iINVALID, iWEIRD}; + +enum op_mnem {oCC, oGE, oNE, oPL, + oNN, oEC, oLC, oGT, + oCS, oLT, oEQ, oMI, + oNR, oES, oLS, oLE, + oSS, oSU, oUU, oINVALID}; + + +bfShift decode_BBB_table(uint16_t BBB); +void decode_cccc_table(const uint16_t cccc, op_mnem& mnemonic); +void decode_DDDDD_table(const uint16_t DDDDD, reg_id& SD); +void decode_DD_table(const uint16_t DD, reg_id& SD); +void decode_DDF_table(const uint16_t DD, const uint16_t F, reg_id& S, reg_id& D); +void decode_EE_table(const uint16_t EE, reg_id& D); +void decode_F_table(const uint16_t F, reg_id& SD); +void decode_h0hF_table(const uint16_t h0h, uint16_t F, reg_id& S, reg_id& D); +void decode_HH_table(const uint16_t HH, reg_id& SD); +void decode_HHH_table(const uint16_t HHH, reg_id& SD); +void decode_IIIIx_table(const uint16_t IIII, const uint16_t x, reg_id& S, reg_id& D); +void decode_JJJF_table(const uint16_t JJJ, const uint16_t F, reg_id& S, reg_id& D); +void decode_JJF_table(const uint16_t JJ, const uint16_t F, reg_id& S, reg_id& D); +void decode_JF_table(const uint16_t J, const uint16_t F, reg_id& S, reg_id& D); +void decode_kSign_table(const uint16_t k, std::string& plusMinus); +void decode_KKK_table(const uint16_t KKK, reg_id& D1, reg_id& D2); +void decode_NN_table(uint16_t NN, reg_id& ret); +void decode_TT_table(uint16_t TT, reg_id& ret); +void decode_QQF_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D); +void decode_QQF_special_table(const uint16_t QQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D); +void decode_QQQF_table(const uint16_t QQQ, const uint16_t F, reg_id& S1, reg_id& S2, reg_id& D); +void decode_RR_table(uint16_t RR, reg_id& ret); +void decode_rr_table(uint16_t rr, reg_id& ret); +void decode_s_table(const uint16_t s, op_mnem& arithmetic); +void decode_ss_table(const uint16_t ss, op_mnem& arithmetic); +void decode_uuuuF_table(const uint16_t uuuu, const uint16_t F, std::string& arg, reg_id& S, reg_id& D); +void decode_Z_table(const uint16_t Z, std::string& ea); + +void assemble_ea_from_m_table(const uint16_t m, const int n, std::string& ea); +void assemble_eas_from_mm_table(uint16_t mm, int n1, int n2, std::string& ea1, std::string& ea2); +void assemble_ea_from_MM_table(uint16_t MM, int n, std::string& ea); +void assemble_ea_from_q_table(uint16_t q, int n, std::string& ea); +void assemble_ea_from_t_table(uint16_t t, uint16_t val, std::string& ea); +void assemble_ea_from_z_table(uint16_t z, int n, std::string& ea); +void assemble_D_from_P_table(uint16_t P, uint16_t ppppp, std::string& D); +void assemble_arguments_from_W_table(uint16_t W, char ma, const reg_id& SD, const std::string& ea, std::string& S, std::string& D); +void assemble_arguments_from_W_table(uint16_t W, char ma, const std::string& SD, const std::string& ea, std::string& S, std::string& D); +void assemble_reg_from_W_table(uint16_t W, char ma, const reg_id& SD, const int8_t xx, std::string& S, std::string& D); +void assemble_address_from_IO_short_address(uint16_t pp, std::string& ea); + +int8_t get_6_bit_signed_value(uint16_t bits); + +// Helpers +uint16_t dsp56156_op_maskn(uint16_t cur, uint16_t mask); + +bool registerOverlap(const reg_id& r0, const size_t bmd, const reg_id& r1); + +uint16_t regValue16(dsp56156_core* cpustate, const reg_id& reg); +void setReg16(dsp56156_core* cpustate, const uint16_t& value, const reg_id& reg); + +std::string regIdAsString(const reg_id& regId); +std::string opMnemonicAsString(const op_mnem& mnem); +reg_id stringAsRegID(const std::string& str); +uint8_t regIDAsNum(const reg_id& regId); + + +} +#endif |