added ucom4 i/o opcodes

This commit is contained in:
hap 2015-02-08 01:16:23 +01:00
parent f80763b734
commit 8717aeab38
3 changed files with 104 additions and 38 deletions

View File

@ -116,10 +116,10 @@ void ucom4_cpu_device::device_start()
m_datamask = (1 << m_datawidth) - 1; m_datamask = (1 << m_datawidth) - 1;
m_dph_mask = m_datamask >> 4; m_dph_mask = m_datamask >> 4;
m_read_a.resolve_safe(0); m_read_a.resolve_safe(0xf);
m_read_b.resolve_safe(0); m_read_b.resolve_safe(0xf);
m_read_c.resolve_safe(0); m_read_c.resolve_safe(0xf);
m_read_d.resolve_safe(0); m_read_d.resolve_safe(0xf);
m_write_c.resolve_safe(); m_write_c.resolve_safe();
m_write_d.resolve_safe(); m_write_d.resolve_safe();
@ -131,9 +131,9 @@ void ucom4_cpu_device::device_start()
// zerofill // zerofill
memset(m_stack, 0, sizeof(m_stack)); memset(m_stack, 0, sizeof(m_stack));
memset(m_port_out, 0, sizeof(m_port_out));
m_op = 0; m_op = 0;
m_prev_op = 0; m_prev_op = 0;
m_arg = 0;
m_skip = false; m_skip = false;
m_pc = 0; m_pc = 0;
m_acc = 0; m_acc = 0;
@ -147,9 +147,9 @@ void ucom4_cpu_device::device_start()
// register for savestates // register for savestates
save_item(NAME(m_stack)); save_item(NAME(m_stack));
save_item(NAME(m_port_out));
save_item(NAME(m_op)); save_item(NAME(m_op));
save_item(NAME(m_prev_op)); save_item(NAME(m_prev_op));
save_item(NAME(m_arg));
save_item(NAME(m_skip)); save_item(NAME(m_skip));
save_item(NAME(m_pc)); save_item(NAME(m_pc));
save_item(NAME(m_acc)); save_item(NAME(m_acc));
@ -185,6 +185,10 @@ void ucom4_cpu_device::device_reset()
m_pc = 0; m_pc = 0;
m_op = 0; m_op = 0;
m_skip = false; m_skip = false;
// clear i/o
for (int i = NEC_UCOM4_PORTC; i <= NEC_UCOM4_PORTI; i++)
output_w(i, 0xf);
} }
@ -215,6 +219,7 @@ void ucom4_cpu_device::execute_run()
debugger_instruction_hook(this, m_pc); debugger_instruction_hook(this, m_pc);
m_op = m_program->read_byte(m_pc); m_op = m_program->read_byte(m_pc);
m_bitmask = 1 << (m_op & 0x03);
m_pc = (m_pc + 1) & m_prgmask; m_pc = (m_pc + 1) & m_prgmask;
fetch_arg(); fetch_arg();

View File

