// license:BSD-3-Clause // copyright-holders:David Haywood /* 68307 SIM module */ #include "emu.h" #include "68307bus.h" #include "68307sim.h" #include "68307tmu.h" /* ports */ #define m68307SIM_PACNT (0x10) #define m68307SIM_PADDR (0x12) #define m68307SIM_PADAT (0x14) #define m68307SIM_PBCNT (0x16) #define m68307SIM_PBDDR (0x18) #define m68307SIM_PBDAT (0x1a) /* interrupt logic */ #define m68307SIM_LICR1 (0x20) #define m68307SIM_LICR2 (0x22) #define m68307SIM_PICR (0x24) #define m68307SIM_PIVR (0x26) /* used for the CS logic */ #define m68307SIM_BR0 (0x40) #define m68307SIM_OR0 (0x42) #define m68307SIM_BR1 (0x44) #define m68307SIM_OR1 (0x46) #define m68307SIM_BR2 (0x48) #define m68307SIM_OR2 (0x4a) #define m68307SIM_BR3 (0x4c) #define m68307SIM_OR3 (0x4e) READ16_MEMBER( m68307_cpu_device::m68307_internal_sim_r ) { assert(m_m68307SIM); m68307_sim &sim = *m_m68307SIM; switch (offset<<1) { case m68307SIM_PADAT: return sim.read_padat(this, space, mem_mask); case m68307SIM_PBDAT: return sim.read_pbdat(this, space, mem_mask); case m68307SIM_LICR2: return sim.m_licr2; case m68307SIM_BR0: return sim.m_br[0]; case m68307SIM_OR0: return sim.m_or[0]; case m68307SIM_BR1: return sim.m_br[1]; case m68307SIM_OR1: return sim.m_or[1]; case m68307SIM_BR2: return sim.m_br[2]; case m68307SIM_OR2: return sim.m_or[2]; case m68307SIM_BR3: return sim.m_br[3]; case m68307SIM_OR3: return sim.m_or[3]; default: logerror("%08x m68307_internal_sim_r %08x, (%04x)\n", m_ppc, offset*2, mem_mask); return 0xff; } return 0x0000; } WRITE16_MEMBER( m68307_cpu_device::m68307_internal_sim_w ) { assert(m_m68307SIM); m68307_sim &sim = *m_m68307SIM; switch (offset<<1) { case m68307SIM_PACNT: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port A (8-bit) Control Register - PACNT)\n", m_ppc, offset*2,data,mem_mask); sim.write_pacnt(data,mem_mask); break; case m68307SIM_PADDR: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port A (8-bit) Direction Register - PADDR)\n", m_ppc, offset*2,data,mem_mask); sim.write_paddr(data,mem_mask); break; case m68307SIM_PADAT: sim.write_padat(this, space, data,mem_mask); break; case m68307SIM_PBCNT: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port B (16-bit) Control Register - PBCNT)\n", m_ppc, offset*2,data,mem_mask); sim.write_pbcnt(data,mem_mask); break; case m68307SIM_PBDDR: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Port B (16-bit) Direction Register - PBDDR)\n", m_ppc, offset*2,data,mem_mask); sim.write_pbddr(data,mem_mask); break; case m68307SIM_PBDAT: sim.write_pbdat(this, space, data, mem_mask); break; case m68307SIM_LICR1: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Latched Interrupt Control Register 1 - LICR1)\n", m_ppc, offset*2,data,mem_mask); sim.write_licr1(this,data,mem_mask); break; case m68307SIM_LICR2: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Latched Interrupt Control Register 2 - LICR2)\n", m_ppc, offset*2,data,mem_mask); sim.write_licr2(this,data,mem_mask); break; case m68307SIM_PICR: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Peripheral Interrupt Control Register - PICR)\n", m_ppc, offset*2,data,mem_mask); sim.write_picr(this,data,mem_mask); break; case m68307SIM_PIVR: logerror("%08x m68307_internal_sim_w %08x, %04x (%04x) (Peripheral Interrupt Vector Register - PIVR)\n", m_ppc, offset*2,data,mem_mask); sim.write_pivr(this,data,mem_mask); break; case m68307SIM_BR0: COMBINE_DATA(&sim.m_br[0]); break; case m68307SIM_OR0: COMBINE_DATA(&sim.m_or[0]); break; case m68307SIM_BR1: COMBINE_DATA(&sim.m_br[1]); break; case m68307SIM_OR1: COMBINE_DATA(&sim.m_or[1]); break; case m68307SIM_BR2: COMBINE_DATA(&sim.m_br[2]); break; case m68307SIM_OR2: COMBINE_DATA(&sim.m_or[2]); break; case m68307SIM_BR3: COMBINE_DATA(&sim.m_br[3]); break; case m68307SIM_OR3: COMBINE_DATA(&sim.m_or[3]); break; default : logerror("%08x m68307_internal_sim_w %08x, %04x (%04x)\n", m_ppc, offset*2,data,mem_mask); break; } } void m68307_cpu_device::m68307_sim::write_pacnt(uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_pacnt); } void m68307_cpu_device::m68307_sim::write_paddr(uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_paddr); } uint16_t m68307_cpu_device::m68307_sim::read_padat(m68307_cpu_device* m68k, address_space &space, uint16_t mem_mask) { if (!m68k->m_porta_r.isnull()) { // for general purpose bits, if configured as 'output' then anything output gets latched // and anything configured as input is read from the port uint8_t outputbits = m_paddr; uint8_t inputbits = ~m_paddr; uint8_t general_purpose_bits = ~m_pacnt; uint8_t indat = m68k->m_porta_r(space, false, (inputbits & general_purpose_bits)&mem_mask) & ((inputbits & general_purpose_bits) & mem_mask); // read general purpose input lines indat |= m68k->m_porta_r(space, true, (inputbits & ~general_purpose_bits)&mem_mask) & ((inputbits & ~general_purpose_bits)& mem_mask); // read dedicated input lines uint8_t outdat = (m_padat & outputbits) & general_purpose_bits; // read general purpose output lines (reads latched data) return (indat | outdat); } else { m68k->logerror("%08x m68307_internal_sim_r (%04x) (Port A (8-bit) Data Register - PADAT)\n", m68k->pcbase(), mem_mask); } return 0xffff; } void m68307_cpu_device::m68307_sim::write_padat(m68307_cpu_device* m68k, address_space &space, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_padat); if (!m68k->m_porta_w.isnull()) { m68k->m_porta_w(space, false, data, 0xff); } else { m68k->logerror("%08x m68307_internal_sim_w %04x (%04x) (Port A (8-bit) Data Register - PADAT)\n", m68k->pcbase(), data,mem_mask); } } void m68307_cpu_device::m68307_sim::write_pbcnt(uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_pbcnt); } void m68307_cpu_device::m68307_sim::write_pbddr(uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_pbddr); } uint16_t m68307_cpu_device::m68307_sim::read_pbdat(m68307_cpu_device* m68k, address_space &space, uint16_t mem_mask) { if (!m68k->m_portb_r.isnull()) { // for general purpose bits, if configured as 'output' then anything output gets latched // and anything configured as input is read from the port uint16_t outputbits = m_pbddr; uint16_t inputbits = ~m_pbddr; uint16_t general_purpose_bits = ~m_pbcnt; uint16_t indat = m68k->m_portb_r(space, false, (inputbits & general_purpose_bits)&mem_mask) & ((inputbits & general_purpose_bits) & mem_mask); // read general purpose input lines indat |= m68k->m_portb_r(space, true, (inputbits & ~general_purpose_bits)&mem_mask) & ((inputbits & ~general_purpose_bits)& mem_mask); // read dedicated input lines uint16_t outdat = (m_pbdat & outputbits) & general_purpose_bits; // read general purpose output lines (reads latched data) return (indat | outdat); } else { m68k->logerror("%08x m68307_internal_sim_r (%04x) (Port B (16-bit) Data Register - PBDAT)\n", m68k->pcbase(), mem_mask); } return 0xffff; } void m68307_cpu_device::m68307_sim::write_pbdat(m68307_cpu_device* m68k, address_space &space, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_pbdat); if (!m68k->m_portb_w.isnull()) { m68k->m_portb_w(space, false, data, mem_mask); } else { m68k->logerror("%08x m68307_internal_sim_w %04x (%04x) (Port B (16-bit) Data Register - PBDAT)\n", m68k->pcbase(), data,mem_mask); } } void m68307_cpu_device::m68307_sim::write_licr1(m68307_cpu_device* m68k, uint16_t data, uint16_t mem_mask) { 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) { 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"); m68k->set_ipl(get_ipl(m68k)); } void m68307_cpu_device::m68307_sim::write_picr(m68307_cpu_device* m68k, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_picr); data = m_picr; m68k->logerror("picr value %04x : Details :\n", data); m68k->logerror("mbipl %01x\n", (data>>0)&7); m68k->logerror("uaipl %01x\n", (data>>4)&7); 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) { COMBINE_DATA(&m_pivr); data = m_pivr; m68k->logerror("pivr value %04x : Details :\n", data); m68k->logerror("unused %01x\n", (data>>0)&0xf); 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++) { m_br[i] = 0xc001; m_or[i] = 0xdffd; } m_licr1 = 0x0000; m_licr2 = 0x0000; m_picr = 0x0000; m_pivr = 0x0f; }