Skip to main content

WDC 65C02 Instruction Set Reference

Processor: Western Design Center 65C02 Architecture: 8-bit CMOS Addressing: 16-bit address bus (64KB) Released: 1983

Overview​

The 65C02 is a CMOS version of the 6502 with bug fixes, additional instructions, and new addressing modes. It maintains backward compatibility with the 6502 while adding significant improvements.

Key Improvements Over 6502​

  1. New Instructions: 8 new opcodes (BRA, PHX, PHY, PLX, PLY, STZ, TRB, TSB)
  2. New Addressing Modes: (ZP) indirect and (ZP),Y indexed
  3. Bug Fixes: JMP indirect page boundary bug fixed
  4. Timing Changes: RMW instructions take 1 fewer cycle
  5. Undefined Opcodes: All behave as NOPs instead of crashing

Registers​

Same as 6502:

  • A - Accumulator (8-bit)
  • X - X Index Register (8-bit)
  • Y - Y Index Register (8-bit)
  • SP - Stack Pointer (8-bit, page 1: $0100-$01FF)
  • PC - Program Counter (16-bit)
  • P - Processor Status Flags (8-bit)

New Instructions (65C02 Only)​

BRA - Branch Always​

Operation: PC = PC + offset

Description: Unconditional relative branch (always taken).

Addressing Mode:

BRA label     ; Relative (-128 to +127 bytes)

Flags Affected: None

Bytes: 2 | Cycles: 3-4

Notes: Always adds 1 cycle for branch taken, plus 1 more if crossing page boundary.

PHX - Push X Register​

Operation: X↓

Description: Pushes the X register onto the stack.

Addressing Mode:

PHX           ; Implied

Flags Affected: None

Bytes: 1 | Cycles: 3

PHY - Push Y Register​

Operation: Y↓

Description: Pushes the Y register onto the stack.

Addressing Mode:

PHY           ; Implied

Flags Affected: None

Bytes: 1 | Cycles: 3

PLX - Pull X Register​

Operation: X↑

Description: Pulls a byte from the stack into the X register.

Addressing Mode:

PLX           ; Implied

Flags Affected: N Z

Bytes: 1 | Cycles: 4

PLY - Pull Y Register​

Operation: Y↑

Description: Pulls a byte from the stack into the Y register.

Addressing Mode:

PLY           ; Implied

Flags Affected: N Z

Bytes: 1 | Cycles: 4

STZ - Store Zero​

Operation: M = 0

