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; virtual bool op_has_param(u8 op) override;
// opcode helpers // opcode helpers
u8 ram_r();
void ram_w(u8 data);
void set_z(u8 data);
void set_cz(u8 data);
void op_illegal(); void op_illegal();
// opcode handlers // opcode handlers

View File

@ -59,12 +59,17 @@ void mn1400_base_device::device_start()
m_op = 0; m_op = 0;
m_prev_op = 0; m_prev_op = 0;
m_param = 0; m_param = 0;
m_ram_address = 0;
memset(m_stack, 0, sizeof(m_stack));
m_sp = 0;
m_a = 0; m_a = 0;
m_x = 0; m_x = 0;
m_y = 0; m_y = 0;
m_status = 0; m_status = 0;
m_c = 0;
m_counter = 0; m_counter = 0;
m_ec = false;
// register for savestates // register for savestates
save_item(NAME(m_pc)); save_item(NAME(m_pc));
@ -72,12 +77,17 @@ void mn1400_base_device::device_start()
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_param)); 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_a));
save_item(NAME(m_x)); save_item(NAME(m_x));
save_item(NAME(m_y)); save_item(NAME(m_y));
save_item(NAME(m_status)); save_item(NAME(m_status));
save_item(NAME(m_c));
save_item(NAME(m_counter)); save_item(NAME(m_counter));
save_item(NAME(m_ec));
// register state for debugger // register state for debugger
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%03X").noshow(); 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, "A", m_a).formatstr("%01X"); // 2
state_add(++m_state_count, "X", m_x).formatstr("%01X"); // 3 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, "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); set_icountptr(m_icount);
} }
@ -125,7 +135,10 @@ void mn1400_base_device::device_reset()
{ {
m_pc = m_prev_pc = 0; m_pc = m_prev_pc = 0;
m_op = m_prev_op = 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(); cycle();
} }
m_ram_address = (m_x << 4 | m_y) & m_datamask;
execute_one(); execute_one();
} }
} }

View File

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

View File

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