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