diff --git a/include/mos6502.enums.h b/include/mos6502.enums.h index d518c63..b756957 100644 --- a/include/mos6502.enums.h +++ b/include/mos6502.enums.h @@ -73,6 +73,7 @@ enum instruction { BCS, // Branch on Carry Set BEQ, // Branch on EQual to zero BIT, // BIT test + BIM, // BIt test (imMediate mode) (* not a real instruction in the processor; just used by us) BMI, // Branch on MInus BNE, // Branch on Not Equal to zero BPL, // Branch on PLus diff --git a/include/mos6502.h b/include/mos6502.h index 69d29f6..89cc6bf 100644 --- a/include/mos6502.h +++ b/include/mos6502.h @@ -182,6 +182,7 @@ DECL_INST(bcc); DECL_INST(bcs); DECL_INST(beq); DECL_INST(bit); +DECL_INST(bim); DECL_INST(bmi); DECL_INST(bne); DECL_INST(bpl); diff --git a/src/mos6502.bits.c b/src/mos6502.bits.c index f9d693b..b4be238 100644 --- a/src/mos6502.bits.c +++ b/src/mos6502.bits.c @@ -74,6 +74,22 @@ DEFINE_INST(bit) } } +/* + * The BIM instruction (which is made up--it's not a real instruction) + * is here to handle the specific use-case of a BIT instruction in + * immediate (IMM) mode. We do this in a separate instruction to avoid + * the need to add logic to the BIT instruction such that it has to know + * or care about its opcode or its address mode. + */ +DEFINE_INST(bim) +{ + // This is the same behavior as BIT + cpu->P &= ~MOS_ZERO; + if (!(cpu->A & oper)) { + cpu->P |= MOS_ZERO; + } +} + /* * Compute the bitwise-exclusive-or between the accumulator and operand, * and store the result in A. diff --git a/src/mos6502.c b/src/mos6502.c index f061491..5474221 100644 --- a/src/mos6502.c +++ b/src/mos6502.c @@ -35,7 +35,7 @@ static int instructions[] = { BVC, EOR, EOR, BAD, BAD, EOR, LSR, BAD, CLI, EOR, BAD, BAD, BAD, EOR, LSR, BAD, // 5x RTS, ADC, BAD, BAD, BAD, ADC, ROR, BAD, PLA, ADC, ROR, BAD, JMP, ADC, ROR, BAD, // 6x BVS, ADC, ADC, BAD, BAD, ADC, ROR, BAD, SEI, ADC, BAD, BAD, BAD, ADC, ROR, BAD, // 7x - BAD, STA, BAD, BAD, STY, STA, STX, BAD, DEY, BIT, TXA, BAD, STY, STA, STX, BAD, // 8x + BAD, STA, BAD, BAD, STY, STA, STX, BAD, DEY, BIM, TXA, BAD, STY, STA, STX, BAD, // 8x BCC, STA, STA, BAD, STY, STA, STX, BAD, TYA, STA, TXS, BAD, BAD, STA, BAD, BAD, // 9x LDY, LDA, LDX, BAD, LDY, LDA, LDX, BAD, TAY, LDA, TAX, BAD, LDY, LDA, LDX, BAD, // Ax BCS, LDA, LDA, BAD, LDY, LDA, LDX, BAD, CLV, LDA, TSX, BAD, LDY, LDA, LDX, BAD, // Bx @@ -65,6 +65,7 @@ static mos6502_instruction_handler instruction_handlers[] = { INST_HANDLER(bcs), INST_HANDLER(beq), INST_HANDLER(bit), + INST_HANDLER(bim), INST_HANDLER(bmi), INST_HANDLER(bne), INST_HANDLER(bpl), diff --git a/src/mos6502.dis.c b/src/mos6502.dis.c index 78b32ed..8921fa0 100644 --- a/src/mos6502.dis.c +++ b/src/mos6502.dis.c @@ -49,6 +49,7 @@ static char *instruction_strings[] = { "BCS", "BEQ", "BIT", + "BIM", "BMI", "BNE", "BPL", diff --git a/tests/mos6502.bits.c b/tests/mos6502.bits.c index 88738c8..93213b8 100644 --- a/tests/mos6502.bits.c +++ b/tests/mos6502.bits.c @@ -56,6 +56,23 @@ Test(mos6502_bits, bit) cr_assert_eq(cpu->P & MOS_ZERO, MOS_ZERO); } +Test(mos6502_bits, bim) +{ + // This version of BIT should not modify the NV flags + cpu->P |= MOS_NEGATIVE; + cpu->P |= MOS_OVERFLOW; + + cpu->A = 63; + mos6502_handle_bim(cpu, 123); + cr_assert_eq(cpu->P & MOS_ZERO, 0); + cr_assert_eq(cpu->P & MOS_NEGATIVE, MOS_NEGATIVE); + cr_assert_eq(cpu->P & MOS_OVERFLOW, MOS_OVERFLOW); + + cpu->A = 4; + mos6502_handle_bim(cpu, 123); + cr_assert_eq(cpu->P & MOS_ZERO, MOS_ZERO); +} + Test(mos6502_bits, eor) { cpu->A = 5;