Description: Stores zero to memory (more efficient than LDA #0 / STA).

Addressing Modes:

STZ $80       ; Zero Page
STZ $80,X ; Zero Page,X
STZ $2000 ; Absolute
STZ $2000,X ; Absolute,X

Flags Affected: None

Bytes: 2-3 | Cycles: 3-5

TRB - Test and Reset Bits​

Operation: Z = !(A & M), M = M & !A

Description: Tests bits (sets Z if A & M == 0), then clears bits in memory where accumulator bits are set.

Addressing Modes:

TRB $80       ; Zero Page
TRB $2000 ; Absolute

Flags Affected: Z

Bytes: 2-3 | Cycles: 5-6

Example:

LDA #$0F      ; Mask for low nibble
TRB $80 ; Test and clear low nibble of $80

TSB - Test and Set Bits​

Operation: Z = !(A & M), M = M | A

Description: Tests bits (sets Z if A & M == 0), then sets bits in memory where accumulator bits are set.

Addressing Modes:

TSB $80       ; Zero Page
TSB $2000 ; Absolute

Flags Affected: Z

Bytes: 2-3 | Cycles: 5-6

Example:

LDA #$80      ; Bit 7 mask
TSB $2000 ; Test and set bit 7

New Addressing Modes (65C02 Only)​

Zero Page Indirect: (ZP)​

Available for: ADC, AND, CMP, EOR, LDA, ORA, SBC, STA

Syntax:

LDA ($80)     ; Load from address stored at $80/$81
STA ($90) ; Store to address stored at $90/$91

Description: Uses a zero page address as a pointer to the actual data location. More efficient than indexed indirect when X is not needed.

Cycles: Typically 1 fewer than ($nn,X) equivalent

Absolute Indexed Indirect: (nnnn,X)​

Available for: JMP only

Syntax:

JMP ($2000,X) ; Jump to address at $2000+X

Description: Enhanced JMP indirect with X index. Useful for jump tables.

Bytes: 3 | Cycles: 6

Bug Fixes​

JMP Indirect Page Boundary​

6502 Bug:

JMP ($10FF)   ; Would fetch high byte from $1000 instead of $1100

65C02 Fix:

JMP ($10FF)   ; Correctly fetches high byte from $1100

The 65C02 properly handles page crossings in JMP indirect mode.

RMW (Read-Modify-Write) Instructions​

6502: ASL, LSR, ROL, ROR memory operations took 6 cycles (zero page) or 7 cycles (absolute)

65C02: Same operations take 5 cycles (zero page) or 6 cycles (absolute)

Instructions affected:

  • ASL memory
  • DEC memory
  • INC memory
  • LSR memory
  • ROL memory
  • ROR memory

Complete Instruction Set​

All 6502 Instructions​

The 65C02 supports all 56 legal 6502 instructions. See 6502 Instruction Set for details.

Additional 65C02 Instructions​

MnemonicDescriptionFlagsBytesCycles
BRABranch Always-23-4
PHXPush X Register-13
PHYPush Y Register-13
PLXPull X RegisterN Z14
PLYPull Y RegisterN Z14
STZStore Zero-2-33-5
TRBTest and Reset BitsZ2-35-6
TSBTest and Set BitsZ2-35-6

Enhanced Instructions (Modified from 6502)​

BIT - Bit Test (Enhanced)​

6502 Modes:

BIT $80       ; Zero Page
BIT $2000 ; Absolute

65C02 Additional Modes:

BIT #$42      ; Immediate (doesn't affect N/V)
BIT $80,X ; Zero Page,X
BIT $2000,X ; Absolute,X

Notes: Immediate mode only affects Z flag (N and V unchanged).

Undefined Opcodes​

6502: Undefined opcodes could crash or have unpredictable behavior.

65C02: All undefined opcodes are treated as single-byte NOPs (no operation). This makes the 65C02 more robust and easier to debug.

Decimal Mode Changes​

The 65C02 fixes several decimal mode issues:

  1. Flags Valid: N, V, Z flags are now valid after ADC/SBC in decimal mode
  2. Timing: Decimal mode no longer adds extra cycles
  3. Behavior: More predictable BCD arithmetic

Code Examples​

Using New Stack Instructions​

; Save registers (more efficient than 6502)
PHX ; Push X
PHY ; Push Y

; ... do work ...

PLY ; Pull Y
PLX ; Pull X
RTS

Using STZ​

; 6502 way (4 bytes, 5 cycles)
LDA #0
STA $2000
STA $2001

; 65C02 way (6 bytes, 8 cycles, but clearer)
STZ $2000 ; More readable
STZ $2001

Using BRA for Loops​

; 6502 way (use dummy branch)
LOOP ; ... code ...
CLC
BCC LOOP ; Always branches

; 65C02 way (clearer intent)
LOOP ; ... code ...
BRA LOOP ; Unconditional branch

Using Zero Page Indirect​

; 6502 way
LDX #0
LDA ($80,X) ; 6 cycles

; 65C02 way
LDA ($80) ; 5 cycles, clearer

Using TRB/TSB for Bit Manipulation​

; Clear bits 0-3 in memory
LDA #$0F
TRB $2000 ; Clear low nibble

; Set bit 7 (enable flag)
LDA #$80
TSB $2000 ; Set bit 7

; Test if any bits are set
LDA #$FF
TRB $2000 ; Z=1 if $2000 was zero

Timing Summary​

Operation Type6502 Cycles65C02 CyclesImprovement
RMW Zero Page55Same
RMW Absolute66Same
JMP Indirect56+1 (but fixes bug)
Decimal ADC/SBC+1+0-1 cycle

Compatibility Notes​

Forward Compatibility​

All 6502 code runs correctly on 65C02 with these exceptions:

  1. Undefined Opcodes: Code relying on undefined opcode behavior will break
  2. Decimal Mode: Code depending on invalid flags in decimal mode may behave differently
  3. Timing: Code with cycle-exact timing may need adjustment

Backward Compatibility​

65C02 code using new instructions will not run on 6502.

References​

  • WDC W65C02S Datasheet
  • Rockwell R65C02 Datasheet
  • Programming the 65816 by David Eyes and Ron Lichty
  • 6502 Assembly Language Programming by Lance Leventhal

See Also​