@ -45,6 +45,20 @@
ucom4_cpu_device::set_write_i_callback(*device, DEVCB_##_devcb); ucom4_cpu_device::set_write_i_callback(*device, DEVCB_##_devcb);
enum
{
NEC_UCOM4_PORTA = 0,
NEC_UCOM4_PORTB,
NEC_UCOM4_PORTC,
NEC_UCOM4_PORTD,
NEC_UCOM4_PORTE,
NEC_UCOM4_PORTF,
NEC_UCOM4_PORTG,
NEC_UCOM4_PORTH,
NEC_UCOM4_PORTI
};
class ucom4_cpu_device : public cpu_device class ucom4_cpu_device : public cpu_device
{ {
@ -117,25 +131,27 @@ protected:
int m_datawidth; int m_datawidth;
int m_prgmask; int m_prgmask;
int m_datamask; int m_datamask;
int m_family; // MCU family (43/44/45) int m_family; // MCU family (43/44/45)
int m_stack_levels; // number of callstack levels int m_stack_levels; // number of callstack levels
UINT16 m_stack[3+1]; // max 3 UINT16 m_stack[3+1]; // max 3
UINT8 m_port_out[0x10]; // last value written to output port
UINT8 m_op; UINT8 m_op;
UINT8 m_prev_op; // previous opcode UINT8 m_prev_op; // previous opcode
UINT8 m_arg; // opcode argument for 2-byte opcodes UINT8 m_arg; // opcode argument for 2-byte opcodes
bool m_skip; // skip next opcode UINT8 m_bitmask; // opcode bit argument
bool m_skip; // skip next opcode
int m_icount; int m_icount;
UINT16 m_pc; // program counter UINT16 m_pc; // program counter
UINT8 m_acc; // 4-bit accumulator UINT8 m_acc; // 4-bit accumulator
UINT8 m_dpl; // 4-bit data pointer low (RAM x) UINT8 m_dpl; // 4-bit data pointer low (RAM x)
UINT8 m_dph; // 4-bit(?) data pointer high (RAM y) UINT8 m_dph; // 4-bit(?) data pointer high (RAM y)
UINT8 m_dph_mask; UINT8 m_dph_mask;
UINT8 m_carry_f; // carry flag UINT8 m_carry_f; // carry flag
UINT8 m_carry_s_f; // carry save flag UINT8 m_carry_s_f; // carry save flag
UINT8 m_timer_f; // timer out flag UINT8 m_timer_f; // timer out flag
UINT8 m_int_f; // interrupt flag UINT8 m_int_f; // interrupt flag
UINT8 m_inte_f; // interrupt enable flag UINT8 m_inte_f; // interrupt enable flag
// i/o handlers // i/o handlers
devcb_read8 m_read_a; devcb_read8 m_read_a;
@ -156,6 +172,8 @@ protected:
void ram_w(UINT8 data); void ram_w(UINT8 data);
void pop_stack(); void pop_stack();
void push_stack(); void push_stack();
UINT8 input_r(int index);
void output_w(int index, UINT8 data);
void op_illegal(); void op_illegal();
bool check_op_43(); bool check_op_43();

View File

@ -31,6 +31,49 @@ void ucom4_cpu_device::push_stack()
m_stack[0] = m_pc; m_stack[0] = m_pc;
} }
UINT8 ucom4_cpu_device::input_r(int index)
{
index &= 0xf;
UINT8 inp = 0xf;
switch (index)
{
case NEC_UCOM4_PORTA: inp = m_read_a(index, 0xff) & 0xf; break;
case NEC_UCOM4_PORTB: inp = m_read_b(index, 0xff) & 0xf; break;
case NEC_UCOM4_PORTC: inp = m_read_c(index, 0xff) & 0xf; break;
case NEC_UCOM4_PORTD: inp = m_read_d(index, 0xff) & 0xf; break;
default:
logerror("%s read from unknown port %c at $%03X\n", tag(), 'A' + index, m_pc);
break;
}
return inp;
}
void ucom4_cpu_device::output_w(int index, UINT8 data)
{
index &= 0xf;
data &= 0xf;
switch (index)
{
case NEC_UCOM4_PORTC: m_write_c(index, data, 0xff); break;
case NEC_UCOM4_PORTD: m_write_d(index, data, 0xff); break;
case NEC_UCOM4_PORTE: m_write_e(index, data, 0xff); break;
case NEC_UCOM4_PORTF: m_write_f(index, data, 0xff); break;
case NEC_UCOM4_PORTG: m_write_g(index, data, 0xff); break;
case NEC_UCOM4_PORTH: m_write_h(index, data, 0xff); break;
case NEC_UCOM4_PORTI: m_write_i(index, data & 7, 0xff); break;
default:
logerror("%s write to unknown port %c = $%X at $%03X\n", tag(), 'A' + index, data & 0xf, m_pc);
break;
}
m_port_out[index] = data;
}
void ucom4_cpu_device::op_illegal() void ucom4_cpu_device::op_illegal()
{ {
logerror("%s unknown opcode $%02X at $%03X\n", tag(), m_op, m_pc); logerror("%s unknown opcode $%02X at $%03X\n", tag(), m_op, m_pc);
@ -240,39 +283,39 @@ void ucom4_cpu_device::op_ded()
void ucom4_cpu_device::op_rmb() void ucom4_cpu_device::op_rmb()
{ {
// RMB B: Reset a single bit of RAM // RMB B: Reset a single bit of RAM
ram_w(ram_r() & ~(1 << (m_op & 0x03))); ram_w(ram_r() & ~m_bitmask);
} }
void ucom4_cpu_device::op_smb() void ucom4_cpu_device::op_smb()
{ {
// SMB B: Set a single bit of RAM // SMB B: Set a single bit of RAM
ram_w(ram_r() | (1 << (m_op & 0x03))); ram_w(ram_r() | m_bitmask);
} }
void ucom4_cpu_device::op_reb() void ucom4_cpu_device::op_reb()
{ {
// REB B: Reset a single bit of output port E // REB B: Reset a single bit of output port E
m_icount--; m_icount--;
op_illegal(); output_w(NEC_UCOM4_PORTE, m_port_out[NEC_UCOM4_PORTE] & ~m_bitmask);
} }
void ucom4_cpu_device::op_seb() void ucom4_cpu_device::op_seb()
{ {
// SEB B: Set a single bit of output port E // SEB B: Set a single bit of output port E
m_icount--; m_icount--;
op_illegal(); output_w(NEC_UCOM4_PORTE, m_port_out[NEC_UCOM4_PORTE] | m_bitmask);
} }
void ucom4_cpu_device::op_rpb() void ucom4_cpu_device::op_rpb()
{ {
// RPB B: Reset a single bit of output port (DPl) // RPB B: Reset a single bit of output port (DPl)
op_illegal(); output_w(m_dpl, m_port_out[m_dpl] & ~m_bitmask);
} }
void ucom4_cpu_device::op_spb() void ucom4_cpu_device::op_spb()
{ {
// SPB B: Set a single bit of output port (DPl) // SPB B: Set a single bit of output port (DPl)
op_illegal(); output_w(m_dpl, m_port_out[m_dpl] | m_bitmask);
} }
@ -340,14 +383,13 @@ void ucom4_cpu_device::op_cm()
void ucom4_cpu_device::op_cmb() void ucom4_cpu_device::op_cmb()
{ {
// CMB B: skip next on bit(ACC) equals bit(RAM) // CMB B: skip next on bit(ACC) equals bit(RAM)
UINT8 mask = 1 << (m_op & 0x03); m_skip = ((m_acc & m_bitmask) == (ram_r() & m_bitmask));
m_skip = ((m_acc & mask) == (ram_r() & mask));
} }
void ucom4_cpu_device::op_tab() void ucom4_cpu_device::op_tab()
{ {
// TAB B: skip next on bit(ACC) // TAB B: skip next on bit(ACC)
m_skip = ((m_acc & (1 << (m_op & 0x03))) != 0); m_skip = ((m_acc & m_bitmask) != 0);
} }
void ucom4_cpu_device::op_cli() void ucom4_cpu_device::op_cli()
@ -362,19 +404,19 @@ void ucom4_cpu_device::op_cli()
void ucom4_cpu_device::op_tmb() void ucom4_cpu_device::op_tmb()
{ {
// TMB B: skip next on bit(RAM) // TMB B: skip next on bit(RAM)
m_skip = ((ram_r() & (1 << (m_op & 0x03))) != 0); m_skip = ((ram_r() & m_bitmask) != 0);
} }
void ucom4_cpu_device::op_tpa() void ucom4_cpu_device::op_tpa()
{ {
// TPA B: skip next on bit(input port A) // TPA B: skip next on bit(input port A)
op_illegal(); m_skip = ((input_r(NEC_UCOM4_PORTA) & m_bitmask) != 0);
} }
void ucom4_cpu_device::op_tpb() void ucom4_cpu_device::op_tpb()
{ {
// TPB B: skip next on bit(input port (DPl)) // TPB B: skip next on bit(input port (DPl))
op_illegal(); m_skip = ((input_r(m_dpl) & m_bitmask) != 0);
} }
@ -392,31 +434,32 @@ void ucom4_cpu_device::op_tit()
void ucom4_cpu_device::op_ia() void ucom4_cpu_device::op_ia()
{ {
// IA: Input port A to ACC // IA: Input port A to ACC
op_illegal(); m_acc = input_r(NEC_UCOM4_PORTA);
} }
void ucom4_cpu_device::op_ip() void ucom4_cpu_device::op_ip()
{ {
// IP: Input port (DPl) to ACC // IP: Input port (DPl) to ACC
op_illegal(); m_acc = input_r(m_dpl);
} }
void ucom4_cpu_device::op_oe() void ucom4_cpu_device::op_oe()
{ {
// OE: Output ACC to port E // OE: Output ACC to port E
m_write_e(0, m_acc, 0xff); output_w(NEC_UCOM4_PORTE, m_acc);
} }
void ucom4_cpu_device::op_op() void ucom4_cpu_device::op_op()
{ {
// OP: Output ACC to port (DPl) // OP: Output ACC to port (DPl)
op_illegal(); output_w(m_dpl, m_acc);
} }
void ucom4_cpu_device::op_ocd() void ucom4_cpu_device::op_ocd()
{ {
// OCD X: Output X to ports C and D // OCD X: Output X to ports C and D
op_illegal(); output_w(NEC_UCOM4_PORTD, m_arg >> 4);
output_w(NEC_UCOM4_PORTC, m_arg & 0xf);
} }