summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/68307sim.cpp
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-01-01 19:24:56 -0500
committer AJR <ajrhacker@users.noreply.github.com>2019-01-01 19:25:47 -0500
commitccc8aaed9781af8e49645b27ea771aaaea28fa06 (patch)
tree56801954da416b5b9a19959f5ff0943b035fb678 /src/devices/machine/68307sim.cpp
parent665c37d8bc7f43a20213852e971c9fc94322635e (diff)
68307: More accurate emulation of internal priority interrupt controller
Diffstat (limited to 'src/devices/machine/68307sim.cpp')
-rw-r--r--src/devices/machine/68307sim.cpp160
1 files changed, 132 insertions, 28 deletions
diff --git a/src/devices/machine/68307sim.cpp b/src/devices/machine/68307sim.cpp
index e912d434006..b5363ecf6af 100644
--- a/src/devices/machine/68307sim.cpp
+++ b/src/devices/machine/68307sim.cpp
@@ -3,7 +3,9 @@
/* 68307 SIM module */
#include "emu.h"
+#include "68307bus.h"
#include "68307sim.h"
+#include "68307tmu.h"
/* ports */
#define m68307SIM_PACNT (0x10)
@@ -249,41 +251,66 @@ void m68307_cpu_device::m68307_sim::write_pbdat(m68307_cpu_device* m68k, address
void m68307_cpu_device::m68307_sim::write_licr1(m68307_cpu_device* m68k, uint16_t data, uint16_t mem_mask)
{
- COMBINE_DATA(&m_licr1);
- data = m_licr1;
- m68k->logerror("m_licr1 value %04x : Details :\n", data);
- m68k->logerror("int4ipl %01x\n", (data>>0)&7);
- m68k->logerror("pir4 %01x\n", (data>>3)&1);
- m68k->logerror("int3ipl %01x\n", (data>>4)&7);
- m68k->logerror("pir3 %01x\n", (data>>7)&1);
- m68k->logerror("int2ipl %01x\n", (data>>8)&7);
- m68k->logerror("pir2 %01x\n", (data>>11)&1);
- m68k->logerror("int1ipl %01x\n", (data>>12)&7);
- m68k->logerror("pir1 %01x\n", (data>>15)&1);
+ m68k->logerror("m_licr1 write %04x : Details :\n", data);
+ if (BIT(data & mem_mask, 3))
+ {
+ m_licr1 = (m_licr1 & 0xfff0) | (data & 0x0007);
+ m68k->logerror("int4ipl %01x\n", (m_licr1>>0)&7);
+ }
+ m68k->logerror("pir4 %01x\n", (m_licr1>>3)&1);
+ if (BIT(data & mem_mask, 7))
+ {
+ m_licr1 = (m_licr1 & 0xff0f) | (data & 0x0070);
+ m68k->logerror("int3ipl %01x\n", (m_licr1>>4)&7);
+ }
+ m68k->logerror("pir3 %01x\n", (m_licr1>>7)&1);
+ if (BIT(data & mem_mask, 11))
+ {
+ m_licr1 = (m_licr1 & 0xf0ff) | (data & 0x0700);
+ m68k->logerror("int2ipl %01x\n", (m_licr1>>8)&7);
+ }
+ m68k->logerror("pir2 %01x\n", (m_licr1>>11)&1);
+ if (BIT(data & mem_mask, 15))
+ {
+ m_licr1 = (m_licr1 & 0x0fff) | (data & 0x7000);
+ m68k->logerror("int1ipl %01x\n", (m_licr1>>12)&7);
+ }
+ m68k->logerror("pir1 %01x\n", (m_licr1>>15)&1);
m68k->logerror("\n");
+
+ m68k->set_ipl(get_ipl(m68k));
}
void m68307_cpu_device::m68307_sim::write_licr2(m68307_cpu_device* m68k, uint16_t data, uint16_t mem_mask)
{
- COMBINE_DATA(&m_licr2);
- uint16_t newdata = m_licr2;
- m68k->logerror("m_licr2 value %04x : Details :\n", newdata);
- m68k->logerror("int8ipl %01x\n", (newdata>>0)&7);
- m68k->logerror("pir8 %01x\n", (newdata>>3)&1);
- m68k->logerror("int7ipl %01x\n", (newdata>>4)&7);
- m68k->logerror("pir7 %01x\n", (newdata>>7)&1);
- m68k->logerror("int6ipl %01x\n", (newdata>>8)&7);
- m68k->logerror("pir6 %01x\n", (newdata>>11)&1);
- m68k->logerror("int5ipl %01x\n", (newdata>>12)&7);
- m68k->logerror("pir5 %01x\n", (newdata>>15)&1);
+ m68k->logerror("m_licr2 write %04x : Details :\n", data);
+ if (BIT(data & mem_mask, 3))
+ {
+ m_licr2 = (m_licr2 & 0xfff0) | (data & 0x0007);
+ m68k->logerror("int8ipl %01x\n", (m_licr2>>0)&7);
+ }
+ m68k->logerror("pir8 %01x\n", (m_licr2>>3)&1);
+ if (BIT(data & mem_mask, 7))
+ {
+ m_licr2 = (m_licr2 & 0xff0f) | (data & 0x0070);
+ m68k->logerror("int7ipl %01x\n", (m_licr2>>4)&7);
+ }
+ m68k->logerror("pir7 %01x\n", (m_licr2>>7)&1);
+ if (BIT(data & mem_mask, 11))
+ {
+ m_licr2 = (m_licr2 & 0xf0ff) | (data & 0x0700);
+ m68k->logerror("int6ipl %01x\n", (m_licr2>>8)&7);
+ }
+ m68k->logerror("pir6 %01x\n", (m_licr2>>11)&1);
+ if (BIT(data & mem_mask, 15))
+ {
+ m_licr2 = (m_licr2 & 0x0fff) | (data & 0x7000);
+ m68k->logerror("int5ipl %01x\n", (m_licr2>>12)&7);
+ }
+ m68k->logerror("pir5 %01x\n", (m_licr2>>15)&1);
m68k->logerror("\n");
- if (data & 0x0008) m_licr2 = m_licr2 & ~0x0008;
- if (data & 0x0080) m_licr2 = m_licr2 & ~0x0080;
- if (data & 0x0800) m_licr2 = m_licr2 & ~0x0800;
- if (data & 0x8000) m_licr2 = m_licr2 & ~0x8000;
-
-
+ m68k->set_ipl(get_ipl(m68k));
}
@@ -297,6 +324,8 @@ void m68307_cpu_device::m68307_sim::write_picr(m68307_cpu_device* m68k, uint16_t
m68k->logerror("t2ipl %01x\n", (data>>8)&7);
m68k->logerror("t1ipl %01x\n", (data>>12)&7);
m68k->logerror("\n");
+
+ m68k->set_ipl(get_ipl(m68k));
}
void m68307_cpu_device::m68307_sim::write_pivr(m68307_cpu_device* m68k, uint16_t data, uint16_t mem_mask)
@@ -308,6 +337,76 @@ void m68307_cpu_device::m68307_sim::write_pivr(m68307_cpu_device* m68k, uint16_t
m68k->logerror("high vector %01x\n", (data>>4)&0xf);
}
+uint8_t m68307_cpu_device::m68307_sim::get_ipl(const m68307_cpu_device *m68k) const
+{
+ // INT7 has highest priority
+ if (0 /*m_int7*/)
+ return 7;
+
+ // LICR1 interrupts from INT1, INT2, INT3, INT4
+ // LICR2 interrupts from INT5, INT6, INT7, INT8
+ uint8_t ipl = 0;
+ uint32_t licr = (m_licr1 << 16) | m_licr2;
+ while (licr != 0)
+ {
+ if (BIT(licr, 31) && (licr >> 28) & 7)
+ ipl = std::max(ipl, uint8_t((licr >> 28) & 7));
+ licr <<= 4;
+ }
+
+ // PICR interrupts from T1, T2, UART, MBUS
+ if (m68k->m_m68307TIMER->timer_int_pending(0))
+ ipl = std::max(ipl, uint8_t((m_picr >> 12) & 7));
+ if (m68k->m_m68307TIMER->timer_int_pending(1))
+ ipl = std::max(ipl, uint8_t((m_picr >> 8) & 7));
+ if (m68k->m_duart->irq_pending())
+ ipl = std::max(ipl, uint8_t((m_picr >> 4) & 7));
+ if (m68k->m_m68307MBUS->m_intpend)
+ ipl = std::max(ipl, uint8_t((m_picr >> 0) & 7));
+
+ return ipl;
+}
+
+uint8_t m68307_cpu_device::m68307_sim::get_int_type(const m68307_cpu_device *m68k, uint8_t pri) const
+{
+ // INT7 has highest priority
+ if (0 /*m_int7*/ && pri == 7)
+ return 0x01;
+
+ // LICR1 interrupts from INT1, INT2, INT3, INT4
+ else if (BIT(m_licr1, 15) && pri == ((m_licr1 >> 12) & 7))
+ return 0x02;
+ else if (BIT(m_licr1, 11) && pri == ((m_licr1 >> 8) & 7))
+ return 0x03;
+ else if (BIT(m_licr1, 7) && pri == ((m_licr1 >> 4) & 7))
+ return 0x04;
+ else if (BIT(m_licr1, 3) && pri == ((m_licr1 >> 0) & 7))
+ return 0x05;
+
+ // LICR2 interrupts from INT5, INT6, INT7, INT8
+ else if (BIT(m_licr2, 15) && pri == ((m_licr2 >> 12) & 7))
+ return 0x06;
+ else if (BIT(m_licr2, 11) && pri == ((m_licr2 >> 8) & 7))
+ return 0x07;
+ else if (BIT(m_licr2, 7) && pri == ((m_licr2 >> 4) & 7))
+ return 0x08;
+ else if (BIT(m_licr2, 3) && pri == ((m_licr2 >> 0) & 7))
+ return 0x09;
+
+ // PICR interrupts from T1, T2, UART, MBUS
+ else if (m68k->m_m68307TIMER->timer_int_pending(0) && pri == ((m_picr >> 12) & 7))
+ return 0x0a;
+ else if (m68k->m_m68307TIMER->timer_int_pending(1) && pri == ((m_picr >> 8) & 7))
+ return 0x0b;
+ else if (m68k->m_duart->irq_pending() && pri == ((m_picr >> 4) & 7))
+ return 0x0c;
+ else if (m68k->m_m68307MBUS->m_intpend && pri == ((m_picr >> 0) & 7))
+ return 0x0d;
+
+ // Spurious interrupt (vectored normally)
+ return 0x00;
+}
+
void m68307_cpu_device::m68307_sim::reset()
{
for (int i=0;i<4;i++)
@@ -315,4 +414,9 @@ void m68307_cpu_device::m68307_sim::reset()
m_br[i] = 0xc001;
m_or[i] = 0xdffd;
}
+
+ m_licr1 = 0x0000;
+ m_licr2 = 0x0000;
+ m_picr = 0x0000;
+ m_pivr = 0x0f;
}