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_dph_mask = m_datamask >> 4;
m_read_a.resolve_safe(0);
m_read_b.resolve_safe(0);
m_read_c.resolve_safe(0);
m_read_d.resolve_safe(0);
m_read_a.resolve_safe(0xf);
m_read_b.resolve_safe(0xf);
m_read_c.resolve_safe(0xf);
m_read_d.resolve_safe(0xf);
m_write_c.resolve_safe();
m_write_d.resolve_safe();
@ -131,9 +131,9 @@ void ucom4_cpu_device::device_start()
// zerofill
memset(m_stack, 0, sizeof(m_stack));
memset(m_port_out, 0, sizeof(m_port_out));
m_op = 0;
m_prev_op = 0;
m_arg = 0;
m_skip = false;
m_pc = 0;
m_acc = 0;
@ -147,9 +147,9 @@ void ucom4_cpu_device::device_start()
// register for savestates
save_item(NAME(m_stack));
save_item(NAME(m_port_out));
save_item(NAME(m_op));
save_item(NAME(m_prev_op));
save_item(NAME(m_arg));
save_item(NAME(m_skip));
save_item(NAME(m_pc));
save_item(NAME(m_acc));
@ -185,6 +185,10 @@ void ucom4_cpu_device::device_reset()
m_pc = 0;
m_op = 0;
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);
m_op = m_program->read_byte(m_pc);
m_bitmask = 1 << (m_op & 0x03);
m_pc = (m_pc + 1) & m_prgmask;
fetch_arg();

View File

@ -45,6 +45,20 @@
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
{
@ -117,25 +131,27 @@ protected:
int m_datawidth;
int m_prgmask;
int m_datamask;
int m_family; // MCU family (43/44/45)
int m_stack_levels; // number of callstack levels
UINT16 m_stack[3+1]; // max 3
int m_family; // MCU family (43/44/45)
int m_stack_levels; // number of callstack levels
UINT16 m_stack[3+1]; // max 3
UINT8 m_port_out[0x10]; // last value written to output port
UINT8 m_op;
UINT8 m_prev_op; // previous opcode
UINT8 m_arg; // opcode argument for 2-byte opcodes
bool m_skip; // skip next opcode
UINT8 m_prev_op; // previous opcode
UINT8 m_arg; // opcode argument for 2-byte opcodes
UINT8 m_bitmask; // opcode bit argument
bool m_skip; // skip next opcode
int m_icount;
UINT16 m_pc; // program counter
UINT8 m_acc; // 4-bit accumulator
UINT8 m_dpl; // 4-bit data pointer low (RAM x)
UINT8 m_dph; // 4-bit(?) data pointer high (RAM y)
UINT16 m_pc; // program counter
UINT8 m_acc; // 4-bit accumulator
UINT8 m_dpl; // 4-bit data pointer low (RAM x)
UINT8 m_dph; // 4-bit(?) data pointer high (RAM y)
UINT8 m_dph_mask;
UINT8 m_carry_f; // carry flag
UINT8 m_carry_s_f; // carry save flag
UINT8 m_timer_f; // timer out flag
UINT8 m_int_f; // interrupt flag
UINT8 m_inte_f; // interrupt enable flag
UINT8 m_carry_f; // carry flag
UINT8 m_carry_s_f; // carry save flag
UINT8 m_timer_f; // timer out flag
UINT8 m_int_f; // interrupt flag
UINT8 m_inte_f; // interrupt enable flag
// i/o handlers
devcb_read8 m_read_a;
@ -156,6 +172,8 @@ protected:
void ram_w(UINT8 data);
void pop_stack();
void push_stack();
UINT8 input_r(int index);
void output_w(int index, UINT8 data);
void op_illegal();
bool check_op_43();

View File

@ -31,6 +31,49 @@ void ucom4_cpu_device::push_stack()
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()
{
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()
{
// 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()
{
// 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()
{
// REB B: Reset a single bit of output port E
m_icount--;
op_illegal();
output_w(NEC_UCOM4_PORTE, m_port_out[NEC_UCOM4_PORTE] & ~m_bitmask);
}
void ucom4_cpu_device::op_seb()
{
// SEB B: Set a single bit of output port E
m_icount--;
op_illegal();
output_w(NEC_UCOM4_PORTE, m_port_out[NEC_UCOM4_PORTE] | m_bitmask);
}
void ucom4_cpu_device::op_rpb()
{
// 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()
{
// 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()
{
// CMB B: skip next on bit(ACC) equals bit(RAM)
UINT8 mask = 1 << (m_op & 0x03);
m_skip = ((m_acc & mask) == (ram_r() & mask));
m_skip = ((m_acc & m_bitmask) == (ram_r() & m_bitmask));
}
void ucom4_cpu_device::op_tab()
{
// 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()
@ -362,19 +404,19 @@ void ucom4_cpu_device::op_cli()
void ucom4_cpu_device::op_tmb()
{
// 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()
{
// 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()
{
// 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()
{
// IA: Input port A to ACC
op_illegal();
m_acc = input_r(NEC_UCOM4_PORTA);
}
void ucom4_cpu_device::op_ip()
{
// IP: Input port (DPl) to ACC
op_illegal();
m_acc = input_r(m_dpl);
}
void ucom4_cpu_device::op_oe()
{
// 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()
{
// OP: Output ACC to port (DPl)
op_illegal();
output_w(m_dpl, m_acc);
}
void ucom4_cpu_device::op_ocd()
{
// 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);
}