summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/melps4/melps4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/melps4/melps4.c')
-rw-r--r--src/emu/cpu/melps4/melps4.c108
1 files changed, 97 insertions, 11 deletions
diff --git a/src/emu/cpu/melps4/melps4.c b/src/emu/cpu/melps4/melps4.c
index 5fdd2b1cab6..c4309c6a3b9 100644
--- a/src/emu/cpu/melps4/melps4.c
+++ b/src/emu/cpu/melps4/melps4.c
@@ -46,12 +46,15 @@ void melps4_cpu_device::state_string_export(const device_state_entry &entry, std
{
// obviously not from a single flags register, letters are made up
case STATE_GENFLAGS:
- strprintf(str, "%c%c%c%c%c",
+ strprintf(str, "%c%c%c%c%c %c%c%c",
m_intp ? 'P':'p',
m_inte ? 'I':'i',
m_sm ? 'S':'s',
m_cps ? 'D':'d',
- m_cy ? 'C':'c'
+ m_cy ? 'C':'c',
+ m_irqflag[0] ? 'X':'.', // exf
+ m_irqflag[1] ? '1':'.', // 1f
+ m_irqflag[2] ? '2':'.' // 2f
);
break;
@@ -111,7 +114,11 @@ void melps4_cpu_device::device_start()
m_skip = false;
m_inte = 0;
m_intp = 1;
+ m_irqflag[0] = m_irqflag[1] = m_irqflag[2] = false;
+ m_tmr_irq_enabled[0] = m_tmr_irq_enabled[1] = false;
+ m_int_state = 0;
m_prohibit_irq = false;
+ m_possible_irq = false;
m_a = 0;
m_b = 0;
@@ -147,7 +154,11 @@ void melps4_cpu_device::device_start()
save_item(NAME(m_skip));
save_item(NAME(m_inte));
save_item(NAME(m_intp));
+ save_item(NAME(m_irqflag));
+ save_item(NAME(m_tmr_irq_enabled));
+ save_item(NAME(m_int_state));
save_item(NAME(m_prohibit_irq));
+ save_item(NAME(m_possible_irq));
save_item(NAME(m_a));
save_item(NAME(m_b));
@@ -165,7 +176,7 @@ void melps4_cpu_device::device_start()
// register state for debugger
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow();
- state_add(STATE_GENFLAGS, "GENFLAGS", m_cy).formatstr("%5s").noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_cy).formatstr("%9s").noshow();
state_add(MELPS4_PC, "PC", m_pc).formatstr("%04X");
state_add(MELPS4_A, "A", m_a).formatstr("%2d"); // show in decimal
@@ -194,18 +205,20 @@ void melps4_cpu_device::device_reset()
{
m_sm = m_sms = false;
m_ba_flag = false;
- m_prohibit_irq = false;
-
m_skip = false;
m_op = m_prev_op = 0;
m_pc = m_prev_pc = 0;
+ op_lcps(); // CPS=0
+
+ // clear interrupts
m_inte = 0;
m_intp = 1;
- op_lcps(); // CPS=0
+ write_v(0);
+ write_w(0);
+ m_irqflag[0] = m_irqflag[1] = m_irqflag[2] = false;
+ m_prohibit_irq = false;
+ m_possible_irq = false;
- m_v = 0;
- m_w = 0;
-
// clear ports
write_d_pin(MELPS4_PORTD_CLR, 0);
write_gen_port(MELPS4_PORTS, 0);
@@ -292,6 +305,73 @@ void melps4_cpu_device::write_d_pin(int bit, int state)
//-------------------------------------------------
+// interrupts
+//-------------------------------------------------
+
+void melps4_cpu_device::execute_set_input(int line, int state)
+{
+ state = (state) ? 1 : 0;
+
+ switch (line)
+ {
+ // external interrupt
+ case MELPS4_INPUT_LINE_INT:
+ // irq on rising/falling edge
+ if (state != m_int_state && state == m_intp)
+ {
+ m_irqflag[0] = true;
+ m_possible_irq = true;
+ }
+ m_int_state = state;
+ break;
+
+ // timer input pin
+ case MELPS4_INPUT_LINE_T:
+ break;
+
+ default:
+ break;
+ }
+}
+
+void melps4_cpu_device::do_interrupt(int which)
+{
+ m_inte = 0;
+ m_irqflag[which] = false;
+
+ m_icount--;
+ push_pc();
+ m_sms = m_sm;
+ m_sm = false;
+ m_op = 0; // fake nop
+ m_pc = m_int_page << 7 | (which * 2);
+
+ standard_irq_callback(which);
+}
+
+void melps4_cpu_device::check_interrupt()
+{
+ if (!m_inte)
+ return;
+
+ int which = 0;
+
+ // assume that lower irq vectors have higher priority
+ if (m_irqflag[0])
+ which = 0;
+ else if (m_irqflag[1] && m_tmr_irq_enabled[0])
+ which = 1;
+ else if (m_irqflag[2] && m_tmr_irq_enabled[1])
+ which = 2;
+ else
+ return;
+
+ do_interrupt(which);
+}
+
+
+
+//-------------------------------------------------
// execute
//-------------------------------------------------
@@ -314,8 +394,14 @@ void melps4_cpu_device::execute_run()
m_prev_op = m_op;
m_prev_pc = m_pc;
- // irq is not accepted during skip or LXY, LA, EI, DI, RT/RTS/RTI or any branch
- //..
+ // Interrupts are not accepted during skips or LXY, LA, EI, DI, RT/RTS/RTI or any branch.
+ // Documentation is conflicting here: older docs say that it is allowed during skips,
+ // newer docs specifically say when interrupts are prohibited.
+ if (m_possible_irq && !m_prohibit_irq && !m_skip)
+ {
+ m_possible_irq = false;
+ check_interrupt();
+ }
m_prohibit_irq = false;
// fetch next opcode