Question

In the spare time I'm starting writing a very simple C++ emulator for the 6502 CPU. I used to write down a lot of assembly code for this CPU so all the opcodes, addressing modes and other stuff are not a big deal.

The 6502 has 56 different instructions plus 13 addressing modes giving a total of 151 different opcodes. To me speed is not an issue so instead of writing a huge switch-case statement and repeat the same code again and again (different opcodes can refer to the same instruction using a different addressing mode) I'd like to separate actual instruction code from the addressing mode code: I found this solution very neat as it would require to write only 13 addressing mode functions and 56 instruction functions without repeat myself.

here the addressing mode functions:

// Addressing modes
uint16_t Addr_ACC(); // ACCUMULATOR
uint16_t Addr_IMM(); // IMMEDIATE
uint16_t Addr_ABS(); // ABSOLUTE
uint16_t Addr_ZER(); // ZERO PAGE
uint16_t Addr_ZEX(); // INDEXED-X ZERO PAGE
uint16_t Addr_ZEY(); // INDEXED-Y ZERO PAGE
uint16_t Addr_ABX(); // INDEXED-X ABSOLUTE
uint16_t Addr_ABY(); // INDEXED-Y ABSOLUTE
uint16_t Addr_IMP(); // IMPLIED
uint16_t Addr_REL(); // RELATIVE
uint16_t Addr_INX(); // INDEXED-X INDIRECT
uint16_t Addr_INY(); // INDEXED-Y INDIRECT
uint16_t Addr_ABI(); // ABSOLUTE INDIRECT

they all returns the actual memory address (16 bit) used by the instruction to read/write the operand/result

the instruction function prototype is:

void Op_ADC(uint16_t addr);
void Op_AND(uint16_t addr);
void Op_ASL(uint16_t addr);
    ...

it takes the 16 bit address, perform its own operations, update the status flags and/or registers, and commit the results (if any) on the same memory address.

Given that code framework I found difficult to use the ACCUMULATOR addressing mode which is the only one to return the actual value of the A internal register instead of a memory address. I could return the value of A using the uin16_t return type and add a boolean flag for such addressing mode but I find it an extremely ugly solution.

The instruction functions should be completely addressing-mode agnostic.

Was it helpful?

Solution

In Sharp6502 (my 6502 emulation engine written in C#) I treat internal registers and external memory both as first-class objects - the MemoryManager class instantiates an object for external memory, and another for internal registers, mapped to a different numeric range. Consequently, memory access and register access are identical at the functional level, since they are both referenced through MemoryManager according to what is basically an index.

Address-mode differentiation is simply a matter of filtering the bit-pattern of the instruction under emulation and performing a very simple calculation to determine the index to be passed to the MemoryManager - this might be implied, or require one or two further bytes, but the underlying mechanism is identical for every instruction.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top