From 1c03b839577289a33ed4e1d1482269e0f98b0e2d Mon Sep 17 00:00:00 2001 From: hap Date: Fri, 20 Sep 2024 19:36:47 +0200 Subject: hmcs400: add standby/stop mode --- src/devices/cpu/hmcs40/hmcs40.cpp | 4 +- src/devices/cpu/hmcs40/hmcs40.h | 2 +- src/devices/cpu/hmcs400/hmcs400.cpp | 85 ++++++++++++++++++++--------------- src/devices/cpu/hmcs400/hmcs400.h | 3 ++ src/devices/cpu/hmcs400/hmcs400op.cpp | 6 ++- 5 files changed, 60 insertions(+), 40 deletions(-) diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp index b7139f0cce6..38e150b9575 100644 --- a/src/devices/cpu/hmcs40/hmcs40.cpp +++ b/src/devices/cpu/hmcs40/hmcs40.cpp @@ -458,7 +458,7 @@ void hmcs45_cpu_device::write_r(u8 index, u8 data) // interrupt/timer //------------------------------------------------- -void hmcs40_cpu_device::do_interrupt() +void hmcs40_cpu_device::take_interrupt() { push_stack(); m_ie = 0; @@ -576,7 +576,7 @@ void hmcs40_cpu_device::execute_run() // check/handle interrupt if (m_ie && (m_iri || m_irt) && !m_block_int) - do_interrupt(); + take_interrupt(); m_block_int = false; // fetch next opcode diff --git a/src/devices/cpu/hmcs40/hmcs40.h b/src/devices/cpu/hmcs40/hmcs40.h index a08e5a2949e..c1c24d81b0d 100644 --- a/src/devices/cpu/hmcs40/hmcs40.h +++ b/src/devices/cpu/hmcs40/hmcs40.h @@ -202,7 +202,7 @@ protected: void cycle(); void increment_tc(); - void do_interrupt(); + void take_interrupt(); // opcode handlers void op_illegal(); diff --git a/src/devices/cpu/hmcs400/hmcs400.cpp b/src/devices/cpu/hmcs400/hmcs400.cpp index c54b4beef93..ced9ac4d7f5 100644 --- a/src/devices/cpu/hmcs400/hmcs400.cpp +++ b/src/devices/cpu/hmcs400/hmcs400.cpp @@ -166,8 +166,6 @@ hd614089_device::hd614089_device(const machine_config &mconfig, const char *tag, void hmcs400_cpu_device::device_start() { - assert(HMCS400_INPUT_LINE_INT0 == 0 && HMCS400_INPUT_LINE_INT1 == 1); - m_program = &space(AS_PROGRAM); m_data = &space(AS_DATA); @@ -188,6 +186,8 @@ void hmcs400_cpu_device::device_start() m_spy = 0; m_st = 0; m_ca = 0; + m_standby = false; + m_stop = false; memset(m_r, 0, sizeof(m_r)); memset(m_r_mask, 0, sizeof(m_r_mask)); @@ -219,6 +219,8 @@ void hmcs400_cpu_device::device_start() save_item(NAME(m_spy)); save_item(NAME(m_st)); save_item(NAME(m_ca)); + save_item(NAME(m_standby)); + save_item(NAME(m_stop)); save_item(NAME(m_r)); save_item(NAME(m_r_mask)); @@ -262,6 +264,8 @@ void hmcs400_cpu_device::device_reset() m_pc = 0; m_sp = 0x3ff; m_st = 1; + m_standby = false; + m_stop = false; // clear peripherals m_irq_flags = 0xaaa8; // IM=1, IF=0, IE=0 @@ -535,29 +539,37 @@ void hmcs400_cpu_device::pmr_w(offs_t offset, u8 data, u8 mem_mask) write_r(3, m_r[3]); } +void hmcs400_cpu_device::take_interrupt(int irq) +{ + cycle(); + cycle(); + push_stack(); + m_irq_flags &= ~1; + + standard_irq_callback(irq, m_pc); + + u8 vector = irq * 2 + 2; + m_prev_pc = m_pc = vector; +} + void hmcs400_cpu_device::check_interrupts() { - // irq priority and vectors are in the same order as the irq control flags - u16 irq = m_irq_flags; + // irq priority is in the same order as the irq control flags + u16 irq = m_irq_flags >> 2; for (int i = 0; i < 7; i++) { - irq >>= 2; - - // do irq when IF=1 and IM=0 + // pending irq when IF=1 and IM=0 if ((irq & 3) == 1) { - cycle(); - cycle(); - push_stack(); - m_irq_flags &= ~1; + if (m_irq_flags & 1) + take_interrupt(i); - standard_irq_callback(i, m_pc); - - m_pc = i * 2 + 2; - m_prev_pc = m_pc; + m_standby = false; return; } + + irq >>= 2; } } @@ -578,24 +590,16 @@ void hmcs400_cpu_device::execute_set_input(int line, int state) { state = state ? 1 : 0; - switch (line) - { - case HMCS400_INPUT_LINE_INT0: case HMCS400_INPUT_LINE_INT1: - { - // active-low, irq on falling edge - state ^= 1; - bool irq = (m_int_line[line] && !state); - m_int_line[line] = state; - - if (irq) - ext_int_edge(line); + if (line != 0 && line != 1) + return; - break; - } + // active-low, irq on falling edge + state ^= 1; + bool irq = (m_int_line[line] && !state); + m_int_line[line] = state; - default: - break; - } + if (irq && !m_stop) + ext_int_edge(line); } @@ -615,7 +619,7 @@ void hmcs400_cpu_device::tm_w(offs_t offset, u8 data, u8 mem_mask) { 0x400, 0x100, 0x40, 0x10, 4, 2, 1, 0 } }; - m_timer_mode[offset] = data; + m_timer_mode[offset] = data & 0xf; m_timer_div[offset] = div[offset][data & 7]; } @@ -705,13 +709,24 @@ u16 hmcs400_cpu_device::fetch() void hmcs400_cpu_device::execute_run() { + // in stop mode, the internal clock is not running + if (m_stop) + { + m_icount = 0; + return; + } + while (m_icount > 0) { m_prev_pc = m_pc; + check_interrupts(); - // check/handle interrupts - if (m_irq_flags & 1) - check_interrupts(); + // in standby mode, opcode execution is halted + if (m_standby) + { + cycle(); + continue; + } // fetch next opcode debugger_instruction_hook(m_pc); diff --git a/src/devices/cpu/hmcs400/hmcs400.h b/src/devices/cpu/hmcs400/hmcs400.h index 8232dddb704..e3776cb39fd 100644 --- a/src/devices/cpu/hmcs400/hmcs400.h +++ b/src/devices/cpu/hmcs400/hmcs400.h @@ -138,6 +138,8 @@ protected: u8 m_spy; // 4-bit SPY register u8 m_st; // status flag u8 m_ca; // carry flag + bool m_standby; // standby mode (SBY opcode) + bool m_stop; // stop mode (STOP opcode) u8 m_r[10]; // R outputs state u8 m_r_mask[10]; @@ -183,6 +185,7 @@ protected: u8 tcbu_r(offs_t offset, u8 mem_mask); void ext_int_edge(int line); + void take_interrupt(int irq); void check_interrupts(); void clock_timer(int timer); void clock_prescaler(); diff --git a/src/devices/cpu/hmcs400/hmcs400op.cpp b/src/devices/cpu/hmcs400/hmcs400op.cpp index d67b7711965..19cecc44b6a 100644 --- a/src/devices/cpu/hmcs400/hmcs400op.cpp +++ b/src/devices/cpu/hmcs400/hmcs400op.cpp @@ -676,11 +676,13 @@ void hmcs400_cpu_device::op_sts() void hmcs400_cpu_device::op_sby() { // SBY: Standby Mode - op_todo(); + m_standby = true; } void hmcs400_cpu_device::op_stop() { // STOP: Stop Mode - op_todo(); + m_stop = true; + if (m_icount > 0) + m_icount = 0; } -- cgit v1.2.3