summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Andrew Gardner <andrew-gardner@users.noreply.github.com>2011-01-25 16:14:13 +0000
committer Andrew Gardner <andrew-gardner@users.noreply.github.com>2011-01-25 16:14:13 +0000
commit512d2af3b4b97533db18e3fab897d4f634e20fac (patch)
treecce77e0a282697a00334d7c7d91be697e796a2a4 /src
parent9cb3b37875fe9ffd5557f944cf83b3f10e8a8296 (diff)
A new WE DSP16A cpu disassembler. [Andrew Gardner]
Notes out of whatsnew.txt * This uses modern devices, but has not been tested in a driver yet, so I may have done something wrong. I will fix it when the time comes. * 60% of the disassembler is complete. I will finish it over the next few days. * There are many similarities in execution to the dsp32, and the existing 32 code will come in handy when it's time to write the execution engine. * This thing is a pleasure compared to the dsp56k.
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/cpu.mak14
-rw-r--r--src/emu/cpu/dsp16/dsp16.c249
-rw-r--r--src/emu/cpu/dsp16/dsp16.h134
-rw-r--r--src/emu/cpu/dsp16/dsp16dis.c475
-rw-r--r--src/mame/mame.mak1
-rw-r--r--src/tools/unidasm.c2
6 files changed, 875 insertions, 0 deletions
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak
index ac2ab0ef3b9..dfa18923bc3 100644
--- a/src/emu/cpu/cpu.mak
+++ b/src/emu/cpu/cpu.mak
@@ -176,6 +176,20 @@ $(CPUOBJ)/apexc/apexc.o: $(CPUSRC)/apexc/apexc.c \
#-------------------------------------------------
+# AT&T DSP16A
+#-------------------------------------------------
+
+ifneq ($(filter DSP16A,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/dsp16
+CPUOBJS += $(CPUOBJ)/dsp16/dsp16.o
+DASMOBJS += $(CPUOBJ)/dsp16/dsp16dis.o
+endif
+
+$(CPUOBJ)/dsp16/dsp16.o: $(CPUSRC)/dsp16/dsp16.c \
+ $(CPUSRC)/dsp16/dsp16.h
+
+
+#-------------------------------------------------
# AT&T DSP32C
#-------------------------------------------------
diff --git a/src/emu/cpu/dsp16/dsp16.c b/src/emu/cpu/dsp16/dsp16.c
new file mode 100644
index 00000000000..3d48a6d855a
--- /dev/null
+++ b/src/emu/cpu/dsp16/dsp16.c
@@ -0,0 +1,249 @@
+/***************************************************************************
+
+ dsp16.h
+
+ WE|AT&T DSP16 series emulator.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "dsp16.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type DSP16 = dsp16_device_config::static_alloc_device_config;
+
+
+
+//**************************************************************************
+// DSP16 DEVICE CONFIG
+//**************************************************************************
+
+dsp16_device_config::dsp16_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
+ : cpu_device_config(mconfig, static_alloc_device_config, "DSP16", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1)
+{ }
+
+
+//-------------------------------------------------
+// static_alloc_device_config - allocate a new
+// configuration object
+//-------------------------------------------------
+
+device_config *dsp16_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
+{
+ return global_alloc(dsp16_device_config(mconfig, tag, owner, clock));
+}
+
+
+//-------------------------------------------------
+// alloc_device - allocate a new device object
+//-------------------------------------------------
+
+device_t *dsp16_device_config::alloc_device(running_machine &machine) const
+{
+ return auto_alloc(&machine, dsp16_device(machine, *this));
+}
+
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp16_device_config::execute_min_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp16_device_config::execute_max_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 dsp16_device_config::execute_input_lines() const
+{
+ return 1; // TODO
+}
+
+
+//-------------------------------------------------
+// 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_config::memory_space_config(int spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config : NULL;
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp16_device_config::disasm_min_opcode_bytes() const
+{
+ return 2;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp16_device_config::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// dsp16_device - constructor
+//-------------------------------------------------
+
+dsp16_device::dsp16_device(running_machine &_machine, const dsp16_device_config &config)
+ : cpu_device(_machine, config),
+ m_pc(0),
+ m_ppc(0),
+ m_icount(0)
+{
+ // Allocate & setup
+}
+
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void dsp16_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ state_save_register_device_item(this, 0, m_pc);
+
+ // register state with the debugger
+ state_add(DSP16_PC, "PC", m_pc);
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void dsp16_device::device_reset()
+{
+ m_pc = m_ppc = 0x0000;
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void dsp16_device::state_import(const device_state_entry &entry)
+{
+
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void dsp16_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ string.printf("");
+}
+
+
+//-------------------------------------------------
+// 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( dsp16 );
+ return CPU_DISASSEMBLE_NAME(dsp16)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+inline UINT32 dsp16_device::program_read(UINT32 addr)
+{
+ return m_program->read_dword(addr << 1);
+}
+
+inline void dsp16_device::program_write(UINT32 addr, UINT32 data)
+{
+ m_program->write_dword(addr << 1, data & 0xffff);
+}
+
+inline UINT32 dsp16_device::opcode_read()
+{
+ return m_direct->read_decrypted_dword(m_pc << 1);
+}
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+void dsp16_device::execute_set_input(int inputnum, int state)
+{
+}
+
+
+void dsp16_device::execute_run()
+{
+ bool check_debugger = ((device_t::m_machine.debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ do
+ {
+ // debugging
+ m_ppc = m_pc; // copy PC to previous PC
+ if (check_debugger)
+ debugger_instruction_hook(this, m_pc);
+
+ // instruction fetch
+ //UINT16 op = opcode_read();
+
+ m_icount--;
+ } while (m_icount > 0);
+}
diff --git a/src/emu/cpu/dsp16/dsp16.h b/src/emu/cpu/dsp16/dsp16.h
new file mode 100644
index 00000000000..e4292d52a15
--- /dev/null
+++ b/src/emu/cpu/dsp16/dsp16.h
@@ -0,0 +1,134 @@
+/***************************************************************************
+
+ dsp16.h
+
+ WE|AT&T DSP16 series emulator.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DSP16_H__
+#define __DSP16_H__
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+//#define MCFG_DSP16_CONFIG(_config)
+// dsp16_device_config::static_set_config(device, _config);
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+extern const device_type DSP16;
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class dsp16_device;
+
+
+// ======================> dsp16_device_config
+
+class dsp16_device_config : public cpu_device_config
+{
+ friend class dsp16_device;
+
+ // construction/destruction
+ dsp16_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+
+public:
+ // allocators
+ static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+ virtual device_t *alloc_device(running_machine &machine) const;
+
+protected:
+ // device_config_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual UINT32 execute_input_lines() const;
+
+ // device_config_memory_interface overrides
+ virtual const address_space_config *memory_space_config(int spacenum = 0) const;
+
+ // device_config_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+
+ // address spaces
+ const address_space_config m_program_config;
+};
+
+
+
+// ======================> dsp16_device
+
+class dsp16_device : public cpu_device
+{
+ friend class dsp16_device_config;
+
+ // construction/destruction
+ dsp16_device(running_machine &_machine, const dsp16_device_config &config);
+
+public:
+ // public interfaces
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_export(const device_state_entry &entry);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_disasm_interface overrides
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+
+
+ // CPU registers
+ UINT16 m_pc;
+
+ // internal stuff
+ UINT16 m_ppc;
+
+ // memory access
+ inline UINT32 program_read(UINT32 addr);
+ inline void program_write(UINT32 addr, UINT32 data);
+ inline UINT32 opcode_read();
+
+ // address spaces
+ address_space* m_program;
+ direct_read_data* m_direct;
+
+ // other internal states
+ int m_icount;
+};
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ DSP16_PC
+};
+
+
+#endif /* __DSP16_H__ */
diff --git a/src/emu/cpu/dsp16/dsp16dis.c b/src/emu/cpu/dsp16/dsp16dis.c
new file mode 100644
index 00000000000..710c22454a7
--- /dev/null
+++ b/src/emu/cpu/dsp16/dsp16dis.c
@@ -0,0 +1,475 @@
+#include "emu.h"
+#include "dsp16.h"
+
+astring disasmF1Field(const UINT8& F1, const UINT8& D, const UINT8& S)
+{
+ astring ret = "";
+ switch (F1)
+ {
+ case 0x00: ret.printf("a%d = p p = x*y", D); break;
+ case 0x01: ret.printf("a%d = a%d + p p = x*y", D, S); break;
+ case 0x02: ret.printf("p = x*y"); break;
+ case 0x03: ret.printf("a%d = a%d - p p = x*y", D, S); break;
+ case 0x04: ret.printf("a$d = p", D); break;
+ case 0x05: ret.printf("a%d = a%d + p", D, S); break;
+ case 0x06: ret.printf("NOP"); break;
+ case 0x07: ret.printf("a%d = a%d - p", D, S); break;
+ case 0x08: ret.printf("a%d = a%d | y", D, S); break;
+ case 0x09: ret.printf("a%d = a%d ^ y", D, S); break;
+ case 0x0a: ret.printf("a%d & y", S); break;
+ case 0x0b: ret.printf("a%d - y", S); break;
+ case 0x0c: ret.printf("a%d = y", D); break;
+ case 0x0d: ret.printf("a%d = a%d + y", D, S); break;
+ case 0x0e: ret.printf("a%d = a%d & y", D, S); break;
+ case 0x0f: ret.printf("a%d = a%d - y", D, S); break;
+
+ default: return "UNKNOWN";
+ }
+ return ret;
+}
+
+astring disasmXField(const UINT8& X)
+{
+ // TODO
+ return "";
+}
+
+astring disasmYField(const UINT8& Y)
+{
+ switch (Y)
+ {
+ case 0x00: return "*r0";
+ case 0x01: return "*r0++";
+ case 0x02: return "*r0--";
+ case 0x03: return "*r0++j";
+
+ case 0x04: return "*r1";
+ case 0x05: return "*r1++";
+ case 0x06: return "*r1--";
+ case 0x07: return "*r1++j";
+
+ case 0x08: return "*r2";
+ case 0x09: return "*r2++";
+ case 0x0a: return "*r2--";
+ case 0x0b: return "*r2++j";
+
+ case 0x0c: return "*r3";
+ case 0x0d: return "*r3++";
+ case 0x0e: return "*r3--";
+ case 0x0f: return "*r3++j";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmZField(const UINT8& Z)
+{
+ switch (Z)
+ {
+ case 0x00: return "*r0zp";
+ case 0x01: return "*r0pz";
+ case 0x02: return "*r0m2";
+ case 0x03: return "*r0jk";
+
+ case 0x04: return "*r1zp";
+ case 0x05: return "*r1pz";
+ case 0x06: return "*r1m2";
+ case 0x07: return "*r1jk";
+
+ case 0x08: return "*r2zp";
+ case 0x09: return "*r2pz";
+ case 0x0a: return "*r2m2";
+ case 0x0b: return "*r2jk";
+
+ case 0x0c: return "*r3zp";
+ case 0x0d: return "*r3pz";
+ case 0x0e: return "*r3m2";
+ case 0x0f: return "*r3jk";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmF2Field(const UINT8& F2, const UINT8& D, const UINT8& S)
+{
+ astring ret = "";
+ switch (F2)
+ {
+ case 0x00: ret.printf("a%d = a%d >> 1", D, S); break;
+ case 0x01: ret.printf("a%d = a%d << 1", D, S); break;
+ case 0x02: ret.printf("a%d = a%d >> 4", D, S); break;
+ case 0x03: ret.printf("a%d = a%d << 4", D, S); break;
+ case 0x04: ret.printf("a%d = a%d >> 8", D, S); break;
+ case 0x05: ret.printf("a%d = a%d << 8", D, S); break;
+ case 0x06: ret.printf("a%d = a%d >> 16", D, S); break;
+ case 0x07: ret.printf("a%d = a%d << 16", D, S); break;
+
+ case 0x08: ret.printf("a%d = p", D); break;
+ case 0x09: ret.printf("a%dh = a%dh + 1", D, S); break;
+ case 0x0a: ret.printf("RESERVED"); break;
+ case 0x0b: ret.printf("a%d = rnd(a%d)", D, S); break;
+ case 0x0c: ret.printf("a%d = y", D); break;
+ case 0x0d: ret.printf("a%d = a%d + 1", D, S); break;
+ case 0x0e: ret.printf("a%d = a%d", D, S); break;
+ case 0x0f: ret.printf("a%d = -a%d", D, S); break;
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmCONField(const UINT8& CON)
+{
+ switch (CON)
+ {
+ case 0x00: return "mi";
+ case 0x01: return "pl";
+ case 0x02: return "eq";
+ case 0x03: return "ne";
+ case 0x04: return "lvs";
+ case 0x05: return "lvc";
+ case 0x06: return "mvs";
+ case 0x07: return "mvc";
+ case 0x08: return "heads";
+ case 0x09: return "tails";
+ case 0x0a: return "c0ge";
+ case 0x0b: return "c0lt";
+ case 0x0c: return "c1ge";
+ case 0x0d: return "c1lt";
+ case 0x0e: return "true";
+ case 0x0f: return "false";
+ case 0x10: return "gt";
+ case 0x11: return "le";
+
+ default: return "RESERVED";
+ }
+ return "";
+}
+
+astring disasmBField(const UINT8& B)
+{
+ switch (B)
+ {
+ case 0x00: return "return";
+ case 0x01: return "ireturn";
+ case 0x02: return "goto pt";
+ case 0x03: return "call pt";
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07: return "RESERVED";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmRImmediateField(const UINT8& R)
+{
+ switch (R)
+ {
+ case 0x00: return "j";
+ case 0x01: return "k";
+ case 0x02: return "rb";
+ case 0x03: return "re";
+ case 0x04: return "r0";
+ case 0x05: return "r1";
+ case 0x06: return "r2";
+ case 0x07: return "r3";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmRField(const UINT8& R)
+{
+ switch (R)
+ {
+ case 0x00: return "r0";
+ case 0x01: return "r1";
+ case 0x02: return "r2";
+ case 0x03: return "r3";
+ case 0x04: return "j";
+ case 0x05: return "k";
+ case 0x06: return "rb";
+ case 0x07: return "re";
+ case 0x08: return "pt";
+ case 0x09: return "pr";
+ case 0x0a: return "pi";
+ case 0x0b: return "i";
+
+ case 0x10: return "x";
+ case 0x11: return "y";
+ case 0x12: return "yl";
+ case 0x13: return "auc";
+ case 0x14: return "psw";
+ case 0x15: return "c0";
+ case 0x16: return "c1";
+ case 0x17: return "c2";
+ case 0x18: return "soic";
+ case 0x19: return "srta";
+ case 0x1a: return "sdx";
+ case 0x1b: return "tdms";
+ case 0x1c: return "pioc";
+ case 0x1d: return "pdx0";
+ case 0x1e: return "pdx1";
+
+ default: return "RESERVED";
+ }
+ return "";
+}
+
+astring disasmIField(const UINT8& I)
+{
+ switch (I)
+ {
+ case 0x00: return "r0/j";
+ case 0x01: return "r1/k";
+ case 0x02: return "r2/rb";
+ case 0x03: return "r3/re";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+bool disasmSIField(const UINT8& SI)
+{
+ switch (SI)
+ {
+ case 0x00: return 0; // Not a software interrupt
+ case 0x01: return 1; // Software Interrupt
+ }
+ return false;
+}
+
+
+/* execute instructions on this CPU until icount expires */
+CPU_DISASSEMBLE( dsp16a )
+{
+ UINT8 opSize = 1;
+ UINT32 dasmflags = 0;
+ UINT16 op = oprom[0] | (oprom[1] << 8);
+ UINT16 op2 = oprom[2] | (oprom[3] << 8);
+
+ // TODO: Test for previous "if CON" instruction and tab the next instruction in?
+
+ const UINT8 opcode = (op >> 11) & 0x1f;
+ switch(opcode)
+ {
+ // Format 1: Multiply/ALU Read/Write Group
+ case 0x06:
+ {
+ // F1, Y
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring f1String = disasmF1Field(F1, D, S);
+ sprintf(buffer, "%s, %s", f1String.cstr(), yString.cstr());
+ opSize = 1;
+ break;
+ }
+ case 0x04: case 0x1c:
+ {
+ // F1 Y=a0[1] | F1 Y=a1[1]
+ // PAGE 3-40 - WIP
+ break;
+ }
+
+ case 0x14: case 0x16:
+ case 0x17: case 0x19:
+ case 0x1b: case 0x1f:
+ {
+ sprintf(buffer, "format 1");
+ break;
+ }
+
+ // Format 1a: Multiply/ALU Read/Write Group (TODO: Seperate)
+ case 0x07:
+ {
+ sprintf(buffer, "format 1a");
+ break;
+ }
+
+ // Format 2: Multiply/ALU Read/Write Group
+ case 0x15: case 0x1d:
+ {
+ sprintf(buffer, "format 2");
+ break;
+ }
+
+ // Format 2a: Multiply/ALU Read/Write Group
+ case 0x05:
+ {
+ sprintf(buffer, "format 2a");
+ break;
+ }
+
+ // Format 3: Special Functions
+ case 0x12:
+ case 0x13:
+ {
+ // if|ifc CON F2
+ const UINT8 CON = (op & 0x001f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F2 = (op & 0x01e0) >> 5;
+ astring f2String = disasmF2Field(F2, D, S);
+ astring conString = disasmCONField(CON);
+ if (op & 0x0800) sprintf(buffer, "if %s : %s", conString.cstr(), f2String.cstr());
+ else sprintf(buffer, "ifc %s : %s", conString.cstr(), f2String.cstr());
+ break;
+ }
+
+ // Format 4: Branch Direct Group
+ case 0x00: case 0x01:
+ case 0x10: case 0x11:
+ {
+ // goto|call JA
+ const UINT16 JA = (op & 0x0fff) | (pc & 0xf000);
+ if (op & 0x8000) sprintf(buffer, "call 0x%04x", JA);
+ else sprintf(buffer, "goto 0x%04x", JA);
+ opSize = 1;
+ break;
+ }
+
+ // Format 5: Branch Indirect Group
+ case 0x18:
+ {
+ // goto B
+ const UINT8 B = (op & 0x0700) >> 8;
+ astring bString = disasmBField(B);
+ sprintf(buffer, "%s", bString.cstr());
+ opSize = 1;
+ break;
+ }
+
+ // Format 6: Contitional Branch Qualifier/Software Interrupt (icall)
+ case 0x1a:
+ {
+ // if CON [goto/call/return]
+ const UINT8 CON = (op & 0x001f);
+ astring conString = disasmCONField(CON);
+ sprintf(buffer, "if %s:", conString.cstr());
+ // TODO: Test for invalid ops
+ // icall
+ if (op == 0xd40e) sprintf(buffer, "icall");
+ opSize = 1;
+ break;
+ }
+
+ // Format 7: Data Move Group
+ case 0x09: case 0x0b:
+ {
+ // R = aS
+ const UINT8 R = (op & 0x03f0) >> 4;
+ const UINT8 S = (op & 0x1000) >> 12;
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", rString.cstr(), (S ? "a1" : "a0"));
+ opSize = 1;
+ break;
+ }
+ case 0x08:
+ {
+ // aT = R
+ const UINT8 R = (op & 0x03f0) >> 4;
+ const UINT8 aT = (op & 0x0400) >> 10;
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", (aT ? "a0" : "a1"), rString.cstr());
+ opSize = 1;
+ break;
+ }
+ case 0x0f:
+ {
+ // R = Y
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring yString = disasmYField(Y);
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", rString.cstr(), yString.cstr());
+ // TODO: Special case the R == [y, y1, or x] case
+ opSize = 1;
+ break;
+ }
+ case 0x0c:
+ {
+ // Y = R
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring yString = disasmYField(Y);
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", yString.cstr(), rString.cstr());
+ opSize = 1;
+ break;
+ }
+ case 0x0d:
+ {
+ // Z : R
+ const UINT8 Z = (op & 0x000f);
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring zString = disasmZField(Z);
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s : %s", zString.cstr(), rString.cstr());
+ opSize = 1;
+ break;
+ }
+
+ // Format 8: Data Move (immediate operand - 2 words)
+ case 0x0a:
+ {
+ // R = N
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = 0x%x", rString.cstr(), op2);
+ opSize = 2;
+ break;
+ }
+
+ // Format 9: Short Immediate Group
+ case 0x02: case 0x03:
+ {
+ // R = M
+ const UINT8 M = (op & 0x00ff);
+ const UINT8 R = (op & 0x0e00) >> 9;
+ astring rString = disasmRImmediateField(R);
+ sprintf(buffer, "%s = 0x%02x", rString.cstr(), M);
+ opSize = 1;
+ break;
+ }
+
+ // Format 10: do - redo
+ case 0x0e:
+ {
+ // do|redo K
+ const UINT8 K = (op & 0x007f);
+ const UINT8 NI = (op & 0x0780) >> 7;
+ sprintf(buffer, "do (next %d inst) %d times", NI, K);
+ // TODO: Limits on K & NI
+ if (NI == 0x00)
+ sprintf(buffer, "redo %d\n", K);
+ opSize = 1;
+ break;
+ }
+
+ // RESERVED
+ case 0x1e:
+ {
+ sprintf(buffer, "RESERVED");
+ break;
+ }
+
+ // UNKNOWN
+ default:
+ {
+ sprintf(buffer, "UNKNOWN");
+ break;
+ }
+ }
+
+ return opSize | dasmflags | DASMFLAG_SUPPORTED;
+}
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index 82ed71b57c0..3f00e21dc57 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -76,6 +76,7 @@ CPUS += ESRIP
CPUS += MIPS
CPUS += SH2
CPUS += SH4
+CPUS += DSP16A
CPUS += DSP32C
CPUS += PIC16C5X
CPUS += PIC16C62X
diff --git a/src/tools/unidasm.c b/src/tools/unidasm.c
index 9ca559c2c59..f6114683c3d 100644
--- a/src/tools/unidasm.c
+++ b/src/tools/unidasm.c
@@ -102,6 +102,7 @@ CPU_DISASSEMBLE( cp1610 );
CPU_DISASSEMBLE( cquestsnd );
CPU_DISASSEMBLE( cquestrot );
CPU_DISASSEMBLE( cquestlin );
+CPU_DISASSEMBLE( dsp16a );
CPU_DISASSEMBLE( dsp32c );
CPU_DISASSEMBLE( dsp56k );
CPU_DISASSEMBLE( hyperstone_generic );
@@ -227,6 +228,7 @@ static const dasm_table_entry dasm_table[] =
{ "cquestsnd", _64be, -3, CPU_DISASSEMBLE_NAME(cquestsnd) },
{ "cquestrot", _64be, -3, CPU_DISASSEMBLE_NAME(cquestrot) },
{ "cquestlin", _64be, -3, CPU_DISASSEMBLE_NAME(cquestlin) },
+ { "dsp16a", _16le, -1, CPU_DISASSEMBLE_NAME(dsp16a) },
{ "dsp32c", _32le, 0, CPU_DISASSEMBLE_NAME(dsp32c) },
{ "dsp56k", _16le, -1, CPU_DISASSEMBLE_NAME(dsp56k) },
{ "hyperstone", _16be, 0, CPU_DISASSEMBLE_NAME(hyperstone_generic) },