mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
hmcs400: add standby/stop mode
This commit is contained in:
parent
e5f4ac1f3a
commit
1c03b83957
5 changed files with 60 additions and 40 deletions
|
@ -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
|
||||
|
|
|
@ -202,7 +202,7 @@ protected:
|
|||
|
||||
void cycle();
|
||||
void increment_tc();
|
||||
void do_interrupt();
|
||||
void take_interrupt();
|
||||
|
||||
// opcode handlers
|
||||
void op_illegal();
|
||||
|
|
|
@ -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 (line != 0 && line != 1)
|
||||
return;
|
||||
|
||||
if (irq)
|
||||
ext_int_edge(line);
|
||||
// active-low, irq on falling edge
|
||||
state ^= 1;
|
||||
bool irq = (m_int_line[line] && !state);
|
||||
m_int_line[line] = state;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue