1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-06-10 14:29:30 +00:00

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.
This commit is contained in:
Peter Evans 2018-02-22 14:07:05 -06:00
parent 691387894a
commit 978ad1faaf
8 changed files with 83 additions and 48 deletions

View File

@ -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

View File

@ -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);

View File

@ -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
};
/*

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -124,6 +124,8 @@ Test(mos6502, would_jump)
case BVS:
case JMP:
case JSR:
case NP2:
case NP3:
case RTS:
case RTI:
expect = true;

View File

@ -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