Skip to content

Appendix C: The 65C02 Processor

This is not meant to be a complete manual on the 65C02 processor, though is meant to serve as a convenient quick reference. Much of this information comes from 6502.org and pagetable.com. It is been placed here for convenience though further information can be found at those (and other) sources.

Overview

The WDC65C02 CPU is a modern version of the MOS6502 with a few additional instructions and addressing modes and is capable of running at up to 14 MHz. On the Commander X16, it is clocked at 8 MHz.

A note about 65C816 Compatibilty

The Commander X16 may be upgraded at some point to use the WDC 65C816 CPU. The 65C816 is mostly compatible with the 65C02, except for 4 instructions (BBRx, BBSx, RMBx, and SMBx).

These instructions may be deprecated in a future release of the emulator, and so we suggest not using these instructions. Some people are already using the 65C816 in their X16 systems, and so using these instructions will cause your programs to malfunction on these computers.

Instruction Tables

Instructions By Number

x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
0x BRK ORA TSB ORA ASL RMB0 PHP ORA ASL TSB ORA ASL BBR0
1x BPL ORA ORA TRB ORA ASL RMB1 CLC ORA INC TRB ORA ASL BBR1
2x JSR AND BIT AND ROL RMB2 PLP AND ROL BIT AND ROL BBR2
3x BMI AND AND BIT AND ROL RMB3 SEC AND DEC BIT AND ROL BBR3
4x RTI EOR EOR LSR RMB4 PHA EOR LSR JMP EOR LSR BBR4
5x BVC EOR EOR EOR LSR RMB5 CLI EOR PHY EOR LSR BBR5
6x RTS ADC STZ ADC ROR RMB6 PLA ADC ROR JMP ADC ROR BBR6
7x BVS ADC ADC STZ ADC ROR RMB7 SEI ADC PLY JMP ADC ROR BBR7
8x BRA STA STY STA STX SMB0 DEY BIT TXA STY STA STX BBS0
9x BCC STA STA STY STA STX SMB1 TYA STA TXS STZ STA STZ BBS1
Ax LDY LDA LDX LDY LDA LDX SMB2 TAY LDA TAX LDY LDA LDX BBS2
Bx BCS LDA LDA LDY LDA LDX SMB3 CLV LDA TSX LDY LDA LDX BBS3
Cx CPY CMP CPY CMP DEC SMB4 INY CMP DEX WAI CPY CMP DEC BBS4
Dx BNE CMP CMP CMP DEC SMB5 CLD CMP PHX STP CMP DEC BBS5
Ex CPX SBC CPX SBC INC SMB6 INX SBC NOP CPX SBC INC BBS6
Fx BEQ SBC SBC SBC INC SMB7 SED SBC PLX SBC INC BBS7

Instructions By Name

ADC AND ASL BBRx BBSx BCC BCS BEQ BIT BMI BNE BPL BRA BRK BVC BVS
CLC CLD CLI CLV CMP CPX CPY DEC DEX DEY EOR INC INX INY JMP JSR
LDA LDX LDY LSR NOP ORA PHA PHP PHX PHY PLA PLP PLX PLY RMBx ROL
ROR RTI RTS SBC SEC SED SEI SMBx STA STP STX STY STZ TAX TAY TRB
TSB TSX TXA TXS TYA WAI

Instructions By Category

Arithmetic ADC SBC
Boolean AND EOR ORA
Bit Shift ASL LSR ROL ROR
Branch BBRx BBSx
Test Bit BIT TRB TSB
Branching BCC BCS BEQ BMI BNE BPL BVC BVS BRA
Misc BRK NOP STP WAI
Flags CLC CLD CLI CLV SEC SED SEI
Compare CMP CPX CPY
Increment/Decrement DEC DEX DEY INX INY INC
Flow JMP JSR RTI RTS
Load Data LDA LDX LDY
Stack PHA PHP PHX PHY PLA PLP PLX PLY
Bit Operations RMBx SMBx
Store Data STA STX STY STZ
Transfer TAX TXA TAY TYA TSX TXS

ADC

Add with Carry

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
ADC #$20     Immediate      $69   2     2     NV----ZC 
ADC $20      Zero Page      $65   2     3     NV----ZC 
ADC $20,X    Zero Page,X    $75   2     4     NV----ZC 
ADC $8080    Absolute       $6D   3     4     NV----ZC 
ADC $8080,X  Absolute,X     $7D   3     4+    NV----ZC +p
ADC $8080,Y  Absolute,Y     $79   3     4+    NV----ZC +p
ADC ($20,X)  Indirect,X     $61   2     6     NV----ZC 
ADC ($20),Y  Indirect,Y     $71   2     5+    NV----ZC +p
ADC ($20)    ZP Indirect    $72   2     5     NV----ZC +c

Add a number to the Accumulator and stores the result in A.

Use the Carry (C) or Overflow (V) flags to determine whether the result was too large for an 8 bit number.

If C is set before operation, then 1 will be added to the result.

