A 6502 Programmer's Introduction to the 65816

by Brett Tabke

After programming in 6502 language for over a decade, I was getting a bit BORED. One can only code the same routines with the same opcodes so many times before the nausea of repetition becomes overpowering. When I heard the news that CMD was building a cartridge based on a 20 MHz 65816 I was overjoyed. For years I've heard those with 65816 bases systems brag about its capabilities. To us old 6502 programmers, the opportunity to program the fabled 65816 is a new lease on life.

The 65816 is an 8-/16-bit register selectable upgrade to the 6502 series processor. With 24 bit addressing of up to 16 Megabytes of RAM, the powerful 65816 is a logical upgrade that leaves 6502 programmers feeling right at home. It is amazing how fast one can adapt to the new processor. It sounds funny to say it, but the only difficulty I have had learning the 65816 is that there are so many options and choices to complete the same task, that it is hard to decide which method is best.

To get started programming the 65816, I would recommend purchasing the book, "Programming the 65816" from The Western Design Center, manufacturer of the 65816. While it is a bit pricey, the sheer quality and content of the 600 page book is worth the money. Rarely, if ever, has there been a CPU manual as thorough and detailed as the Western Design book. If you know 6502 assembly, then Programming the 65816 is probably the only 65816 book you will ever need.

Getting a Feel for the Modes

The 65816 may be operated in Native mode or 6502 Emulation mode. Emulation mode is a 100% 6502 compatible mode where the whole processor looks and feels like a vintage 6502. Native mode offers 8- or 16-bit user registers and full access to 24-bit addressing.

While in emulation mode, not only are all the 6502 opcodes present in their virgin form, but the new 65816 instructions are also available for usage. In fact, the first lesson to learn about programming the 65816 is that emulation mode is much more powerful than a stock 6502. The only true difference between emulation mode and our venerable C64's 6510 processor is that unimplemented opcodes will not produce the results expected on the former. Since all 256 of the potential opcodes are now implemented on the 65816, older C64 software that uses previously unimplemented opcodes will produce erratic results.

To select between emulation and native modes, a new phantom hidden emulation bit (E) was added to the status register. Shown in programming models hanging on top of the Carry bit, the emulation bit is only accessible by one instruction. The new instruction (XCE) exchanges the status of the Carry bit and Emulation bit. To move to emulation mode, set the carry and issue an XCE instruction. To move to native mode, clear the carry and issue the XCE instruction.

My, How Your Index Registers Have Grown!

While in native mode there are two new directly accessible bits present in the status register. The 65816 implements new hardware interrupt vectors which include a new hardware BRK vector in ROM; therefore, the old BRK bit of the status register is no longer needed. The BRK bit is replaced with the X bit to select either 8- or 16-bit index registers. The former empty bit 5 is now filled with the M bit to specify the accumulator and memory access as 8- or 16-bit.

Two new instructions are used to clear or set bits within the status register. The SEP instruction sets bits, and REP clears bits. SEP and REP use a one byte immediate addressing mode operand to specify which bits are to be set or cleared. For example, to set the X bit for 8 bit user registers:

SEP #%00010000 ; set bit 4 for 8-bit index
; registers.


Or to clear bit 4:
REP #%00010000 ; clear bit 4 for 16-bit index
; registers.


When in 8 bit mode, the index registers perform their function in standard 6502 form. When status bit X is set to 0, both the X and Y index registers become 16 bits wide. With a 16-bit index register you can now reach out to a full 64K with the various indexed addressing modes. An absolute load to an index register in 16-bit mode will retrieve 2 bytes of memory-the one at the effective address and the one at the effective address plus one. Simple things like INX or DEY work on a full 16 bit, which means you no longer have to specify a memory location for various counters, and loops based on index counters can now be coded in a more efficient manner.

