diff options
Diffstat (limited to 'src/devices/cpu/t11/t11.cpp')
-rw-r--r-- | src/devices/cpu/t11/t11.cpp | 200 |
1 files changed, 189 insertions, 11 deletions
diff --git a/src/devices/cpu/t11/t11.cpp b/src/devices/cpu/t11/t11.cpp index c4f22b93732..487a7a57003 100644 --- a/src/devices/cpu/t11/t11.cpp +++ b/src/devices/cpu/t11/t11.cpp @@ -14,7 +14,6 @@ #include "emu.h" #include "t11.h" #include "t11dasm.h" -#include "debugger.h" /************************************* @@ -37,12 +36,20 @@ 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) +{ + 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) { + 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) @@ -52,9 +59,10 @@ t11_device::t11_device(const machine_config &mconfig, device_type type, const ch , m_cp_state(0) , m_vec_active(false) , m_pf_active(false) + , m_berr_active(false) , m_hlt_active(false) , m_out_reset_func(*this) - , m_in_iack_func(*this) + , m_in_iack_func(*this, 0) // default vector (T-11 User's Guide, p. A-11) { m_program_config.m_is_octal = true; for (auto ® : m_reg) @@ -66,6 +74,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 +93,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 +163,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 +212,122 @@ 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) + { + WWORD(VM1_SEL1, RWORD(VM1_SEL1) & ~SEL1_HALT); + PUSH(PSW); + PUSH(PC); + PC = RWORD(m_vsel); + PSW = RWORD(m_vsel + 2); + } + // 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_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) + { + int vec = 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) // FIXME + WWORD(VM1_SEL1, RWORD(VM1_SEL1) | SEL1_HALT); + else + WWORD(VM1_SEL1, RWORD(VM1_SEL1) & ~SEL1_HALT); + PUSH(PSW); + PUSH(PC); + PC = RWORD(m_vsel); + PSW = RWORD(m_vsel + 2); + 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) +{ + // 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 @@ -222,9 +348,14 @@ void t11_device::t11_check_irqs() return; } - // PF has next-highest priority - int priority = PSW & 0340; - if (m_power_fail && priority != 0340) + // non-maskable hardware traps + if (m_bus_error) + { + m_bus_error = false; + take_interrupt(T11_TIMEOUT); + return; + } + else if (m_power_fail) { m_power_fail = false; take_interrupt(T11_PWRFAIL); @@ -233,10 +364,10 @@ void t11_device::t11_check_irqs() // compare the priority of the CP interrupt to the PSW const struct irq_table_entry *irq = &irq_table[m_cp_state & 15]; - if (irq->priority > priority) + if (irq->priority > (PSW & 0340)) { // call the callback - standard_irq_callback(m_cp_state & 15); + standard_irq_callback(m_cp_state & 15, PC); // T11 encodes the interrupt level on DAL<12:8> uint8_t iaddr = bitswap<4>(~m_cp_state & 15, 0, 1, 2, 3); @@ -305,8 +436,6 @@ void t11_device::device_start() m_initial_pc = initial_pc[c_initial_mode >> 13]; space(AS_PROGRAM).cache(m_cache); space(AS_PROGRAM).specific(m_program); - m_out_reset_func.resolve_safe(); - m_in_iack_func.resolve_safe(0); // default vector (T-11 User's Guide, p. A-11) save_item(NAME(m_ppc.w.l)); save_item(NAME(m_reg[0].w.l)); @@ -326,6 +455,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"); @@ -364,6 +497,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()) @@ -404,7 +556,21 @@ void t11_device::device_reset() m_wait_state = 0; 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() @@ -447,6 +613,12 @@ void t11_device::execute_set_input(int irqline, int state) m_pf_active = (state != CLEAR_LINE); break; + case BUS_ERROR: + if (state != CLEAR_LINE && !m_berr_active) + m_bus_error = true; + m_berr_active = (state != CLEAR_LINE); + break; + case HLT_LINE: if (state != CLEAR_LINE && !m_hlt_active) m_ext_halt = true; @@ -483,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(); + } } } |