C is set when result is more than 255 ($FF)
Z is set when result is zero
V is set when signed result is too large. (Goes below -128 or above 127).
N is set when result is negative (bit 7=1)

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

AND

Logical And

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
AND #$20     Immediate      $29   2     2     N-----Z- 
AND $20      Zero Page      $25   2     3     N-----Z- 
AND $20,X    Zero Page,X    $35   2     4     N-----Z- 
AND $8080    Absolute       $2D   3     4     N-----Z- 
AND $8080,X  Absolute,X     $3D   3     4+    N-----Z- +p
AND $8080,Y  Absolute,Y     $39   3     4+    N-----Z- +p
AND ($20,X)  Indirect,X     $21   2     6     N-----Z- 
AND ($20),Y  Indirect,Y     $31   2     5+    N-----Z- +p
AND ($20)    ZP Indirect    $32   2     5     N-----Z- +c

Bitwise AND the provided value with the Accumulator.

  • Sets N (Negative) flag if the bit 7 of the result is 1, and otherewise clears it.
  • Sets Z (Zero) is the result is zero, and otherwise clears it

AND #$FF will leave A unaffected (but still set the flags).
AND #$00 will clear A.
AND #$0F will clear the high nibble of A, leaving a value of $00 to $0F in A.

M A Result
0 0 0
0 1 0
1 0 0
1 1 1

Other Boolean Instructions:
EOR exclusive-OR
ORA bitwise OR

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

ASL

Arithmetic Shift Left

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
ASL A        Accumulator    $0A   1     2     N-----ZC 
ASL $20      Zero Page      $06   2     5     N-----ZC
ASL $20,X    Zero Page,X    $16   2     6     N-----ZC
ASL $8080    Absolute       $0E   3     6     N-----ZC
ASL $8080,X  Absolute,X     $1E   3     6+    N-----ZC +p

Shifts all bits to the left by one position, moving 0 into the low bit.

0 is shifted into bit 0.
Bit 7 is shifted to Carry.

Similar instructions:
LSR is the opposite instruction and shifts to the right.
ROL shifts left through Carry.

+p: Add 1 cycle if a page boundary is crossed when forming address.


[Opcodes] | [By Name] | [By Category]

BBRx

Branch on Bit Reset

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
BBR0 $20,$8080 ZP Relative    $0F   3     5     -------- +c -816
BBR1 $20,$8080 ZP Relative    $1F   3     5     -------- +c -816
BBR2 $20,$8080 ZP Relative    $2F   3     5     -------- +c -816
BBR3 $20,$8080 ZP Relative    $3F   3     5     -------- +c -816
BBR4 $20,$8080 ZP Relative    $4F   3     5     -------- +c -816
BBR5 $20,$8080 ZP Relative    $5F   3     5     -------- +c -816
BBR6 $20,$8080 ZP Relative    $6F   3     5     -------- +c -816
BBR7 $20,$8080 ZP Relative    $7F   3     5     -------- +c -816

Branch to LABEL if bit x of zero page address is 0 where x is the number of the specific bit (0-7).

+c: New for the 65C02 -816: Not available on the 65C816

BBR Example

  check_flag:
    BBR3 zeropage_flag, flag_not_set
  flag_set:
    NOP
    ...
  flag_not_set:
    NOP
    ...

