NES CPU

REGISTERS

Label Name width
A Accumulator byte
X Index byte
Y Index byte
PC Program Counter 2-byte
S Stack Pointer byte
P Status Register byte

status flags

N V ss D I Z C
Negative Overflow No CPU effect, see: the B flag Decimal Interrupt Disable Zero Carry

ADDRESSING MODES

Abbr Name Formula Cycles
d,x Zero page indexed val = PEEK((arg + X) % 256) 4
d,y Zero page indexed val = PEEK((arg + Y) % 256) 4
a,x Absolute indexed val = PEEK(arg + X) 4+
a,y Absolute indexed val = PEEK(arg + Y) 4+
(d,x) Indexed indirect val = PEEK(PEEK((arg + X) % 256) + PEEK((arg + X + 1) % 256) * 256) 6
(d),y Indirect indexed val = PEEK(PEEK(arg) + PEEK((arg + 1) % 256) * 256 + Y) 5+
  Implicit    
A Accumulator val = A  
#v Immediate    

Other addressing

Abbr Name Notes
  Implicit Instructions like RTS or CLC have no address operand, the destination of results are implied.
A Accumulator Many instructions can operate on the accumulator, e.g. LSR A. Some assemblers will treat no operand as an implicit A where applicable.
#v Immediate Uses the 8-bit operand itself as the value for the operation, rather than fetching a value from a memory address.
d Zero page Fetches the value from an 8-bit address on the zero page.
a Absolute Fetches the value from a 16-bit address anywhere in memory.
label Relative Branch instructions (e.g. BEQ, BCS) have a relative addressing mode that specifies an 8-bit signed offset relative to the current PC.
(a) Indirect The JMP instruction has a special indirect addressing mode that can jump to the address stored in a 16-bit pointer anywhere in memory.

MEMORY MAP

address contant address contant
$0000 ~ $1FFF RAM $0000 ~ $00FF Zero Page
    $0100 ~ $01FF Stack
    $0200 ~ $07FF RAM
    $0800 ~ $1FFF Mirrors
$2000 ~ $401F I/O Registers $2000 ~ $2007 I/O Registers (NES PPU registers)
    $2008 ~ $3FFF Mirrors
    $4000 ~ $4017 I/O Registers (NES APU and I/O registers)
    $4018 ~ $401F I/O Registers (APU and I/O functionality)
$4020 ~ $5FFF Espansion ROM $4020 ~ $5FFF Espansion ROM
$6000 ~ $7FFF SRAM $6000 ~ $7FFF SRAM
$8000 ~ $FFFF PRG-ROM $8000 ~ $BFFF Lower Bank
    $C000 ~ $FFFF Upper Bank

POWER UP STAT

P = $34 (IRQ disabled)

A, X, Y = 0

S = $FD

$4017 = $00 (frame irq enabled)

$4015 = $00 (all channels disabled)

$4000-​$400F = $00

$4010-​$4013 = $00

All 15 bits of noise channel LFSR = $0000. The first time the LFSR is clocked from the all-0s state, it will shift in a 1.

CPU unofficial opcodes

  +00 +04 +08 +0C +10 +14 +18 +1C +01 +05 +09 +0D +11 +15 +19 +1D +02 +06 +0A +0E +12 +16 +1A +1E +03 +07 +0B +0F +13 +17 +1B +1F
00 BRK NOP d PHP NOP a BPL *+d NOP d,x CLC NOP a,x ORA (d,x) ORA d ORA #i ORA a ORA (d),y ORA d,x ORA a,y ORA a,x STP ASL d ASL ASL a STP ASL d,x NOP ASL a,x SLO (d,x) SLO d ANC #i SLO a SLO (d),y SLO d,x SLO a,y SLO a,x
20 JSR a BIT d PLP BIT a BMI *+d NOP d,x SEC NOP a,x AND (d,x) AND d AND #i AND a AND (d),y AND d,x AND a,y AND a,x STP ROL d ROL ROL a STP ROL d,x NOP ROL a,x RLA (d,x) RLA d ANC #i RLA a RLA (d),y RLA d,x RLA a,y RLA a,x
40 RTI NOP d PHA JMP a BVC *+d NOP d,x CLI NOP a,x EOR (d,x) EOR d EOR #i EOR a EOR (d),y EOR d,x EOR a,y EOR a,x STP LSR d LSR LSR a STP LSR d,x NOP LSR a,x SRE (d,x) SRE d ALR #i SRE a SRE (d),y SRE d,x SRE a,y SRE a,x
60 RTS NOP d PLA JMP (a) BVS *+d NOP d,x SEI NOP a,x ADC (d,x) ADC d ADC #i ADC a ADC (d),y ADC d,x ADC a,y ADC a,x STP ROR d ROR ROR a STP ROR d,x NOP ROR a,x RRA (d,x) RRA d ARR #i RRA a RRA (d),y RRA d,x RRA a,y RRA a,x
80 NOP #i STY d DEY STY a BCC *+d STY d,x TYA SHY a,x STA (d,x) STA d NOP #i STA a STA (d),y STA d,x STA a,y STA a,x NOP #i STX d TXA STX a STP STX d,y TXS SHX a,y SAX (d,x) SAX d XAA #i SAX a AHX (d),y SAX d,y TAS a,y AHX a,y
A0 LDY #i LDY d TAY LDY a BCS *+d LDY d,x CLV LDY a,x LDA (d,x) LDA d LDA #i LDA a LDA (d),y LDA d,x LDA a,y LDA a,x LDX #i LDX d TAX LDX a STP LDX d,y TSX LDX a,y LAX (d,x) LAX d LAX #i LAX a LAX (d),y LAX d,y LAS a,y LAX a,y
C0 CPY #i CPY d INY CPY a BNE *+d NOP d,x CLD NOP a,x CMP (d,x) CMP d CMP #i CMP a CMP (d),y CMP d,x CMP a,y CMP a,x NOP #i DEC d DEX DEC a STP DEC d,x NOP DEC a,x DCP (d,x) DCP d AXS #i DCP a DCP (d),y DCP d,x DCP a,y DCP a,x
E0 CPX #i CPX d INX CPX a BEQ *+d NOP d,x SED NOP a,x SBC (d,x) SBC d SBC #i SBC a SBC (d),y SBC d,x SBC a,y SBC a,x NOP #i INC d NOP INC a STP INC d,x NOP INC a,x ISC (d,x) ISC d SBC #i ISC a ISC (d),y ISC d,x ISC a,y ISC a,x

Logical and arithmetic commands:

OP FLAGS
   
VAL OP AD CYCLES FLAGS
00 BRK   7 –1- —-
01 ORA (d, x) 6 *— –*-
02        
         
         
         

Virtual to Real

if x>=$2000 and x<$4020
	do IO
if x>=$4020
	return x-$37E0
if x>$800
	return x % $800

Power up state

P = $34 (IRQ disabled)

A, X, Y = 0

S = $FD

$4017 = $00 (frame irq enabled)

$4015 = $00 (all channels disabled)

$4000-$400F = $00 (not sure about $4010-$4013)