diff --git a/src/devices/cpu/mn1880/mn1880.cpp b/src/devices/cpu/mn1880/mn1880.cpp index 628a27561b4..e07a0da0341 100644 --- a/src/devices/cpu/mn1880/mn1880.cpp +++ b/src/devices/cpu/mn1880/mn1880.cpp @@ -76,15 +76,14 @@ mn1880_device::mn1880_device(const machine_config &mconfig, device_type type, co : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_BIG, 8, 16, 0) , m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0, data_map) - , m_cpu_select(false) , m_cpum(0) , m_ustate(microstate::UNKNOWN) , m_da(0) , m_tmp1(0) , m_tmp2(0) - , m_output_queued(false) + , m_output_queue_state(0xff) , m_icount(0) - , m_ie{0, 0} + , m_if(0) { } @@ -95,22 +94,26 @@ mn1880_device::mn1880_device(const machine_config &mconfig, const char *tag, dev u8 mn1880_device::ie0_r() { - return m_ie[0]; + return (get_active_cpu().ie & 0x00f) | (m_cpu[0].iemask ? 0x10 : 0) | (m_cpu[1].iemask ? 0x20 : 0); } void mn1880_device::ie0_w(u8 data) { - m_ie[0] = data; + cpu_registers &cpu = output_queued() ? m_cpu[m_output_queue_state] : get_active_cpu(); + cpu.ie = (cpu.ie & 0xff0) | (data & 0x0f); + m_cpu[0].iemask = BIT(data, 4); + m_cpu[1].iemask = BIT(data, 5); } u8 mn1880_device::ie1_r() { - return m_ie[1]; + return (get_active_cpu().ie & 0xff0) >> 4; } void mn1880_device::ie1_w(u8 data) { - m_ie[1] = data; + cpu_registers &cpu = output_queued() ? m_cpu[m_output_queue_state] : get_active_cpu(); + cpu.ie = u16(data) << 4 | (cpu.ie & 0x00f); } u8 mn1880_device::cpum_r() @@ -120,7 +123,7 @@ u8 mn1880_device::cpum_r() void mn1880_device::cpum_w(u8 data) { - m_cpum = data; + m_cpum = (data & 0xef) | (m_cpum & 0x10); } void mn1880_device::internal_data_map(address_map &map) @@ -151,60 +154,68 @@ void mn1880_device::device_start() using namespace std::placeholders; state_add(MN1880_IP, "IP", - [this] () { return m_cpu[int(m_cpu_select)].ip; }, - [this] (u16 data) { m_cpu[int(m_cpu_select)].ip = data; } + [this] () { return get_active_cpu().ip; }, + [this] (u16 data) { get_active_cpu().ip = data; } ).noshow(); state_add(STATE_GENPC, "GENPC", - [this] () { return m_cpu[int(m_cpu_select)].ip; }, - [this] (u16 data) { m_cpu[int(m_cpu_select)].ip = data; } + [this] () { return get_active_cpu().ip; }, + [this] (u16 data) { get_active_cpu().ip = data; } ).noshow(); state_add(STATE_GENPCBASE, "CURPC", - [this] () { return m_cpu[int(m_cpu_select)].irp; }, - [this] (u16 data) { m_cpu[int(m_cpu_select)].irp = data; } + [this] () { return get_active_cpu().irp; }, + [this] (u16 data) { get_active_cpu().irp = data; } ).noshow(); state_add(MN1880_IR, "IR", - [this] () { return m_cpu[int(m_cpu_select)].ir; }, - [this] (u8 data) { m_cpu[int(m_cpu_select)].ir = data; } + [this] () { return get_active_cpu().ir; }, + [this] (u8 data) { get_active_cpu().ir = data; } ).noshow(); state_add(MN1880_FS, "FS", - [this] () { return m_cpu[int(m_cpu_select)].fs; }, - [this] (u8 data) { m_cpu[int(m_cpu_select)].fs = data; } + [this] () { return get_active_cpu().fs; }, + [this] (u8 data) { get_active_cpu().fs = data; } ).noshow(); state_add(STATE_GENFLAGS, "FLAGS", - [this] () { return m_cpu[int(m_cpu_select)].fs; }, - [this] (u8 data) { m_cpu[int(m_cpu_select)].fs = data; } + [this] () { return get_active_cpu().fs; }, + [this] (u8 data) { get_active_cpu().fs = data; } ).formatstr("%10s").noshow(); state_add(MN1880_XP, "XP", - [this] () { return m_cpu[int(m_cpu_select)].xp; }, - [this] (u16 data) { m_cpu[int(m_cpu_select)].xp = data; } + [this] () { return get_active_cpu().xp; }, + [this] (u16 data) { get_active_cpu().xp = data; } ).noshow(); state_add(MN1880_YP, "YP", - [this] () { return m_cpu[int(m_cpu_select)].yp; }, - [this] (u16 data) { m_cpu[int(m_cpu_select)].yp = data; } + [this] () { return get_active_cpu().yp; }, + [this] (u16 data) { get_active_cpu().yp = data; } ).noshow(); state_add(MN1880_XPL, "XPl", - [this] () { return m_cpu[int(m_cpu_select)].xp & 0x00ff; }, - [this] (u8 data) { setl(m_cpu[int(m_cpu_select)].xp, data); } + [this] () { return get_active_cpu().xp & 0x00ff; }, + [this] (u8 data) { setl(get_active_cpu().xp, data); } ).noshow(); state_add(MN1880_XPH, "XPh", - [this] () { return (m_cpu[int(m_cpu_select)].xp & 0xff00 >> 8); }, - [this] (u8 data) { seth(m_cpu[int(m_cpu_select)].xp, data); } + [this] () { return (get_active_cpu().xp & 0xff00 >> 8); }, + [this] (u8 data) { seth(get_active_cpu().xp, data); } ).noshow(); state_add(MN1880_YPL, "YPl", - [this] () { return m_cpu[int(m_cpu_select)].yp & 0x00ff; }, - [this] (u8 data) { setl(m_cpu[int(m_cpu_select)].yp, data); } + [this] () { return get_active_cpu().yp & 0x00ff; }, + [this] (u8 data) { setl(get_active_cpu().yp, data); } ).noshow(); state_add(MN1880_YPH, "YPh", - [this] () { return (m_cpu[int(m_cpu_select)].yp & 0xff00 >> 8); }, - [this] (u8 data) { seth(m_cpu[int(m_cpu_select)].yp, data); } + [this] () { return (get_active_cpu().yp & 0xff00 >> 8); }, + [this] (u8 data) { seth(get_active_cpu().yp, data); } ).noshow(); state_add(MN1880_SP, "SP", - [this] () { return m_cpu[int(m_cpu_select)].sp; }, - [this] (u16 data) { m_cpu[int(m_cpu_select)].sp = data; } + [this] () { return get_active_cpu().sp; }, + [this] (u16 data) { get_active_cpu().sp = data; } ).noshow(); state_add(MN1880_LP, "LP", - [this] () { return m_cpu[int(m_cpu_select)].lp; }, - [this] (u16 data) { m_cpu[int(m_cpu_select)].lp = data; } + [this] () { return get_active_cpu().lp; }, + [this] (u16 data) { get_active_cpu().lp = data; } + ).noshow(); + state_add(MN1880_IE, "IE", + [this] () { return get_active_cpu().ie; }, + [this] (u16 data) { get_active_cpu().ie = data; } + ).mask(0xfff).noshow(); + state_add(MN1880_IE, "IEMASK", + [this] () { return get_active_cpu().iemask; }, + [this] (bool data) { get_active_cpu().iemask = data; } ).noshow(); for (int i = 0; i < 2; i++) @@ -216,11 +227,12 @@ void mn1880_device::device_start() state_add(MN1880_YPA + i, util::string_format("YP%c", 'a' + i).c_str(), m_cpu[i].yp); state_add(MN1880_SPA + i, util::string_format("SP%c", 'a' + i).c_str(), m_cpu[i].sp); state_add(MN1880_LPA + i, util::string_format("LP%c", 'a' + i).c_str(), m_cpu[i].lp); + state_add(MN1880_IEA + i, util::string_format("IE%c", 'a' + i).c_str(), m_cpu[i].ie).mask(0xfff); + state_add(MN1880_IEMASKA + i, util::string_format("IEMASK%c", 'a' + i).c_str(), m_cpu[i].iemask); state_add_divider(MN1880_DIVIDER1 + i); } - state_add(MN1880_IE0, "IE0", m_ie[0]); - state_add(MN1880_IE1, "IE1", m_ie[1]); + state_add(MN1880_IF, "IF", m_if).mask(0xfff); state_add(MN1880_CPUM, "CPUM", m_cpum); save_item(STRUCT_MEMBER(m_cpu, ip)); @@ -231,14 +243,15 @@ void mn1880_device::device_start() save_item(STRUCT_MEMBER(m_cpu, yp)); save_item(STRUCT_MEMBER(m_cpu, sp)); save_item(STRUCT_MEMBER(m_cpu, lp)); - save_item(NAME(m_cpu_select)); + save_item(STRUCT_MEMBER(m_cpu, ie)); + save_item(STRUCT_MEMBER(m_cpu, iemask)); + save_item(NAME(m_if)); save_item(NAME(m_cpum)); save_item(NAME(m_ustate)); save_item(NAME(m_da)); save_item(NAME(m_tmp1)); save_item(NAME(m_tmp2)); - save_item(NAME(m_output_queued)); - save_item(NAME(m_ie)); + save_item(NAME(m_output_queue_state)); } void mn1880_device::device_reset() @@ -249,6 +262,8 @@ void mn1880_device::device_reset() cpu.fs |= 0x10; // HACK: skip fake first instruction in debugger cpu.ir = 0xf6; cpu.wait = 0; + cpu.ie = 0; + cpu.iemask = true; } m_cpu[0].ip = 0x0000; m_cpu[1].ip = 0x0020; @@ -259,11 +274,10 @@ void mn1880_device::device_reset() m_cpu[1].sp = 0x0200; m_cpu[1].lp = 0x0160; - m_ie[0] = 0x30; - m_ie[1] = 0x00; + m_if = 0; m_cpum = 0x0c; m_ustate = microstate::NEXT; - m_output_queued = false; + m_output_queue_state = 0xff; } const mn1880_device::microstate mn1880_device::s_decode_map[256] = @@ -440,13 +454,13 @@ void mn1880_device::cpu_registers::branch(u16 label) void mn1880_device::swap_cpus() { - if ((m_cpum & 0x03) != (m_cpu_select ? 0x01 : 0x02)) - m_cpu_select = !m_cpu_select; + if ((m_cpum & 0x03) != (BIT(m_cpum, 4) ? 0x01 : 0x02)) + m_cpum ^= 0x10; } void mn1880_device::next_instruction(u8 input) { - cpu_registers &cpu = m_cpu[int(m_cpu_select)]; + cpu_registers &cpu = get_active_cpu(); if ((cpu.fs & 0x0f) != 0) cpu.fs = (cpu.fs - 1) | 0x10; else @@ -464,13 +478,13 @@ void mn1880_device::execute_run() { while (m_icount-- > 0) { - cpu_registers &cpu = m_cpu[int(m_cpu_select)]; + cpu_registers &cpu = get_active_cpu(); if (m_ustate == microstate::NEXT && cpu.wait == 0) { if (!BIT(cpu.fs, 4)) debugger_instruction_hook(cpu.irp); - if (!m_output_queued && !BIT(s_input_queue_map[cpu.ir >> 4], cpu.ir & 0x0f)) + if (!output_queued() && !BIT(s_input_queue_map[cpu.ir >> 4], cpu.ir & 0x0f)) m_ustate = s_decode_map[cpu.ir]; } @@ -485,10 +499,10 @@ void mn1880_device::execute_run() } else { - if (m_output_queued) + if (output_queued()) { m_data.write_byte(m_da, m_tmp1 & 0x00ff); - m_output_queued = false; + m_output_queue_state = 0xff; } if (BIT(s_input_queue_map[cpu.ir >> 4], cpu.ir & 0x0f)) { @@ -569,7 +583,7 @@ void mn1880_device::execute_run() m_da = cpu.xp; if ((cpu.fs & 0x1f) != 0) ++cpu.xp; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -597,7 +611,7 @@ void mn1880_device::execute_run() case microstate::MOVL35_4: m_tmp1 = m_data.read_byte(cpu.yp); m_da = m_tmp2 + 1; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -612,7 +626,7 @@ void mn1880_device::execute_run() m_da = cpu.xp; if ((cpu.fs & 0x1f) != 0) ++cpu.xp; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -660,7 +674,7 @@ void mn1880_device::execute_run() m_data.write_byte(m_da, m_tmp1 & 0x00ff); ++m_da; m_tmp1 >>= 8; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -679,7 +693,7 @@ void mn1880_device::execute_run() m_tmp1 = m_data.read_byte(m_da); // TODO: read latch instead of terminal cpu.fs = (m_tmp1 & 0x80) | (cpu.fs & 0x7f); m_tmp1 <<= 1; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -696,7 +710,7 @@ void mn1880_device::execute_run() case microstate::ASR_2: m_tmp1 = cpu.asrc(m_data.read_byte(m_da)); // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -812,7 +826,7 @@ void mn1880_device::execute_run() case microstate::XCH4_2: m_tmp1 = m_data.read_byte(m_da); // TODO: read latch instead of terminal m_tmp1 = (m_tmp1 << 4) | (m_tmp1 >> 4); - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -867,7 +881,7 @@ void mn1880_device::execute_run() case microstate::ROL_2: m_tmp1 = cpu.rolc(m_data.read_byte(m_da)); // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -888,7 +902,7 @@ void mn1880_device::execute_run() case microstate::ROR_2: m_tmp1 = cpu.rorc(m_data.read_byte(m_da)); // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -948,7 +962,7 @@ void mn1880_device::execute_run() m_data.write_byte(m_da, m_tmp1 & 0x00ff); ++m_da; cpu.xp = m_da; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1050,7 +1064,7 @@ void mn1880_device::execute_run() m_data.write_byte(m_da, m_tmp1 & 0x00ff); m_tmp1 >>= 8; m_da = m_tmp2; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1095,7 +1109,7 @@ void mn1880_device::execute_run() if ((cpu.fs & 0x1f) != 0) ++cpu.xp; m_tmp1 >>= 8; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1160,7 +1174,7 @@ void mn1880_device::execute_run() case microstate::MOVL5E_4: m_tmp1 = m_data.read_byte(m_da); m_da = m_tmp2 + 1; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1272,7 +1286,7 @@ void mn1880_device::execute_run() cpu.fs |= 0x40; else cpu.fs &= 0xbf; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1321,7 +1335,7 @@ void mn1880_device::execute_run() cpu.fs |= 0x40; else cpu.fs &= 0xbf; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1370,7 +1384,7 @@ void mn1880_device::execute_run() cpu.fs |= 0x40; else cpu.fs &= 0xbf; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1415,7 +1429,7 @@ void mn1880_device::execute_run() case microstate::SUBC_3: m_tmp1 = cpu.subcz(m_data.read_byte(m_da), m_tmp1, BIT(cpu.fs, 7), BIT(cpu.fs, 4)); // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1460,7 +1474,7 @@ void mn1880_device::execute_run() case microstate::SUBD_3: m_tmp1 = cpu.subdcz(m_data.read_byte(m_da), m_tmp1, BIT(cpu.fs, 7)); // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1474,7 +1488,7 @@ void mn1880_device::execute_run() else cpu.fs &= 0xbf; } - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1519,7 +1533,7 @@ void mn1880_device::execute_run() case microstate::ADDC_3: m_tmp1 = cpu.addcz(m_data.read_byte(m_da), m_tmp1, BIT(cpu.fs, 7), BIT(cpu.fs, 4)); // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1577,7 +1591,7 @@ void mn1880_device::execute_run() else cpu.fs &= 0xbf; } - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1703,7 +1717,7 @@ void mn1880_device::execute_run() m_tmp1 = cpu.subcz(m_data.read_byte(m_da), m_tmp1, BIT(cpu.fs, 7), true); // TODO: read latch instead of terminal if (!BIT(cpu.ir, 1)) cpu.xp = m_da + 1; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1757,7 +1771,7 @@ void mn1880_device::execute_run() m_tmp1 = cpu.addcz(m_data.read_byte(m_da), m_tmp1, BIT(cpu.fs, 7), true); // TODO: read latch instead of terminal if (!BIT(cpu.ir, 1)) cpu.xp = m_da + 1; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -1822,7 +1836,7 @@ void mn1880_device::execute_run() m_tmp1 = m_data.read_byte(m_da); // TODO: read latch instead of terminal cpu.sp = m_da + 1; m_da = m_tmp2; - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -2175,13 +2189,13 @@ void mn1880_device::execute_run() case microstate::MOV1_4: m_tmp1 |= m_data.read_byte(m_da); // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; case microstate::MOV1N_4: m_tmp1 = m_data.read_byte(m_da) & ~m_tmp1; // TODO: read latch instead of terminal - m_output_queued = true; + set_output_queued(); next_instruction(input); break; @@ -2334,7 +2348,7 @@ void mn1880_device::state_string_export(const device_state_entry &entry, std::st { case STATE_GENFLAGS: { - u8 fs = m_cpu[int(m_cpu_select)].fs; + u8 fs = get_active_cpu().fs; str = string_format("%c%c%c%c RC=%-2d", BIT(fs, 7) ? 'C' : '.', // Carry flag BIT(fs, 6) ? 'Z' : '.', // Zero flag @@ -2345,11 +2359,11 @@ void mn1880_device::state_string_export(const device_state_entry &entry, std::st } case MN1880_IPA: - str = string_format("%04X%c", m_cpu[0].ip, m_cpu_select ? ' ' : '*'); + str = string_format("%04X%c", m_cpu[0].ip, BIT(m_cpum, 4) ? ' ' : '*'); break; case MN1880_IPB: - str = string_format("%04X%c", m_cpu[1].ip, m_cpu_select ? '*' : ' '); + str = string_format("%04X%c", m_cpu[1].ip, BIT(m_cpum, 4) ? '*' : ' '); break; } } diff --git a/src/devices/cpu/mn1880/mn1880.h b/src/devices/cpu/mn1880/mn1880.h index 7d3e060998f..b0d09abbfe6 100644 --- a/src/devices/cpu/mn1880/mn1880.h +++ b/src/devices/cpu/mn1880/mn1880.h @@ -21,8 +21,10 @@ public: MN1880_YPL, MN1880_YPH, MN1880_SP, MN1880_SPA, MN1880_SPB, MN1880_LP, MN1880_LPA, MN1880_LPB, + MN1880_IE, MN1880_IEA, MN1880_IEB, + MN1880_IEMASK, MN1880_IEMASKA, MN1880_IEMASKB, MN1880_DIVIDER1, MN1880_DIVIDER2, - MN1880_IE0, MN1880_IE1, + MN1880_IF, MN1880_CPUM }; @@ -50,7 +52,7 @@ protected: private: struct cpu_registers { - cpu_registers() : ip(0), irp(0), ir(0), fs(0), xp(0), yp(0), sp(0), lp(0), wait(0) { } + cpu_registers() : ip(0), irp(0), ir(0), fs(0), xp(0), yp(0), sp(0), lp(0), wait(0), ie(0), iemask(false) { } u8 addcz(u8 data1, u8 data2, bool carry, bool holdz); u8 adddcz(u8 data1, u8 data2, bool carry); @@ -70,6 +72,8 @@ private: u16 sp; u16 lp; u16 wait; + u16 ie; + bool iemask; }; enum class microstate : u8 { @@ -172,6 +176,11 @@ private: static void setl(u16 &pr, u8 data) { pr = (pr & 0xff00) | data; } static void seth(u16 &pr, u8 data) { pr = (pr & 0x00ff) | (data << 8); } + cpu_registers &get_active_cpu() { return m_cpu[BIT(m_cpum, 4)]; } + const cpu_registers &get_active_cpu() const { return m_cpu[BIT(m_cpum, 4)]; } + bool output_queued() const { return m_output_queue_state != 0xff; } + void set_output_queued() { m_output_queue_state = BIT(m_cpum, 4); } + u8 ie0_r(); void ie0_w(u8 data); u8 ie1_r(); @@ -196,17 +205,16 @@ private: // execution state cpu_registers m_cpu[2]; - bool m_cpu_select; u8 m_cpum; microstate m_ustate; u16 m_da; u16 m_tmp1; u16 m_tmp2; - bool m_output_queued; + u8 m_output_queue_state; s32 m_icount; // interrupt state - u8 m_ie[2]; + u16 m_if; }; DECLARE_DEVICE_TYPE(MN1880, mn1880_device)