The formerly empty status register bit 5 is now referred to as bit M. M is used to specify an 8- or 16-bit wide acculmulator and memory accesses. When in 8 bit mode, (M=1), the high order 8 bits are still accessible by exchanging the low and high bytes with a XBA instruction-it is like having two acculmulators! However; when set for a full 16-bit wide accumulator, all math and accumulator oriented logical intructions operate on all 16 bits! If you add up the clock cycles and bytes required to perform a standard two byte addition, you can start to see the true power of 16-bit registers.

More Register Improvements

Zero Page has now been renamed to Direct Page-corporate thinking, go figure. A new processor register D was added to allow Direct Page to be moved anywhere within the first 64K of memory. The direct page register is 16 bits wide, so you can now specify the start of direct page at any byte. Several old instructions now include direct page addressing as well. To move direct page, just push the new value onto the stack (16 bits) and then PLD to pull it into the direct page register. You may also transfer the value from the 16-bit accumulator to the direct page register with the TCD instruction. Direct page may also be moved while in emulation mode.

While in native mode, the stack pointer is a full 16 bits wide, which means the stack is no longer limited to just 256 bytes. It can be moved anywhere within the first 64K of memory (although while in emulation mode, the stack is located at page one). There are several new addressing modes that can use the stack pointer as a quasi-index register to access memory. Numerous new push and pull instructions allow you to manipulate the stack. A few of the more useful stack intructions useful to programmers, are the new instructions to push & pull index registers with PHX/PHY and PLX/PLY.

Two other new processors registers are the Program Bank Register (PBR) and the Data Bank Register (DBR). The Program Bank Register can be thought of as extending the program counter out to 24 bits. Although you can JSR and JMP to routines located in other RAM banks, individual routines on the 65816 still must run within a single bank of 64K-there's no automatic rollover from one bank of RAM to the next when executing successive instructions. In this sense, it may help to think of the 65816 processor as a marriage of Commodore's C128 Memory Management Unit (MMU) and an 'enhanced' 6502-a very similar concept.

The Data Bank Register is used to reach out to any address within the 16 megabyte address space of the 65816. When any of the addressing modes that specify a 16-bit address are used, the Data Bank byte is appended to the instruction address. This allows access to all 16 megabytes without having to resort to 24-bit addressing instruction, and helps enable code that can operate from any bank.

New Addressing Modes

There are new addressing modes on the 65816. Several new instructions are designed to help relocatable code that can execute at any address. The use of relocatable code on the 6502 was extremely limited. With 16 megabytes of address space, writing relocatable code increases the overall utility of the program. To write relocatable code, several new instructions use Program Counter Relative Long addressing. This allows relative branching within a 64K bank of RAM. There's also Stack Relative addressing, and a push instruction to place the program counter onto the stack, so that a code fragment can pull it back off and can instantly know its execution address.

Another new feature are two Block Move instructions, one for forward MVP and one for backward MVN. Simply load the 16-bit X register with the starting address, the Y index register with the ending address, the accumulator with the number of bytes to move, and issue the MVP or MVN instructions. MVN is for move negative, and MVP is for move positive, so that your moves don't overwrite themselves. Block Moves use two operand bytes: one for the source bank of 64K and one for the destination bank. Memory is moved at the rate of seven clock cycles per byte.

Several new addressing modes are used to access the full address space. A 65816 assembler would decode "long" addressing given this input:

LDA $0445F2; load byte from $45F2 of RAM
; bank 4
LDA $03412F,x; load byte from $412F of bank 3
; plus x.

Quite a few instructions have been given new addressing modes. How many times have you wanted to do this:
LDA ($12); load indirect without an
; offset.


Or how about a table of routine addresses:
JSR ($1234,x) ; jump to a subroutine via
; indexed indirect addressing!


Other fun new instructions:
TXY,TYX Transfer directly between index registers
BRABranch always regardless of status bits
TSBTest and set any bit of a byte
TRBTest and reset (clear) any bit of a byte
INC A/DEC AIncrement or decrement the accumulator directly
STZStore a zero to any byte

Summing Up

