diff --git a/src/65c02isa.csv b/src/65c02isa.csv index 225d866..efb6319 100644 --- a/src/65c02isa.csv +++ b/src/65c02isa.csv @@ -1,5 +1,5 @@ opcode_id,mnemonic,addressing,size,emulation,modify_pc -OP_BRK,"brk",IMPLIED,1,NULL,false +OP_BRK,"brk",IMPLIED,2,emul_brk,true OP_ORA_IZPX,"ora",IZPX,2,emul_ora,false OP_NOPI_3,"nop",IMMEDIATE,2,NULL,false OP_NOPI_4,"nop",IMPLIED,1,NULL,false diff --git a/src/emulation.c b/src/emulation.c index ec24e90..801ae7d 100644 --- a/src/emulation.c +++ b/src/emulation.c @@ -240,6 +240,33 @@ 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 */ +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; + +} + /* BVC - branch on overflow clear */ void emul_bvc(rk65c02emu_t *e, void *id, instruction_t *i) @@ -568,7 +595,7 @@ emul_pla(rk65c02emu_t *e, void *id, instruction_t *i) instruction_status_adjust_negative(e, e->regs.A); } -/* PLA - pull from stack to processor flags */ +/* PLP - pull from stack to processor flags */ void emul_plp(rk65c02emu_t *e, void *id, instruction_t *i) { diff --git a/src/rk65c02.h b/src/rk65c02.h index 7d3e084..9b3e208 100644 --- a/src/rk65c02.h +++ b/src/rk65c02.h @@ -42,6 +42,8 @@ struct reg_state { #define STACK_START 0x0100 #define STACK_END 0x01FF +#define VECTOR_IRQ 0xFFFE /* also used for BRK */ + #define BIT(val,n) ((val) & (1 << (n))) typedef struct reg_state reg_state_t;