summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2015-05-31 19:44:05 +0200
committer hap <happppp@users.noreply.github.com>2015-05-31 19:44:05 +0200
commit8c828a727f363e334215600af3654b2bcf88a71a (patch)
tree47bd65c8aaf72869491e38d871df8343d2929465 /src/emu/cpu
parentb2d2d4de2d19f7d8486bc2e1af0ac61b86d9faf9 (diff)
added i/o ports+opcodes
Diffstat (limited to 'src/emu/cpu')
-rw-r--r--src/emu/cpu/melps4/m58846.c6
-rw-r--r--src/emu/cpu/melps4/melps4.c105
-rw-r--r--src/emu/cpu/melps4/melps4.h115
-rw-r--r--src/emu/cpu/melps4/melps4op.inc36
4 files changed, 234 insertions, 28 deletions
diff --git a/src/emu/cpu/melps4/m58846.c b/src/emu/cpu/melps4/m58846.c
index bcc50e06ca3..fb5760cabaa 100644
--- a/src/emu/cpu/melps4/m58846.c
+++ b/src/emu/cpu/melps4/m58846.c
@@ -30,7 +30,7 @@ ADDRESS_MAP_END
// device definitions
m58846_device::m58846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : melps4_cpu_device(mconfig, M58846, "M58846", tag, owner, clock, 11, ADDRESS_MAP_NAME(program_2kx9), 7, ADDRESS_MAP_NAME(data_128x4), "m58846", __FILE__)
+ : melps4_cpu_device(mconfig, M58846, "M58846", tag, owner, clock, 11, ADDRESS_MAP_NAME(program_2kx9), 7, ADDRESS_MAP_NAME(data_128x4), 12 /* number of D pins */, 2 /* subroutine page */, 1 /* interrupt page */, "m58846", __FILE__)
{ }
@@ -50,10 +50,6 @@ offs_t m58846_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *o
void m58846_device::device_start()
{
melps4_cpu_device::device_start();
-
- // set fixed state
- m_sm_page = 2;
- m_int_page = 1;
}
diff --git a/src/emu/cpu/melps4/melps4.c b/src/emu/cpu/melps4/melps4.c
index 342147892b3..4e9305b2cc5 100644
--- a/src/emu/cpu/melps4/melps4.c
+++ b/src/emu/cpu/melps4/melps4.c
@@ -75,6 +75,21 @@ void melps4_cpu_device::device_start()
m_data = &space(AS_DATA);
m_prgmask = (1 << m_prgwidth) - 1;
m_datamask = (1 << m_datawidth) - 1;
+ m_d_mask = (1 << m_d_pins) - 1;
+
+ // resolve callbacks
+ m_read_k.resolve_safe(0);
+ m_read_d.resolve_safe(0);
+ m_read_s.resolve_safe(0);
+ m_read_f.resolve_safe(0);
+ m_read_t.resolve_safe(0);
+
+ m_write_d.resolve_safe();
+ m_write_s.resolve_safe();
+ m_write_f.resolve_safe();
+ m_write_g.resolve_safe();
+ m_write_u.resolve_safe();
+ m_write_t.resolve_safe();
// zerofill
m_pc = 0;
@@ -83,6 +98,10 @@ void melps4_cpu_device::device_start()
m_op = 0;
m_prev_op = 0;
m_bitmask = 0;
+
+ m_port_d = 0;
+ m_port_s = 0;
+ m_port_f = 0;
m_sm = m_sms = false;
m_ba_flag = false;
@@ -115,6 +134,10 @@ void melps4_cpu_device::device_start()
save_item(NAME(m_prev_op));
save_item(NAME(m_bitmask));
+ save_item(NAME(m_port_d));
+ save_item(NAME(m_port_s));
+ save_item(NAME(m_port_f));
+
save_item(NAME(m_sm));
save_item(NAME(m_sms));
save_item(NAME(m_ba_flag));
@@ -181,6 +204,88 @@ void melps4_cpu_device::device_reset()
m_v = 0;
m_w = 0;
+
+ // clear ports
+ write_d_pin(MELPS4_PORTD_CLR, 0);
+ write_gen_port(MELPS4_PORTS, 0);
+ write_gen_port(MELPS4_PORTF, 0);
+ write_gen_port(MELPS4_PORTG, 0);
+ write_gen_port(MELPS4_PORTU, 0);
+ m_write_t(0);
+}
+
+
+
+//-------------------------------------------------
+// i/o handling
+//-------------------------------------------------
+
+UINT8 melps4_cpu_device::read_gen_port(int port)
+{
+ // input generic port
+ switch (port)
+ {
+ case MELPS4_PORTS:
+ return m_port_s | m_read_s(port, 0xff);
+ case MELPS4_PORTF:
+ return m_port_f | (m_read_f(port, 0xff) & 0xf);
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void melps4_cpu_device::write_gen_port(int port, UINT8 data)
+{
+ // output generic port
+ switch (port)
+ {
+ case MELPS4_PORTS:
+ m_port_s = data;
+ m_write_s(port, data, 0xff);
+ break;
+ case MELPS4_PORTF:
+ m_port_f = data & 0xf;
+ m_write_f(port, data & 0xf, 0xff);
+ break;
+ case MELPS4_PORTG:
+ m_write_g(port, data & 0xf, 0xff);
+ break;
+ case MELPS4_PORTU:
+ m_write_u(port, data & 1, 0xff);
+ break;
+
+ default:
+ break;
+ }
+}
+
+int melps4_cpu_device::read_d_pin(int bit)
+{
+ // read port D, return state of selected pin
+ bit &= 0xf;
+ UINT16 d = (m_port_d | m_read_d(bit, 0xffff)) & m_d_mask;
+ return d >> bit & 1;
+}
+
+void melps4_cpu_device::write_d_pin(int bit, int state)
+{
+ // clear all port D pins
+ if (bit == MELPS4_PORTD_CLR)
+ {
+ m_port_d = 0;
+ m_write_d(bit, 0, 0xffff);
+ }
+
+ // set/reset one port D pin
+ else
+ {
+ bit &= 0xf;
+ m_port_d = ((m_port_d & (~(1 << bit))) | (state << bit)) & m_d_mask;
+ m_write_d(bit, m_port_d, 0xffff);
+ }
}
diff --git a/src/emu/cpu/melps4/melps4.h b/src/emu/cpu/melps4/melps4.h
index ba6c18f4695..6fcc27c4364 100644
--- a/src/emu/cpu/melps4/melps4.h
+++ b/src/emu/cpu/melps4/melps4.h
@@ -12,6 +12,58 @@
#include "emu.h"
+// I/O ports setup
+
+// K input or A/D input port, up to 16 pins
+#define MCFG_MELPS4_READ_K_CB(_devcb) \
+ melps4_cpu_device::set_read_k_callback(*device, DEVCB_##_devcb);
+
+// D discrete I/O port, up to 16 pins - offset 0-15 for bit, 16 for all pins clear
+#define MCFG_MELPS4_READ_D_CB(_devcb) \
+ melps4_cpu_device::set_read_d_callback(*device, DEVCB_##_devcb);
+#define MCFG_MELPS4_WRITE_D_CB(_devcb) \
+ melps4_cpu_device::set_write_d_callback(*device, DEVCB_##_devcb);
+
+// 8-bit S generic I/O port
+#define MCFG_MELPS4_READ_S_CB(_devcb) \
+ melps4_cpu_device::set_read_s_callback(*device, DEVCB_##_devcb);
+#define MCFG_MELPS4_WRITE_S_CB(_devcb) \
+ melps4_cpu_device::set_write_s_callback(*device, DEVCB_##_devcb);
+
+// 4-bit F generic I/O port
+#define MCFG_MELPS4_READ_F_CB(_devcb) \
+ melps4_cpu_device::set_read_f_callback(*device, DEVCB_##_devcb);
+#define MCFG_MELPS4_WRITE_F_CB(_devcb) \
+ melps4_cpu_device::set_write_f_callback(*device, DEVCB_##_devcb);
+
+// 4-bit G generic output port
+#define MCFG_MELPS4_WRITE_G_CB(_devcb) \
+ melps4_cpu_device::set_write_g_callback(*device, DEVCB_##_devcb);
+
+// 1-bit U generic output port
+#define MCFG_MELPS4_WRITE_U_CB(_devcb) \
+ melps4_cpu_device::set_write_u_callback(*device, DEVCB_##_devcb);
+
+// T timer I/O pin
+#define MCFG_MELPS4_READ_T_CB(_devcb) \
+ melps4_cpu_device::set_read_t_callback(*device, DEVCB_##_devcb);
+#define MCFG_MELPS4_WRITE_T_CB(_devcb) \
+ melps4_cpu_device::set_write_t_callback(*device, DEVCB_##_devcb);
+
+
+#define MELPS4_PORTD_CLR 16
+
+// only generic ports here (S is 8-bit)
+enum
+{
+ MELPS4_PORTS = 0,
+ MELPS4_PORTF = 2,
+ MELPS4_PORTG,
+ MELPS4_PORTU
+};
+
+
+
// pinout reference
/*
@@ -45,20 +97,46 @@ class melps4_cpu_device : public cpu_device
{
public:
// construction/destruction
- melps4_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source)
+ melps4_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, int d_pins, UINT8 sm_page, UINT8 int_page, const char *shortname, const char *source)
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
, m_program_config("program", ENDIANNESS_LITTLE, 16, prgwidth, -1, program)
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
, m_prgwidth(prgwidth)
, m_datawidth(datawidth)
- , m_stack_levels(3)
- , m_sm_page(14)
- , m_int_page(12)
+ , m_d_pins(d_pins)
+ , m_sm_page(sm_page)
+ , m_int_page(int_page)
, m_xami_mask(0xf)
, m_sp_mask(0x7<<4)
, m_ba_op(0x01)
+ , m_stack_levels(3)
+ , m_read_k(*this)
+ , m_read_d(*this)
+ , m_read_s(*this)
+ , m_read_f(*this)
+ , m_read_t(*this)
+ , m_write_d(*this)
+ , m_write_s(*this)
+ , m_write_f(*this)
+ , m_write_g(*this)
+ , m_write_u(*this)
+ , m_write_t(*this)
{ }
+ // static configuration helpers
+ template<class _Object> static devcb_base &set_read_k_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_k.set_callback(object); }
+ template<class _Object> static devcb_base &set_read_d_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_d.set_callback(object); }
+ template<class _Object> static devcb_base &set_read_s_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_s.set_callback(object); }
+ template<class _Object> static devcb_base &set_read_f_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_f.set_callback(object); }
+ template<class _Object> static devcb_base &set_read_t_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_t.set_callback(object); }
+
+ template<class _Object> static devcb_base &set_write_d_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_d.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_s_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_s.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_f_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_f.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_g_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_g.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_u_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_u.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_t_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_t.set_callback(object); }
+
protected:
// device-level overrides
virtual void device_start();
@@ -89,17 +167,19 @@ protected:
int m_icount;
// fixed settings or mask options that differ between MCU type
- int m_prgwidth; // number of bits and bitmask for ROM/RAM size
+ int m_prgwidth; // number of bits and bitmask for ROM/RAM size: see melps4.c for info
int m_datawidth; // "
int m_prgmask; // "
int m_datamask; // "
+ int m_d_pins; // number of D port pins and bitmask: 11 on '40,'41,'42,'44, 8 on '43, 12 on '45,'46, 16 on '47
+ int m_d_mask; // "
- UINT8 m_stack_levels; // 3 levels on MELPS 4, 12 levels on MELPS 41/42
UINT8 m_sm_page; // subroutine default page: 14 on '40 to '44, 2 on '45,'46, 0 on '47
UINT8 m_int_page; // interrupt routine page: 12 on '40 to '44, 1 on '45,'46, 2 on '47
UINT8 m_xami_mask; // mask option for XAMI opcode on '40,'41,'45 (0xf for others)
UINT16 m_sp_mask; // SP opcode location(middle 4 bits): 7 on '40 to '46, 3 on '47
UINT16 m_ba_op; // BA opcode location: 1 on '40 to '46, N/A on '47
+ UINT8 m_stack_levels; // 3 levels on MELPS 4, 12 levels on MELPS 41/42
// internal state, misc regs
UINT16 m_pc; // program counter (11 or 10-bit)
@@ -108,6 +188,10 @@ protected:
UINT16 m_op;
UINT16 m_prev_op;
UINT8 m_bitmask; // opcode bit argument
+
+ UINT16 m_port_d; // last written port data
+ UINT8 m_port_s; // "
+ UINT8 m_port_f; // "
bool m_sm, m_sms; // subroutine mode flag + stack
bool m_ba_flag; // temp flag indicates BA opcode was executed
@@ -133,6 +217,25 @@ protected:
UINT8 m_v; // timer control V
UINT8 m_w; // timer control W
+ // i/o handlers
+ devcb_read16 m_read_k;
+ devcb_read16 m_read_d;
+ devcb_read8 m_read_s;
+ devcb_read8 m_read_f;
+ devcb_read_line m_read_t;
+
+ devcb_write16 m_write_d;
+ devcb_write8 m_write_s;
+ devcb_write8 m_write_f;
+ devcb_write8 m_write_g;
+ devcb_write8 m_write_u;
+ devcb_write_line m_write_t;
+
+ UINT8 read_gen_port(int port);
+ void write_gen_port(int port, UINT8 data);
+ int read_d_pin(int bit);
+ void write_d_pin(int bit, int state);
+
// misc internal helpers
UINT8 ram_r();
void ram_w(UINT8 data);
diff --git a/src/emu/cpu/melps4/melps4op.inc b/src/emu/cpu/melps4/melps4op.inc
index 5d2f6d38a94..46780efb616 100644
--- a/src/emu/cpu/melps4/melps4op.inc
+++ b/src/emu/cpu/melps4/melps4op.inc
@@ -529,43 +529,44 @@ void melps4_cpu_device::op_rti()
void melps4_cpu_device::op_cld()
{
// CLD: clear port D
- op_illegal();
+ write_d_pin(MELPS4_PORTD_CLR, 0);
}
void melps4_cpu_device::op_cls()
{
// CLS: clear port S
- op_illegal();
+ write_gen_port(MELPS4_PORTS, 0);
}
void melps4_cpu_device::op_clds()
{
// CLDS: CLD, CLS
- op_illegal();
+ op_cld();
+ op_cls();
}
void melps4_cpu_device::op_sd()
{
// SD: set port D bit designated by Y
- op_illegal();
+ write_d_pin(m_y, 1);
}
void melps4_cpu_device::op_rd()
{
// RD: reset port D bit designated by Y
- op_illegal();
+ write_d_pin(m_y, 0);
}
void melps4_cpu_device::op_szd()
{
// SZD: skip next if port D bit designated by Y is 0
- op_illegal();
+ m_skip = !read_d_pin(m_y);
}
void melps4_cpu_device::op_osab()
{
// OSAB: output A and B to port S
- op_illegal();
+ write_gen_port(MELPS4_PORTS, m_b << 4 | m_a);
}
void melps4_cpu_device::op_ospa()
@@ -577,49 +578,50 @@ void melps4_cpu_device::op_ospa()
void melps4_cpu_device::op_ose()
{
// OSE: output E to port S
- op_illegal();
+ write_gen_port(MELPS4_PORTS, m_e);
}
void melps4_cpu_device::op_ias()
{
// IAS i: transfer port S(hi/lo) to A
- op_illegal();
+ int shift = (m_op & 1) ? 0 : 4;
+ m_a = read_gen_port(MELPS4_PORTS) >> shift & 0xf;
}
void melps4_cpu_device::op_ofa()
{
// OFA: output A to port F
- op_illegal();
+ write_gen_port(MELPS4_PORTF, m_a);
}
void melps4_cpu_device::op_iaf()
{
// IAF: input port F to A
- op_illegal();
+ m_a = read_gen_port(MELPS4_PORTF);
}
void melps4_cpu_device::op_oga()
{
// OGA: output A to port G
- op_illegal();
+ write_gen_port(MELPS4_PORTG, m_a);
}
void melps4_cpu_device::op_iak()
{
// IAK: input port K to A
- op_illegal();
+ m_a = m_read_k(0, 0xffff) & 0xf;
}
void melps4_cpu_device::op_szk()
{
// SZK j: skip next if port K bit is reset
- op_illegal();
+ m_skip = !(m_read_k(0, 0xffff) & m_bitmask);
}
void melps4_cpu_device::op_su()
{
// SU/RU: set/reset port U
- op_illegal();
+ write_gen_port(MELPS4_PORTU, m_op & 1);
}
@@ -628,15 +630,15 @@ void melps4_cpu_device::op_su()
void melps4_cpu_device::op_ei()
{
// EI: enable interrupt flag
- m_inte = 1;
m_prohibit_irq = true;
+ m_inte = 1;
}
void melps4_cpu_device::op_di()
{
// DI: disable interrupt flag
- m_inte = 0;
m_prohibit_irq = true;
+ m_inte = 0;
}
void melps4_cpu_device::op_inth()