diff options
Diffstat (limited to 'src/devices/cpu/t11/t11.cpp')
-rw-r--r-- | src/devices/cpu/t11/t11.cpp | 176 |
1 files changed, 172 insertions, 4 deletions
diff --git a/src/devices/cpu/t11/t11.cpp b/src/devices/cpu/t11/t11.cpp index 9e2af21ba29..f347f655025 100644 --- a/src/devices/cpu/t11/t11.cpp +++ b/src/devices/cpu/t11/t11.cpp @@ -36,12 +36,22 @@ DEFINE_DEVICE_TYPE(T11, t11_device, "t11", "DEC T11") +DEFINE_DEVICE_TYPE(K1801VM1, k1801vm1_device, "k1801vm1", "K1801VM1") DEFINE_DEVICE_TYPE(K1801VM2, k1801vm2_device, "k1801vm2", "K1801VM2") +k1801vm1_device::k1801vm1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : t11_device(mconfig, K1801VM1, tag, owner, clock) + , z80_daisy_chain_interface(mconfig, *this) +{ + c_insn_set = IS_LEIS | IS_MXPS | IS_VM1; +} + k1801vm2_device::k1801vm2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : t11_device(mconfig, K1801VM2, tag, owner, clock) + , z80_daisy_chain_interface(mconfig, *this) { + c_insn_set = IS_LEIS | IS_EIS | IS_MXPS | IS_VM2; } t11_device::t11_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) @@ -66,6 +76,7 @@ t11_device::t11_device(const machine_config &mconfig, device_type type, const ch t11_device::t11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : t11_device(mconfig, T11, tag, owner, clock) { + c_insn_set = IS_LEIS | IS_MFPT | IS_MXPS | IS_T11; } device_memory_interface::space_config_vector t11_device::memory_space_config() const @@ -84,8 +95,7 @@ device_memory_interface::space_config_vector t11_device::memory_space_config() c int t11_device::ROPCODE() { - PC &= 0xfffe; - int val = m_cache.read_word(PC); + int val = m_cache.read_word(PC & 0xfffe); PC += 2; return val; } @@ -155,6 +165,8 @@ int t11_device::POP() #define GET_V (PSW & VFLAG) #define GET_Z (PSW & ZFLAG) #define GET_N (PSW & NFLAG) +#define GET_T (PSW & (1 << 4)) +#define GET_I (PSW & (1 << 7)) /* clears flags */ #define CLR_C (PSW &= ~CFLAG) @@ -202,6 +214,119 @@ static const struct irq_table_entry irq_table[] = { 7<<5, 0140 } }; +// PSW7 masks external interrupts (except IRQ1) -- IRQ2, IRQ3, VIRQ +// PSW11 also masks IRQ1. PSW10 also masks ACLO. +void k1801vm1_device::t11_check_irqs() +{ + // 2. bus error on vector fetch; nm, vec 160012 + // 3. double bus error; nm, vec 160006 + // 4. bus error; PSW11, PSW10 + if (m_bus_error) + { + m_bus_error = false; + m_mcir = MCIR_IRQ; + m_vsel = T11_TIMEOUT; + } + // 5. illegal insn; nm + else if (m_mcir == MCIR_ILL) + { + take_interrupt(m_vsel); + } + // 6. trace trap; WCPU + else if (m_trace_trap && m_mcir == MCIR_NONE) // allow trap_to() to execute first + { + if (GET_T) + { + m_mcir = MCIR_IRQ; + m_vsel = T11_BPT; + } + else + m_trace_trap = false; + } + else if (GET_T) + { + m_trace_trap = true; + } + // 7. power fail (ACLO pin); PSW10 + else if (m_power_fail) + { + m_mcir = MCIR_IRQ; + m_vsel = T11_PWRFAIL; + } + // 8. external HALT (nIRQ1 pin); PSW11, PSW10 + else if (m_hlt_active) + { + m_hlt_active = 0; + m_mcir = MCIR_HALT; + m_vsel = VM1_HALT; + } + // 9. internal timer, vector 0270; PSW7, PSW10 + // 10. line clock (nIRQ2 pin); PSW7, PSW10 + else if (BIT(m_cp_state, 2) && !GET_I) + { + m_mcir = MCIR_IRQ; + m_vsel = VM1_EVNT; + } + // 11. nIRQ3 pin; PSW7, PSW10 + else if (BIT(m_cp_state, 3) && !GET_I) + { + m_mcir = MCIR_IRQ; + m_vsel = VM1_IRQ3; + } + // 12. nVIRQ pin; PSW7, PSW10 + else if (m_vec_active && !GET_I) + { + device_z80daisy_interface *intf = daisy_get_irq_device(); + int vec = (intf != nullptr) ? intf->z80daisy_irq_ack() : m_in_iack_func(0); + if (vec == -1 || vec == 0) + { + m_vec_active = 0; + return; + } + m_mcir = MCIR_IRQ; + m_vsel = vec; + } + + switch (m_mcir) + { + case MCIR_SET: + if (m_vsel >= 0160000) + take_interrupt_halt(m_vsel); + else + take_interrupt(m_vsel); + break; + + case MCIR_IRQ: + take_interrupt(m_vsel); + break; + + case MCIR_HALT: + take_interrupt_halt(m_vsel); + break; + } + + m_mcir = MCIR_NONE; +} + +void k1801vm1_device::take_interrupt_halt(uint16_t vector) +{ + // vectors in HALT mode are word (not doubleworld) aligned + assert((vector & 1) == 0); + + // enter HALT mode + WWORD(VM1_SEL1, RWORD(VM1_SEL1) | SEL1_HALT); + + // push the old state, set the new one + WWORD(VM1_STACK, PC); + WWORD(VM1_STACK + 2, PSW); + PCD = RWORD(vector); + PSW = RWORD(vector + 2); + + // count cycles and clear the WAIT flag + m_icount -= 114; + m_wait_state = 0; +} + void t11_device::t11_check_irqs() { // HLT is nonmaskable @@ -329,6 +454,10 @@ void t11_device::device_start() save_item(NAME(m_hlt_active)); save_item(NAME(m_power_fail)); save_item(NAME(m_ext_halt)); + save_item(NAME(m_trace_trap)); + save_item(NAME(m_check_irqs)); + save_item(NAME(m_mcir)); + save_item(NAME(m_vsel)); // Register debugger state state_add( T11_PC, "PC", m_reg[7].w.l).formatstr("%06O"); @@ -341,8 +470,8 @@ void t11_device::device_start() state_add( T11_R4, "R4", m_reg[4].w.l).formatstr("%06O"); state_add( T11_R5, "R5", m_reg[5].w.l).formatstr("%06O"); - state_add(STATE_GENPC, "GENPC", m_reg[7].w.l).noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_ppc.w.l).noshow(); + state_add(STATE_GENPC, "GENPC", m_reg[7].w.l).formatstr("%06O").noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_ppc.w.l).formatstr("%06O").noshow(); state_add(STATE_GENFLAGS, "GENFLAGS", m_psw.b.l).formatstr("%8s").noshow(); set_icountptr(m_icount); @@ -367,6 +496,25 @@ void t11_device::state_string_export(const device_state_entry &entry, std::strin } } +void k1801vm1_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + str = string_format("%c%c%c%c%c%c%c%c", + m_psw.b.l & 0x80 ? 'I':'.', + m_psw.b.l & 0x40 ? '?':'.', + m_psw.b.l & 0x20 ? '?':'.', + m_psw.b.l & 0x10 ? 'T':'.', + m_psw.b.l & 0x08 ? 'N':'.', + m_psw.b.l & 0x04 ? 'Z':'.', + m_psw.b.l & 0x02 ? 'V':'.', + m_psw.b.l & 0x01 ? 'C':'.' + ); + break; + } +} + void k1801vm2_device::state_string_export(const device_state_entry &entry, std::string &str) const { switch (entry.index()) @@ -409,6 +557,19 @@ void t11_device::device_reset() m_power_fail = false; m_bus_error = false; m_ext_halt = false; + m_trace_trap = false; + m_check_irqs = false; +} + +void k1801vm1_device::device_reset() +{ + t11_device::device_reset(); + + PC = RWORD(VM1_SEL1) & 0177400; + WWORD(VM1_SEL1, RWORD(VM1_SEL1) | SEL1_HALT); + + m_mcir = MCIR_NONE; + m_vsel = 0; } void k1801vm2_device::device_reset() @@ -479,6 +640,7 @@ void t11_device::execute_run() if (m_wait_state) { + debugger_wait_hook(); m_icount = 0; return; } @@ -493,6 +655,12 @@ void t11_device::execute_run() op = ROPCODE(); (this->*s_opcode_table[op >> 3])(op); + + if (m_check_irqs || m_trace_trap || GET_T) + { + m_check_irqs = false; + t11_check_irqs(); + } } } |