As you can see, the 65816 opens up a whole new world of programming-it feels like a new lease on life. Of course, it's going to take some time to learn the new processor. But while the 20 MHz speed is a nice perk, I believe that the real power of CMD's new peripheral is indeed the engine under its hood: the 65816-a super CPU!



Native Mode Options

While in Native Mode, the m flag controls the size of Accumulator A and most Memory Operations, while the x flag controls the size of the X and Y Index Registers. This provides 4 different configuration possibilities, as charted below. The REP and SEP instructions are used in combination to swith configurations.
mxA/MX/YInstructions
0015-bit16-bitREP #$30
0116-bit8-bitREP #$20
SEP #$10
108-bit16-bitREP #$10
SEP #$20
118-bit8-bitSEP #$30

It is important to note that the m flag will control the size of all operations dealing with memory except in operations involving the X and Y Index Registers (CPX, CPY, LDX, LDY, STX and STY) when the x flag controls the size.



Emulation Notes

While in Emulation Mode, Accumulator A is forced to 8-bit mode. You can, however, access the upper 8 bits with instructions that specify Accumulator B, and all 16 bits at once with instructions that specify Accumulator C. The X and Y Index Registers are also forced to 8-bit mode, with no means available to access the upper 8 bits. To further assist in compatibility, the Stack is forced to Page 1 of Bank 0. The Direct page Register (D) is fully functional in this mode, allowing direct page to be placed anywhere in Bank 0. Likewise, the Program Bank Register (PBR) and Data Bank Register (DBR) are also fully functional. While it would seem that these latter items would allow programs to operate from any bank in Emulation mode, there are some caveats; interrups will force the program bank to zero without saving the PBR first, and RTI won't attempt to restore the bank. Therefore, Native mode would be recommended to execute programs in other banks.

Guide to 6502/65C02/65816 Instructions

| a | | b | | c | | d | | e | | i | | j | | l | | m | | n | | o | | p | | r | | s | | t | | w | | x |

