mirror of
https://github.com/holub/mame
synced 2025-04-23 17:00:53 +03:00
cpu/t11: Improved trace trap processing, and added basic interrupt processing to the K1801VM1. (#12151)
This commit is contained in:
parent
91c9b46710
commit
26ba3b1af9
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user