diff options
author | 2019-01-01 19:24:56 -0500 | |
---|---|---|
committer | 2019-01-01 19:25:47 -0500 | |
commit | ccc8aaed9781af8e49645b27ea771aaaea28fa06 (patch) | |
tree | 56801954da416b5b9a19959f5ff0943b035fb678 /src/devices/machine/68307sim.cpp | |
parent | 665c37d8bc7f43a20213852e971c9fc94322635e (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.cpp | 160 |
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; } |