summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author shattered <shattered@users.noreply.github.com>2024-03-23 15:31:06 +0000
committer GitHub <noreply@github.com>2024-03-24 02:31:06 +1100
commit26ba3b1af9e37ac7766bdbb806efe4743bfd9cbe (patch)
tree68904f3c5ef79383b7f2f8777cc75a32eae2b624 /src
parent91c9b46710e00492e16790cbafc30298d6ad344f (diff)
cpu/t11: Improved trace trap processing, and added basic interrupt processing to the K1801VM1. (#12151)
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/t11/t11.cpp133
-rw-r--r--src/devices/cpu/t11/t11.h25
-rw-r--r--src/devices/cpu/t11/t11ops.hxx50
3 files changed, 189 insertions, 19 deletions
diff --git a/src/devices/cpu/t11/t11.cpp b/src/devices/cpu/t11/t11.cpp
index 448dec30feb..487a7a57003 100644
--- a/src/devices/cpu/t11/t11.cpp
+++ b/src/devices/cpu/t11/t11.cpp
@@ -163,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)
@@ -210,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
@@ -337,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");
@@ -436,6 +558,8 @@ 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()
@@ -444,6 +568,9 @@ void k1801vm1_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()
@@ -528,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();
+ }
}
}
diff --git a/src/devices/cpu/t11/t11.h b/src/devices/cpu/t11/t11.h
index b4e8032d165..cb4c2d477c8 100644
--- a/src/devices/cpu/t11/t11.h
+++ b/src/devices/cpu/t11/t11.h
@@ -51,14 +51,25 @@ protected:
T11_IOT = 020, // IOT instruction vector
T11_PWRFAIL = 024, // Power fail vector
T11_EMT = 030, // EMT instruction vector
- T11_TRAP = 034 // TRAP instruction vector
+ T11_TRAP = 034, // TRAP instruction vector
+ // K1801 vectors
+ VM1_EVNT = 0100, // EVNT pin vector
+ VM1_IRQ3 = 0270, // IRQ3 pin vector
+ VM1_HALT = 0160002, // HALT instruction vector
+ VM2_HALT = 0170 // HALT instruction vector
};
// K1801 microcode constants
enum
{
VM1_STACK = 0177674, // start of HALT mode save area
VM1_SEL1 = 0177716, // DIP switch register (read) and HALT mode selector (write)
- SEL1_HALT = 010
+ SEL1_HALT = 010,
+ MCIR_ILL = -2,
+ MCIR_SET = -1,
+ MCIR_WAIT = 0,
+ MCIR_NONE = 1,
+ MCIR_HALT = 2,
+ MCIR_IRQ = 3
};
enum
{
@@ -106,6 +117,8 @@ protected:
PAIR m_psw;
uint16_t m_initial_pc;
uint8_t m_wait_state;
+ int8_t m_mcir;
+ uint16_t m_vsel;
uint8_t m_cp_state;
bool m_vec_active;
bool m_pf_active;
@@ -114,6 +127,8 @@ protected:
bool m_power_fail;
bool m_bus_error;
bool m_ext_halt;
+ bool m_check_irqs;
+ bool m_trace_trap;
int m_icount;
memory_access<16, 1, 0, ENDIANNESS_LITTLE>::cache m_cache;
memory_access<16, 1, 0, ENDIANNESS_LITTLE>::specific m_program;
@@ -128,7 +143,8 @@ protected:
inline void WWORD(int addr, int data);
inline void PUSH(int val);
inline int POP();
- void t11_check_irqs();
+
+ virtual void t11_check_irqs();
void take_interrupt(uint8_t vector);
void trap_to(uint16_t vector);
@@ -1190,6 +1206,9 @@ protected:
// device_state_interface overrides
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ virtual void t11_check_irqs() override;
+ void take_interrupt_halt(uint16_t vector);
};
diff --git a/src/devices/cpu/t11/t11ops.hxx b/src/devices/cpu/t11/t11ops.hxx
index ea7471e1fd9..cdcfedb8ced 100644
--- a/src/devices/cpu/t11/t11ops.hxx
+++ b/src/devices/cpu/t11/t11ops.hxx
@@ -224,8 +224,8 @@
#define MOVB_X(s,d) int sreg, dreg, source, result, ea; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; PUT_DW_##d((signed char)result)
#define MOVB_M(s,d) int sreg, dreg, source, result, ea; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; PUT_DBT_##d(result)
/* MTPS: flags = src */
-#define MTPS_R(d) int dreg, dest; GET_DB_##d; PSW = (PSW & ~0xef) | (dest & 0xef); t11_check_irqs()
-#define MTPS_M(d) int dreg, dest, ea; GET_DB_##d; PSW = (PSW & ~0xef) | (dest & 0xef); t11_check_irqs()
+#define MTPS_R(d) int dreg, dest; GET_DB_##d; PSW = (PSW & ~0xef) | (dest & 0xef); m_check_irqs = true
+#define MTPS_M(d) int dreg, dest, ea; GET_DB_##d; PSW = (PSW & ~0xef) | (dest & 0xef); m_check_irqs = true
/* NEG: dst = -dst */
#define NEG_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = -dest; SETW_NZ; if (dest == 0x8000) SET_V; if (result) SET_C; PUT_DW_DREG(result)
#define NEG_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = -dest; SETW_NZ; if (dest == 0x8000) SET_V; if (result) SET_C; PUT_DW_EA(result)
@@ -273,11 +273,22 @@
void t11_device::trap_to(uint16_t vector)
{
- PUSH(PSW);
- PUSH(PC);
- PC = RWORD(vector);
- PSW = RWORD(vector + 2);
- t11_check_irqs();
+ if (c_insn_set & IS_VM1)
+ {
+ m_vsel = vector;
+ if (vector == T11_ILLINST || vector == T11_TIMEOUT)
+ m_mcir = MCIR_ILL;
+ else
+ m_mcir = MCIR_SET;
+ }
+ else
+ {
+ PUSH(PSW);
+ PUSH(PC);
+ PC = RWORD(vector);
+ PSW = RWORD(vector + 2);
+ }
+ m_check_irqs = true;
}
void t11_device::op_0000(uint16_t op)
@@ -286,11 +297,11 @@ void t11_device::op_0000(uint16_t op)
{
case 0x00: /* HALT */ halt(op); break;
case 0x01: /* WAIT */ m_icount = 0; m_wait_state = 1; break;
- case 0x02: /* RTI */ m_icount -= 24; PC = POP(); PSW = POP(); t11_check_irqs(); break;
- case 0x03: /* BPT */ m_icount -= 48; trap_to(0x0c); break;
- case 0x04: /* IOT */ m_icount -= 48; trap_to(0x10); break;
+ case 0x02: /* RTI */ m_icount -= 24; PC = POP(); PSW = POP(); if (GET_T) m_trace_trap = true; m_check_irqs = true; break;
+ case 0x03: /* BPT */ m_icount -= 48; trap_to(T11_BPT); break;
+ case 0x04: /* IOT */ m_icount -= 48; trap_to(T11_IOT); break;
case 0x05: /* RESET */ m_out_reset_func(ASSERT_LINE); m_out_reset_func(CLEAR_LINE); m_icount -= 110; break;
- case 0x06: /* RTT */ if (c_insn_set & IS_LEIS) { m_icount -= 33; PC = POP(); PSW = POP(); t11_check_irqs(); } else illegal(op); break;
+ case 0x06: /* RTT */ if (c_insn_set & IS_LEIS) { m_icount -= 33; PC = POP(); PSW = POP(); m_check_irqs = true; } else illegal(op); break;
case 0x07: /* MFPT */ if (c_insn_set & IS_MFPT) REGB(0) = 4; else illegal(op); break;
default: illegal(op); break;
@@ -324,11 +335,18 @@ void t11_device::op_0001(uint16_t op)
void t11_device::halt(uint16_t op)
{
m_icount -= 48;
- PUSH(PSW);
- PUSH(PC);
- PC = m_initial_pc + 4;
- PSW = 0340;
- t11_check_irqs();
+ if (c_insn_set & IS_VM1)
+ {
+ trap_to(VM1_HALT);
+ }
+ else
+ {
+ PUSH(PSW);
+ PUSH(PC);
+ PC = m_initial_pc + 4;
+ PSW = 0340;
+ }
+ m_check_irqs = true;
}
void t11_device::illegal(uint16_t op)