From faa824e306935435b13f9a24017819a5def2fdd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Kujawa?= Date: Tue, 31 Jan 2017 23:08:23 +0100 Subject: [PATCH] Implement emulation of ADC, plug the overflow test. While here fix numerous test cases, lol. --- src/65c02isa.csv | 20 +++++++-------- src/emulation.c | 38 +++++++++++++++++++++++++++ test/test_emulation.c | 60 ++++++++++++++++++++++++++----------------- 3 files changed, 85 insertions(+), 33 deletions(-) diff --git a/src/65c02isa.csv b/src/65c02isa.csv index efb6319..a111c7b 100644 --- a/src/65c02isa.csv +++ b/src/65c02isa.csv @@ -96,35 +96,35 @@ OP_EOR_ABSX,"eor",ABSOLUTEX,3,emul_eor,false OP_LSR_ABSX,"lsr",ABSOLUTEX,3,emul_lsr,false OP_BBR5_REL,"bbr5",ZPR,2,emul_bbr5,true OP_RTS,"rts",IMPLIED,1,emul_rts,false -OP_ADC_IZPX,"adc",IZPX,2,NULL,false +OP_ADC_IZPX,"adc",IZPX,2,emul_adc,false OP_NOPI_63,"nop",IMMEDIATE,2,NULL,false OP_NOPI_64,"nop",IMPLIED,1,NULL,false OP_STZ_ZP,"stz",ZP,2,emul_stz,false -OP_ADC_ZP,"adc",ZP,2,NULL,false +OP_ADC_ZP,"adc",ZP,2,emul_adc,false OP_ROR_ZP,"ror",ZP,2,emul_ror,false OP_RMB6_ZP,"rmb6",ZP,2,emul_rmb6,false OP_PLA,"pla",IMPLIED,1,emul_pla,false -OP_ADC_IMM,"adc",IMMEDIATE,2,NULL,false +OP_ADC_IMM,"adc",IMMEDIATE,2,emul_adc,false OP_ROR,"ror",ACCUMULATOR,1,emul_ror,false OP_NOPI_6C,"nop",IMPLIED,1,NULL,false OP_JMP_IABS,"jmp",IABSOLUTE,3,emul_jmp,true -OP_ADC_ABS,"adc",ABSOLUTE,3,NULL,false +OP_ADC_ABS,"adc",ABSOLUTE,3,emul_adc,false OP_ROR_ABS,"ror",ABSOLUTE,3,emul_ror,false OP_BBR6_REL,"bbr6",ZPR,2,emul_bbr6,true OP_BVS_REL,"bvs",RELATIVE,2,emul_bvs,true -OP_ADC_IZPY,"adc",IZPY,2,NULL,false -OP_ADC_IZP,"adc",IZP,2,NULL,false +OP_ADC_IZPY,"adc",IZPY,2,emul_adc,false +OP_ADC_IZP,"adc",IZP,2,emul_adc,false OP_NOPI_74,"nop",IMPLIED,1,NULL,false OP_STZ_ZPX,"stz",ZPX,2,emul_stz,false -OP_ADC_ZPX,"adc",ZPX,2,NULL,false +OP_ADC_ZPX,"adc",ZPX,2,emul_adc,false OP_ROR_ZPX,"ror",ZPX,2,emul_ror,false OP_RMB7_ZP,"rmb7",ZP,2,emul_rmb7,false OP_SEI,"sei",IMPLIED,1,emul_sei,false -OP_ADC_ABSY,"adc",ABSOLUTEY,3,NULL,false +OP_ADC_ABSY,"adc",ABSOLUTEY,3,emul_adc,false OP_PLY,"ply",IMPLIED,1,emul_ply,false OP_NOPI_7C,"nop",IMPLIED,1,NULL,false OP_JMP_IABSX,"jmp",IABSOLUTEX,3,emul_jmp,true -OP_ADC_ABSX,"adc",ABSOLUTEX,3,NULL,false +OP_ADC_ABSX,"adc",ABSOLUTEX,3,emul_adc,false OP_ROR_ABSX,"ror",ABSOLUTEX,3,emul_ror,false OP_BBR7_REL,"bbr7",ZPR,2,emul_bbr7,true OP_BRA_REL,"bra",RELATIVE,2,emul_bra,true @@ -215,7 +215,7 @@ OP_NOPI_D5,"nop",ZPX,2,NULL,false OP_CMP_ZPX,"cmp",ZPX,2,emul_cmp,false OP_DEC_ZPX,"dec",ZPX,2,emul_dec,false OP_SMB5_ZP,"smb5",ZP,2,emul_smb5,false -OP_CLD,"cld",IMPLIED,1,NULL,false +OP_CLD,"cld",IMPLIED,1,emul_cld,false OP_CMP_ABSY,"cmp",ABSOLUTEY,3,emul_cmp,false OP_PHX,"phx",IMPLIED,1,emul_phx,false OP_STP,"stp",IMPLIED,1,emul_stp,false diff --git a/src/emulation.c b/src/emulation.c index eb881c9..622774f 100644 --- a/src/emulation.c +++ b/src/emulation.c @@ -11,6 +11,37 @@ void emul_bbs(rk65c02emu_t *, void *, instruction_t *, uint8_t); /* Implementation of emulation of instructions follows below */ +/* ADC - add with carry */ +void +emul_adc(rk65c02emu_t *e, void *id, instruction_t *i) +{ + uint8_t arg; + uint16_t res; /* meh */ + + arg = instruction_data_read_1(e, (instrdef_t *) id, i); + res = e->regs.A + arg; + + if (e->regs.P & P_CARRY) + res++; + + if ((e->regs.A ^ res) & (arg ^ res) & 0x80) + e->regs.P |= P_SIGN_OVERFLOW; + else + e->regs.P &= ~P_SIGN_OVERFLOW; + + /* if the result does not fit into 8 bits then set carry */ + if (res > 0xFF) + e->regs.P |= P_CARRY; + else + e->regs.P &= ~P_CARRY; + + /* squash the result into accumulator's 8 bits, lol */ + e->regs.A = (uint8_t) res; + + instruction_status_adjust_zero(e, e->regs.A); + instruction_status_adjust_negative(e, e->regs.A); +} + /* AND - logical AND */ void emul_and(rk65c02emu_t *e, void *id, instruction_t *i) @@ -294,6 +325,13 @@ emul_clc(rk65c02emu_t *e, void *id, instruction_t *i) e->regs.P &= ~P_CARRY; } +/* CLD - clear decimal flag */ +void +emul_cld(rk65c02emu_t *e, void *id, instruction_t *i) +{ + e->regs.P &= ~P_DECIMAL; +} + /* CLI - clear interrupt disable flag */ void emul_cli(rk65c02emu_t *e, void *id, instruction_t *i) diff --git a/test/test_emulation.c b/test/test_emulation.c index f0f897c..197ded0 100644 --- a/test/test_emulation.c +++ b/test/test_emulation.c @@ -844,7 +844,7 @@ ATF_TC_BODY(emul_jmp, tc) rom_path("test_emulation_jmp_abs.rom", tc))); rk65c02_step(&e, 3); - ATF_CHECK(e.regs.PC = 0xC000); + ATF_CHECK(e.regs.PC == 0xC000); /* JMP indirect absolute */ e.regs.PC = ROM_LOAD_ADDR; @@ -855,7 +855,7 @@ ATF_TC_BODY(emul_jmp, tc) bus_write_1(&b, 0x21, 0xC0); rk65c02_step(&e, 3); - ATF_CHECK(e.regs.PC = 0xC000); + ATF_CHECK(e.regs.PC == 0xC000); /* JMP indirect absolute X */ e.regs.PC = ROM_LOAD_ADDR; @@ -867,7 +867,7 @@ ATF_TC_BODY(emul_jmp, tc) bus_write_1(&b, 0x41, 0xC0); rk65c02_step(&e, 3); - ATF_CHECK(e.regs.PC = 0xC000); + ATF_CHECK(e.regs.PC == 0xC000); } ATF_TC_WITHOUT_HEAD(emul_jsr_rts); @@ -885,9 +885,9 @@ ATF_TC_BODY(emul_jsr_rts, tc) rom_path("test_emulation_jsr_rts.rom", tc))); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC006); + ATF_CHECK(e.regs.PC == 0xC006); rk65c02_start(&e); - ATF_CHECK(e.regs.PC = 0xC006); + ATF_CHECK(e.regs.PC == 0xC006); } @@ -907,9 +907,9 @@ ATF_TC_BODY(emul_branch, tc) e.regs.P &= ~P_CARRY; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); /* BCS */ @@ -919,9 +919,9 @@ ATF_TC_BODY(emul_branch, tc) e.regs.P |= P_CARRY; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); /* BRA */ @@ -930,7 +930,7 @@ ATF_TC_BODY(emul_branch, tc) rom_path("test_emulation_bra.rom", tc))); rk65c02_step(&e, 1); - ATF_CHECK(e.regs.PC = 0xC004); + ATF_CHECK(e.regs.PC == 0xC004); rk65c02_start(&e); /* BEQ */ @@ -940,9 +940,9 @@ ATF_TC_BODY(emul_branch, tc) e.regs.P |= P_ZERO; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); /* BMI */ @@ -952,9 +952,9 @@ ATF_TC_BODY(emul_branch, tc) e.regs.P |= P_NEGATIVE; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); /* BNE */ @@ -962,11 +962,11 @@ ATF_TC_BODY(emul_branch, tc) ATF_REQUIRE(bus_load_file(&b, ROM_LOAD_ADDR, rom_path("test_emulation_bne.rom", tc))); - e.regs.P |= P_NEGATIVE; + e.regs.P &= ~P_ZERO; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); /* BPL */ @@ -976,9 +976,9 @@ ATF_TC_BODY(emul_branch, tc) e.regs.P &= ~P_NEGATIVE; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); /* BVC */ @@ -988,9 +988,9 @@ ATF_TC_BODY(emul_branch, tc) e.regs.P &= ~P_SIGN_OVERFLOW; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); /* BVS */ @@ -1000,11 +1000,23 @@ ATF_TC_BODY(emul_branch, tc) e.regs.P |= P_SIGN_OVERFLOW; rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC005); + ATF_CHECK(e.regs.PC == 0xC005); rk65c02_step(&e, 2); - ATF_CHECK(e.regs.PC = 0xC003); + ATF_CHECK(e.regs.PC == 0xC003); rk65c02_start(&e); +} +ATF_TC_WITHOUT_HEAD(emul_sign_overflow); +ATF_TC_BODY(emul_sign_overflow, tc) +{ + rk65c02emu_t e; + bus_t b; + + b = bus_init(); + e = rk65c02_init(&b); + + ATF_REQUIRE(rom_start(&e, "test_emulation_sign_overflow.rom", tc)); + ATF_CHECK(bus_read_1(&b, 0x20) == 0x0); } @@ -1035,6 +1047,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, emul_txa_tya_tax_tay); ATF_TP_ADD_TC(tp, emul_sta); + ATF_TP_ADD_TC(tp, emul_sign_overflow); + return (atf_no_error()); }