Assembler ExampleHEXAddressing Mode02C02816BytesCycles
ADC Add With Carry [Flags affected: n,v,z,c]
ADC (dp,X)
61DP Indexed Indirect,Xxxx261,2,4
ADC sr,S
63Stack Relative x241,4
ADC dp
65Direct Page xxx231,2,4
ADC [dp]
67DP Indirect Longx261,2,4
ADC #const
69Immediatexxx21721,4
ADC addr
6DAbsolutexxx341,4
ADC long
6FAbsolute Longx451,4
ADC ( dp),Y
71DP Indirect Indexed, Yxxx251,2,3,4
ADC (dp)
72DP Indirectxx251,2,4
ADC (sr,S),Y
73SR Indirect Indexed,Yx271,4
ADC dp,X
75DP Indexed,Xxxx241,2,4
ADC [dp],Y
77DP Indirect Long Indexed, Yx261,2,4
ADC addr,Y
79Absolute Indexed,Yxxx341,3,4
ADC addr,X
7DAbsolute Indexed,Xxxx341,3,4
ADC long,X
7FAbsolute Long Indexed,Xx451,4
AND AND Accumulator With Memory [Flags affected: n,z]
AND (dp,X)
21DP Indexed Indirect,Xxxx261,2
AND sr,S
23Stack Relative x241
AND dp
25Direct Page xxx231,2
AND [dp]
27DP Indirect Longx261,2
AND #const
29Immediatexxx21721
AND addr
2DAbsolutexxx341
AND long
2FAbsolute Longx451
AND (dp),Y
31DP Indirect Indexed, Yxxx251,2,3
AND (dp)
32DP Indirectxx251,2
AND (sr,S),Y
33SR Indirect Indexed,Yx271
AND dp,X
35DP Indexed,Xxxx241,2
AND [dp],Y
37DP Indirect Long Indexed, Yx261,2
AND addr,Y
39Absolute Indexed,Yxxx341,3
AND addr,X
3DAbsolute Indexed,Xxxx341,3
AND long,X
3FAbsolute Long Indexed,Xx451
ASL Accumulator or Memory Shift Left [Flags affected: n,z,c]
ASL dp
06Direct Pagexxx252,5
ASL A
0AAccumulatorxxx12
ASL addr
0EAbsolutexxx365
ASL dp,X
16DP Indexed,Xxxx262,5
ASL addr,X
1EAbsolute Indexed,Xxxx375,6
BCC Branch if Carry Clear [Flags affected: none][Alias: BLT]
BCC nearlabel
90Program Counter Relativexxx227,8
BCS Branch if Carry Set [Flags affected: none][Alias: BGE]
BCS nearlabel
B0Program Counter Relativexxx227,8
BEQ Branch if Equal [Flags affected: none]
BEQ nearlabel
F0Program Counter Relativexxx227,8
BIT Test Bits [Flags affected: z (immediate mode) n,v,z (non-immediate modes)]
BIT dp
24Direct Pagexxx231,2
BIT addr
2CAbsolutexxx341
BIT dp,X
34DP Indexed,Xxx241,2
BIT addr,X
3CAbsolute Indexed,Xxx341,3
BIT #const
89Immediatexx21721
BMI Branch if Minus [Flags affected: none]
BMI nearlabel
30Program Counter Relativexxx227,8
BNE Branch if Not Equal [Flags affected: none]
BNE nearlabel
D0Program Counter Relativexxx227,8
BPL Branch if Plus [Flags affected: none]
BPL nearlabel
10Program Counter Relativexxx227,8
BRA Branch Always [Flags affected: none]
BRA nearlabel
80Program Counter Relativexx238
BRK Break [Flags affected: b,i (6502) b,d,i (65C02/65816 Emulation) d,i (65816 Native)]
BRK
00Stack/Interrupt xxx2 18 79
BRL Branch Long Always [Flags affected: none]
BRL label
82Program Counter Relative Longx34
BVC Branch if Overflow Clear [Flags affected: none]
BVC nearlabel
50Program Counter Relativexxx227,8
BVS Branch if Overflow Set [Flags affected: none]
BVS nearlabel
70Program Counter Relativexxx227,8
CLC Clear Carry [Flags affected: c]
CLC
18Implied xxx12
CLD Clear Decimal Mode Flag [Flags affected: d]
CLD
D8Implied xxx12
CLI Clear Interrupt Disable Flag [Flags affected: i]
CLI
58Implied xxx12
CLV Clear Overflow Flag [Flags affected: v]
CLV
B8Implied xxx12
CMP Compare Accumulator With Memory [Flags affected: n,z,c]
CMP (dp,X)
C1DP Indexed Indirect,Xxxx261,2
CMP sr,S
C3Stack Relative x241
CMP dp
C5Direct Page xxx231,2
CMP [dp]
C7DP Indirect Longx261,2
CMP #const
C9Immediatexxx21721
CMP addr
CDAbsolutexxx341
CMP long
CFAbsolute Longx451
CMP (dp),Y
D1DP Indirect Indexed, Yxxx251,2,3
CMP (dp)
D2DP Indirectxx251,2
CMP (sr,S),Y
D3SR Indirect Indexed,Yx271
CMP dp,X
D5DP Indexed,Xxxx241,2
CMP [dp],Y
D7DP Indirect Long Indexed, Yx261,2
CMP addr,Y
D9Absolute Indexed,Yxxx341,3
CMP addr,X
DDAbsolute Indexed,Xxxx341,3
CMP long,X
DFAbsolute Long Indexed,Xx451
COP Co-Processor Enable [Flags affected: d,i]
COP const
02Stack/Interrupt x218 79
CPX Compare Index Register X with Memory [Flags affected: n,z,c]
CPX #const
E0Immediate xxx219 210
CPX dp
E4Direct Page xxx2 32,10
CPX addr
ECAbsolute xxx3 410
CPY Compare Index Register Y with Memory [Flags affected: n,z,c]
CPY #const
C0Immediate xxx219 210
CPY dp
C4Direct Page xxx2 32,10
CPY addr
CCAbsolute xxx3 410
DEC Decrement [Flags affected: n,z]
DEC A
3AAccumulator xx1 2
DEC dp
C6Direct Page xxx2 52,5
DEC addr
CEAbsolute xxx3 65
DEC dp,X
D6DP Indexed,X xxx2 62,5
DEC addr,X
DEAbsolute Indexed,X xxx3 75,6
DEX Decrement Index Register X [Flags affected: n,z]
DEX
CAImplied xxx1 2
DEY Decrement Index Register Y [Flags affected: n,z]
DEY
88Implied xxx1 2
EOR Exclusive-OR Accumulator with Memory [Flags affected: n,z]
EOR (dp,X)
41DP Indexed Indirect,Xxxx261,2
EOR sr,S
43Stack Relative x241
EOR dp
45Direct Page xxx231,2
EOR [dp]
47DP Indirect Longx261,2
EOR #const
49Immediatexxx21721
EOR addr
4DAbsolutexxx341
EOR long
4FAbsolute Longx451
EOR (dp),Y
51DP Indirect Indexed, Yxxx251,2,3
EOR (dp)
52DP Indirectxx251,2
EOR (sr,S),Y
53SR Indirect Indexed,Yx271
EOR dp,X
55DP Indexed,Xxxx241,2
EOR [dp],Y
57DP Indirect Long Indexed, Yx261,2
EOR addr,Y
59Absolute Indexed,Yxxx341,3
EOR addr,X
5DAbsolute Indexed,Xxxx341,3
EOR long,X
5FAbsolute Long Indexed,Xx451
INC Increment [Flags affected: n,z]
INC A
1AAccumulatorxx12
INC dp
E6Direct Pagexxx252,5
INC addr
EEAbsolutexxx365
INC dp,X
F6DP Indexed,Xxxx262,5
INC addr,X
FEAbsolute Indexed,Xxxx375,6
INX Increment Index Register X [Flags affected: n,z]
INX
E8Impliedxxx12
INY Increment Index Register Y [Flags affected: n,z]
INY
C8Impliedxxx12
JMP Jump [Flags affected: none][Alias: JML for all Long addressing modes]
JMP addr
4CAbsolutexxx33
JMP long
5CAbsolute Longx44
JMP (addr)
6CAbsolute Indirectxxx3511,12
JMP (addr,X)
7CAbsolute Indexed Indirectxx36
JMP [addr]
DCAbsolute Indirect Longx36
JSR Jump to Subroutine [Flags affected: none][Alias: JSL for Absolute Long]
JSR addr
20Absolutexxx36
JSR long
22Absolute Longx48
JSR (addr,X))
FCAbsolute Indexed Indirectx38
LDA Load Accumulator from Memory [Flags affected: n,z]
LDA (dp,X)
A1DP Indexed Indirect,Xxxx261,2
LDA sr,S
A3Stack Relative x241
LDA dp
A5Direct Page xxx231,2
LDA [dp]
A7DP Indirect Longx261,2
LDA #const
A9Immediatexxx21721
LDA addr
ADAbsolutexxx341
LDA long
AFAbsolute Longx451
LDA (dp),Y
B1DP Indirect Indexed, Yxxx251,2,3
LDA (dp)
B2DP Indirectxx251,2
LDA (sr,S),Y
B3SR Indirect Indexed,Yx271
LDA dp,X
B5DP Indexed,Xxxx241,2
LDA [dp],Y
B7DP Indirect Long Indexed, Yx261,2
LDA addr,Y
B9Absolute Indexed,Yxxx341,3
LDA addr,X
BDAbsolute Indexed,Xxxx341,3
LDA long,X
BFAbsolute Long Indexed,Xx451
LDX Load Index Register X from Memory [Flags affected: n,z]
LDX #const
A2Immediatexxx2 19 210
LDX dp
A6Direct Pagexxx232,10
LDX addr
AEAbsolutexxx3410
LDX dp,Y
B6DP Indexed,Yxxx242,10
LDX addr,Y
BEAbsolute Indexed,Yxxx343,10
LDY Load Index Register Y from Memory [Flags affected: n,z]
LDY #const
A0Immediatexxx2 19 210
LDY dp
A4Direct Pagexxx232,10
LDY addr
ACAbsolutexxx3410
LDY dp,X
B4DP Indexed,Xxxx242,10
LDY addr,X
BCAbsolute Indexed,Xxxx343,10
LSR Logical Shift Memory or Accumulator Right [Flags affected: n,z,c]
LSR dp
46Direct Pagexxx2 52,5
LSR A
4AAccumulatorxxx12
LSR addr
4EAbsolutexxx365
LSR dp,X
56DP Indexed,Xxxx262,5
LSR addr,X
5EAbsolute Indexed,Xxxx375,6
MVN Block Move Negative [Flags affected: none][Registers: X,Y,C]
MVN srcbk,destbk
54Block Movex3 13
MVP Block Move Positive [Flags affected: none][Registers: X,Y,C]
MVN srcbk,destbk
44Block Movex3 13
NOP No Operation [Flags affected: none]
NOP
EAImpliedxxx1 2
ORA OR Accumulator with Memory [Flags affected: n,z]
ORA (dp,X)
01DP Indexed Indirect,Xxxx261,2
ORA sr,S
03Stack Relative x241
ORA dp
05Direct Page xxx231,2
ORA [dp]
07DP Indirect Longx261,2
ORA #const
09Immediatexxx21721
ORA addr
0DAbsolutexxx341
ORA long
0FAbsolute Longx451
ORA (dp),Y
11DP Indirect Indexed, Yxxx251,2,3
ORA (dp)
12DP Indirectxx251,2
ORA (sr,S),Y
13SR Indirect Indexed,Yx271
ORA dp,X
15DP Indexed,Xxxx241,2
ORA [dp],Y
17DP Indirect Long Indexed, Yx261,2
ORA addr,Y
19Absolute Indexed,Yxxx341,3
ORA addr,X
1DAbsolute Indexed,Xxxx341,3
ORA long,X
1FAbsolute Long Indexed,Xx451
PEA Push Effective Absolute Address [Flags affected: none]
PEA addr
F4Stack (Absolute) x35
PEI Push Effective Indirect Address [Flags affected: none]
PEI (dp)
D4Stack (DP Indirect) x262
PER Push Effective PC Relative Indirect Address [Flags affected: none]
PER label
62Stack (PC Relative Long) x36
PHA Push Accumulator [Flags affected: none]
PHA
48Stack (Push) xxx131
PHB Push Data Bank Register [Flags affected: none]
PHB
8BStack (Push) x13
PHD Push Direct Page Register [Flags affected: none]
PHD
0BStack (Push) x14
PHK Push Program Bank Register [Flags affected: none]
PHK
4BStack (Push) x13
PHP Push Processor Status Register [Flags affected: none]
PHP
08Stack (Push) xxx13
PHX Push Index Register X [Flags affected: none]
PHX
DAStack (Push) xx1310
PHY Push Index Register Y [Flags affected: none]
PHY
5AStack (Push) xx1310
PLA Pull Accumulator [Flags affected: n,z]
PLA
68Stack (Pull) xxx141
PLB Pull Data Bank Register [Flags affected: n,z]
PLB
ABStack (Pull) x14
PLD Pull Direct Page Register [Flags affected: n,z]
PLD
2BStack (Pull) x15
PLP Pull Processor Status Register [Flags affected: n,z]
PLP
28Stack (Pull) xxx14
PLX Pull Index Register X [Flags affected: n,z]
PLX
FAStack (Pull) xx1410
PLY Pull Index Register Y [Flags affected: n,z]
PLY
7AStack (Pull) xx1410
REP Reset Processor Status Bits [Flags affected: all except b per operand]
REP #const
C2Immediate x23
ROL Rotate Memory or Accumulator Left [Flags affected: n,z,c]
ROL dp
26Direct Pagexxx2 52,5
ROL A
2AAccumulatorxxx12
ROL addr
2EAbsolutexxx365
ROL dp,X
36DP Indexed,Xxxx262,5
ROL addr,X
3EAbsolute Indexed,Xxxx375,6
ROR Rotate Memory or Accumulator Right [Flags affected: n,z,c]
ROR dp
66Direct Pagexxx2 52,5
ROR A
6AAccumulatorxxx12
ROR addr
6EAbsolutexxx365
ROR dp,X
76DP Indexed,Xxxx262,5
ROR addr,X
7EAbsolute Indexed,Xxxx375,6
RTI Return from Interrupt [Flags affected: all except b]
RTI
40Stack (RTI) xxx169
RTL Return from Subroutine Long [Flags affected: none]
RTL
6BStack (RTL) x16
RTS Return from Subroutine [Flags affected: none]
RTS
60Stack (RTS) xxx16
SBC Subtract with Borrow from Accumulator [Flags affected: n,v,z,c]
SBC (dp,X)
E1DP Indexed Indirect,Xxxx261,2,4
SBC sr,S
E3Stack Relative x241,4
SBC dp
E5Direct Page xxx231,2,4
SBC [dp]
E7DP Indirect Longx261,2,4
SBC #const
E9Immediatexxx21721,4
SBC addr
EDAbsolutexxx341,4
SBC long
EFAbsolute Longx451,4
SBC (dp),Y
F1DP Indirect Indexed, Yxxx251,2,3,4
SBC (dp)
F2DP Indirectxx251,2,4
SBC (sr,S),Y
F3SR Indirect Indexed,Yx271,4
SBC dp,X
F5DP Indexed,Xxxx241,2,4
SBC [dp],Y
F7DP Indirect Long Indexed, Yx261,2,4
SBC addr,Y
F9Absolute Indexed,Yxxx341,3,4
SBC addr,X
FDAbsolute Indexed,Xxxx341,3,4
SBC long,X
FFAbsolute Long Indexed,Xx451,4
SEC Set Carry Flag [Flags affected: c]
SEC
38Implied xxx12
SED Set Decimal Flag [Flags affected: d]
SED
F8Implied xxx12
SEI Set Interrupt Disable Flag [Flags affected: i]
SEI
78Implied xxx12
SEP Set Processor Status Bits [Flags affected: all except b per operand]
SEP
E2Immediate x23
STA Store Accumulator to Memory [Flags affected: none]
STA (dp,X)
81DP Indexed Indirect,Xxxx261,2
STA sr,S
83Stack Relative x241
STA dp
85Direct Page xxx231,2
STA [dp]
87DP Indirect Longx261,2
STA addr
8DAbsolutexxx341
STA long
8FAbsolute Longx451
STA (dp),Y
91DP Indirect Indexed, Yxxx261,2
STA (dp)
92DP Indirectxx251,2
STA (sr,S),Y
93SR Indirect Indexed,Yx271
STA dpX
95DP Indexed,Xxxx241,2
STA [dp],Y
97DP Indirect Long Indexed, Yx261,2
STA addr,Y
99Absolute Indexed,Yxxx351
STA addr,X
9DAbsolute Indexed,Xxxx351
STA long,X
9FAbsolute Long Indexed,Xx451
STP Stop Processor [Flags affected: none]
STP
DBImplied x1314
STX Store Index Register X to Memory [Flags affected: none]
STX dp
86Direct Page xxx232,10
STX addr
8EAbsolute xxx3410
STX dp,Y
96DP Indexed,Y xxx242,10
STY Store Index Register Y to Memory [Flags affected: none]
STY dp
84Direct Page xxx232,10
STY addr
8CAbsolute xxx3410
STY dp,X
94DP Indexed,X xxx242,10
STZ Store Zero to Memory [Flags affected: none]
STZ dp
64Direct Page xx231,2
STZ dp,X
74DP Indexed,X xx241,2
STZ addr
9CAbsolute xx341
STZ addr,X
9EAbsolute Indexed,X xx351
TAX Transfer Accumulator to Index Register X [Flags affected: n,z]
TAX
AAImplied xxx12
TAY Transfer Accumulator to Index Register Y [Flags affected: n,z]
TAY
A8Implied xxx12
TCD Transfer 16-bit Accumulator to Direct Page Register [Flags affected: n,z]
TCD
5BImplied x12
TCS Transfer 16-bit Accumulator to Stack Pointer [Flags affected: none]
TCS
1BImplied x12
TDC Transfer Direct Page Register to 16-bit Accumulator [Flags affected: n,z]
TDC
7BImplied x12
TRB Test and Reset Memory Bits Against Accumulator [Flags affected: z]
TRB dp
14Direct Page xx252,5
TRB addr
1CAbsolute xx363
TSB Test and Set Memory Bits Against Accumulator [Flags affected: z]
TSB dp
04Direct Page xx252,5
TSB addr
0CAbsolute xx365
TSC Transfer Stack Pointer to 16-bit Accumulator [Flags affected: n,z]
TSC
3BImplied x12
TSX Transfer Stack Pointer to Index Register X [Flags affected: n,z]
TSX
BAImplied xxx12
TXA Transfer Index Register X to Accumulator [Flags affected: n,z]
TXA
8AImplied xxx12
TXS Transfer Index Register X to Stack Pointer [Flags affected: none]
TXS
9AImplied xxx12
TXY Transfer Index Register X to Index Register Y [Flags affected: n,z]
TXY
9BImplied x12
TYA Transfer Index Register Y to Accumulator [Flags affected: n,z]
TYA
98Implied xxx12
TYX Transfer Index Register Y to Index Register X [Flags affected: n,z]
TYX
BBImplied x12
WAI Wait for Interrupt [Flags affected: none]
WAI
CBImplied x1315
WDM Reserved for Future Expansion [Flags affected: none (subject to change)]
WDM
42n/a x2 16 n/a16
XBA Exchange B and A 8-bit Accumulators [Flags affected: n,z]
XBA
EBImplied x13
XCE Exchange Carry and Emulation Flags [Flags affected: m,b/x,c,e]
XCE
FBImplied x12

