summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/scmp
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
commitf88cefad27a1737c76e09d99c9fb43e173506081 (patch)
tree2d8167d03579c46e226471747eb4407bd00ed6fa /src/devices/cpu/scmp
parente92ac9e0fa8e99869894bea00589bbb526be30aa (diff)
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/devices/cpu/scmp')
-rw-r--r--src/devices/cpu/scmp/scmp.c566
-rw-r--r--src/devices/cpu/scmp/scmp.h120
-rw-r--r--src/devices/cpu/scmp/scmpdasm.c153
3 files changed, 839 insertions, 0 deletions
diff --git a/src/devices/cpu/scmp/scmp.c b/src/devices/cpu/scmp/scmp.c
new file mode 100644
index 00000000000..edd8502c1c5
--- /dev/null
+++ b/src/devices/cpu/scmp/scmp.c
@@ -0,0 +1,566 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/*****************************************************************************
+ *
+ * scmp.c
+ *
+ * National Semiconductor SC/MP CPU Disassembly
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "scmp.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+const device_type SCMP = &device_creator<scmp_device>;
+const device_type INS8060 = &device_creator<ins8060_device>;
+
+
+scmp_device::scmp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, SCMP, "INS 8050 SC/MP", tag, owner, clock, "ins8050", __FILE__)
+ , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
+ , m_flag_out_func(*this)
+ , m_sout_func(*this)
+ , m_sin_func(*this)
+ , m_sensea_func(*this)
+ , m_senseb_func(*this)
+ , m_halt_func(*this)
+{
+}
+
+
+scmp_device::scmp_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
+ , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
+ , m_flag_out_func(*this)
+ , m_sout_func(*this)
+ , m_sin_func(*this)
+ , m_sensea_func(*this)
+ , m_senseb_func(*this)
+ , m_halt_func(*this)
+{
+}
+
+
+ins8060_device::ins8060_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : scmp_device(mconfig, INS8060, "INS 8060 SC/MP II", tag, owner, clock, "ins8060", __FILE__)
+{
+}
+
+
+offs_t scmp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( scmp );
+ return CPU_DISASSEMBLE_NAME(scmp)(this, buffer, pc, oprom, opram, options);
+}
+
+
+UINT16 scmp_device::ADD12(UINT16 addr, INT8 val)
+{
+ return ((addr + val) & 0x0fff) | (addr & 0xf000);
+}
+
+UINT8 scmp_device::ROP()
+{
+ UINT16 pc = m_PC.w.l;
+ m_PC.w.l = ADD12(m_PC.w.l,1);
+ return m_direct->read_byte( pc);
+}
+
+UINT8 scmp_device::ARG()
+{
+ UINT16 pc = m_PC.w.l;
+ m_PC.w.l = ADD12(m_PC.w.l,1);
+ return m_direct->read_byte(pc);
+}
+
+UINT8 scmp_device::RM(UINT32 a)
+{
+ return m_program->read_byte(a);
+}
+
+void scmp_device::WM(UINT32 a, UINT8 v)
+{
+ m_program->write_byte(a, v);
+}
+
+void scmp_device::illegal(UINT8 opcode)
+{
+#if VERBOSE
+ UINT16 pc = m_PC.w.l;
+ LOG(("SC/MP illegal instruction %04X $%02X\n", pc-1, opcode));
+#endif
+}
+
+PAIR *scmp_device::GET_PTR_REG(int num)
+{
+ switch(num) {
+ case 1: return &m_P1;
+ case 2: return &m_P2;
+ case 3: return &m_P3;
+ default :
+ return &m_PC;
+ }
+}
+
+void scmp_device::BIN_ADD(UINT8 val)
+{
+ UINT16 tmp = m_AC + val + ((m_SR >> 7) & 1);
+ UINT8 ov = (((m_AC & 0x80)==(val & 0x80)) && ((m_AC & 0x80)!=(tmp & 0x80))) ? 0x40 : 0x00;
+
+ m_AC = tmp & 0xff;
+ m_SR &= 0x3f; // clear CY/L and OV flag
+ m_SR |= (tmp & 0x100) ? 0x80 : 0x00; // set CY/L
+ m_SR |= ov;
+}
+
+void scmp_device::DEC_ADD(UINT8 val)
+{
+ UINT16 tmp = m_AC + val + ((m_SR >> 7) & 1);
+ if ((tmp & 0x0f) > 9) tmp +=6;
+ m_AC = tmp % 0xa0;
+ m_SR &= 0x7f; // clear CY/L flag
+ m_SR |= (tmp > 0x99) ? 0x80 : 0x00;
+}
+
+UINT16 scmp_device::GET_ADDR(UINT8 code)
+{
+ UINT16 addr = 0;
+ INT8 offset = 0;
+ UINT16 retVal = 0;
+ UINT16 ptr = GET_PTR_REG(code & 0x03)->w.l;
+
+ UINT8 arg = ARG();
+ if (arg == 0x80) {
+ offset = m_ER;
+ } else {
+ if (arg & 0x80) {
+ offset = (INT8)arg;
+ } else {
+ offset = arg;
+ }
+ }
+
+ addr = ADD12(ptr,offset);
+
+ if (code & 0x04) {
+ if (code & 0x03) {
+ // Auto-indexed
+ if (offset < 0) {
+ // pre decrement
+ GET_PTR_REG(code & 0x03)->w.l = addr;
+ retVal = addr;
+ } else {
+ // post increment
+ retVal = ptr;
+ GET_PTR_REG(code & 0x03)->w.l = addr;
+ }
+ } else {
+ // Immediate
+ }
+ } else {
+ // Indexed
+ retVal = addr;
+ }
+ return retVal;
+}
+
+void scmp_device::execute_one(int opcode)
+{
+ UINT8 tmp;
+ UINT8 ptr = opcode & 3;
+ if (BIT(opcode,7)) {
+ // two bytes instructions
+ switch (opcode)
+ {
+ // Memory Reference Instructions
+ case 0xc0 : case 0xc1 : case 0xc2 : case 0xc3 :
+ case 0xc5 : case 0xc6 : case 0xc7 :
+ //LD
+ m_icount -= 18;
+ m_AC = RM(GET_ADDR(opcode));
+ break;
+ case 0xc8 : case 0xc9 : case 0xca : case 0xcb :
+ case 0xcd : case 0xce : case 0xcf :
+ // ST
+ m_icount -= 18;
+ WM(GET_ADDR(opcode),m_AC);
+ break;
+ case 0xd0 : case 0xd1 : case 0xd2 : case 0xd3 :
+ case 0xd5 : case 0xd6 : case 0xd7 :
+ // AND
+ m_icount -= 18;
+ m_AC &= RM(GET_ADDR(opcode));
+ break;
+ case 0xd8 : case 0xd9 : case 0xda : case 0xdb :
+ case 0xdd : case 0xde : case 0xdf :
+ //OR
+ m_icount -= 18;
+ m_AC |= RM(GET_ADDR(opcode));
+ break;
+ case 0xe0 : case 0xe1 : case 0xe2 : case 0xe3 :
+ case 0xe5 : case 0xe6 : case 0xe7 :
+ // XOR
+ m_icount -= 18;
+ m_AC ^= RM(GET_ADDR(opcode));
+ break;
+ case 0xe8 : case 0xe9 : case 0xea : case 0xeb :
+ case 0xed : case 0xee : case 0xef :
+ // DAD
+ m_icount -= 23;
+ DEC_ADD(RM(GET_ADDR(opcode)));
+ break;
+ case 0xf0 : case 0xf1 : case 0xf2 : case 0xf3 :
+ case 0xf5 : case 0xf6 : case 0xf7 :
+ // ADD
+ m_icount -= 19;
+ BIN_ADD(RM(GET_ADDR(opcode)));
+ break;
+ case 0xf8 : case 0xf9 : case 0xfa : case 0xfb :
+ case 0xfd : case 0xfe : case 0xff :
+ // CAD
+ m_icount -= 20;
+ BIN_ADD(~RM(GET_ADDR(opcode)));
+ break;
+ // Memory Increment/Decrement Instructions
+ case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
+ // IDL
+ {
+ UINT16 addr = GET_ADDR(opcode);
+ m_icount -= 22;
+ m_AC = RM(addr) + 1;
+ WM(addr,m_AC);
+ }
+ break;
+ case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
+ // DLD
+ {
+ UINT16 addr = GET_ADDR(opcode);
+ m_icount -= 22;
+ m_AC = RM(addr) - 1;
+ WM(addr,m_AC);
+ }
+ break;
+ // Immediate Instructions
+ case 0xc4 : // LDI
+ m_icount -= 10;
+ m_AC = ARG();
+ break;
+ case 0xd4 : // ANI
+ m_icount -= 10;
+ m_AC &= ARG();
+ break;
+ case 0xdc : // ORI
+ m_icount -= 10;
+ m_AC |= ARG();
+ break;
+ case 0xe4 : // XRI
+ m_icount -= 10;
+ m_AC ^= ARG();
+ break;
+ case 0xec : // DAI
+ m_icount -= 15;
+ DEC_ADD(ARG());
+ break;
+ case 0xf4 : // ADI
+ m_icount -= 11;
+ BIN_ADD(ARG());
+ break;
+ case 0xfc : // CAI
+ m_icount -= 12;
+ BIN_ADD(~ARG());
+ break;
+ // Transfer Instructions
+ case 0x90 : case 0x91 : case 0x92 : case 0x93 :// JMP
+ m_icount -= 11;
+ m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)ARG());
+ break;
+ case 0x94 : case 0x95 : case 0x96 : case 0x97 :
+ // JP
+ m_icount -= 9;
+ tmp = ARG();
+ if (!(m_AC & 0x80)) {
+ m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)tmp);
+ m_icount -= 2;
+ }
+ break;
+ case 0x98 : case 0x99 : case 0x9a : case 0x9b :
+ // JZ
+ m_icount -= 9;
+ tmp = ARG();
+ if (!m_AC) {
+ m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)tmp);
+ m_icount -= 2;
+ }
+ break;
+ case 0x9c : case 0x9d : case 0x9e : case 0x9f :
+ // JNZ
+ m_icount -= 9;
+ tmp = ARG();
+ if (m_AC) {
+ m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)tmp);
+ m_icount -= 2;
+ }
+ break;
+ // Double-Byte Miscellaneous Instructions
+ case 0x8f: // DLY
+ tmp = ARG();
+ m_icount -= 13 + (m_AC * 2) + (((UINT32)tmp) << 1) + (((UINT32)tmp) << 9);
+ m_AC = 0xff;
+ break;
+ // Others are illegal
+ default : m_icount -= 1;
+ illegal (opcode);
+ break;
+ }
+ } else {
+ // one byte instructions
+ switch (opcode)
+ {
+ // Extension Register Instructions
+ case 0x40: // LDE
+ m_icount -= 6;
+ m_AC = m_ER;
+ break;
+ case 0x01: // XAE
+ m_icount -= 7;
+ tmp = m_AC;
+ m_AC = m_ER;
+ m_ER = tmp;
+ break;
+ case 0x50: // ANE
+ m_icount -= 6;
+ m_AC &= m_ER;
+ break;
+ case 0x58: // ORE
+ m_icount -= 6;
+ m_AC |= m_ER;
+ break;
+ case 0x60: // XRE
+ m_icount -= 6;
+ m_AC ^= m_ER;
+ break;
+ case 0x68: // DAE
+ m_icount -= 11;
+ DEC_ADD(m_ER);
+ break;
+ case 0x70: // ADE
+ m_icount -= 7;
+ BIN_ADD(m_ER);
+ break;
+ case 0x78: // CAE
+ m_icount -= 8;
+ BIN_ADD(~m_ER);
+ break;
+ // Pointer Register Move Instructions
+ case 0x30: case 0x31: case 0x32: case 0x33: // XPAL
+ m_icount -= 8;
+ tmp = m_AC;
+ m_AC = GET_PTR_REG(ptr)->b.l;
+ GET_PTR_REG(ptr)->b.l = tmp;
+ break;
+ case 0x34: case 0x35 :case 0x36: case 0x37:
+ // XPAH
+ m_icount -= 8;
+ tmp = m_AC;
+ m_AC = GET_PTR_REG(ptr)->b.h;
+ GET_PTR_REG(ptr)->b.h = tmp;
+ break;
+ case 0x3c: case 0x3d :case 0x3e: case 0x3f:
+ // XPPC
+ {
+ UINT16 tmp16 = ADD12(m_PC.w.l,-1); // Since PC is incremented we need to fix it
+ m_icount -= 7;
+ m_PC.w.l = GET_PTR_REG(ptr)->w.l;
+ GET_PTR_REG(ptr)->w.l = tmp16;
+ // After exchange CPU increment PC
+ m_PC.w.l = ADD12(m_PC.w.l,1);
+ }
+ break;
+ // Shift, Rotate, Serial I/O Instructions
+ case 0x19: // SIO
+ m_icount -= 5;
+ m_sout_func(m_ER & 0x01);
+ m_ER >>= 1;
+ m_ER |= m_sin_func() ? 0x80 : 0x00;
+ break;
+ case 0x1c: // SR
+ m_icount -= 5;
+ m_AC >>= 1;
+ break;
+ case 0x1d: // SRL
+ m_icount -= 5;
+ m_AC >>= 1;
+ m_AC |= m_SR & 0x80; // add C/L flag
+ break;
+ case 0x1e: // RR
+ m_icount -= 5;
+ m_AC = (m_AC >> 1) | ((m_AC & 0x01) << 7);
+ break;
+ case 0x1f: // RRL
+ m_icount -= 5;
+ tmp = (m_AC & 0x01) << 7;
+ m_AC = (m_AC >> 1) | (m_SR & 0x80);
+ m_SR = (m_SR & 0x7f) | tmp;
+ break;
+ // Single Byte Miscellaneous Instructions
+ case 0x00: // HALT
+ m_icount -= 8;
+ m_halt_func(1);
+ m_halt_func(0);
+ break;
+ case 0x02: // CCL
+ m_icount -= 5;
+ m_SR &= 0x7f;
+ break;
+ case 0x03: // SCL
+ m_icount -= 5;
+ m_SR |= 0x80;
+ break;
+ case 0x04: // DINT
+ m_icount -= 6;
+ m_SR &= 0xf7;
+ break;
+ case 0x05: // IEN
+ m_icount -= 6;
+ m_SR |= 0x08;
+ break;
+ case 0x06: // CSA
+ m_icount -= 5;
+ m_SR &= 0xcf; // clear SA and SB flags
+ m_SR |= m_sensea_func() ? 0x10 : 0x00;
+ m_SR |= m_senseb_func() ? 0x20 : 0x00;
+ m_AC = m_SR;
+ break;
+ case 0x07: // CAS
+ m_icount -= 6;
+ m_SR = m_AC;
+ m_flag_out_func(m_SR & 0x07);
+ break;
+ case 0x08: // NOP
+ m_icount -= 5;
+ break;
+ // Others are illegal
+ default : m_icount -= 1;
+ illegal (opcode);
+ break;
+ }
+ }
+}
+
+
+/***************************************************************************
+ COMMON EXECUTION
+***************************************************************************/
+void scmp_device::take_interrupt()
+{
+ UINT16 tmp = ADD12(m_PC.w.l,-1); // We fix PC so at return it goes to current location
+ m_SR &= 0xf7; // clear IE flag
+
+ m_icount -= 8; // assumption
+ // do XPPC 3
+ m_PC.w.l = GET_PTR_REG(3)->w.l;
+ GET_PTR_REG(3)->w.l = tmp;
+ // After exchange CPU increment PC
+ m_PC.w.l = ADD12(m_PC.w.l,1);
+}
+
+void scmp_device::execute_run()
+{
+ do
+ {
+ if ((m_SR & 0x08) && (m_sensea_func())) {
+ take_interrupt();
+ }
+ debugger_instruction_hook(this, m_PC.d);
+ execute_one(ROP());
+
+ } while (m_icount > 0);
+}
+
+/***************************************************************************
+ CORE INITIALIZATION
+***************************************************************************/
+
+void scmp_device::device_start()
+{
+ /* set up the state table */
+ {
+ state_add(SCMP_PC, "PC", m_PC.w.l);
+ state_add(STATE_GENPC, "GENPC", m_PC.w.l).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_SR).noshow().formatstr("%8s");
+ state_add(SCMP_P1, "P1", m_P1.w.l);
+ state_add(SCMP_P2, "P2", m_P2.w.l);
+ state_add(SCMP_P3, "P3", m_P3.w.l);
+ state_add(SCMP_AC, "AC", m_AC);
+ state_add(SCMP_ER, "ER", m_ER);
+ state_add(SCMP_SR, "SR", m_SR);
+ }
+
+ m_program = &space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ /* resolve callbacks */
+ m_flag_out_func.resolve_safe();
+ m_sout_func.resolve_safe();
+ m_sin_func.resolve_safe(0);
+ m_sensea_func.resolve_safe(0);
+ m_senseb_func.resolve_safe(0);
+ m_halt_func.resolve_safe();
+
+ save_item(NAME(m_PC));
+ save_item(NAME(m_P1));
+ save_item(NAME(m_P2));
+ save_item(NAME(m_P3));
+ save_item(NAME(m_AC));
+ save_item(NAME(m_ER));
+ save_item(NAME(m_SR));
+
+ m_icountptr = &m_icount;
+}
+
+
+
+/***************************************************************************
+ COMMON RESET
+***************************************************************************/
+
+void scmp_device::device_reset()
+{
+ m_PC.d = 0;
+ m_P1.d = 0;
+ m_P2.d = 0;
+ m_P3.d = 0;
+ m_AC = 0;
+ m_ER = 0;
+ m_SR = 0;
+}
+
+
+
+/***************************************************************************
+ COMMON STATE IMPORT/EXPORT
+***************************************************************************/
+
+void scmp_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "%c%c%c%c%c%c%c%c",
+ (m_SR & 0x80) ? 'C' : '.',
+ (m_SR & 0x40) ? 'V' : '.',
+ (m_SR & 0x20) ? 'B' : '.',
+ (m_SR & 0x10) ? 'A' : '.',
+ (m_SR & 0x08) ? 'I' : '.',
+ (m_SR & 0x04) ? '2' : '.',
+ (m_SR & 0x02) ? '1' : '.',
+ (m_SR & 0x01) ? '0' : '.');
+ break;
+ }
+}
diff --git a/src/devices/cpu/scmp/scmp.h b/src/devices/cpu/scmp/scmp.h
new file mode 100644
index 00000000000..86590f93546
--- /dev/null
+++ b/src/devices/cpu/scmp/scmp.h
@@ -0,0 +1,120 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+#ifndef __SCMP_H__
+#define __SCMP_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ SCMP_PC, SCMP_P1, SCMP_P2, SCMP_P3, SCMP_AC, SCMP_ER, SCMP_SR,
+ SCMP_GENPC = STATE_GENPC,
+ SCMP_GENSP = STATE_GENSP,
+ SCMP_GENPCBASE = STATE_GENPCBASE
+};
+
+
+#define MCFG_SCMP_CONFIG(_flag_out_devcb, _sout_devcb, _sin_devcb, _sensea_devcb, _senseb_devcb, _halt_devcb) \
+ scmp_device::set_flag_out_cb(*device, DEVCB_##_flag_out_devcb); \
+ scmp_device::set_sout_cb(*device, DEVCB_##_sout_devcb); \
+ scmp_device::set_sin_cb(*device, DEVCB_##_sin_devcb); \
+ scmp_device::set_sensea_cb(*device, DEVCB_##_sensea_devcb); \
+ scmp_device::set_senseb_cb(*device, DEVCB_##_senseb_devcb); \
+ scmp_device::set_halt_cb(*device, DEVCB_##_halt_devcb);
+
+
+class scmp_device : public cpu_device
+{
+public:
+ // construction/destruction
+ scmp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ scmp_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+
+ // static configuration helpers
+ template<class _Object> static devcb_base &set_flag_out_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_flag_out_func.set_callback(object); }
+ template<class _Object> static devcb_base &set_sout_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_sout_func.set_callback(object); }
+ template<class _Object> static devcb_base &set_sin_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_sin_func.set_callback(object); }
+ template<class _Object> static devcb_base &set_sensea_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_sensea_func.set_callback(object); }
+ template<class _Object> static devcb_base &set_senseb_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_senseb_func.set_callback(object); }
+ template<class _Object> static devcb_base &set_halt_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_halt_func.set_callback(object); }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const { return 5; }
+ virtual UINT32 execute_max_cycles() const { return 131593; }
+ virtual UINT32 execute_input_lines() const { return 0; }
+ virtual void execute_run();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
+
+ // device_state_interface overrides
+ void state_string_export(const device_state_entry &entry, std::string &str);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
+ virtual UINT32 disasm_max_opcode_bytes() const { return 2; }
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+private:
+ address_space_config m_program_config;
+
+ PAIR m_PC;
+ PAIR m_P1;
+ PAIR m_P2;
+ PAIR m_P3;
+ UINT8 m_AC;
+ UINT8 m_ER;
+ UINT8 m_SR;
+
+ address_space *m_program;
+ direct_read_data *m_direct;
+ int m_icount;
+
+ devcb_write8 m_flag_out_func;
+ devcb_write_line m_sout_func;
+ devcb_read_line m_sin_func;
+ devcb_read_line m_sensea_func;
+ devcb_read_line m_senseb_func;
+ devcb_write_line m_halt_func;
+
+ inline UINT16 ADD12(UINT16 addr, INT8 val);
+ inline UINT8 ROP();
+ inline UINT8 ARG();
+ inline UINT8 RM(UINT32 a);
+ inline void WM(UINT32 a, UINT8 v);
+ inline void illegal(UINT8 opcode);
+ inline PAIR *GET_PTR_REG(int num);
+ inline void BIN_ADD(UINT8 val);
+ inline void DEC_ADD(UINT8 val);
+ inline UINT16 GET_ADDR(UINT8 code);
+ void execute_one(int opcode);
+ void take_interrupt();
+
+};
+
+
+class ins8060_device : public scmp_device
+{
+public:
+ // construction/destruction
+ ins8060_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 2 - 1) / 2; }
+ virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 2); }
+};
+
+
+extern const device_type SCMP;
+extern const device_type INS8060;
+
+
+#endif
diff --git a/src/devices/cpu/scmp/scmpdasm.c b/src/devices/cpu/scmp/scmpdasm.c
new file mode 100644
index 00000000000..f8bcc491ce4
--- /dev/null
+++ b/src/devices/cpu/scmp/scmpdasm.c
@@ -0,0 +1,153 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/*****************************************************************************
+ *
+ * scmpdasm.c
+ *
+ * National Semiconductor SC/MP CPU Disassembly
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+
+#define OP(A) oprom[(A) - PC]
+#define ARG(A) opram[(A) - PC]
+
+CPU_DISASSEMBLE( scmp )
+{
+ unsigned PC = pc;
+ UINT8 op = OP(pc++);
+ UINT8 ptr = op & 3;
+
+ if (BIT(op,7)) {
+ // two bytes instructions
+ char as[10];
+ char aspr[10];
+ UINT8 arg = ARG(pc); pc++;
+ if (arg==0x80) {
+ sprintf(as,"E");
+ } else {
+ if (arg & 0x80) {
+ sprintf(as,"-$%02x",0x100-arg);
+ } else {
+ sprintf(as,"+$%02x",arg);
+ }
+ }
+ sprintf(aspr,"%s(%d)",as,ptr);
+
+ switch (op)
+ {
+ // Memory Reference Instructions
+ case 0xc0 : sprintf (buffer,"ld %s",as); break;
+ case 0xc1 : case 0xc2 : case 0xc3 :
+ sprintf (buffer,"ld %s",aspr);break;
+ case 0xc5 : case 0xc6 : case 0xc7 :
+ sprintf (buffer,"ld @%s",aspr); break;
+ case 0xc8 : sprintf (buffer,"st %s",as); break;
+ case 0xc9 : case 0xca : case 0xcb :
+ sprintf (buffer,"st %s",aspr);break;
+ case 0xcd : case 0xce : case 0xcf :
+ sprintf (buffer,"st @%s",aspr); break;
+ case 0xd0 : sprintf (buffer,"and %s",as); break;
+ case 0xd1 : case 0xd2 : case 0xd3 :
+ sprintf (buffer,"and %s",aspr);break;
+ case 0xd5 : case 0xd6 : case 0xd7 :
+ sprintf (buffer,"and @%s",aspr); break;
+ case 0xd8 : sprintf (buffer,"or %s",as); break;
+ case 0xd9 : case 0xda : case 0xdb :
+ sprintf (buffer,"or %s",aspr);break;
+ case 0xdd : case 0xde : case 0xdf :
+ sprintf (buffer,"or @%s",aspr); break;
+ case 0xe0 : sprintf (buffer,"xor %s",as); break;
+ case 0xe1 : case 0xe2 : case 0xe3 :
+ sprintf (buffer,"xor %s",aspr);break;
+ case 0xe5 : case 0xe6 : case 0xe7 :
+ sprintf (buffer,"xor @%s",aspr); break;
+ case 0xe8 : sprintf (buffer,"dad %s",as); break;
+ case 0xe9 : case 0xea : case 0xeb :
+ sprintf (buffer,"dad %s",aspr);break;
+ case 0xed : case 0xee : case 0xef :
+ sprintf (buffer,"dad @%s",aspr); break;
+ case 0xf0 : sprintf (buffer,"add %s",as); break;
+ case 0xf1 : case 0xf2 : case 0xf3 :
+ sprintf (buffer,"add %s",aspr);break;
+ case 0xf5 : case 0xf6 : case 0xf7 :
+ sprintf (buffer,"add @%s",aspr); break;
+ case 0xf8 : sprintf (buffer,"cad %s",as); break;
+ case 0xf9 : case 0xfa : case 0xfb :
+ sprintf (buffer,"cad %s",aspr);break;
+ case 0xfd : case 0xfe : case 0xff :
+ sprintf (buffer,"cad @%s",aspr); break;
+ // Memory Increment/Decrement Instructions
+ case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
+ sprintf (buffer,"ild %s",aspr); break;
+ case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
+ sprintf (buffer,"dld %s",aspr); break;
+ // Immediate Instructions
+ case 0xc4 : sprintf (buffer,"ldi $%02x",arg); break;
+ case 0xd4 : sprintf (buffer,"ani $%02x",arg); break;
+ case 0xdc : sprintf (buffer,"ori $%02x",arg); break;
+ case 0xe4 : sprintf (buffer,"xri $%02x",arg); break;
+ case 0xec : sprintf (buffer,"dai $%02x",arg); break;
+ case 0xf4 : sprintf (buffer,"adi $%02x",arg); break;
+ case 0xfc : sprintf (buffer,"cai $%02x",arg); break;
+ // Transfer Instructions
+ case 0x90 : sprintf (buffer,"jmp %s",as);break;
+ case 0x91 : case 0x92 : case 0x93 :
+ sprintf (buffer,"jmp %s",aspr);break;
+ case 0x94 : sprintf (buffer,"jp %s",as); break;
+ case 0x95 : case 0x96 : case 0x97 :
+ sprintf (buffer,"jp %s",aspr); break;
+ case 0x98 : sprintf (buffer,"jz %s",as); break;
+ case 0x99 : case 0x9a : case 0x9b :
+ sprintf (buffer,"jz %s",aspr); break;
+ case 0x9c : sprintf (buffer,"jnz %s",as); break;
+ case 0x9d : case 0x9e : case 0x9f :
+ sprintf (buffer,"jnz %s",aspr); break;
+ // Double-Byte Miscellaneous Instructions
+ case 0x8f: sprintf (buffer,"dly $%02x",arg); break;
+ // Others are illegal
+ default : sprintf (buffer,"illegal"); pc--; break; // Illegal we consider without param
+ }
+ } else {
+ // one byte instructions
+ switch (op)
+ {
+ // Extension Register Instructions
+ case 0x40: sprintf (buffer,"lde"); break;
+ case 0x01: sprintf (buffer,"xae"); break;
+ case 0x50: sprintf (buffer,"ane"); break;
+ case 0x58: sprintf (buffer,"ore"); break;
+ case 0x60: sprintf (buffer,"xre"); break;
+ case 0x68: sprintf (buffer,"dae"); break;
+ case 0x70: sprintf (buffer,"ade"); break;
+ case 0x78: sprintf (buffer,"cae"); break;
+ // Pointer Register Move Instructions
+ case 0x30: case 0x31 :case 0x32: case 0x33:
+ sprintf (buffer,"xpal %d",ptr); break;
+ case 0x34: case 0x35 :case 0x36: case 0x37:
+ sprintf (buffer,"xpah %d",ptr); break;
+ case 0x3c: case 0x3d :case 0x3e: case 0x3f:
+ sprintf (buffer,"xppc %d",ptr); break;
+ // Shift, Rotate, Serial I/O Instructions
+ case 0x19: sprintf (buffer,"sio"); break;
+ case 0x1c: sprintf (buffer,"sr"); break;
+ case 0x1d: sprintf (buffer,"srl"); break;
+ case 0x1e: sprintf (buffer,"rr"); break;
+ case 0x1f: sprintf (buffer,"rrl"); break;
+ // Single Byte Miscellaneous Instructions
+ case 0x00: sprintf (buffer,"halt"); break;
+ case 0x02: sprintf (buffer,"ccl"); break;
+ case 0x03: sprintf (buffer,"scl"); break;
+ case 0x04: sprintf (buffer,"dint"); break;
+ case 0x05: sprintf (buffer,"ien"); break;
+ case 0x06: sprintf (buffer,"csa"); break;
+ case 0x07: sprintf (buffer,"cas"); break;
+ case 0x08: sprintf (buffer,"nop"); break;
+ // Others are illegal
+ default : sprintf (buffer,"illegal"); break;
+ }
+ }
+
+ return (pc - PC);
+}