mn1400: add most opcodes

This commit is contained in:
hap 2023-05-07 03:10:58 +02:00
parent 3226714fff
commit ce807c207f
4 changed files with 147 additions and 8 deletions

View File

@ -56,6 +56,10 @@ protected:
virtual bool op_has_param(u8 op) override;
// opcode helpers
u8 ram_r();
void ram_w(u8 data);
void set_z(u8 data);
void set_cz(u8 data);
void op_illegal();
// opcode handlers

View File

@ -59,12 +59,17 @@ void mn1400_base_device::device_start()
m_op = 0;
m_prev_op = 0;
m_param = 0;
m_ram_address = 0;
memset(m_stack, 0, sizeof(m_stack));
m_sp = 0;
m_a = 0;
m_x = 0;
m_y = 0;
m_status = 0;
m_c = 0;
m_counter = 0;
m_ec = false;
// register for savestates
save_item(NAME(m_pc));
@ -72,12 +77,17 @@ void mn1400_base_device::device_start()
save_item(NAME(m_op));
save_item(NAME(m_prev_op));
save_item(NAME(m_param));
save_item(NAME(m_ram_address));
save_item(NAME(m_stack));
save_item(NAME(m_sp));
save_item(NAME(m_a));
save_item(NAME(m_x));
save_item(NAME(m_y));
save_item(NAME(m_status));
save_item(NAME(m_c));
save_item(NAME(m_counter));
save_item(NAME(m_ec));
// register state for debugger
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%03X").noshow();
@ -89,7 +99,7 @@ void mn1400_base_device::device_start()
state_add(++m_state_count, "A", m_a).formatstr("%01X"); // 2
state_add(++m_state_count, "X", m_x).formatstr("%01X"); // 3
state_add(++m_state_count, "Y", m_y).formatstr("%01X"); // 4
state_add(++m_state_count, "CNT", m_y).formatstr("%02X"); // 5
state_add(++m_state_count, "CNT", m_counter).formatstr("%02X"); // 5
set_icountptr(m_icount);
}
@ -125,7 +135,10 @@ void mn1400_base_device::device_reset()
{
m_pc = m_prev_pc = 0;
m_op = m_prev_op = 0;
m_param = 0;
m_status = 0;
// clear output ports
m_c = 0;
}
@ -190,6 +203,7 @@ void mn1400_base_device::execute_run()
cycle();
}
m_ram_address = (m_x << 4 | m_y) & m_datamask;
execute_one();
}
}

View File

