mirror of
https://github.com/rkujawa/rk65c02.git
synced 2024-12-04 19:50:19 +00:00
Add RTI emulation and test case.
This commit is contained in:
parent
d29be055f9
commit
5cca703020
@ -63,7 +63,7 @@ OP_BIT_ABSX,"bit",ABSOLUTEX,3,emul_bit,false
|
|||||||
OP_AND_ABSX,"and",ABSOLUTEX,3,emul_and,false
|
OP_AND_ABSX,"and",ABSOLUTEX,3,emul_and,false
|
||||||
OP_ROL_ABSX,"rol",ABSOLUTEX,3,emul_rol,false
|
OP_ROL_ABSX,"rol",ABSOLUTEX,3,emul_rol,false
|
||||||
OP_BBR3_REL,"bbr3",ZPR,2,emul_bbr3,true
|
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_EOR_IZPX,"eor",IZPX,2,emul_eor,false
|
||||||
OP_NOPI_43,"invalid",IMMEDIATE,2,NULL,false
|
OP_NOPI_43,"invalid",IMMEDIATE,2,NULL,false
|
||||||
OP_NOPI_44,"invalid",IMPLIED,1,NULL,false
|
OP_NOPI_44,"invalid",IMPLIED,1,NULL,false
|
||||||
|
|
@ -639,6 +639,20 @@ emul_ply(rk65c02emu_t *e, void *id, instruction_t *i)
|
|||||||
e->regs.Y = stack_pop(e);
|
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 */
|
/* RTS - return from subroutine */
|
||||||
void
|
void
|
||||||
emul_rts(rk65c02emu_t *e, void *id, instruction_t *i)
|
emul_rts(rk65c02emu_t *e, void *id, instruction_t *i)
|
||||||
|
@ -10,18 +10,19 @@
|
|||||||
#include "instruction.h"
|
#include "instruction.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define ISR_ADDR 0xC100
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test case for software generated interrupt (by BRK instruction).
|
* Test case for software generated interrupt (by BRK instruction).
|
||||||
*/
|
*/
|
||||||
ATF_TC_WITHOUT_HEAD(intr_brk);
|
ATF_TC_WITHOUT_HEAD(intr_brk);
|
||||||
ATF_TC_BODY(intr_brk, tc)
|
ATF_TC_BODY(intr_brk, tc)
|
||||||
{
|
{
|
||||||
const uint16_t isr_addr = 0xC100;
|
const uint16_t isr_addr = ISR_ADDR;
|
||||||
|
|
||||||
rk65c02emu_t e;
|
rk65c02emu_t e;
|
||||||
bus_t b;
|
bus_t b;
|
||||||
|
|
||||||
|
|
||||||
b = bus_init();
|
b = bus_init();
|
||||||
e = rk65c02_init(&b);
|
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_TCS(tp)
|
||||||
{
|
{
|
||||||
ATF_TP_ADD_TC(tp, intr_brk);
|
ATF_TP_ADD_TC(tp, intr_brk);
|
||||||
|
ATF_TP_ADD_TC(tp, intr_rti);
|
||||||
|
|
||||||
return (atf_no_error());
|
return (atf_no_error());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user