#include #include #include #include #include "bus.h" #include "rk65c02.h" #include "utils.h" ATF_TC_WITHOUT_HEAD(emul_bit); ATF_TC_BODY(emul_bit, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* BIT immediate */ e.regs.A = 0x40; ATF_REQUIRE(rom_start(&e, "test_emulation_bit_imm.rom")); ATF_CHECK(!(e.regs.P & P_ZERO)); ATF_CHECK(e.regs.P & P_SIGN_OVERFLOW); ATF_CHECK(!(e.regs.P & P_NEGATIVE)); /* BIT zero page */ e.regs.A = 0x40; bus_write_1(&b, 0x10, 0x80); ATF_REQUIRE(rom_start(&e, "test_emulation_bit_zp.rom")); ATF_CHECK(e.regs.P & P_ZERO); ATF_CHECK(!(e.regs.P & P_SIGN_OVERFLOW)); ATF_CHECK(e.regs.P & P_NEGATIVE); /* BIT zero page X */ e.regs.A = 0x40; e.regs.X = 0x1; bus_write_1(&b, 0x10, 0x40); ATF_REQUIRE(rom_start(&e, "test_emulation_bit_zpx.rom")); ATF_CHECK(!(e.regs.P & P_ZERO)); ATF_CHECK(e.regs.P & P_SIGN_OVERFLOW); ATF_CHECK(!(e.regs.P & P_NEGATIVE)); /* BIT absolute */ e.regs.A = 0x80; bus_write_1(&b, 0x2010, 0x80); ATF_REQUIRE(rom_start(&e, "test_emulation_bit_abs.rom")); ATF_CHECK(!(e.regs.P & P_ZERO)); ATF_CHECK(!(e.regs.P & P_SIGN_OVERFLOW)); ATF_CHECK(e.regs.P & P_NEGATIVE); /* BIT absolute X */ e.regs.A = 0x40; e.regs.X = 0x2; bus_write_1(&b, 0x2010, 0x80); ATF_REQUIRE(rom_start(&e, "test_emulation_bit_absx.rom")); ATF_CHECK(e.regs.P & P_ZERO); ATF_CHECK(!(e.regs.P & P_SIGN_OVERFLOW)); ATF_CHECK(e.regs.P & P_NEGATIVE); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_dex_dey); ATF_TC_BODY(emul_dex_dey, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* DEX */ e.regs.X = 0x1; ATF_REQUIRE(rom_start(&e, "test_emulation_dex.rom")); ATF_CHECK(e.regs.X == 0x0); /* DEX underflow */ ATF_REQUIRE(rom_start(&e, "test_emulation_dex.rom")); ATF_CHECK(e.regs.X == 0xFF); /* DEY */ e.regs.Y = 0x1; ATF_REQUIRE(rom_start(&e, "test_emulation_dey.rom")); ATF_CHECK(e.regs.Y == 0x0); /* DEY underflow */ ATF_REQUIRE(rom_start(&e, "test_emulation_dey.rom")); ATF_CHECK(e.regs.Y == 0xFF); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_inx_iny); ATF_TC_BODY(emul_inx_iny, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* INX */ e.regs.X = 0; ATF_REQUIRE(rom_start(&e, "test_emulation_inx.rom")); ATF_CHECK(e.regs.X == 0x1); /* INX overflow */ e.regs.X = 0xFF; ATF_REQUIRE(rom_start(&e, "test_emulation_inx.rom")); ATF_CHECK(e.regs.X == 0x0); /* INY */ e.regs.Y = 0; ATF_REQUIRE(rom_start(&e, "test_emulation_iny.rom")); ATF_CHECK(e.regs.Y == 0x1); /* INY overflow */ e.regs.Y = 0xFF; ATF_REQUIRE(rom_start(&e, "test_emulation_iny.rom")); ATF_CHECK(e.regs.Y == 0x0); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_lda); ATF_TC_BODY(emul_lda, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* LDA immediate */ ATF_REQUIRE(rom_start(&e, "test_emulation_lda_imm.rom")); /* ATF_CHECK(e.state == STOPPED); // separate test case for states? */ ATF_CHECK(e.regs.PC == ROM_LOAD_ADDR+3); // separate test case for PC? */ ATF_CHECK(e.regs.A == 0xAF); /* LDA zero page */ bus_write_1(&b, 0x10, 0xAE); ATF_REQUIRE(rom_start(&e, "test_emulation_lda_zp.rom")); ATF_CHECK(e.regs.A == 0xAE); /* LDA absolute */ bus_write_1(&b, 0x2F5A, 0xEA); ATF_REQUIRE(rom_start(&e, "test_emulation_lda_abs.rom")); ATF_CHECK(e.regs.A == 0xEA); /* LDA absolute X */ bus_write_1(&b, 0x2F5A, 0xEB); e.regs.X = 0x5A; ATF_REQUIRE(rom_start(&e, "test_emulation_lda_absx.rom")); ATF_CHECK(e.regs.A == 0xEB); /* LDA absolute X */ bus_write_1(&b, 0x2F5E, 0xEC); e.regs.Y = 0x5E; ATF_REQUIRE(rom_start(&e, "test_emulation_lda_absy.rom")); ATF_CHECK(e.regs.A == 0xEC); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_stz); ATF_TC_BODY(emul_stz, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* STZ zp */ bus_write_1(&b, 0x10, 0xAA); ATF_REQUIRE(rom_start(&e, "test_emulation_stz_zp.rom")); ATF_CHECK(bus_read_1(&b, 0x10) == 0x00); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_clc_sec); ATF_TC_BODY(emul_clc_sec, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* SEC */ e.regs.P &= ~P_CARRY; ATF_REQUIRE(rom_start(&e, "test_emulation_sec.rom")); ATF_CHECK(e.regs.P & P_CARRY); /* CLC */ ATF_REQUIRE(rom_start(&e, "test_emulation_clc.rom")); ATF_CHECK(e.regs.P ^ P_CARRY); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_and); ATF_TC_BODY(emul_and, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* AND immediate */ e.regs.A = 0xFF; ATF_REQUIRE(rom_start(&e, "test_emulation_and_imm.rom")); ATF_CHECK(e.regs.A == 0xAA); /* AND zero page */ /* bus_write_1(&b, 0x10, 0xAE); ATF_REQUIRE(rom_start(&e, "test_emulation_and_zp.rom")); ATF_CHECK(e.regs.A == 0xAE);*/ bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_nop); ATF_TC_BODY(emul_nop, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); e.regs.PC = ROM_LOAD_ADDR; ATF_REQUIRE(rom_start(&e, "test_emulation_nop.rom")); ATF_CHECK(e.regs.PC == ROM_LOAD_ADDR+2); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_sta); ATF_TC_BODY(emul_sta, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* STA zero page */ e.regs.A = 0xAA; ATF_REQUIRE(rom_start(&e, "test_emulation_sta_zp.rom")); ATF_CHECK(bus_read_1(&b, 0x20) == 0xAA); /* STA zero page X */ e.regs.A = 0x55; e.regs.X = 0x1; ATF_REQUIRE(rom_start(&e, "test_emulation_sta_zpx.rom")); ATF_CHECK(bus_read_1(&b, 0x20) == 0x55); /* STA absolute */ e.regs.A = 0xAA; ATF_REQUIRE(rom_start(&e, "test_emulation_sta_abs.rom")); ATF_CHECK(bus_read_1(&b, 0x2010) == 0xAA); /* STA absolute X */ e.regs.A = 0x55; e.regs.X = 0x10; ATF_REQUIRE(rom_start(&e, "test_emulation_sta_absx.rom")); ATF_CHECK(bus_read_1(&b, 0x2010) == 0x55); /* STA absolute Y */ e.regs.A = 0xAA; e.regs.X = 0; e.regs.Y = 0x1; ATF_REQUIRE(rom_start(&e, "test_emulation_sta_absy.rom")); ATF_CHECK(bus_read_1(&b, 0x2010) == 0xAA); /* STA indirect zero */ e.regs.A = 0x55; bus_write_1(&b, 0x25, 0x10); bus_write_1(&b, 0x26, 0x20); ATF_REQUIRE(rom_start(&e, "test_emulation_sta_izp.rom")); ATF_CHECK(bus_read_1(&b, 0x2010) == 0x55); /* STA indirect zero page X */ e.regs.A = 0xAA; e.regs.X = 0x4; e.regs.Y = 0; ATF_REQUIRE(rom_start(&e, "test_emulation_sta_izpx.rom")); ATF_CHECK(bus_read_1(&b, 0x2010) == 0xAA); /* STA indirect zero page Y */ e.regs.A = 0x54; e.regs.X = 0; e.regs.Y = 0x1; ATF_REQUIRE(rom_start(&e, "test_emulation_sta_izpy.rom")); ATF_CHECK(bus_read_1(&b, 0x2010) == 0x55); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_ora); ATF_TC_BODY(emul_ora, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* ORA immediate */ e.regs.A = 0x55; ATF_REQUIRE(rom_start(&e, "test_emulation_ora_imm.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA zero page */ e.regs.A = 0xAA; bus_write_1(&b, 0x10, 0x55); ATF_REQUIRE(rom_start(&e, "test_emulation_ora_zp.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA zero page X */ e.regs.A = 0xAA; e.regs.X = 0x11; bus_write_1(&b, 0x21, 0x55); ATF_REQUIRE(rom_start(&e, "test_emulation_ora_zpx.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA absolute */ e.regs.A = 0x55; bus_write_1(&b, 0x2A01, 0xAA); ATF_REQUIRE(rom_start(&e, "test_emulation_ora_abs.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA absolute X */ e.regs.A = 0xAA; e.regs.X = 0x1; bus_write_1(&b, 0x2A01, 0x55); ATF_REQUIRE(rom_start(&e, "test_emulation_ora_absx.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA absolute Y */ e.regs.A = 0x55; e.regs.X = 0; e.regs.Y = 0x2; bus_write_1(&b, 0x2A02, 0xAA); ATF_REQUIRE(rom_start(&e, "test_emulation_ora_absy.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA indirect zero */ e.regs.A = 0xAA; bus_write_1(&b, 0x2A04, 0x55); bus_write_1(&b, 0x12, 0x04); bus_write_1(&b, 0x13, 0x2A); ATF_REQUIRE(rom_start(&e, "test_emulation_ora_izp.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA indirect zero page X */ e.regs.A = 0xAA; e.regs.X = 0x2; e.regs.Y = 0; ATF_REQUIRE(rom_start(&e, "test_emulation_ora_izpx.rom")); ATF_CHECK(e.regs.A == 0xFF); /* ORA indirect zero page Y */ e.regs.A = 0xAA; e.regs.X = 0; e.regs.Y = 0x1; bus_write_1(&b, 0x2A04, 0x54); bus_write_1(&b, 0x14, 0x04); bus_write_1(&b, 0x15, 0x2A); ATF_REQUIRE(rom_start(&e, "test_emulation_ora_izpy.rom")); ATF_CHECK(e.regs.A == 0xFF); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_txa_tya_tax_tay); ATF_TC_BODY(emul_txa_tya_tax_tay, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); e.regs.A = 0x0; e.regs.X = 0xAA; e.regs.Y = 0x55; ATF_REQUIRE(rom_start(&e, "test_emulation_txa.rom")); ATF_CHECK(e.regs.A == 0xAA); ATF_REQUIRE(rom_start(&e, "test_emulation_tya.rom")); ATF_CHECK(e.regs.A == 0x55); ATF_REQUIRE(rom_start(&e, "test_emulation_tax.rom")); ATF_CHECK(e.regs.X == 0x55); e.regs.A = 0xFF; ATF_REQUIRE(rom_start(&e, "test_emulation_tay.rom")); ATF_CHECK(e.regs.A == 0xFF); bus_finish(&b); } /* test stack operation and stack related opcodes - PLA, PHA... */ ATF_TC_WITHOUT_HEAD(emul_stack); ATF_TC_BODY(emul_stack, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* place 0xAA on stack */ e.regs.SP = 0xFF; e.regs.A = 0xAA; ATF_REQUIRE(rom_start(&e, "test_emulation_pha.rom")); ATF_CHECK(e.regs.SP == 0xFE); ATF_CHECK(bus_read_1(e.bus, STACK_END) == 0xAA); /* * Run again to see if stack pointer further decrements and we'll * end up with one more value on stack. */ e.regs.PC = ROM_LOAD_ADDR; e.regs.A = 0xAB; rk65c02_start(&e); ATF_CHECK(e.regs.SP == 0xFD); ATF_CHECK(bus_read_1(e.bus, STACK_END) == 0xAA); ATF_CHECK(bus_read_1(e.bus, STACK_END-1) == 0xAB); /* * Now let's see if loading back into accumulator works. */ e.regs.A = 0x0; ATF_REQUIRE(rom_start(&e, "test_emulation_pla.rom")); ATF_CHECK(e.regs.SP == 0xFE); ATF_CHECK(e.regs.A == 0xAB); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_php_plp); ATF_TC_BODY(emul_php_plp, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); e.regs.SP = 0xFF; e.regs.P |= P_CARRY|P_ZERO|P_UNDEFINED; ATF_REQUIRE(rom_start(&e, "test_emulation_php.rom")); ATF_CHECK(e.regs.SP == 0xFE); ATF_CHECK(bus_read_1(e.bus, STACK_END) == (P_CARRY|P_ZERO|P_UNDEFINED)); /* * Now let's see if loading back into accumulator works. */ bus_write_1(e.bus, STACK_END, P_CARRY|P_DECIMAL); ATF_REQUIRE(rom_start(&e, "test_emulation_plp.rom")); ATF_CHECK(e.regs.SP == 0xFF); ATF_CHECK(e.regs.P == (P_CARRY|P_DECIMAL|P_UNDEFINED)); bus_finish(&b); } ATF_TC_WITHOUT_HEAD(emul_phx_phy_plx_ply); ATF_TC_BODY(emul_phx_phy_plx_ply, tc) { rk65c02emu_t e; bus_t b; b = bus_init(); e = rk65c02_init(&b); /* check push X to stack */ e.regs.X = 0xAA; e.regs.SP = 0xFF; ATF_REQUIRE(rom_start(&e, "test_emulation_phx.rom")); ATF_CHECK(e.regs.SP == 0xFE); ATF_CHECK(bus_read_1(e.bus, STACK_END) == 0xAA); /* check pull X from stack */ e.regs.X = 0; ATF_REQUIRE(rom_start(&e, "test_emulation_plx.rom")); ATF_CHECK(e.regs.SP == 0xFF); ATF_CHECK(e.regs.X == 0xAA); /* check push Y to stack */ e.regs.Y = 0x55; e.regs.SP = 0xFF; ATF_REQUIRE(rom_start(&e, "test_emulation_phy.rom")); ATF_CHECK(e.regs.SP == 0xFE); ATF_CHECK(bus_read_1(e.bus, STACK_END) == 0x55); /* check pull X from stack */ e.regs.Y = 0xFF; ATF_REQUIRE(rom_start(&e, "test_emulation_ply.rom")); ATF_CHECK(e.regs.SP == 0xFF); ATF_CHECK(e.regs.Y == 0x55); bus_finish(&b); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, emul_and); ATF_TP_ADD_TC(tp, emul_bit); ATF_TP_ADD_TC(tp, emul_dex_dey); ATF_TP_ADD_TC(tp, emul_clc_sec); ATF_TP_ADD_TC(tp, emul_inx_iny); ATF_TP_ADD_TC(tp, emul_lda); ATF_TP_ADD_TC(tp, emul_nop); ATF_TP_ADD_TC(tp, emul_ora); ATF_TP_ADD_TC(tp, emul_stz); ATF_TP_ADD_TC(tp, emul_php_plp); ATF_TP_ADD_TC(tp, emul_phx_phy_plx_ply); ATF_TP_ADD_TC(tp, emul_stack); ATF_TP_ADD_TC(tp, emul_txa_tya_tax_tay); ATF_TP_ADD_TC(tp, emul_sta); return (atf_no_error()); }