@ -70,14 +70,19 @@ protected:
u8 m_op;
u8 m_prev_op;
u8 m_param;
u8 m_ram_address;
u16 m_stack[2];
u8 m_sp;
u8 m_a;
u8 m_x;
u8 m_y;
u8 m_status;
u16 m_c;
u8 m_counter;
bool m_ec;
enum
enum : u8
{
FLAG_Z = 1,
FLAG_C = 2,

View File

@ -9,6 +9,34 @@
// internal helpers
u8 mn1400_cpu_device::ram_r()
{
return m_data->read_byte(m_ram_address) & 0xf;
}
void mn1400_cpu_device::ram_w(u8 data)
{
m_data->write_byte(m_ram_address, data & 0xf);
}
void mn1400_cpu_device::set_z(u8 data)
{
if ((data & 0xf) == 0)
m_status |= FLAG_Z;
else
m_status &= ~FLAG_Z;
}
void mn1400_cpu_device::set_cz(u8 data)
{
set_z(data);
if (data & 0x10)
m_status |= FLAG_C;
else
m_status &= ~FLAG_C;
}
void mn1400_cpu_device::op_illegal()
{
logerror("unknown opcode $%02X at $%03X\n", m_op, m_prev_pc);
@ -22,91 +50,124 @@ void mn1400_cpu_device::op_illegal()
void mn1400_cpu_device::op_l()
{
// L: load A from memory
m_a = ram_r();
set_z(m_a);
}
void mn1400_cpu_device::op_ld()
{
// LD: load A direct from memory
m_ram_address = m_op & 3;
op_l();
}
void mn1400_cpu_device::op_li()
{
// LI: load A immediate
m_a = m_op & 0xf;
set_z(m_a);
}
void mn1400_cpu_device::op_lic()
{
// LIC: L + increment Y
cycle();
op_l();
op_icy();
}
void mn1400_cpu_device::op_ldc()
{
// LDC: L + decrement Y
cycle();
op_l();
op_dcy();
}
void mn1400_cpu_device::op_st()
{
// S: store A into memory
ram_w(m_a);
}
void mn1400_cpu_device::op_std()
{
// STD: store A direct into memory
m_ram_address = m_op & 3;
op_st();
}
void mn1400_cpu_device::op_stic()
{
// STIC: S + increment Y
// STIC: ST + increment Y
cycle();
op_st();
op_icy();
}
void mn1400_cpu_device::op_stdc()
{
// STDC: S + decrement Y
// STDC: ST + decrement Y
cycle();
op_st();
op_dcy();
}
void mn1400_cpu_device::op_lx()
{
// LX: load X immediate
m_x = m_op & 7;
}
void mn1400_cpu_device::op_ly()
{
// LY: load Y immediate
m_y = m_op & 0xf;
}
void mn1400_cpu_device::op_tax()
{
// TAX: transfer A to X
m_x = m_a;
}
void mn1400_cpu_device::op_tay()
{
// TAY: transfer A to Y
m_y = m_a;
}
void mn1400_cpu_device::op_tya()
{
// TYA: transfer Y to A
m_a = m_y;
set_z(m_a);
}
void mn1400_cpu_device::op_tacu()
{
// TACU: transfer A to counter upper
m_counter = (m_counter & 0xf) | (m_a << 4);
}
void mn1400_cpu_device::op_tacl()
{
// TACL: transfer A to counter lower
m_counter = (m_counter & 0xf0) | m_a;
}
void mn1400_cpu_device::op_tcau()
{
// TCAU: transfer counter upper to A
m_a = m_counter >> 4;
set_z(m_a);
}
void mn1400_cpu_device::op_tcal()
{
// TCAL: transfer counter lower to A
m_a = m_counter & 0xf;
set_z(m_a);
}
@ -120,91 +181,131 @@ void mn1400_cpu_device::op_nop()
void mn1400_cpu_device::op_and()
{
// AND: AND A with memory
m_a &= ram_r();
set_z(m_a);
}
void mn1400_cpu_device::op_andi()
{
// ANDI: AND A with immediate
m_a &= (m_op & 0xf);
set_z(m_a);
}
void mn1400_cpu_device::op_or()
{
// OR: OR A with memory
m_a |= ram_r();
set_z(m_a);
}
void mn1400_cpu_device::op_xor()
{
// XOR: XOR A with memory
m_a ^= ram_r();
set_z(m_a);
}
void mn1400_cpu_device::op_a()
{
// A: add memory + carry to A
u8 c = (m_status & FLAG_C) ? 1 : 0;
m_a += ram_r() + c;
set_cz(m_a);
m_a &= 0xf;
}
void mn1400_cpu_device::op_ai()
{
// AI: add immediate to A
m_a += m_op & 0xf;
set_cz(m_a);
m_a &= 0xf;
}
void mn1400_cpu_device::op_cpl()
{
// CPL: complement A
m_a ^= 0xf;
set_z(m_a);
}
void mn1400_cpu_device::op_c()
{
// C: compare A to memory
// C: compare A with memory
set_cz((m_a ^ 0xf) + ram_r() + 1);
}
void mn1400_cpu_device::op_ci()
{
// CI: compare A to immediate
// CI: compare A with immediate
set_cz(m_a + (~m_op & 0xf) + 1);
}
void mn1400_cpu_device::op_cy()
{
// CY: compare A to Y
// CY: compare A with Y
set_z(m_y ^ (m_op & 0xf));
}
void mn1400_cpu_device::op_sl()
{
// SL: shift left A
m_a += m_a;
set_cz(m_a);
m_a &= 0xf;
}
void mn1400_cpu_device::op_icy()
{
// ICY: increment Y
m_y = (m_y + 1) & 0xf;
set_z(m_y);
}
void mn1400_cpu_device::op_dcy()
{
// DCY: decrement Y
m_y = (m_y - 1) & 0xf;
set_z(m_y);
}
void mn1400_cpu_device::op_icm()
{
// ICM: increment memory
cycle();
u8 temp = ram_r() + 1;
ram_w(temp);
set_cz(temp);
}
void mn1400_cpu_device::op_dcm()
{
// DCM: decrement memory
cycle();
u8 temp = ram_r() - 1;
ram_w(temp);
set_cz(temp);
}
void mn1400_cpu_device::op_sm()
{
// SM: set memory bits
cycle();
ram_w(ram_r() | (m_op & 0xf));
}
void mn1400_cpu_device::op_rm()
{
// RM: reset memory bits
cycle();
ram_w(ram_r() & (~m_op & 0xf));
}
void mn1400_cpu_device::op_tb()
{
// TB: test A bits
set_z(m_a & (m_op & 0xf));
}
@ -261,21 +362,25 @@ void mn1400_cpu_device::op_cco()
void mn1400_cpu_device::op_rc()
{
// RC: reset CF
m_status &= ~FLAG_C;
}
void mn1400_cpu_device::op_rp()
{
// RP: reset PS
m_status &= ~FLAG_P;
}
void mn1400_cpu_device::op_sc()
{
// SC: set CF
m_status |= FLAG_C;
}
void mn1400_cpu_device::op_sp()
{
// SP: set PS
m_status |= FLAG_P;
}
void mn1400_cpu_device::op_bs01()
@ -286,29 +391,40 @@ void mn1400_cpu_device::op_bs01()
void mn1400_cpu_device::op_bpcz()
{
// B(N)P/C/Z: branch on status
u8 mask = m_status & (m_op >> 1 & 7);
if (bool(m_op & 1) == bool(mask))
m_pc = (m_prev_pc & ~0xff) | m_param;
}
void mn1400_cpu_device::op_jmp()
{
// JMP: jump
m_pc = ((m_op & 0xf) << 8 | m_param) & m_prgmask;
}
void mn1400_cpu_device::op_cal()
{
// CAL: call subroutine
m_stack[m_sp] = m_pc;
m_sp = (m_sp + 1) % m_stack_levels;
op_jmp();
}
void mn1400_cpu_device::op_ret()
{
// RET: return from subroutine
m_sp = (m_stack_levels + m_sp - 1) % m_stack_levels;
m_pc = m_stack[m_sp] & m_prgmask;
}
void mn1400_cpu_device::op_ec()
{
// EC: enable counter
m_ec = true;
}
void mn1400_cpu_device::op_dc()
{
// DC: disable counter
m_ec = false;
}