The above BBR3 looks at value in zeropage_flag (here it's a label to an actual zero page address) and if bit 3 of the value is zero the branch would be taken to @flag_not_set.


[Opcodes] | [By Name] | [By Category]

BBSx

Branch on Bit Set

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
BBS0 $20,$8080 ZP Relative    $8F   3     5     -------- +c -816
BBS1 $20,$8080 ZP Relative    $9F   3     5     -------- +c -816
BBS2 $20,$8080 ZP Relative    $AF   3     5     -------- +c -816
BBS3 $20,$8080 ZP Relative    $BF   3     5     -------- +c -816
BBS4 $20,$8080 ZP Relative    $CF   3     5     -------- +c -816
BBS5 $20,$8080 ZP Relative    $DF   3     5     -------- +c -816
BBS6 $20,$8080 ZP Relative    $EF   3     5     -------- +c -816
BBS7 $20,$8080 ZP Relative    $FF   3     5     -------- +c -816

Branch to LABEL if bit x of zero page address is 1 where x is the number of the specific bit (0-7).

+c: New for the 65C02 -816: Not available on the 65C816

BBS Example

check_flag:
    BBS3 zeropage_flag, flag_set
flag_not_set:
    NOP
    ...
flag_set:
    NOP
    ...

The above BBR3 looks at value in zeropage_flag (here it's a label to an actual zero page address) and if bit 3 of the value is zero the branch would be taken to @flag_set.


[Opcodes] | [By Name] | [By Category]

BIT

Test Bit

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
BIT $20      Zero Page      $24   2     3     NV----Z- 
BIT $8080    Absolute       $2C   3     4     NV----Z- 
BIT #$20     Immediate      $89   2     2     ------Z- +c
BIT $20,X    Zero Page,X    $34   2     4     NV----Z- +c
BIT $8080,X  Absolute,X     $3C   3     4+    NV----Z- +c +p
  • Sets Z (Zero) flag based on an AND of value provided to the Accumulator.
  • Sets N (Negative) flag to the value of bit 7 at the provided address (NOTE: not with immediate).
  • Sets V (Overflow) flag to the value of bit 6 at the provided addres (NOTE: not with immediate).

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

Bcc

Branch Instructions

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
BCC $8080    Relative       $90   2    2/3+   -------- +p Carry Clear
BCS $8080    Relative       $B0   2    2/3+   -------- +p Carry Set
BEQ $8080    Relative       $F0   2    2/3+   -------- +p Equal: Zero bit set
BMI $8080    Relative       $30   2    2/3+   -------- +p Negative bit set
BNE $8080    Relative       $D0   2    2/3+   -------- +p Not Equal: Zero bit clear
BPL $8080    Relative       $10   2    2/3+   -------- +p Negative bit clear
BVC $8080    Relative       $50   2    2/3+   -------- +p oVerflow Clear
BVS $8080    Relative       $70   2    2/3+   -------- +p oVerflow Set
BRA $8080    Relative       $80   2    3/4+   -------- +p +c Always

The branch instructions take the branch when the related flag is Set (1) or Clear (0).

When combined with CMP, this is the 6502's "IF THEN" construct.

LDA $1234  ; Reads the value of address $1234
CMP #$20   ; Compares it with the literal $20 (32)
BEQ Match  ; If they are equal, move to the label "Match".

The operand is a relative address, based on the Program Counter at the start of the next opcode. As a result, you can only branch 127 bytes forward or 128 bytes back. However, most assemblers take a label or an address literal. So the assembled value will be computed based on the PC and the entered value.

For example, if the PC is $1000, the statement BCS $1023 will be $B0 $21.

BCC also functions as "branch less-than" (<) after a comparison (some assemblers support a BLT macro/alias). Similarly, BCS also functions as "branch greater-than-or-equal" (>=) after a comparison (some assemblers support a BGE macro/alias).

+p: Execution takes one additional cycle when branching crosses a page boundary. +c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

BRK

Break: Software Interrupt

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
BRK          Implied        $00   1     7     ---BD--- 

BRK is a software interrupt. With any interrupt several things happen:

  1. The Program Counter is incremented by 2 bytes.
  2. The new PC and flags are pushed onto the stack (pushed flags has B set on BRK).
  3. The B flag is set (but only valid in stack memory flags interrupt pushed).
  4. The D (Decimal) flag is cleared, forcing the CPU into binary mode.
  5. The CPU reads the address from the IRQ vector at $FFFE and jumps there.

On the X16, BRK will jump out of the running program to the machine monitor. You can then examine the state of the CPU registers and memory.

The B flag (as pushed on the stack) is used to distinguish a BRK from an NMI. An interrupt triggered by asserting the NMI pin does not set the B flag, and so the X16 does a warm boot of BASIC, rather than jumping to MONitor.


[Opcodes] | [By Name] | [By Category]

CLC

Clear Carry

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
CLC          Implied        $18   1     2     -------C 

Clears the Carry flag. This is useful before ADC to prevent an extra 1 during addition. C is also often used in KERNAL routines to alter the operation of the routine or return certain information.


[Opcodes] | [By Name] | [By Category]

CLD

Clear Decimal Flag

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
CLD          Implied        $D8   1     2     ----D--- 

Clears the Decimal flag. This switches the CPU back to binary operation if it was previously in BCD mode.


[Opcodes] | [By Name] | [By Category]

CLI

Clear Interrupt Disable

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
CLI          Implied        $58   1     2     -----I-- 

Clear Interrupt disable. This allows IRQ interrupts to proceed normally. NMI and RST are always enabled.

Use SEI to disable interrupts


[Opcodes] | [By Name] | [By Category]

CLV

Clear oVerflow

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
CLV          Implied        $B8   1     2     -V------ 

Clear the Overflow (V) flag after an arithmetic operation, such as ADC or SBC.


[Opcodes] | [By Name] | [By Category]

CMP

Compare A to memory

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
CMP #$20     Immediate      $C9   2     2     N-----ZC 
CMP $20      Zero Page      $C5   2     3     N-----ZC 
CMP $20,X    Zero Page,X    $D5   2     4     N-----ZC 
CMP $8080    Absolute       $CD   3     4     N-----ZC 
CMP $8080,X  Absolute,X     $DD   3     4+    N-----ZC +p
CMP $8080,Y  Absolute,Y     $D9   3     4+    N-----ZC +p
CMP ($20,X)  Indirect,X     $C1   2     6     N-----ZC 
CMP ($20),Y  Indirect,Y     $D1   2     5+    N-----ZC +p
CMP ($20)    ZP Indirect    $D2   2     5     N-----ZC +c

Compares the value in the Accumulator (A) with the given value. It sets flags based on subtracting A - Value.

  • Sets C (Carry) flag if the value in A is >= given value
  • Clears C (Carry) flag if the value in A is < given value
  • Sets Z (Zero) flag if the values are equal
  • Clears Z (Zero) flag if the values are not equal
  • Sets N (Negative) flag if value in A is < given value

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

CPX

Compare X to memory

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
CPX #$20     Immediate      $E0   2     2     N-----ZC 
CPX $20      Zero Page      $E4   2     3     N-----ZC 
CPX $8080    Absolute       $EC   3     4     N-----ZC 

Compares the value in the X register with the given value. It sets flags based on subtracting X - Value.

  • Sets C (Carry) flag if the value in X is >= given value
  • Clears C (Carry) flag if the value in X is < given value
  • Sets Z (Zero) flag if the values are equal
  • Clears Z (Zero) flag if the values are not equal
  • Sets N (Negative) flag if value in X is < given value

[Opcodes] | [By Name] | [By Category]

CPY

Compare Y to memory

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
CPY #$20     Immediate      $C0   2     2     N-----ZC 
CPY $20      Zero Page      $C4   2     3     N-----ZC 
CPY $8080    Absolute       $CC   3     4     N-----ZC 

Compares the value in the Y register with the given value. It sets flags based on subtracting Y - Value.

  • Sets C (Carry) flag if the value in Y is >= given value
  • Clears C (Carry) flag if the value in Y is < given value
  • Sets Z (Zero) flag if the values are equal
  • Clears Z (Zero) flag if the values are not equal
  • Sets N (Negative) flag if value in Y is < given value

[Opcodes] | [By Name] | [By Category]

DEC

Decrement Value

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
DEC A        Accumulator    $3A   1     2     N-----Z- +c
DEC $20      Zero Page      $C6   2     5     N-----Z- 
DEC $20,X    Zero Page,X    $D6   2     6     N-----Z- 
DEC $8080    Absolute       $CE   3     6     N-----Z- 
DEC $8080,X  Absolute,X     $DE   3     7     N-----Z- 
DEX          Implied        $CA   1     2     N-----Z- 
DEY          Implied        $88   1     2     N-----Z- 

Decrement value by one: this subtracts 1 from memory or the designated register, leaving the new value in its place.

DEC with an operand operates on memory.

DEX operates on the X register
DEY operates on the Y register
DEC A or DEC operates on the Accumulator.

  • Sets N (Negative) flag if the two's compliment value is negative
  • Sets Z (Zero) flag is the value is zero

+c: New for the 65C02

16-bit DEC Example

You can peform a 16-bit DEC by chaining two DECs together, testing the low byte before decrementing the high byte:

;16 bit decrement
      LDA Num_Low
      BNE skip
      DEC Num_High
skip: DEC Num_Low

[Opcodes] | [By Name] | [By Category]

EOR

Exclusive OR

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
EOR #$20     Immediate      $49   2     2     N-----Z- 
EOR $20      Zero Page      $45   2     3     N-----Z- 
EOR $20,X    Zero Page,X    $55   2     4     N-----Z- 
EOR $8080    Absolute       $4D   3     4     N-----Z- 
EOR $8080,X  Absolute,X     $5D   3     4+    N-----Z- +p
EOR $8080,Y  Absolute,Y     $59   3     4+    N-----Z- +p
EOR ($20,X)  Indirect,X     $41   2     6     N-----Z- 
EOR ($20),Y  Indirect,Y     $51   2     5+    N-----Z- +p
EOR ($20)    ZP Indirect    $52   2     5     N-----Z- +c

Perform an exclusive OR of the given value in A (the accumulator), storing the result in A.

The exclusive OR version of ORA.

  • Sets N (Negative) flag if the two's compliment value is negative
  • Sets Z (Zero) flag is the value is zero

Exclusive OR returns a 1 bit for each bit that is different in the values tested. It returns a 0 for each bit that is the same.

EOR #$00 has no effect on A, but still sets the Z and N flags.
EOR #$FF inverts the bits in A.

M A Result
0 0 0
0 1 1
1 0 1
1 1 0

Other Boolean Instructions:
ORA bitwise OR
AND bitwise AND

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

INC

Increment Value

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
INC A        Accumulator    $1A   1     2     N-----Z- +c
INC $20      Zero Page      $E6   2     5     N-----Z- 
INC $20,X    Zero Page,X    $F6   2     6     N-----Z- 
INC $8080    Absolute       $EE   3     6     N-----Z- 
INC $8080,X  Absolute,X     $FE   3     6/7   N-----Z- 
INX          Implied        $E8   1     2     N-----Z- 
INY          Implied        $C8   1     2     N-----Z- 

Increment by one: this adds 1 to memory or the designated register, leaving the new value in its place.

  • Sets N (Negative) flag if the two's compliment value is negative
  • Sets Z (Zero) flag is the value is zero

INC oper operates on memory.
INX operates on the X register.
INY operates on the Y register.
INC A or INC with no operand operates on the Accumulator.

+c: New for the 65C02

16-bit INC Example

You can peform a 16-bit INC by chaining two INCs together, testing the low byte after incrementing it.

;16 bit increment
        INC Addr_Low
        BNE skip
        INC Addr_High
skip:   ...

[Opcodes] | [By Name] | [By Category]

JMP

Jump to new address

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
JMP $8080    Absolute       $4C   3     3     -------- 
JMP ($8080)  Indirect       $6C   3     5     -------- 
JMP $8080,X  Absolute,X     $7C   3     6     -------- +c

Jump to specified memory location and begin execution from this point.

Note for indirect jumps: The CPU does not correctly retrieve the second byte of the pointer from the next page, so you should never use a pointer address on the last byte of a page. ie: $12FF. [Issue is fixed on 65C02]

+c: New for the 65C02

(Absolute,X) and Jump Tables

(Absolute,X) is an additional mode for the 65C02 and is commonly used for implementing jump tables.

So we might have something like:

important_jump_table:
  .word routine1
  .word routine2
...

LDX #$02     ; table index * 2
JMP (important_jump_table,x)

The above would jump to the address of routine2, and is much faster than the old 6502 method of pushing the two bytes onto the stack and performing an RTS.


[Opcodes] | [By Name] | [By Category]

JSR

Jump to Subroutine

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
JSR $8080    Absolute       $20   3     6     -------- 

Stores the address of the Program Counter to the stack.
Jump to specified memory location and begin execution from this point.

This is used to run subroutines in user programs, as well as running KERNAL routines. RTS is used at the end of the routine to return to the instruction immediately after the JSR.

Be careful to always match JSR and RTS, as imbalanced JSR/RTS operations will either overflow or underflow the stack.


[Opcodes] | [By Name] | [By Category]

LDA

Read memory to Accumulator

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
LDA #$20     Immediate      $A9   2     2     N-----Z- 
LDA $20      Zero Page      $A5   2     3     N-----Z- 
LDA $20,X    Zero Page,X    $B5   2     4     N-----Z- 
LDA $8080    Absolute       $AD   3     4     N-----Z- 
LDA $8080,X  Absolute,X     $BD   3     4+    N-----Z- +p
LDA $8080,Y  Absolute,Y     $B9   3     4+    N-----Z- +p
LDA ($20,X)  Indirect,X     $A1   2     6     N-----Z- 
LDA ($20),Y  Indirect,Y     $B1   2     5+    N-----Z- +p
LDA ($20)    ZP Indirect    $B2   2     5     N-----Z- +c

Place the given value from memory into the accumulator (A).

  • Sets N (Negative) flag if the two's compliment value is negative
  • Sets Z (Zero) flag is the value is zero

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

LDX

Read memory to X Index Register

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
LDX #$20     Immediate      $A2   2     2     N-----Z- 
LDX $20      Zero Page      $A6   2     3     N-----Z- 
LDX $20,Y    Zero Page,Y    $B6   2     4     N-----Z- 
LDX $8080    Absolute       $AE   3     4     N-----Z- 
LDX $8080,Y  Absolute,Y     $BE   3     4+    N-----Z- +p

Place the given value from memory into the X register.

  • Sets N (Negative) flag if the two's compliment value is negative
  • Sets Z (Zero) flag is the value is zero

+p: Add 1 cycle if a page boundary is crossed when forming address.


[Opcodes] | [By Name] | [By Category]

LDY

Read memory to Y Index Register

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
LDY #$20     Immediate      $A0   2     2     N-----Z- 
LDY $20      Zero Page      $A4   2     3     N-----Z- 
LDY $20,X    Zero Page,X    $B4   2     4     N-----Z- 
LDY $8080    Absolute       $AC   3     4     N-----Z- 
LDY $8080,X  Absolute,X     $BC   3     4+    N-----Z- +p

Place the given value from memory into the Y register.

  • Sets N (Negative) flag if the two's compliment value is negative
  • Sets Z (Zero) flag is the value is zero

+p: Add 1 cycle if a page boundary is crossed when forming address.


[Opcodes] | [By Name] | [By Category]

LSR

Logical Shift Right

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
LSR A        Accumulator    $4A   1     2     N-----Z- 
LSR $20      Zero Page      $46   2     5     N-----Z- 
LSR $20,X    Zero Page,X    $56   2     6     N-----Z- 
LSR $8080    Absolute       $4E   3     6     N-----Z- 
LSR $8080,X  Absolute,X     $5E   3    6/7    N-----Z-

Shifts all bits to the right by one position.

Bit 0 is shifted into Carry.
0 shifted into bit 7.

Similar instructions:
ASL is the opposite instruction, shifting to the left.
ROR rotates bit 0 through Carry to bit 7.


[Opcodes] | [By Name] | [By Category]

NOP

No Operation

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
NOP          Implied        $EA   1     2     -------- 

NOP simply does nothing for 2 clock cycles. No registers are affected, and no memory reads or writes occur. This can be used to delay the clock by 2 ticks.

It's also a useful way to blank out unwanted instructions in memory or in a machine language program on disk. By changing the byte values of the opcode and operands to $EA, you can effectively cancel out an instruction.

It is also useful for adding small delays to your code. For instance, to add a bit of delay when writing to the YM2151 chip (see Chapter 11 - YM Write Procedure).


[Opcodes] | [By Name] | [By Category]

ORA

Logical OR

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
ORA #$20     Immediate      $09   2     2     N-----Z- 
ORA $20      Zero Page      $05   2     3     N-----Z- 
ORA $20,X    Zero Page,X    $15   2     4     N-----Z- 
ORA $8080    Absolute       $0D   3     4     N-----Z- 
ORA $8080,X  Absolute,X     $1D   3     4+    N-----Z- +p
ORA $8080,Y  Absolute,Y     $19   3     4+    N-----Z- +p
ORA ($20,X)  Indirect,X     $01   2     6     N-----Z- 
ORA ($20),Y  Indirect,Y     $11   2     5+    N-----Z- +p
ORA ($20)    ZP Indirect    $12   2     5     N-----Z- +c

Perform a logical OR of the given value in A (the Accumulator), storing the result in A.

  • Sets N (Negative) flag if the two's compliment value is negative
  • Sets Z (Zero) flag is the value is zero

OR #$00 has no effect on A, but still sets the Z and N flags.
OR #$FF results in $FF.

M A Result
0 0 0
0 1 1
1 0 1
1 1 1

Other Boolean Instructions:
EOR exclusive-OR
AND bitwise AND

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

PHA

Push to stack

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
PHA          Implied        $48   1     3     -------- 
PHP          Implied        $08   1     3     -------- 
PHX          Implied        $DA   1     3     -------- +c
PHY          Implied        $5A   1     3     -------- +c

Pushes a register to the stack.

This instruction copies the value in the affected register to the address of the stack pointer, then moves the stack pointer downward by one byte.

Be careful to match Push and Pull operations so that you don't accidentally overflow or underflow the stack.

PHP pushes the Flags, also called P for Program Status Register.

The corresponding "Pull" instructions are PLA, PHP, PHX, and PHY.

+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

PLA

Pull from stack

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
PLA          Implied        $68   1     4     N-----Z- 
PLP          Implied        $28   1     4     NV--DIZC 
PLX          Implied        $FA   1     4     N-----Z- +c
PLY          Implied        $7A   1     4     N-----Z- +c

Pulls a value from the stack into a register.

This instruction moves the stack pointer up by one byte, then copies the value from the address of the stack pointer to the affected register.

Be careful to match Push and Pull operations so that you don't accidentally overflow or underflow the stack.

PLP pulls the Flags, also called P for Program Status Register.

Use TXS or TSX to directly manage the stack pointer.

The corresponding "Push" instructions are PHA, PHP, PHX, and PHY.

+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

RMBx

Memory Bit Operations

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
RMB0 $20     Zero Page      $07   2     5     -------- +c -816
RMB1 $20     Zero Page      $17   2     5     -------- +c -816
RMB2 $20     Zero Page      $27   2     5     -------- +c -816
RMB3 $20     Zero Page      $37   2     5     -------- +c -816
RMB4 $20     Zero Page      $47   2     5     -------- +c -816
RMB5 $20     Zero Page      $57   2     5     -------- +c -816
RMB6 $20     Zero Page      $67   2     5     -------- +c -816
RMB7 $20     Zero Page      $77   2     5     -------- +c -816

Set bit x to 0 at the given zero page address where x is the number of the specified bit (0-7).

Often used in conjunction with BBR and BBS.

+c: New for the 65C02 -816: Not available on the 65C816


[Opcodes] | [By Name] | [By Category]

ROL

Rotate Left

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
ROL A        Accumulator    $2A   1     2     N-----ZC 
ROL $20      Zero Page      $26   2     5     N-----ZC 
ROL $20,X    Zero Page,X    $36   2     6     N-----ZC 
ROL $8080    Absolute       $2E   3     6     N-----ZC 
ROL $8080,X  Absolute,X     $3E   3    6/7    N-----ZC +p

Rotate all bits to the left one position. The value in the carry (C) flag is shifted into bit 0 and the original bit 7 is shifted into the carry (C).

ASL shifts left, moving 0 into bit 0
ROR rotates to the right.

+p: Add 1 cycle if a page boundary is crossed when forming address.


[Opcodes] | [By Name] | [By Category]

ROR

Rotate Right

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
ROR A        Accumulator    $6A   1     2     N-----ZC 
ROR $20      Zero Page      $66   2     5     N-----ZC 
ROR $20,X    Zero Page,X    $76   2     6     N-----ZC 
ROR $8080    Absolute       $7E   3     6     N-----ZC 
ROR $8080,X  Absolute,X     $6E   3    6/7    N-----ZC +p

Rotate all bits to the right one position. The value in the carry (C) flag is shifted into bit 7 and the original bit 0 is shifted into the carry (C).

LSR shifts right, placing 0 into bit 7.
ROL rotates to the left.

+p: Add 1 cycle if a page boundary is crossed when forming address.


[Opcodes] | [By Name] | [By Category]

RTI

Return from Interrupt

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
RTI          Implied        $40   1     6     -------- 

Return from an interrupt by popping three values off the stack. The first is for the status register (P) followed by the two bytes of the program counter.

Note that unlike RTS, the popped address is the actual return address (rather than address-1).


[Opcodes] | [By Name] | [By Category]

RTS

Return from Subroutine

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
RTS          Implied        $60   1     6     -------- 

Typically used at the end of a subroutine. It jumps back to the address after the JSR that called it by popping the top 2 bytes off the stack and transferring control to that address +1.


[Opcodes] | [By Name] | [By Category]

SBC

Subtract With Carry

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
SBC #$20     Immediate      $E9   2     2     NV----ZC 
SBC $20      Zero Page      $E5   2     3     NV----ZC 
SBC $20,X    Zero Page,X    $F5   2     4     NV----ZC 
SBC $8080    Absolute       $ED   3     4     NV----ZC 
SBC $8080,X  Absolute,X     $FD   3     4+    NV----ZC +p
SBC $8080,Y  Absolute,Y     $F9   3     4+    NV----ZC +p
SBC ($20,X)  Indirect,X     $E1   2     6     NV----ZC 
SBC ($20),Y  Indirect,Y     $F1   2     5+    NV----ZC +p
SBC ($20)    ZP Indirect    $F2   2     5     NV----ZC +c

Subtract the operand from A and places the result in A.

When Carry is 0, an additional 1 is subtracted.

There is no "Subtract without carry". To do that, use SEC first to set the Carry flag.

If D=1, subtraction is Binary Coded Decimal. If D=0 then subtraction is binary.

C is clear when result is less than 0. (ie: Borrow took place)
Z is set when result is zero
V is set when signed result goes below -128 or above 127.
N is set when result is negative (bit 7=1)

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

SEC

Set Carry

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
SEC          Implied        $38   1     2     -------C 

Sets the Carry flag. This is used before SBC to prevent an extra subtract. C is also often used in KERNAL routines to alter the operation of the routine or return certain information.


[Opcodes] | [By Name] | [By Category]

SED

Set Decimal

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
SED          Implied        $F8   1     2     ----D--- 

Sets the Decimal flag. This will put the CPU in BCD mode, which affects the behavior of ADC and SBC.

In binary mode, adding 1 to $09 will set the Accumulator to $0F.
In BCD mode, adding 1 to $09 will set the Accumulator to $10.

Using BCD allows for easier conversion of binary numbers to decimal. BCD also allows for storing decimal numbers without loss of precision due to power-of-2 rounding.


[Opcodes] | [By Name] | [By Category]

SEI

Set Interrupt Disable

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
SEI          Implied        $78   1     2     -----I-- 

Sets or clears the Interrupt Disable flag. When I is set, the CPU will not execute IRQ interrupts, even if the line is asserted. Use CLI to re-enable interrupts.


[Opcodes] | [By Name] | [By Category]

SMBx

Set Memory Bit

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
SMB0 $20     Zero Page      $87   2     5     -------- +c -816
SMB1 $20     Zero Page      $97   2     5     -------- +c -816
SMB2 $20     Zero Page      $A7   2     5     -------- +c -816
SMB3 $20     Zero Page      $B7   2     5     -------- +c -816
SMB4 $20     Zero Page      $C7   2     5     -------- +c -816
SMB5 $20     Zero Page      $D7   2     5     -------- +c -816
SMB6 $20     Zero Page      $E7   2     5     -------- +c -816
SMB7 $20     Zero Page      $F7   2     5     -------- +c -816

Set bit x to 1 at the given zero page address where x is the number of the specific bit (0-7).

Often used in conjunction with BBR and BBS.

Specific to the 65C02 (unavailable on the 65C816)

+c: New for the 65C02 -816: Not available on the 65C816


[Opcodes] | [By Name] | [By Category]

STA

Store Accumulator contents to memory

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
STA $20      Zero Page      $85   2     3     -------- 
STA $20,X    Zero Page,X    $95   2     4     -------- 
STA $8080    Absolute       $8D   3     4     -------- 
STA $8080,X  Absolute,X     $9D   3     5+    -------- +p
STA $8080,Y  Absolute,Y     $99   3     5+    -------- +p
STA ($20,X)  Indirect,X     $81   2     6     -------- 
STA ($20),Y  Indirect,Y     $91   2     6+    -------- +p
STA ($20)    ZP Indirect    $92   2     5     -------- +c

Place the given value from the accumulator (A) into memory.

+p: Add 1 cycle if a page boundary is crossed when forming address.
+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

STP

Stop

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
STP          Implied        $DB   1     3     -------- +c

Stops (or halts) the processor and places it in a lower power state until a hardware reset occurs. For the X16 emulator, when the debugger is enabled using the -debug command-line parameter, the STP instruction will break into the debugger automatically.

If debugging is not enabled, the emulator will prompt the user to close the emulator or reset the emulation.

+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

STX

Save X Index Register contents to memory

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
STX $20      Zero Page      $86   2     3     -------- 
STX $20,Y    Zero Page,Y    $96   2     4     -------- 
STX $8080    Absolute       $8E   3     4     -------- 

[Opcodes] | [By Name] | [By Category]

STY

Save Y Index Register contents to memory

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
STY $20      Zero Page      $84   2     3     -------- 
STY $20,X    Zero Page,X    $94   2     4     -------- 
STY $8080    Absolute       $8C   3     4     -------- 

[Opcodes] | [By Name] | [By Category]

STZ

Set memory to zero

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
STZ $20      Zero Page      $64   2     3     -------- +c
STZ $20,X    Zero Page,X    $74   2     4     -------- +c
STZ $8080    Absolute       $9C   3     4     -------- +c
STZ $8080,X  Absolute,X     $9E   3     5     -------- +c

+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

TRB

Test and reset bit

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
TRB $20      Zero Page      $14   2     5     ------Z- +c
TRB $8080    Absolute       $1C   3     5     ------Z- +c

Effectively an inverted AND between memory and the Accumulator. The bits that are 1 in the Accumulator are set to 0 in memory.

  • Sets Z (Zero) flag if all bits from the AND are zero.

+c: New for the 65C02

TRB Example

          ; Assume location $20 has a value of $11.
LDA #$01  ; Load a bit mask of 0000 0001
TRB $20   ; Apply the mask and reset bit 0
          ; Location $20 now has a value of $10.

This is conceptually similar to

LDA #$01 ; We want to clear bit 1 of the data
EOR #$FF ; Invert the mask, so $01 becomes $FE (1111 1110)
AND $20  ; AND with memory, saving the result in .A
STA $20  ; Store it back to memory.

[Opcodes] | [By Name] | [By Category]

TSB

Test and set bit

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
TSB $20      Zero Page      $04   2     5     ------Z- +c
TSB $8080    Absolute       $0C   3     5     ------Z- +c

Performs an OR with each bit in the accumulator and memory. Each bit that is 1 in the Accumulator is set to 1 in memory. This is similar to an ORA operation, execpt that the result is stored in memory, not in A.

The Z flag is set based on the final result of the operation, ie: the memory data is 0.

+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

Txx

Transfer between registers

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
TAX          Implied        $AA   1     2     N-----Z- Copy from .A to .X
TXA          Implied        $8A   1     2     N-----Z- Copy from .X to .A
TAY          Implied        $A8   1     2     N-----Z- Copy from .A to .Y
TYA          Implied        $98   1     2     N-----Z- Copy from .Y to .A
TSX          Implied        $BA   1     2     N-----Z- Copy from Stack Pointer to .X
TXS          Implied        $9A   1     2     -------- Copy from .X to Stack Pointer

Copies data from one register to anohter.

TSX and TSX copy between the Stack Pointer and the X register. This is the only way to directly control the Stack Pointer. To initialize the Stack Pointer to a specific address, you can use the following instructions.

LDX #$FF
TXS

[Opcodes] | [By Name] | [By Category]

WAI

Wait

SYNTAX       MODE           HEX  LEN  CYCLES  FLAGS    
WAI          Implied        $CB   1     3     -------- +c

Effectively stops the processor until a hardware interrupt occurs. The intterupt is processed immediately, and execution resumes in the Interrupt handler.

NMI, IRQ, and RST (Reset) will recover from the WAI condition.

Normally, an instruction completes its operation before actually handling an interrupt. But if WAI has executed, the CPU does not need to defer the interrupt, and so the interrupt can be handled immediately.

+c: New for the 65C02


[Opcodes] | [By Name] | [By Category]

Status Flags

Flags are stored in the P register. PHP and PLP can be used to directly manipulate this register. Otherwise the flags are used to indicate certain statuses and changed by various instructions.

P-Register:

NV1B DIZC

N = Negative
V = oVerflow
1 = Always 1
B = Interrupt Flag
D = Decimal Mode
I = Interupts Disabled
Z = Zero
C = Carry

Replacement Macros for Bit Instructions

Since BBRx, BBSx, RMBx, and SMBx should not be used, to maintain compatibility with the 65C816, here are some example macros that can be used to help convert existing software that may have been using these instructions:

.macro bbs bit_position, data, destination
 .if (bit_position = 7)
  bit data
  bmi destination
 .else
  .if (bit_position = 6)
   bit data
   bvs destination
  .else
   lda data
   and #1 << bit_position
   bne destination
  .endif
  .endif
.endmacro

.macro bbr bit_position, data, destination
 .if (bit_position = 7)
  bit data
  bpl destination
 .else
  .if (bit_position = 6)
   bit data
   bvc destination
  .else
   lda data
   and #1 << bit_position
   beq destination
  .endif
 .endif
.endmacro

.macro rmb bit, destination
 lda #$1 << bit
 trb destination
.endmacro

.macro smb bit, destination
 lda #$1 << bit
 tsb destination
.endmacro

The above is CA65 specific but the code should work similarly for other languages. The logic can also be used to if using an assembly language tool that does not have macro support with small changes.

Further Reading

a different page