From 978ad1faafca8603ae5fe0666052f46782215646 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Thu, 22 Feb 2018 14:07:05 -0600 Subject: [PATCH] Formerly "BAD" instructions are now forms of NOPs But weird forms. In most cases they basically are NOPs, except with different opcodes. In other cases, we call them NP2 and NP3s, and do so because they consume 2 or 3 bytes respectively (vs. just 1 with NOP). We had to teach some arcane magic to the emulator for this to work. We may want to refactor to decouple the number of bytes consumed from the address mode. --- include/mos6502.enums.h | 4 +++ include/mos6502.h | 2 ++ src/mos6502.addr.c | 32 +++++++++---------- src/mos6502.c | 68 ++++++++++++++++++++++------------------- src/mos6502.dis.c | 8 +++++ src/mos6502.exec.c | 8 +++++ tests/mos6502.c | 2 ++ tests/mos6502.exec.c | 7 +++++ 8 files changed, 83 insertions(+), 48 deletions(-) diff --git a/include/mos6502.enums.h b/include/mos6502.enums.h index 07f9c06..f2c6212 100644 --- a/include/mos6502.enums.h +++ b/include/mos6502.enums.h @@ -47,6 +47,8 @@ enum addr_mode { ABS, // absolute ABX, // absolute x-index ABY, // absolute y-index + BY2, // Consume 2 bytes (for NP2) + BY3, // Consume 3 bytes (for NP3) IMM, // immediate IMP, // implied IND, // indirect @@ -102,6 +104,8 @@ enum instruction { LDY, // LoaD Y LSR, // Logical Shift Right NOP, // NO oPeration + NP2, // No oPeration (2 bytes consumed) + NP3, // No oPeration (3 bytes consumed) ORA, // OR with Accumulator PHA, // PusH Accumulator PHP, // PusH Predicate register diff --git a/include/mos6502.h b/include/mos6502.h index c4a79c8..bf6a66e 100644 --- a/include/mos6502.h +++ b/include/mos6502.h @@ -211,6 +211,8 @@ DECL_INST(ldx); DECL_INST(ldy); DECL_INST(lsr); DECL_INST(nop); +DECL_INST(np2); +DECL_INST(np3); DECL_INST(ora); DECL_INST(pha); DECL_INST(php); diff --git a/src/mos6502.addr.c b/src/mos6502.addr.c index 54a9572..88f308b 100644 --- a/src/mos6502.addr.c +++ b/src/mos6502.addr.c @@ -19,22 +19,22 @@ */ static int addr_modes[] = { // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F - IMP, IDX, NOA, NOA, ZPG, ZPG, ZPG, NOA, IMP, IMM, ACC, NOA, ABS, ABS, ABS, NOA, // 0x - 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 - REL, IDY, ZPG, NOA, NOA, ZPX, ZPX, NOA, IMP, ABY, IMP, NOA, NOA, ABX, ABX, NOA, // 5x - IMP, IDX, NOA, NOA, ZPG, ZPG, ZPG, NOA, IMP, IMM, ACC, NOA, IND, ABS, ABS, NOA, // 6x - REL, IDY, ZPG, NOA, ZPX, ZPX, ZPX, NOA, IMP, ABY, IMP, NOA, ABX, ABX, ABX, NOA, // 7x - REL, IDX, NOA, NOA, ZPG, ZPG, ZPG, NOA, IMP, IMM, IMP, NOA, ABS, ABS, ABS, NOA, // 8x - REL, IDY, ZPG, NOA, ZPX, ZPX, ZPY, NOA, IMP, ABY, IMP, NOA, ABS, ABX, ABX, NOA, // 9x - IMM, IDX, IMM, NOA, ZPG, ZPG, ZPG, NOA, IMP, IMM, IMP, NOA, ABS, ABS, ABS, NOA, // Ax - REL, IDY, ZPG, NOA, ZPX, ZPX, ZPY, NOA, IMP, ABY, IMP, NOA, ABX, ABX, ABY, NOA, // Bx - IMM, IDX, NOA, NOA, ZPG, ZPG, ZPG, NOA, IMP, IMM, IMP, NOA, ABS, ABS, ABS, NOA, // Cx - REL, IDY, ZPG, NOA, NOA, ZPX, ZPX, NOA, IMP, ABY, IMP, NOA, NOA, ABX, ABX, NOA, // Dx - IMM, IDX, NOA, NOA, ZPG, ZPG, ZPG, NOA, IMP, IMM, IMP, NOA, ABS, ABS, ABS, NOA, // Ex - REL, IDY, ZPG, NOA, NOA, ZPX, ZPX, NOA, IMP, ABY, IMP, NOA, NOA, ABX, ABX, NOA, // Fx + IMP, IDX, BY2, IMP, ZPG, ZPG, ZPG, IMP, IMP, IMM, ACC, IMP, ABS, ABS, ABS, IMP, // 0x + REL, IDY, ZPG, IMP, ZPG, ZPX, ZPX, IMP, IMP, ABY, ACC, IMP, ABS, ABX, ABX, IMP, // 1x + ABS, IDX, BY2, IMP, ZPG, ZPG, ZPG, IMP, IMP, IMM, ACC, IMP, ABS, ABS, ABS, IMP, // 2x + REL, IDY, ZPG, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABY, ACC, IMP, ABX, ABX, ABX, IMP, // 3x + IMP, IDX, BY2, IMP, BY2, ZPG, ZPG, IMP, IMP, IMM, ACC, IMP, ABS, ABS, ABS, IMP, // 4x + REL, IDY, ZPG, IMP, BY2, ZPX, ZPX, IMP, IMP, ABY, IMP, IMP, BY3, ABX, ABX, IMP, // 5x + IMP, IDX, BY2, IMP, ZPG, ZPG, ZPG, IMP, IMP, IMM, ACC, IMP, IND, ABS, ABS, IMP, // 6x + REL, IDY, ZPG, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABY, IMP, IMP, ABX, ABX, ABX, IMP, // 7x + REL, IDX, BY2, IMP, ZPG, ZPG, ZPG, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, // 8x + REL, IDY, ZPG, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABY, IMP, IMP, ABS, ABX, ABX, IMP, // 9x + IMM, IDX, IMM, IMP, ZPG, ZPG, ZPG, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, // Ax + REL, IDY, ZPG, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABY, IMP, IMP, ABX, ABX, ABY, IMP, // Bx + IMM, IDX, BY2, IMP, ZPG, ZPG, ZPG, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, // Cx + REL, IDY, ZPG, IMP, BY2, ZPX, ZPX, IMP, IMP, ABY, IMP, IMP, BY3, ABX, ABX, IMP, // Dx + IMM, IDX, BY2, IMP, ZPG, ZPG, ZPG, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, // Ex + REL, IDY, ZPG, IMP, BY2, ZPX, ZPX, IMP, IMP, ABY, IMP, IMP, BY3, ABX, ABX, IMP, // Fx }; /* diff --git a/src/mos6502.c b/src/mos6502.c index 6e0f123..3a05b41 100644 --- a/src/mos6502.c +++ b/src/mos6502.c @@ -27,22 +27,22 @@ */ static int instructions[] = { // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F - BRK, ORA, BAD, BAD, TSB, ORA, ASL, BAD, PHP, ORA, ASL, BAD, TSB, ORA, ASL, BAD, // 0x - 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 - BVC, EOR, EOR, BAD, BAD, EOR, LSR, BAD, CLI, EOR, PHY, BAD, BAD, EOR, LSR, BAD, // 5x - RTS, ADC, BAD, BAD, STZ, ADC, ROR, BAD, PLA, ADC, ROR, BAD, JMP, ADC, ROR, BAD, // 6x - BVS, ADC, ADC, BAD, STZ, ADC, ROR, BAD, SEI, ADC, PLY, BAD, JMP, ADC, ROR, BAD, // 7x - BRA, 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, STZ, STA, STZ, 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 - CPY, CMP, BAD, BAD, CPY, CMP, DEC, BAD, INY, CMP, DEX, BAD, CPY, CMP, DEC, BAD, // Cx - BNE, CMP, CMP, BAD, BAD, CMP, DEC, BAD, CLD, CMP, PHX, BAD, BAD, CMP, DEC, BAD, // Dx - CPX, SBC, BAD, BAD, CPX, SBC, INC, BAD, INX, SBC, NOP, BAD, CPX, SBC, INC, BAD, // Ex - BEQ, SBC, SBC, BAD, BAD, SBC, INC, BAD, SED, SBC, PLX, BAD, BAD, SBC, INC, BAD, // Fx + BRK, ORA, NP2, NOP, TSB, ORA, ASL, NOP, PHP, ORA, ASL, NOP, TSB, ORA, ASL, NOP, // 0x + BPL, ORA, ORA, NOP, TRB, ORA, ASL, NOP, CLC, ORA, INC, NOP, TRB, ORA, ASL, NOP, // 1x + JSR, AND, NP2, NOP, BIT, AND, ROL, NOP, PLP, AND, ROL, NOP, BIT, AND, ROL, NOP, // 2x + BMI, AND, AND, NOP, BIT, AND, ROL, NOP, SEC, AND, DEC, NOP, BIT, AND, ROL, NOP, // 3x + RTI, EOR, NP2, NOP, NP2, EOR, LSR, NOP, PHA, EOR, LSR, NOP, JMP, EOR, LSR, NOP, // 4x + BVC, EOR, EOR, NOP, NP2, EOR, LSR, NOP, CLI, EOR, PHY, NOP, NP3, EOR, LSR, NOP, // 5x + RTS, ADC, NP2, NOP, STZ, ADC, ROR, NOP, PLA, ADC, ROR, NOP, JMP, ADC, ROR, NOP, // 6x + BVS, ADC, ADC, NOP, STZ, ADC, ROR, NOP, SEI, ADC, PLY, NOP, JMP, ADC, ROR, NOP, // 7x + BRA, STA, NP2, NOP, STY, STA, STX, NOP, DEY, BIM, TXA, NOP, STY, STA, STX, NOP, // 8x + BCC, STA, STA, NOP, STY, STA, STX, NOP, TYA, STA, TXS, NOP, STZ, STA, STZ, NOP, // 9x + LDY, LDA, LDX, NOP, LDY, LDA, LDX, NOP, TAY, LDA, TAX, NOP, LDY, LDA, LDX, NOP, // Ax + BCS, LDA, LDA, NOP, LDY, LDA, LDX, NOP, CLV, LDA, TSX, NOP, LDY, LDA, LDX, NOP, // Bx + CPY, CMP, NP2, NOP, CPY, CMP, DEC, NOP, INY, CMP, DEX, NOP, CPY, CMP, DEC, NOP, // Cx + BNE, CMP, CMP, NOP, NP2, CMP, DEC, NOP, CLD, CMP, PHX, NOP, NP3, CMP, DEC, NOP, // Dx + CPX, SBC, NP2, NOP, CPX, SBC, INC, NOP, INX, SBC, NOP, NOP, CPX, SBC, INC, NOP, // Ex + BEQ, SBC, SBC, NOP, NP2, SBC, INC, NOP, SED, SBC, PLX, NOP, NP3, SBC, INC, NOP, // Fx }; /* @@ -94,6 +94,8 @@ static mos6502_instruction_handler instruction_handlers[] = { INST_HANDLER(ldy), INST_HANDLER(lsr), INST_HANDLER(nop), + INST_HANDLER(np2), + INST_HANDLER(np3), INST_HANDLER(ora), INST_HANDLER(pha), INST_HANDLER(php), @@ -132,22 +134,22 @@ 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, 5, 3, 5, 0, 3, 2, 2, 0, 6, 4, 6, 0, // 0x - 2, 5, 5, 0, 5, 4, 6, 0, 2, 4, 2, 0, 6, 4, 6, 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, 6, 0, // 3x - 6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0, // 4x - 2, 5, 5, 0, 0, 4, 6, 0, 2, 4, 3, 0, 0, 4, 6, 0, // 5x - 6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 5, 4, 6, 0, // 6x - 2, 5, 5, 0, 4, 4, 6, 0, 2, 4, 4, 0, 6, 4, 6, 0, // 7x - 3, 6, 0, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0, // 8x - 2, 6, 5, 0, 4, 4, 4, 0, 2, 5, 2, 0, 4, 5, 5, 0, // 9x - 2, 6, 2, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0, // Ax - 2, 5, 5, 0, 4, 4, 4, 0, 2, 4, 2, 0, 4, 4, 4, 0, // Bx - 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 3, 0, // Cx - 2, 5, 5, 0, 0, 4, 6, 0, 2, 4, 3, 0, 0, 4, 7, 0, // Dx - 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, // Ex - 2, 5, 5, 0, 0, 4, 6, 0, 2, 4, 4, 0, 0, 4, 7, 0, // Fx + 7, 6, 2, 1, 5, 3, 5, 1, 3, 2, 2, 1, 6, 4, 6, 1, // 0x + 2, 5, 5, 1, 5, 4, 6, 1, 2, 4, 2, 1, 6, 4, 6, 1, // 1x + 6, 6, 2, 1, 3, 3, 5, 1, 4, 2, 2, 1, 4, 4, 6, 1, // 2x + 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 2, 1, 4, 4, 6, 1, // 3x + 6, 6, 2, 1, 3, 3, 5, 1, 3, 2, 2, 1, 3, 4, 6, 1, // 4x + 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 3, 1, 8, 4, 6, 1, // 5x + 6, 6, 2, 1, 3, 3, 5, 1, 4, 2, 2, 1, 5, 4, 6, 1, // 6x + 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 4, 1, 6, 4, 6, 1, // 7x + 3, 6, 2, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1, // 8x + 2, 6, 5, 1, 4, 4, 4, 1, 2, 5, 2, 1, 4, 5, 5, 1, // 9x + 2, 6, 2, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1, // Ax + 2, 5, 5, 1, 4, 4, 4, 1, 2, 4, 2, 1, 4, 4, 4, 1, // Bx + 2, 6, 2, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 3, 1, // Cx + 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 3, 1, 4, 4, 7, 1, // Dx + 2, 6, 2, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1, // Ex + 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 4, 1, 4, 4, 7, 1, // Fx }; /* @@ -462,6 +464,8 @@ mos6502_would_jump(int inst_code) inst_code == BVS || inst_code == JMP || inst_code == JSR || + inst_code == NP2 || // this is KIND of a hack, but it works! + inst_code == NP3 || // these jump ahead by 2 or 3 bytes (respectively) inst_code == RTS || inst_code == RTI; } diff --git a/src/mos6502.dis.c b/src/mos6502.dis.c index 0e6b637..8a28e86 100644 --- a/src/mos6502.dis.c +++ b/src/mos6502.dis.c @@ -78,6 +78,8 @@ static char *instruction_strings[] = { "LDY", "LSR", "NOP", + "NP2", + "NP3", "ORA", "PHA", "PHP", @@ -231,11 +233,17 @@ int mos6502_dis_expected_bytes(int addr_mode) { switch (addr_mode) { + // This is kind of not a real address mode? We use it to tell + // the code to skip three bytes for opcodes that use it. + case BY3: + return 3; + // These are 16-bit operands, because they work with absolute // addresses in memory. case ABS: case ABY: case ABX: + case BY2: // (also not a real address mode!) case IND: return 2; diff --git a/src/mos6502.exec.c b/src/mos6502.exec.c index aba595e..0890b70 100644 --- a/src/mos6502.exec.c +++ b/src/mos6502.exec.c @@ -68,6 +68,14 @@ DEFINE_INST(nop) // do nothing } +DEFINE_INST(np2) +{ +} + +DEFINE_INST(np3) +{ +} + /* * Here we return from an interrupt, which effectively resets the PC * register to the last value on the stack. diff --git a/tests/mos6502.c b/tests/mos6502.c index 2d13c80..060eafb 100644 --- a/tests/mos6502.c +++ b/tests/mos6502.c @@ -124,6 +124,8 @@ Test(mos6502, would_jump) case BVS: case JMP: case JSR: + case NP2: + case NP3: case RTS: case RTI: expect = true; diff --git a/tests/mos6502.exec.c b/tests/mos6502.exec.c index 72419f1..2c0402d 100644 --- a/tests/mos6502.exec.c +++ b/tests/mos6502.exec.c @@ -45,6 +45,13 @@ Test(mos6502_exec, jsr) cr_assert_eq(mos6502_pop_stack(cpu), 125); } +/* + * In addition to nop, we also have np2 and np3 which also do nothing. + * We're just passing on those. + * + * Test(mos6502_exec, np2) + * Test(mos6502_exec, np3) + */ Test(mos6502_exec, nop) { // currently this test does nothing -- we _should_ test to see if we