NOTES

1 Add 1 cycle if m=0 (16-bit memory/accumulator)
2 Add 1 cycle if low byte of Direct Page Register is non-zero
3 Add 1 cycle if adding index crosses a page boundary
4 Add 1 cycle if 65C02 and d=1 (65C02 in decimal mode)
5 Add 2 cycles if m=0 (16-bit memory/accumulator)
6 Subtract 1 cycle if 65C02 and no page boundary crossed
7 Add 1 cycle if branch is taken
8 Add 1 cycle if branch taken crosses page boundary on 6502, 65C02, or 65816's 6502 emulation mode (e=1)
9 Add 1 cycle for 65816 native mode (e=0)
10 Add 1 cycle if x=0 (16-bit index registers)
11 Add 1 cycle if 65C02
12 6502: Yields incorrect results if low byte of operand is $FF (i.e., operand is $xxFF)
13 7 cycles per byte moved
14 Uses 3 cycles to shut the processor down: additional cycles are required by reset to restart it
15 Uses 3 cycles to shut the processor down: additional cycles are required by interrupt to restart it
16 Byte and cycle counts subject to change in future processors which expand WDM into 2-byte opcode portions of instructions of varying lengths
17 Add 1 byte if m=0 (16-bit memory/accumulator)
18 Opcode is 1 byte, but program counter value pushed onto stack is incremented by 2 allowing for optional signature byte
19 Add 1 byte if x=0 (16-bit index registers)

Copyright © 1996 Creative Micro Designs, Inc.
Reprinted with permission from Commodore World magazine, Issue #16.