From ce807c207f2bc123cadcc52a50e8865e0f875dbe Mon Sep 17 00:00:00 2001 From: hap Date: Sun, 7 May 2023 03:10:58 +0200 Subject: mn1400: add most opcodes --- src/devices/cpu/mn1400/mn1400.h | 4 ++ src/devices/cpu/mn1400/mn1400base.cpp | 18 ++++- src/devices/cpu/mn1400/mn1400base.h | 7 +- src/devices/cpu/mn1400/mn1400op.cpp | 126 ++++++++++++++++++++++++++++++++-- 4 files changed, 147 insertions(+), 8 deletions(-) diff --git a/src/devices/cpu/mn1400/mn1400.h b/src/devices/cpu/mn1400/mn1400.h index 3dfb42009a4..1f31fc39f5e 100644 --- a/src/devices/cpu/mn1400/mn1400.h +++ b/src/devices/cpu/mn1400/mn1400.h @@ -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 diff --git a/src/devices/cpu/mn1400/mn1400base.cpp b/src/devices/cpu/mn1400/mn1400base.cpp index 2877e750a55..d6868956925 100644 --- a/src/devices/cpu/mn1400/mn1400base.cpp +++ b/src/devices/cpu/mn1400/mn1400base.cpp @@ -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(); } } diff --git a/src/devices/cpu/mn1400/mn1400base.h b/src/devices/cpu/mn1400/mn1400base.h index 161fc9a185c..b0596a46dd7 100644 --- a/src/devices/cpu/mn1400/mn1400base.h +++ b/src/devices/cpu/mn1400/mn1400base.h @@ -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, diff --git a/src/devices/cpu/mn1400/mn1400op.cpp b/src/devices/cpu/mn1400/mn1400op.cpp index 60904f55df6..eb37c18ebd8 100644 --- a/src/devices/cpu/mn1400/mn1400op.cpp +++ b/src/devices/cpu/mn1400/mn1400op.cpp @@ -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; } -- cgit v1.2.3