diff options
author | 2015-05-31 19:44:05 +0200 | |
---|---|---|
committer | 2015-05-31 19:44:05 +0200 | |
commit | 8c828a727f363e334215600af3654b2bcf88a71a (patch) | |
tree | 47bd65c8aaf72869491e38d871df8343d2929465 /src/emu/cpu | |
parent | b2d2d4de2d19f7d8486bc2e1af0ac61b86d9faf9 (diff) |
added i/o ports+opcodes
Diffstat (limited to 'src/emu/cpu')
-rw-r--r-- | src/emu/cpu/melps4/m58846.c | 6 | ||||
-rw-r--r-- | src/emu/cpu/melps4/melps4.c | 105 | ||||
-rw-r--r-- | src/emu/cpu/melps4/melps4.h | 115 | ||||
-rw-r--r-- | src/emu/cpu/melps4/melps4op.inc | 36 |
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() |