From a4c3d1c4efa3cd1222ecf4934ee43eddcb9bd076 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Thu, 22 Feb 2018 00:39:33 -0600 Subject: [PATCH] Implement the TRB (Test and Reset Bits) instruction --- include/mos6502.enums.h | 1 + include/mos6502.h | 1 + src/mos6502.addr.c | 2 +- src/mos6502.c | 5 +++-- src/mos6502.dis.c | 1 + src/mos6502.loadstor.c | 31 +++++++++++++++++++++++++++++++ tests/mos6502.loadstor.c | 17 +++++++++++++++++ 7 files changed, 55 insertions(+), 3 deletions(-) diff --git a/include/mos6502.enums.h b/include/mos6502.enums.h index 7268655..8b2761f 100644 --- a/include/mos6502.enums.h +++ b/include/mos6502.enums.h @@ -125,6 +125,7 @@ enum instruction { STZ, // STore Zero TAX, // Transfer Accumulator to X TAY, // Transfer Accumulator to Y + TRB, // Test and Reset Bits TSX, // Transfer Stack register to X TXA, // Transfer X to Accumulator TXS, // Transfer X to Stack register diff --git a/include/mos6502.h b/include/mos6502.h index 7e13288..33bdd4c 100644 --- a/include/mos6502.h +++ b/include/mos6502.h @@ -234,6 +234,7 @@ DECL_INST(sty); DECL_INST(stz); DECL_INST(tax); DECL_INST(tay); +DECL_INST(trb); DECL_INST(tsx); DECL_INST(txa); DECL_INST(txs); diff --git a/src/mos6502.addr.c b/src/mos6502.addr.c index 56d9b51..fa0a5dd 100644 --- a/src/mos6502.addr.c +++ b/src/mos6502.addr.c @@ -20,7 +20,7 @@ static int addr_modes[] = { // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F IMP, IDX, NOA, NOA, NOA, ZPG, ZPG, NOA, IMP, IMM, ACC, NOA, NOA, ABS, ABS, NOA, // 0x - REL, IDY, ZPG, NOA, NOA, ZPX, ZPX, NOA, IMP, ABY, ACC, NOA, NOA, ABX, ABX, NOA, // 1x + REL, IDY, ZPG, NOA, ZPG, ZPX, ZPX, NOA, IMP, ABY, ACC, NOA, ABS, ABX, ABX, NOA, // 1x ABS, IDX, NOA, NOA, ZPG, ZPG, ZPG, NOA, IMP, IMM, ACC, NOA, ABS, ABS, ABS, NOA, // 2x REL, IDY, ZPG, NOA, ZPX, ZPX, ZPX, NOA, IMP, ABY, ACC, NOA, ABX, ABX, ABX, NOA, // 3x IMP, IDX, NOA, NOA, NOA, ZPG, ZPG, NOA, IMP, IMM, ACC, NOA, ABS, ABS, ABS, NOA, // 4x diff --git a/src/mos6502.c b/src/mos6502.c index 3f9aa43..b59e921 100644 --- a/src/mos6502.c +++ b/src/mos6502.c @@ -28,7 +28,7 @@ static int instructions[] = { // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F BRK, ORA, BAD, BAD, BAD, ORA, ASL, BAD, PHP, ORA, ASL, BAD, BAD, ORA, ASL, BAD, // 0x - BPL, ORA, ORA, BAD, BAD, ORA, ASL, BAD, CLC, ORA, INC, BAD, BAD, ORA, ASL, BAD, // 1x + BPL, ORA, ORA, BAD, TRB, ORA, ASL, BAD, CLC, ORA, INC, BAD, TRB, ORA, ASL, BAD, // 1x JSR, AND, BAD, BAD, BIT, AND, ROL, BAD, PLP, AND, ROL, BAD, BIT, AND, ROL, BAD, // 2x BMI, AND, AND, BAD, BIT, AND, ROL, BAD, SEC, AND, DEC, BAD, BIT, AND, ROL, BAD, // 3x RTI, EOR, BAD, BAD, BAD, EOR, LSR, BAD, PHA, EOR, LSR, BAD, JMP, EOR, LSR, BAD, // 4x @@ -117,6 +117,7 @@ static mos6502_instruction_handler instruction_handlers[] = { INST_HANDLER(stz), INST_HANDLER(tax), INST_HANDLER(tay), + INST_HANDLER(trb), INST_HANDLER(tsx), INST_HANDLER(txa), INST_HANDLER(txs), @@ -131,7 +132,7 @@ static mos6502_instruction_handler instruction_handlers[] = { static int cycles[] = { // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0, // 0x - 2, 5, 5, 0, 0, 4, 6, 0, 2, 4, 2, 0, 0, 4, 7, 0, // 1x + 2, 5, 5, 0, 5, 4, 6, 0, 2, 4, 2, 0, 6, 4, 7, 0, // 1x 6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0, // 2x 2, 5, 5, 0, 4, 4, 6, 0, 2, 4, 2, 0, 4, 4, 7, 0, // 3x 6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0, // 4x diff --git a/src/mos6502.dis.c b/src/mos6502.dis.c index ad0aa09..ab34638 100644 --- a/src/mos6502.dis.c +++ b/src/mos6502.dis.c @@ -101,6 +101,7 @@ static char *instruction_strings[] = { "STZ", "TAX", "TAY", + "TRB", "TSX", "TXA", "TXS", diff --git a/src/mos6502.loadstor.c b/src/mos6502.loadstor.c index bef57c7..25bdb8b 100644 --- a/src/mos6502.loadstor.c +++ b/src/mos6502.loadstor.c @@ -156,6 +156,37 @@ DEFINE_INST(tay) cpu->Y = cpu->A; } +/* + * This is a really funky instruction. And not in the good, dancy kinda + * way. + * + * First, it does a BIT-style test to see if A & oper are zero; if so, + * it sets the Z flag. + * + * Second, it clears all bits in eff_addr where A's corresponding bits + * are set to 1. It ignores all bits in eff_addr where A's bits are + * zero. + * + * E.g.: + * + * A: 01011001 (accumulator) + * M: 11111111 (value in memory) + * R: 10100110 (result) + * + * And, as following that, the Z flag should be zero because A&M is a + * non-zero result. + */ +DEFINE_INST(trb) +{ + cpu->P &= ~MOS_ZERO; + if (!(cpu->A & oper)) { + cpu->P |= MOS_ZERO; + } + + mos6502_set(cpu, cpu->eff_addr, + (cpu->A ^ 0xff) & oper); +} + /* * Transfer the stack pointer (S register) to X. */ diff --git a/tests/mos6502.loadstor.c b/tests/mos6502.loadstor.c index d1eb292..3108f06 100644 --- a/tests/mos6502.loadstor.c +++ b/tests/mos6502.loadstor.c @@ -140,6 +140,23 @@ Test(mos6502_loadstor, tay) cr_assert_eq(cpu->Y, 111); } +Test(mos6502_loadstor, trb) +{ + cpu->A = 6; + mos6502_handle_trb(cpu, 3); + cr_assert_eq(cpu->P & MOS_ZERO, 0); + cpu->A = 9; + mos6502_handle_trb(cpu, 2); + cr_assert_eq(cpu->P & MOS_ZERO, MOS_ZERO); + + cpu->eff_addr = 111; + mos6502_set(cpu, cpu->eff_addr, 123); + mos6502_handle_trb(cpu, 123); + + cr_assert_eq(mos6502_get(cpu, cpu->eff_addr), + (cpu->A ^ 0xff) & 123); +} + Test(mos6502_loadstor, tsx) { cpu->S = 111;