1
0
mirror of https://github.com/rkujawa/rk65c02.git synced 2024-12-04 04:51:27 +00:00

Add RTI emulation and test case.

This commit is contained in:
Radosław Kujawa 2017-02-08 15:55:39 +01:00
parent d29be055f9
commit 5cca703020
3 changed files with 71 additions and 3 deletions

View File

@ -63,7 +63,7 @@ OP_BIT_ABSX,"bit",ABSOLUTEX,3,emul_bit,false
OP_AND_ABSX,"and",ABSOLUTEX,3,emul_and,false
OP_ROL_ABSX,"rol",ABSOLUTEX,3,emul_rol,false
OP_BBR3_REL,"bbr3",ZPR,2,emul_bbr3,true
OP_RTI,"rti",IMPLIED,1,NULL,false
OP_RTI,"rti",IMPLIED,1,emul_rti,true
OP_EOR_IZPX,"eor",IZPX,2,emul_eor,false
OP_NOPI_43,"invalid",IMMEDIATE,2,NULL,false
OP_NOPI_44,"invalid",IMPLIED,1,NULL,false

1 opcode_id mnemonic addressing size emulation modify_pc
63 OP_AND_ABSX and ABSOLUTEX 3 emul_and false
64 OP_ROL_ABSX rol ABSOLUTEX 3 emul_rol false
65 OP_BBR3_REL bbr3 ZPR 2 emul_bbr3 true
66 OP_RTI rti IMPLIED 1 NULL emul_rti false true
67 OP_EOR_IZPX eor IZPX 2 emul_eor false
68 OP_NOPI_43 invalid IMMEDIATE 2 NULL false
69 OP_NOPI_44 invalid IMPLIED 1 NULL false

View File

@ -639,6 +639,20 @@ emul_ply(rk65c02emu_t *e, void *id, instruction_t *i)
e->regs.Y = stack_pop(e);
}
/* RTI - return from interrupt */
void
emul_rti(rk65c02emu_t *e, void *id, instruction_t *i)
{
uint16_t retaddr;
/* restore processor status from stack */
e->regs.P = stack_pop(e) | P_UNDEFINED;
/* restore PC */
retaddr = stack_pop(e);
retaddr|= stack_pop(e) << 8;
e->regs.PC = retaddr;
}
/* RTS - return from subroutine */
void
emul_rts(rk65c02emu_t *e, void *id, instruction_t *i)

View File

@ -10,18 +10,19 @@
#include "instruction.h"
#include "utils.h"
#define ISR_ADDR 0xC100
/*
* Test case for software generated interrupt (by BRK instruction).
*/
ATF_TC_WITHOUT_HEAD(intr_brk);
ATF_TC_BODY(intr_brk, tc)
{
const uint16_t isr_addr = 0xC100;
const uint16_t isr_addr = ISR_ADDR;
rk65c02emu_t e;
bus_t b;
b = bus_init();
e = rk65c02_init(&b);
@ -61,9 +62,62 @@ ATF_TC_BODY(intr_brk, tc)
*/
}
/*
* Test case for return from interrupt by RTI instruction.
*/
ATF_TC_WITHOUT_HEAD(intr_rti);
ATF_TC_BODY(intr_rti, tc)
{
bus_t b;
rk65c02emu_t e;
uint8_t *asmbuf;
uint16_t israsmpc;
uint8_t bsize;
b = bus_init();
e = rk65c02_init(&b);
israsmpc = ISR_ADDR;
ATF_REQUIRE(assemble_single_implied(&asmbuf, &bsize, "nop"));
ATF_REQUIRE(bus_load_buf(&b, israsmpc, asmbuf, bsize));
free(asmbuf);
israsmpc += bsize;
ATF_REQUIRE(assemble_single_implied(&asmbuf, &bsize, "rti"));
ATF_REQUIRE(bus_load_buf(&b, israsmpc, asmbuf, bsize));
free(asmbuf);
israsmpc += bsize;
ATF_REQUIRE(assemble_single_implied(&asmbuf, &bsize, "nop"));
ATF_REQUIRE(bus_load_buf(&b, ROM_LOAD_ADDR, asmbuf, bsize));
free(asmbuf);
/* There's a return address and saved processor flags on stack. */
e.regs.SP = 0xFF;
stack_push(&e, ROM_LOAD_ADDR >> 8);
stack_push(&e, ROM_LOAD_ADDR & 0xFF);
stack_push(&e, e.regs.P);
/* We're in the middle of interrupt service routine, just before RTI. */
e.regs.PC = ISR_ADDR;
rk65c02_step(&e, 1);
ATF_CHECK(e.regs.PC == ISR_ADDR + 1);
rk65c02_dump_regs(&e);
rk65c02_dump_stack(&e, 0x4);
/* Step onto RTI. */
rk65c02_step(&e, 1);
rk65c02_dump_regs(&e);
/* Check if we're back in the main program. */
ATF_CHECK(e.regs.PC == ROM_LOAD_ADDR);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, intr_brk);
ATF_TP_ADD_TC(tp, intr_rti);
return (atf_no_error());
}