1
0
mirror of https://github.com/rkujawa/rk65c02.git synced 2025-03-03 14:29:23 +00:00

Add preliminary support for interrupts.

This commit is contained in:
Radosław Kujawa 2017-02-04 21:44:13 +01:00
parent 4ed2016621
commit ac48e5435f
3 changed files with 38 additions and 21 deletions

View File

@ -271,31 +271,14 @@ emul_bra(rk65c02emu_t *e, void *id, instruction_t *i)
program_counter_branch(e, (int8_t) i->op1);
}
/* BRK - break! or rather, jump to break vector */
/* BRK - break! or rather cause an IRQ in software */
void
emul_brk(rk65c02emu_t *e, void *id, instruction_t *i)
{
uint16_t retaddr;
retaddr = e->regs.PC + 2;
/* push return address to the stack */
stack_push(e, retaddr >> 8);
stack_push(e, retaddr & 0xFF);
/* push processor status to the stack with break flag set */
stack_push(e, e->regs.P | P_BREAK);
/*
* The IRQ disable is set, decimal flags is cleared _after_ pushing
* the P register to the stack.
*/
e->regs.P |= P_IRQ_DISABLE;
e->regs.P &= ~P_DECIMAL;
/* load address from IRQ vector into program counter */
e->regs.PC = bus_read_1(e->bus, VECTOR_IRQ);
e->regs.PC |= bus_read_1(e->bus, VECTOR_IRQ + 1) << 8;
e->regs.PC += 2;
e->regs.P |= P_BREAK;
rk65c02_irq(e);
}
/* BVC - branch on overflow clear */

View File

@ -26,9 +26,38 @@ rk65c02_init(bus_t *b)
/* reset also clears the decimal flag */
e.regs.P &= ~P_DECIMAL;
e.irq = false;
return e;
}
/*
* Do interrupt'ey things and start the interrupt service routine.
*/
void
rk65c02_irq(rk65c02emu_t *e)
{
/* push return address to the stack */
stack_push(e, e->regs.PC >> 8);
stack_push(e, e->regs.PC & 0xFF);
/* push processor status to the stack with break flag set */
stack_push(e, e->regs.P);
/*
* The IRQ disable is set, decimal flags is cleared _after_ pushing
* the P register to the stack.
*/
e->regs.P |= P_IRQ_DISABLE;
e->regs.P &= ~P_DECIMAL;
/* break flag is only saved to the stack, it is not present in the ISR... */
e->regs.P &= ~P_BREAK;
/* load address from IRQ vector into program counter */
e->regs.PC = bus_read_1(e->bus, VECTOR_IRQ);
e->regs.PC |= bus_read_1(e->bus, VECTOR_IRQ + 1) << 8;
}
/*
* Execute a single instruction within emulator.
*/
@ -38,6 +67,9 @@ rk65c02_exec(rk65c02emu_t *e)
instruction_t i;
instrdef_t id;
if (e->irq && (!(e->regs.P & P_IRQ_DISABLE)))
rk65c02_irq(e);
/* XXX: handle breakpoints and watch points */
/* if disassembly-when-running enabled */

View File

@ -53,6 +53,7 @@ struct rk65c02emu {
bus_t *bus;
reg_state_t regs;
emu_stop_reason_t stopreason;
bool irq; /* interrupt request line state, true is asserted */
};
typedef struct rk65c02emu rk65c02emu_t;
@ -61,6 +62,7 @@ rk65c02emu_t rk65c02_init(bus_t *);
void rk65c02_start(rk65c02emu_t *);
void rk65c02_step(rk65c02emu_t *, uint16_t);
void rk65c02_dump_regs(rk65c02emu_t *);
void rk65c02_irq(rk65c02emu_t *e);
#endif