summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-01-02 11:42:05 -0500
committer AJR <ajrhacker@users.noreply.github.com>2019-01-02 11:51:52 -0500
commit9b86a0fd86d04b427e86ec0f20e38c4efeba69a0 (patch)
treef953c98d0317ad14a036961f88ecba0739916677
parentb841540955f5fc00ef04eb84b7f22645e909d4e3 (diff)
68340: Interrupt overhaul
- Interrupts are now properly acknowledged and arbitrated. (Many remain unimplemented.) - Interrupts are no longer automatically cleared upon acknowledgment except for the Programmable Interrupt Timer. - Timer unit clears COM and sets TC and TO in the status register on applicable conditions. - Timer unit's confusion of IE0 (TC IRQ enable) with IE2 (TO IRQ enable) has been sorted out.
-rw-r--r--src/devices/machine/68340.cpp89
-rw-r--r--src/devices/machine/68340.h9
-rw-r--r--src/devices/machine/68340ser.cpp17
-rw-r--r--src/devices/machine/68340ser.h4
-rw-r--r--src/devices/machine/68340sim.cpp59
-rw-r--r--src/devices/machine/68340sim.h1
-rw-r--r--src/devices/machine/68340tmu.cpp64
-rw-r--r--src/devices/machine/68340tmu.h8
8 files changed, 159 insertions, 92 deletions
diff --git a/src/devices/machine/68340.cpp b/src/devices/machine/68340.cpp
index 6110a5345cb..827bb48c7aa 100644
--- a/src/devices/machine/68340.cpp
+++ b/src/devices/machine/68340.cpp
@@ -7,6 +7,13 @@
#include "emu.h"
#include "68340.h"
+#include <algorithm>
+
+#define LOG_BASE (1 << 1U)
+#define LOG_IPL (1 << 2U)
+#define VERBOSE (LOG_BASE)
+#include "logmacro.h"
+
DEFINE_DEVICE_TYPE(M68340, m68340_cpu_device, "mc68340", "MC68340")
int m68340_cpu_device::calc_cs(offs_t address) const
@@ -41,17 +48,88 @@ uint16_t m68340_cpu_device::get_cs(offs_t address)
+void m68340_cpu_device::update_ipl()
+{
+ uint8_t new_ipl = std::max({
+ pit_irq_level(),
+ m_serial->irq_level(),
+ m_timer[0]->irq_level(),
+ m_timer[1]->irq_level()
+ });
+ if (m_ipl != new_ipl)
+ {
+ if (m_ipl != 0)
+ set_input_line(m_ipl, CLEAR_LINE);
+ LOGMASKED(LOG_IPL, "Changing interrupt level from %d to %d\n", m_ipl, new_ipl);
+ m_ipl = new_ipl;
+ if (m_ipl != 0)
+ set_input_line(m_ipl, ASSERT_LINE);
+ }
+}
+
+IRQ_CALLBACK_MEMBER(m68340_cpu_device::int_ack)
+{
+ uint8_t pit_iarb = pit_arbitrate(irqline);
+ uint8_t scu_iarb = m_serial->arbitrate(irqline);
+ uint8_t t1_iarb = m_timer[0]->arbitrate(irqline);
+ uint8_t t2_iarb = m_timer[1]->arbitrate(irqline);
+ uint8_t iarb = std::max({pit_iarb, scu_iarb, t1_iarb, t2_iarb});
+ LOGMASKED(LOG_IPL, "Level %d interrupt arbitration: PIT = %X, SCU = %X, T1 = %X, T2 = %X\n", irqline, pit_iarb, scu_iarb, t1_iarb, t2_iarb);
+ int response = 0;
+ uint32_t vector = standard_irq_callback(irqline);
+
+ if (iarb != 0)
+ {
+ if (iarb == scu_iarb)
+ {
+ vector = m_serial->irq_vector();
+ LOGMASKED(LOG_IPL, "SCU acknowledged interrupt with vector %02X\n", vector);
+ response++;
+ }
+
+ if (iarb == t1_iarb)
+ {
+ vector = m_timer[0]->irq_vector();
+ LOGMASKED(LOG_IPL, "T1 acknowledged interrupt with vector %02X\n", vector);
+ response++;
+ }
+
+ if (iarb == t2_iarb)
+ {
+ vector = m_timer[1]->irq_vector();
+ LOGMASKED(LOG_IPL, "T2 acknowledged interrupt with vector %02X\n", vector);
+ response++;
+ }
+
+ if (iarb == pit_iarb)
+ {
+ vector = pit_iack();
+ LOGMASKED(LOG_IPL, "PIT acknowledged interrupt with vector %02X\n", vector);
+ response++;
+ }
+ }
+
+ if (response == 0)
+ logerror("Spurious interrupt (level %d)\n", irqline);
+ else if (response > 1)
+ logerror("%d modules responded to interrupt (level %d, IARB = %X)\n", response, irqline, iarb);
+
+ return vector;
+}
+
+
/* 68340 specifics - MOVE */
READ32_MEMBER( m68340_cpu_device::m68340_internal_base_r )
{
- logerror("%08x m68340_internal_base_r %08x, (%08x)\n", m_ppc, offset*4,mem_mask);
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BASE, "%08x m68340_internal_base_r %08x, (%08x)\n", m_ppc, offset*4,mem_mask);
return m_m68340_base;
}
WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w )
{
- logerror("%08x m68340_internal_base_w %08x, %08x (%08x)\n", m_ppc, offset*4,data,mem_mask);
+ LOGMASKED(LOG_BASE, "%08x m68340_internal_base_w %08x, %08x (%08x)\n", m_ppc, offset*4,data,mem_mask);
// other conditions?
if (m_dfc==0x7)
@@ -69,7 +147,7 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w )
}
COMBINE_DATA(&m_m68340_base);
- logerror("%08x m68340_internal_base_w %08x, %08x (%08x) (m_m68340_base write)\n", pc(), offset*4,data,mem_mask);
+ LOGMASKED(LOG_BASE, "%08x m68340_internal_base_w %08x, %08x (%08x) (m_m68340_base write)\n", pc(), offset*4,data,mem_mask);
// map new modules
if (m_m68340_base&1)
@@ -103,7 +181,7 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w )
}
else
{
- logerror("%08x m68340_internal_base_w %08x, %04x (%04x) (should fall through?)\n", pc(), offset*4,data,mem_mask);
+ LOGMASKED(LOG_BASE, "%08x m68340_internal_base_w %08x, %04x (%04x) (should fall through?)\n", pc(), offset*4,data,mem_mask);
}
@@ -148,6 +226,7 @@ m68340_cpu_device::m68340_cpu_device(const machine_config &mconfig, const char *
m_m68340SIM = nullptr;
m_m68340DMA = nullptr;
m_m68340_base = 0;
+ m_ipl = 0;
}
void m68340_cpu_device::device_reset()
@@ -179,4 +258,6 @@ void m68340_cpu_device::device_start()
m_m68340_base = 0x00000000;
m_internal = &space(AS_PROGRAM);
+
+ m_int_ack_callback = device_irq_acknowledge_delegate(FUNC(m68340_cpu_device::int_ack), this);
}
diff --git a/src/devices/machine/68340.h b/src/devices/machine/68340.h
index 3a661ff742c..12af250c5b2 100644
--- a/src/devices/machine/68340.h
+++ b/src/devices/machine/68340.h
@@ -53,11 +53,16 @@ private:
required_device<mc68340_serial_module_device> m_serial;
required_device_array<mc68340_timer_module_device, 2> m_timer;
+ void update_ipl();
+ IRQ_CALLBACK_MEMBER(int_ack);
+
TIMER_CALLBACK_MEMBER(periodic_interrupt_timer_callback);
void start_68340_sim();
- void do_pit_irq();
void do_tick_pit();
+ uint8_t pit_irq_level() const;
+ uint8_t pit_arbitrate(uint8_t level) const;
+ uint8_t pit_iack();
int calc_cs(offs_t address) const;
int get_timer_index(mc68340_timer_module_device *timer) { return (timer == m_timer[0].target()) ? 0 : 1; }
@@ -100,6 +105,8 @@ private:
emu_timer *m_irq_timer;
+ uint8_t m_ipl;
+
devcb_write8 m_pa_out_cb;
devcb_read8 m_pa_in_cb;
devcb_write8 m_pb_out_cb;
diff --git a/src/devices/machine/68340ser.cpp b/src/devices/machine/68340ser.cpp
index 622b63a2a5f..fcf6708305e 100644
--- a/src/devices/machine/68340ser.cpp
+++ b/src/devices/machine/68340ser.cpp
@@ -127,12 +127,13 @@ void mc68340_serial_module_device::write(offs_t offset, uint8_t data)
m_mcrl = data;
LOGSERIAL("PC: %08x %s %04x, %04x (MCRL - Module Configuration Register Low byte)\n", m_cpu->pcbase(), FUNCNAME, offset, data);
LOGSERIAL("- Supervisor registers %s - not implemented\n", data & REG_MCRL_SUPV ? "requries supervisor privileges" : "can be accessed by user privileged software");
- LOGSERIAL("- Interrupt Arbitration level: %02x - not implemented\n", data & REG_MCRL_ARBLV);
+ LOGSERIAL("- Interrupt Arbitration level: %02x\n", data & REG_MCRL_ARBLV);
break;
case REG_ILR:
m_ilr = data;
LOGSERIAL("PC: %08x %s %04x, %04x (ILR - Interrupt Level Register)\n", m_cpu->pcbase(), FUNCNAME, offset, data);
LOGSERIAL("- Interrupt Level: %02x\n", data & REG_ILR_MASK);
+ m_cpu->update_ipl();
break;
case REG_IVR:
m_ivr = data;
@@ -148,19 +149,7 @@ void mc68340_serial_module_device::write(offs_t offset, uint8_t data)
WRITE_LINE_MEMBER( mc68340_serial_module_device::irq_w )
{
LOGINT("IRQ!\n%s\n", FUNCNAME);
- if (m_ilr > 0)
- {
- if (((m_cpu->m_m68340SIM->m_avr_rsr >> (8 + m_ilr)) & 1) != 0) // use autovector ?
- {
- LOGINT("- Autovector level %d\n", m_ilr);
- m_cpu->set_input_line(m_ilr, HOLD_LINE);
- }
- else // otherwise not...
- {
- LOGINT("- Vector %02x level %d\n", m_ivr, m_ilr);
- m_cpu->set_input_line_and_vector(m_ilr, HOLD_LINE, m_ivr);
- }
- }
+ m_cpu->update_ipl();
}
mc68340_serial_module_device::mc68340_serial_module_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
diff --git a/src/devices/machine/68340ser.h b/src/devices/machine/68340ser.h
index 210edba58aa..e658d719c05 100644
--- a/src/devices/machine/68340ser.h
+++ b/src/devices/machine/68340ser.h
@@ -28,6 +28,10 @@ public:
virtual void write(offs_t offset, uint8_t data) override;
DECLARE_WRITE_LINE_MEMBER(irq_w);
+ uint8_t irq_level() const { return irq_pending() ? (m_ilr & REG_ILR_MASK) : 0; }
+ uint8_t irq_vector() const { return m_ivr; }
+ uint8_t arbitrate(uint8_t level) const { return (irq_level() == level) ? (m_mcrl & REG_MCRL_ARBLV) : 0; }
+
protected:
m68340_cpu_device *m_cpu;
diff --git a/src/devices/machine/68340sim.cpp b/src/devices/machine/68340sim.cpp
index a9506f32944..cf299ba2b22 100644
--- a/src/devices/machine/68340sim.cpp
+++ b/src/devices/machine/68340sim.cpp
@@ -20,7 +20,7 @@
#define LOG_PIT (1U << 8)
#define LOG_CS (1U << 9)
-//#define VERBOSE (LOG_CS)
+#define VERBOSE (LOG_PIT)
#define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here
#include "logmacro.h"
@@ -61,7 +61,7 @@ READ16_MEMBER( m68340_cpu_device::m68340_internal_sim_r )
val = sim.m_syncr;
break;
- case m68340_sim::REG_AVR_RSR:
+ case m68340_sim::REG_AVR_RSR: // Manual seems to say that AVR only autovectors externally triggered interrupts (INT1-INT7)
LOGSIM("- %08x %s %04x, (%04x) (AVR, RSR - Auto Vector Register, Reset Status Register) - not implemented\n", m_ppc, FUNCNAME, offset*2,mem_mask);
val = sim.m_avr_rsr;
break;
@@ -165,6 +165,7 @@ WRITE16_MEMBER( m68340_cpu_device::m68340_internal_sim_w )
COMBINE_DATA(&sim.m_picr);
LOGPIT("- PIRQL: Periodic Interrupt Level %d%s\n", (data & m68340_sim::REG_PICR_PIRQL) >> 8, (data & m68340_sim::REG_PICR_PIRQL) == 0 ? " (disabled)" : "");
LOGPIT("- PIV : Periodic Interrupt Vector %02x\n", (data & m68340_sim::REG_PICR_PIVEC));
+ update_ipl();
break;
case m68340_sim::REG_PITR:
@@ -426,35 +427,6 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_sim_cs_w )
}
}
-void m68340_cpu_device::do_pit_irq()
-{
- assert(m_m68340SIM);
- m68340_sim &sim = *m_m68340SIM;
-
- //logerror("do_pit_irq\n");
- int timer_irq_level = (sim.m_picr & 0x0700) >> 8;
- int timer_irq_vector = (sim.m_picr & 0x00ff) >> 0;
-
- if (timer_irq_level) // 0 is irq disabled
- {
- int use_autovector = (sim.m_avr_rsr >> (8 + timer_irq_level)) & 1;
-
- LOGPIT("PIT IRQ triggered, Lvl: %d using Vector: %d (0 = auto vector)\n", timer_irq_level, use_autovector ? 0 : timer_irq_vector);
-
- if (use_autovector)
- {
- //logerror("irq with autovector\n");
- set_input_line(timer_irq_level, HOLD_LINE);
- }
- else
- {
- //logerror("irq without autovector\n");
- set_input_line_and_vector(timer_irq_level, HOLD_LINE, timer_irq_vector);
- }
-
- }
-}
-
TIMER_CALLBACK_MEMBER(m68340_cpu_device::periodic_interrupt_timer_callback)
{
do_tick_pit();
@@ -518,7 +490,7 @@ void m68340_sim::reset()
m_picr= 0x000f;
m_pitr= 0x0000; // TODO: read MODCK pin to set the clock modes for watch dog and periodic timer
m_swsr= 0x0000;
-
+ m_pit_irq = false;
}
/* do_tick_pit works on whole clock cycles, no flank support */
@@ -544,7 +516,8 @@ void m68340_cpu_device::do_tick_pit()
if (sim.m_pit_counter == 0) // Zero detect
{
LOGPIT("PIT timer reached zero!\n");
- do_pit_irq();
+ sim.m_pit_irq = true;
+ update_ipl();
}
}
@@ -557,3 +530,23 @@ WRITE_LINE_MEMBER( m68340_cpu_device::extal_w )
do_tick_pit();
}
}
+
+uint8_t m68340_cpu_device::pit_irq_level() const
+{
+ return m_m68340SIM->m_pit_irq ? (m_m68340SIM->m_picr & m68340_sim::REG_PICR_PIRQL) >> 8 : 0;
+}
+
+uint8_t m68340_cpu_device::pit_arbitrate(uint8_t level) const
+{
+ if (pit_irq_level() == level)
+ return m_m68340SIM->m_mcr & m68340_sim::REG_MCR_ARBLV;
+ else
+ return 0;
+}
+
+uint8_t m68340_cpu_device::pit_iack()
+{
+ m_m68340SIM->m_pit_irq = false;
+ update_ipl();
+ return m_m68340SIM->m_picr & m68340_sim::REG_PICR_PIVEC;
+}
diff --git a/src/devices/machine/68340sim.h b/src/devices/machine/68340sim.h
index d8447b999fc..3c839984db2 100644
--- a/src/devices/machine/68340sim.h
+++ b/src/devices/machine/68340sim.h
@@ -32,6 +32,7 @@ public:
// Timers and counters
uint8_t m_pit_counter;
+ bool m_pit_irq;
void reset();
diff --git a/src/devices/machine/68340tmu.cpp b/src/devices/machine/68340tmu.cpp
index 660079aaded..1ceaf65f600 100644
--- a/src/devices/machine/68340tmu.cpp
+++ b/src/devices/machine/68340tmu.cpp
@@ -21,7 +21,6 @@
#define LOG_INT (1U << 4)
//#define VERBOSE (LOG_SETUP|LOG_INT|LOG_TIMER)
-#define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here
#include "logmacro.h"
@@ -86,6 +85,8 @@ READ16_MEMBER( mc68340_timer_module_device::read )
break;
case REG_COM:
val = m_com;
+ if (!machine().side_effects_disabled())
+ m_sr &= ~REG_SR_COM;
LOGTIMER("- %08x %s %04x, %04x (%04x) (COM - Compare Register)\n", m_cpu->pcbase(), FUNCNAME, offset * 2, val, mem_mask);
break;
default:
@@ -121,13 +122,14 @@ WRITE16_MEMBER( mc68340_timer_module_device::write )
LOGTIMER("- Clocks are %s\n", data & REG_MCR_STP ? "stopped" : "running");
LOGTIMER("- Freeze signal %s - not implemented\n", data & REG_MCR_FRZ1 ? "stops execution" : "is ignored");
LOGTIMER("- Supervisor registers %s - not implemented\n", data & REG_MCR_SUPV ? "requries supervisor privileges" : "can be accessed by user privileged software");
- LOGTIMER("- Interrupt Arbitration level: %02x - not implemented\n", data & REG_MCR_ARBLV);
+ LOGTIMER("- Interrupt Arbitration level: %02x\n", data & REG_MCR_ARBLV);
break;
case REG_IR:
COMBINE_DATA(&m_ir);
LOGTIMER("PC: %08x %s %04x, %04x (%04x) (IR - Interrupt Register)\n", m_cpu->pcbase(), FUNCNAME, offset * 2, data, mem_mask);
LOGTIMER("- Interrupt level : %02x\n", (data & REG_IR_INTLEV) >> 8);
LOGTIMER("- Interrupt vector: %02x\n", (data & REG_IR_INTVEC));
+ m_cpu->update_ipl();
break;
case REG_CR:
COMBINE_DATA(&m_cr);
@@ -135,9 +137,9 @@ WRITE16_MEMBER( mc68340_timer_module_device::write )
LOGTIMER("- Software reset: %s\n", (data & REG_CR_SWR) ? "inactive" : "active" );
LOGTIMER("- Enabled interrupts: %02x TO:%d TG:%d TC:%d\n",
data & REG_CR_INTMSK,
- (data & REG_CR_IE0) ? 1 : 0,
+ (data & REG_CR_IE2) ? 1 : 0,
(data & REG_CR_IE1) ? 1 : 0,
- (data & REG_CR_IE2) ? 1 : 0);
+ (data & REG_CR_IE0) ? 1 : 0);
LOGTIMER("- TGE signal, TGATE%d is %s\n", m_cpu->get_timer_index(this) + 1, (data & REG_CR_TGE) ? "enabled" : "disabled");
LOGTIMER("- PCLK: Counter uses %s\n", (data & REG_CR_PCLK) ? "prescaler" : "clock");
LOGTIMER("- CPE: Counter is %s\n", (data & REG_CR_CPE) ? "enabled" : "disabled");
@@ -163,6 +165,7 @@ WRITE16_MEMBER( mc68340_timer_module_device::write )
register (PREL1). TODO: make sure of the intial load of PREL1 on first falling flank */
if (m_cr & REG_CR_SWR)
{
+ m_sr &= ~REG_SR_COM;
if (m_cr & REG_CR_CPE)
{
m_sr |= REG_SR_ON; // Starts the counter
@@ -202,13 +205,14 @@ WRITE16_MEMBER( mc68340_timer_module_device::write )
/* IRQ - Interrupt Request bit
1 = An interrupt condition has occurred. This bit is the logical OR of the enabled TO, TG, and TC interrupt bits.
0 = The bit(s) that caused the interrupt condition has been cleared. If an IRQ signal has been asserted, it is negated when this bit is cleared. */
- data = (m_sr & ~(data & (REG_SR_TO | REG_SR_TG | REG_SR_TC))); // Clear only the set interrupt bits
- if ((data & (REG_SR_TO | REG_SR_TG | REG_SR_TC)) == 0)
+ m_sr &= ~(data & mem_mask & (REG_SR_TO | REG_SR_TG | REG_SR_TC)); // Clear only the set interrupt bits
+ if ((m_sr & (REG_SR_IRQ | REG_SR_TO | REG_SR_TG | REG_SR_TC)) == REG_SR_IRQ)
{
- data &= ~REG_SR_IRQ;
- // TODO: clear IRQ line
+ LOGINT("TIMER IRQ cleared\n");
+ m_sr &= ~REG_SR_IRQ;
+ m_cpu->update_ipl();
}
- COMBINE_DATA(&m_sr);
+ data = m_sr;
LOGTIMER("PC %08x %s %04x, %04x (%04x) (SR - Status/Prescaler Register)\n", m_cpu->pcbase(), FUNCNAME, offset * 2, data, mem_mask);
LOGTIMER("- IRQ: %s\n", (data & REG_SR_IRQ) ? "Yes" : "None");
LOGTIMER("- TO TimeOut int : %s\n", (data & REG_SR_TO) ? "Asserted" : "Cleared");
@@ -238,6 +242,7 @@ WRITE16_MEMBER( mc68340_timer_module_device::write )
COMBINE_DATA(&m_com);
LOGTIMER("PC %08x %s %04x, %04x (%04x) (COM - Compare Register)\n", m_cpu->pcbase(), FUNCNAME, offset * 2, data, mem_mask);
LOGTIMER("- COM15-COM0: %04x\n", (data & 0xfff));
+ m_sr &= ~REG_SR_COM;
break;
default:
LOGTIMER("- %08x FUNCNAME %08x, %08x (%08x) - not implemented\n", m_cpu->pcbase(), offset * 2, data, mem_mask);
@@ -267,10 +272,8 @@ WRITE_LINE_MEMBER( mc68340_timer_module_device::tgate_w)
m_sr |= REG_SR_TG;
if (m_cr & REG_CR_IE1)
{
- LOGTIMER(" - TG interrupt");
+ LOGTIMER(" - TG interrupt\n");
do_timer_irq();
- m_sr |= REG_SR_IRQ;
-
}
}
m_sr |= REG_SR_TGL;
@@ -307,27 +310,12 @@ void mc68340_timer_module_device::device_start()
void mc68340_timer_module_device::do_timer_irq()
{
- assert(m_cpu->m_m68340SIM);
- m68340_sim &sim = *m_cpu->m_m68340SIM;
- int timer_irq_level = (m_ir & 0x0700) >> 8;
- int timer_irq_vector = (m_ir & 0x00ff) >> 0;
-
- if (timer_irq_level) // 0 is irq disabled
+ assert((m_sr & (REG_SR_TO | REG_SR_TG | REG_SR_TC)) != 0);
+ if ((m_sr & REG_SR_IRQ) == 0)
{
- int use_autovector = (sim.m_avr_rsr >> (8 + timer_irq_level)) & 1;
-
- LOGINT("TIMER IRQ triggered, Lvl: %d using Vector: %d (0 = auto vector)\n", timer_irq_level, use_autovector ? 0 : timer_irq_vector);
-
- if (use_autovector)
- {
- //logerror("irq with autovector\n");
- m_cpu->set_input_line(timer_irq_level, HOLD_LINE);
- }
- else
- {
- //logerror("irq without autovector\n");
- m_cpu->set_input_line_and_vector(timer_irq_level, HOLD_LINE, timer_irq_vector);
- }
+ LOGINT("TIMER IRQ triggered\n");
+ m_sr |= REG_SR_IRQ;
+ m_cpu->update_ipl();
}
}
@@ -358,7 +346,7 @@ void mc68340_timer_module_device::do_timer_tick()
affected by disabling the timer (SWR = 0).*/
if (m_cntr == m_com) // Check COM register
{
- m_sr |= (REG_SR_TC | REG_SR_COM);
+ m_sr |= REG_SR_COM;
}
}
@@ -457,22 +445,22 @@ void mc68340_timer_module_device::do_timer_tick()
if (m_cntr_reg == 0) // timer reached timeout value?
{
+ m_sr &= ~REG_SR_COM;
m_cntr = m_prel1; // TODO: Support prel2 for certain modes
+ m_sr |= REG_SR_TO;
if (m_cr & REG_CR_IE2)
{
- LOGTIMER(" - TO interrupt");
+ LOGTIMER(" - TO interrupt\n");
do_timer_irq();
- m_sr |= REG_SR_IRQ;
}
}
if ((m_sr & REG_SR_COM) != 0) // timer reached compare value? )
{
+ m_sr |= REG_SR_TC;
if (m_cr & REG_CR_IE0)
{
- LOGTIMER(" - TC interrupt");
+ LOGTIMER(" - TC interrupt\n");
do_timer_irq();
- m_sr |= REG_SR_IRQ;
-
}
}
}
diff --git a/src/devices/machine/68340tmu.h b/src/devices/machine/68340tmu.h
index 005f66fba6d..0582debd475 100644
--- a/src/devices/machine/68340tmu.h
+++ b/src/devices/machine/68340tmu.h
@@ -22,6 +22,10 @@ public:
DECLARE_WRITE_LINE_MEMBER( tin_w );
DECLARE_WRITE_LINE_MEMBER( tgate_w );
+ uint8_t irq_level() const { return (m_sr & REG_SR_IRQ) ? (m_ir & REG_IR_INTLEV) >> 8 : 0; }
+ uint8_t irq_vector() const { return m_ir & REG_IR_INTVEC; }
+ uint8_t arbitrate(uint8_t level) const { return (irq_level() == level) ? (m_mcr & REG_MCR_ARBLV) : 0; }
+
protected:
m68340_cpu_device *m_cpu;
@@ -75,9 +79,9 @@ public:
enum {
REG_CR_SWR = 0x8000,
REG_CR_INTMSK = 0x7000,
- REG_CR_IE0 = 0x4000,
+ REG_CR_IE2 = 0x4000,
REG_CR_IE1 = 0x2000,
- REG_CR_IE2 = 0x1000,
+ REG_CR_IE0 = 0x1000,
REG_CR_TGE = 0x0800,
REG_CR_PCLK = 0x0400,
REG_CR_CPE = 0x0200,