CPU Introduction

Last updated:

The NES CPU is a Ricoh 2A03 — a 6502 with no decimal mode. Each cycle below is one memory access on the bus; the CPU never sits idle, so even "do nothing" steps show up as discarded reads.

CPU flow

The CPU is built to execute instructions sequentially, one by one, by reading them from memory. An instruction is 1, 2, or 3 bytes long, and the first byte is always the opcode ("operation code") — a one-byte number that identifies the instruction.

Addresses on this CPU are 16 bits long (2 bytes) — that's a 64 KiB address space, $0000 to $FFFF.

The CPU tracks where it's reading from with a 16-bit register called PC (program counter): the address of the next byte to read. The basic operation read [PC]; PC++ is called a fetch. Executing an instruction is a sequence of fetches — first the opcode, then the remaining bytes (if any).

Cycle 1 of every instruction is therefore the same: fetch the opcode to identify the instruction.

So the whole CPU is a loop: fetch an opcode, do whatever it says, repeat.

loop {
    opcode = read(PC); PC++   // cycle 1: fetch the opcode
    execute(opcode)           // the rest of the cycles depend on the instruction
}

execute is empty for now — filling it in, one opcode at a time, is the work of the checkpoint. Everything else on the CPU pages is detail that hangs off this loop.

Example

Say PC = $8000 and memory contains:

$8000   C9
$8001   42
$8002   ...

The CPU is about to start a new instruction. It fetches the opcode:

cycle 1   read [$8000] → C9       (opcode); PC = $8001

C9 is the opcode for an instruction that does something specific with one operand byte (what exactly isn't important here). The CPU fetches the operand:

cycle 2   read [$8001] → 42       (operand); PC = $8002

PC sits at $8002, ready for the next opcode fetch.