summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/dsp16/dsp16.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/dsp16/dsp16.c')
-rw-r--r--src/devices/cpu/dsp16/dsp16.c453
1 files changed, 453 insertions, 0 deletions
diff --git a/src/devices/cpu/dsp16/dsp16.c b/src/devices/cpu/dsp16/dsp16.c
new file mode 100644
index 00000000000..9f1de0c79f6
--- /dev/null
+++ b/src/devices/cpu/dsp16/dsp16.c
@@ -0,0 +1,453 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrew Gardner
+/***************************************************************************
+
+ dsp16.h
+
+ WE|AT&T DSP16 series emulator.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "dsp16.h"
+
+//
+// TODO:
+// * Store the cache in 15 unique memory locations as it is on-chip.
+// * Modify cycle counts when running from within the cache
+// * A write to PI resets the pseudoramdom sequence generator) (page 2-4)
+// * Handle virtual shift addressing using RB & RE (when RE is enabled) (page 2-6)
+// * The ALU sign-extends 32-bit operands from y or p to 36 bits and produces a 36-bit output
+// * Interrupt lines (page 2-15)
+//
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+// device type definition
+const device_type DSP16 = &device_creator<dsp16_device>;
+
+
+//-------------------------------------------------
+// dsp16_device - constructor
+//-------------------------------------------------
+
+dsp16_device::dsp16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, DSP16, "DSP16", tag, owner, clock, "dsp16", __FILE__),
+ m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1),
+ m_data_config("data", ENDIANNESS_LITTLE, 16, 16, -1),
+ m_i(0),
+ m_pc(0),
+ m_pt(0),
+ m_pr(0),
+ m_pi(0),
+ m_j(0),
+ m_k(0),
+ m_rb(0),
+ m_re(0),
+ m_r0(0),
+ m_r1(0),
+ m_r2(0),
+ m_r3(0),
+ m_x(0),
+ m_y(0),
+ m_p(0),
+ m_a0(0),
+ m_a1(0),
+ m_auc(0),
+ m_psw(0),
+ m_c0(0),
+ m_c1(0),
+ m_c2(0),
+ m_sioc(0),
+ m_srta(0),
+ m_sdx(0),
+ m_pioc(0),
+ m_pdx0(0),
+ m_pdx1(0),
+ m_ppc(0),
+ m_cacheStart(CACHE_INVALID),
+ m_cacheEnd(CACHE_INVALID),
+ m_cacheRedoNextPC(CACHE_INVALID),
+ m_cacheIterations(0),
+ m_program(NULL),
+ m_data(NULL),
+ m_direct(NULL),
+ m_icount(0)
+{
+ // Allocate & setup
+}
+
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void dsp16_device::device_start()
+{
+ // register state with the debugger
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ //state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_psw).callimport().callexport().formatstr("%10s").noshow();
+ state_add(DSP16_PC, "PC", m_pc);
+ state_add(DSP16_I, "I", m_i);
+ state_add(DSP16_PT, "PT", m_pt);
+ state_add(DSP16_PR, "PR", m_pr);
+ state_add(DSP16_PI, "PI", m_pi);
+ state_add(DSP16_J, "J", m_j);
+ state_add(DSP16_K, "K", m_k);
+ state_add(DSP16_RB, "RB", m_rb);
+ state_add(DSP16_RE, "RE", m_re);
+ state_add(DSP16_R0, "R0", m_r0);
+ state_add(DSP16_R1, "R1", m_r1);
+ state_add(DSP16_R2, "R2", m_r2);
+ state_add(DSP16_R3, "R3", m_r3);
+ state_add(DSP16_X, "X", m_x);
+ state_add(DSP16_Y, "Y", m_y);
+ state_add(DSP16_P, "P", m_p);
+ state_add(DSP16_A0, "A0", m_a0).mask(U64(0xfffffffff));
+ state_add(DSP16_A1, "A1", m_a1).mask(U64(0xfffffffff));
+ state_add(DSP16_AUC, "AUC", m_auc).formatstr("%8s");
+ state_add(DSP16_PSW, "PSW", m_psw).formatstr("%16s");
+ state_add(DSP16_C0, "C0", m_c0);
+ state_add(DSP16_C1, "C1", m_c1);
+ state_add(DSP16_C2, "C2", m_c2);
+ state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%10s");
+ state_add(DSP16_SRTA, "SRTA", m_srta);
+ state_add(DSP16_SDX, "SDX", m_sdx);
+ state_add(DSP16_PIOC, "PIOC", m_pioc).formatstr("%16s");
+ state_add(DSP16_PDX0, "PDX0", m_pdx0);
+ state_add(DSP16_PDX1, "PDX1", m_pdx1);
+
+ // register our state for saving
+ save_item(NAME(m_i));
+ save_item(NAME(m_pc));
+ save_item(NAME(m_pt));
+ save_item(NAME(m_pr));
+ save_item(NAME(m_pi));
+ save_item(NAME(m_j));
+ save_item(NAME(m_k));
+ save_item(NAME(m_rb));
+ save_item(NAME(m_re));
+ save_item(NAME(m_r0));
+ save_item(NAME(m_r1));
+ save_item(NAME(m_r2));
+ save_item(NAME(m_r3));
+ save_item(NAME(m_x));
+ save_item(NAME(m_y));
+ save_item(NAME(m_p));
+ save_item(NAME(m_a0));
+ save_item(NAME(m_a1));
+ save_item(NAME(m_auc));
+ save_item(NAME(m_psw));
+ save_item(NAME(m_c0));
+ save_item(NAME(m_c1));
+ save_item(NAME(m_c2));
+ save_item(NAME(m_sioc));
+ save_item(NAME(m_srta));
+ save_item(NAME(m_sdx));
+ save_item(NAME(m_pioc));
+ save_item(NAME(m_pdx0));
+ save_item(NAME(m_pdx1));
+ save_item(NAME(m_ppc));
+ save_item(NAME(m_cacheStart));
+ save_item(NAME(m_cacheEnd));
+ save_item(NAME(m_cacheRedoNextPC));
+ save_item(NAME(m_cacheIterations));
+
+ // get our address spaces
+ m_program = &space(AS_PROGRAM);
+ m_data = &space(AS_DATA);
+ m_direct = &m_program->direct();
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void dsp16_device::device_reset()
+{
+ // Page 7-5
+ m_pc = 0x0000;
+ m_pi = 0x0000;
+ m_sioc = 0x0000; // (page 5-4)
+
+ // SRTA is unaltered by reset
+ m_pioc = 0x0008;
+ m_rb = 0x0000;
+ m_re = 0x0000;
+
+ // AUC is not affected by reset
+ m_ppc = m_pc;
+
+ // Hacky cache emulation.
+ m_cacheStart = CACHE_INVALID;
+ m_cacheEnd = CACHE_INVALID;
+ m_cacheRedoNextPC = CACHE_INVALID;
+ m_cacheIterations = 0;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *dsp16_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config :
+ (spacenum == AS_DATA) ? &m_data_config :
+ NULL;
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void dsp16_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "(below)");
+ break;
+
+ case DSP16_AUC:
+ {
+ std::string alignString;
+ const UINT8 align = m_auc & 0x03;
+ switch (align)
+ {
+ case 0x00: strprintf(alignString,"xy"); break;
+ case 0x01: strprintf(alignString,"/4"); break;
+ case 0x02: strprintf(alignString,"x4"); break;
+ case 0x03: strprintf(alignString,",,"); break;
+ }
+ strprintf(str, "%c%c%c%c%c%s",
+ m_auc & 0x40 ? 'Y':'.',
+ m_auc & 0x20 ? '1':'.',
+ m_auc & 0x10 ? '0':'.',
+ m_auc & 0x08 ? '1':'.',
+ m_auc & 0x04 ? '0':'.',
+ alignString.c_str());
+ break;
+ }
+
+ case DSP16_PSW:
+ strprintf(str, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ m_psw & 0x8000 ? 'M':'.',
+ m_psw & 0x4000 ? 'E':'.',
+ m_psw & 0x2000 ? 'L':'.',
+ m_psw & 0x1000 ? 'V':'.',
+ m_psw & 0x0800 ? ',':',',
+ m_psw & 0x0400 ? ',':',',
+ m_psw & 0x0200 ? 'O':'.',
+ m_psw & 0x0100 ? '1':'.',
+ m_psw & 0x0080 ? '1':'.',
+ m_psw & 0x0040 ? '1':'.',
+ m_psw & 0x0020 ? '1':'.',
+ m_psw & 0x0010 ? 'O':'.',
+ m_psw & 0x0008 ? '1':'.',
+ m_psw & 0x0004 ? '1':'.',
+ m_psw & 0x0002 ? '1':'.',
+ m_psw & 0x0001 ? '1':'.');
+ break;
+
+ case DSP16_PIOC:
+ {
+ std::string strobeString;
+ const UINT8 strobe = (m_pioc & 0x6000) >> 13;
+ switch (strobe)
+ {
+ case 0x00: strprintf(strobeString, "1T"); break;
+ case 0x01: strprintf(strobeString, "2T"); break;
+ case 0x02: strprintf(strobeString, "3T"); break;
+ case 0x03: strprintf(strobeString, "4T"); break;
+ }
+ strprintf(str, "%c%s%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ m_pioc & 0x8000 ? 'I':'.',
+ strobeString.c_str(),
+ m_pioc & 0x1000 ? 'O':'I',
+ m_pioc & 0x0800 ? 'O':'I',
+ m_pioc & 0x0400 ? 'S':'.',
+ m_pioc & 0x0200 ? 'I':'.',
+ m_pioc & 0x0100 ? 'O':'.',
+ m_pioc & 0x0080 ? 'P':'.',
+ m_pioc & 0x0040 ? 'P':'.',
+ m_pioc & 0x0020 ? 'I':'.',
+ m_pioc & 0x0010 ? 'I':'.',
+ m_pioc & 0x0008 ? 'O':'.',
+ m_pioc & 0x0004 ? 'P':'.',
+ m_pioc & 0x0002 ? 'P':'.',
+ m_pioc & 0x0001 ? 'I':'.');
+ break;
+ }
+
+ // Placeholder for a better view later (TODO)
+ case DSP16_SIOC:
+ {
+ std::string clkString;
+ const UINT8 clk = (m_sioc & 0x0180) >> 7;
+ switch (clk)
+ {
+ case 0x00: strprintf(clkString, "/4"); break;
+ case 0x01: strprintf(clkString, "12"); break;
+ case 0x02: strprintf(clkString, "16"); break;
+ case 0x03: strprintf(clkString, "20"); break;
+ }
+ strprintf(str, "%c%s%c%c%c%c%c%c%c",
+ m_sioc & 0x0200 ? 'I':'O',
+ clkString.c_str(),
+ m_sioc & 0x0040 ? 'L':'M',
+ m_sioc & 0x0020 ? 'I':'O',
+ m_sioc & 0x0010 ? 'I':'O',
+ m_sioc & 0x0008 ? 'I':'O',
+ m_sioc & 0x0004 ? 'I':'O',
+ m_sioc & 0x0002 ? '2':'1',
+ m_sioc & 0x0001 ? '2':'1');
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp16_device::disasm_min_opcode_bytes() const
+{
+ return 2;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp16_device::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t dsp16_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( dsp16a );
+ return CPU_DISASSEMBLE_NAME(dsp16a)(this, buffer, pc, oprom, opram, options);
+}
+
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+inline UINT32 dsp16_device::data_read(const UINT16& addr)
+{
+ return m_data->read_word(addr << 1);
+}
+
+inline void dsp16_device::data_write(const UINT16& addr, const UINT16& data)
+{
+ m_data->write_word(addr << 1, data & 0xffff);
+}
+
+inline UINT32 dsp16_device::opcode_read(const UINT8 pcOffset)
+{
+ const UINT16 readPC = m_pc + pcOffset;
+ return m_direct->read_dword(readPC << 1);
+}
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp16_device::execute_min_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp16_device::execute_max_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 dsp16_device::execute_input_lines() const
+{
+ return 1;
+}
+
+
+void dsp16_device::execute_set_input(int inputnum, int state)
+{
+ // Only has one external IRQ line
+}
+
+
+void dsp16_device::execute_run()
+{
+ // HACK TO MAKE CPU DO NOTHING.
+ // REMOVE IF DEVELOPING CPU CORE.
+ m_icount = 0;
+ return;
+
+ do
+ {
+ // debugging
+ m_ppc = m_pc; // copy PC to previous PC
+ debugger_instruction_hook(this, m_pc);
+
+ // instruction fetch & execute
+ UINT8 cycles;
+ UINT8 pcAdvance;
+ const UINT16 op = opcode_read();
+ execute_one(op, cycles, pcAdvance);
+
+ // step
+ m_pc += pcAdvance;
+ m_icount -= cycles;
+
+ // The 16 bit PI "shadow" register gets set to PC on each instruction except
+ // when an interrupt service routine is active (TODO: Interrupt check) (page 2-4)
+ m_pi = m_pc;
+
+ } while (m_icount > 0);
+}
+
+#include "dsp16ops.inc"