6502 Instruction Set author Neil Franklin, last modification 2008.05.16 Basics: ------- All numbers and bit patterns in this file are usually given in hex, seldom in binary, never in decimal or octal. Sources for this data: ---------------------- 1. List of instruction mnemonics and opcodes and byte lengths (but no flags), in format like "by opcode number" table below, assembled manually from data in an 6502 programming book borrowed from an library sometime mid 1980s. Used that for programming Commodore 64 (second computer I owned, third I programmed) for years, so it can be assumed to be correct. 2. Page condensing above list and adding reconstruction of flags from memory, in format like "instruction code grid" table below. Used that when writing an 6502 emulator, which was capable of running an existing 16k 6502 program, so it can also be assumed to be correct. (BTW: This file started its life as an attempt to digitalise that page, and snowballed after that, including adding all the other processors instruction set files) 3. Source code of above mentioned 6502 emulator, available at: http://neil.franklin.ch/Projects/Soft64/ in particular the actual CPU at: http://neil.franklin.ch/Projects/Soft64/Soft64View.m in mpu_64us(). Of course errors of my own are to be expected. Registers: ---------- (in order: data, address, pc, flags) A 8bit Accumulator X Y 8bit Index Registers (00,XX or 00,YY merged as high,low addr) S 8bit Stack Pointer (01,SS merged as high,low address) (push post-decr(!), pull pre-incr(!)) PC 16bit Program Counter PSR 8bit Processor Status Register (= flags) Processor Status Register, Flags: --------------------------------- (in order: from MSB/7 to LSB/0) N Negative (result bit7 set) V oVerflow (arithmetic result carry bit6->bit7) 1 allways 1 B Break (1 after BRK, 0 after IRQ) D Decimal mode (1 makes ADC/SBC decimal, 0 leaves them binary) I Interupt disable (1 disables IRQ) Z Zero (result all bits cleared) C Carry (arithmetic result carry bit7->"bit8") General policy seems to be: - arithmetic: set all NVZC (except compares only NZC) - decrement/increment: set NZ, leave VC unchanged, so address inc/dec leaves VC - logic stuff and load: set NZ (except bit test special V behaviour (bit6)) - store: leave all flags (exept TXA and TYA which pretend to be loads) - shift/rotate: set NZC - jump/branch/call/return: leave all flags unchanged Memory: ------- Program+Data memory 64k*8bit (16bit address space) (I/O uses part of above, memory mapped I/O (section of address space)) Addressing Modes, in Assembler Syntax: -------------------------------------- (in order: reg, immediate, address, reg indirect, reg indexed, pc, mem indir) A accumulator #ii immediate8 (2 hex digits) ss short-direct8 (in zero page, gives 00ss) (2 hex digits) hhll long-direct16 (absolute) (4 hex digits) -nameless- stack pointer indirect decrement/increment (only PH*/PL* instr) ss,X ss,Y short8 + index register (2 hex digits) (ss,Y only for LDX/STX) hhll,X hhll,Y long16 + index register (4 hex digits) nn PC + offset8 (-128..+127) (only B* instr) (hhll) long16 indirect (only JMP () instr) (4 hex digits) (ss,X) short8 + X register preindex, then indirect (2 hex digits) (ss),Y short8 indirect, then + Y register postindex (2 hex digits) Instruction Formats, in Machine Code Bytes: ------------------------------------------- (in order: simple, immediate, memory, jump, conditional) oo opcode8 ooii opcode8 immediate8 ooss opcode8 address8 oollhh opcode8 address-low8 address-high8 (= little endian) ocnn opcode5+condition3 offset8 (only B* instr) Instruction Bit Patterns and Operations: ---------------------------------------- (in order: functional grouping: arithmetic, data transfer, jumps, auxillary) arithmetic/logic and load/store A ooommm01 ooo..... opcode operation 000..... ORA A = A bitwise-OR mem[address]; FlagsNZ "OR Accumulator" 001..... AND A = A bitwise-AND mem[address]; FlagsNZ "AND" 010..... EOR A = A bitwise-excl-OR mem[address]; FlagsNZ "Exclusice OR" 011..... ADC A = A + mem[address] + FlagC; FlagsNVZC "ADd with Carry" 100..... STA mem[address] = A "STore Accumulator" 101..... LDA A = mem[address]; FlagsNZ "LoaD Accumulator" 110..... CMP FlagsNZC = A - mem[address] "CoMPare" 111..... SBC A = A - mem[address] - FlagC; FlagsNVZC "SuBtract w Carry" ...mmm.. mode address ...000.. (ss,X) mem[mem[PC+]+X] (address8 zeropage +preindex, indirect16) (next to useless, (ss),X or (ss,S) would be better) ...001.. ss mem[PC+] (address8 zeropage) ...010.. #ii PC+ (immediate8) (not combinable with STA, modifying immed is senseless) ...011.. hhll mem[PC++] (address16 absolute) ...100.. (ss),Y mem[mem[PC+]]+Y (address8 zeropage, indirec16 +postindex) ...101.. ss,X mem[PC+]+X (address8 zeropage +index) ...110.. hhll,X mem[PC++]+X (address16 absolute +index) ...111.. hhll,Y mem[PC++]+Y (address16 absolute +index) shift/rotate and load/store X and increment/decrement memory ooommm10 ooo..... opcode operation 000..... ASL FlagC,mem[address] = mem[address],0; FlagsNZ "Arithmetic Shift Left" 001..... ROL FlagC,mem[address] = mem[address],FlagC; FlagsNZ "ROtate Left" 010..... LSR mem[address],FlagC = 0,mem[address]; FlagsNZ "Logical Shift Right" 011..... ROR mem[address],FlagC = FlagC,mem[address]; FlagsNZ "ROtate Right" 100..... STX mem[address] = X; -none- (is a store) "STore X register" = TXA A = X (= STX A); FlagsNZ (despite store!) "Transfer X register to Accumulator" = TXS S = X (= STX S); -none- (despite TXA!) "Transfer Stack pointer to Accumulator" 101..... LDX X = mem[address]; FlagsNZ "LoaD X register" = TAX X = A (= LDX A); FlagsNZ "Transfer Accumulator to X register" = TSX X = S (= LDY S); FlagsNZ "Transfer Accumulator to Stack pointer" 110..... DEC mem[address] = mem[address] - 1; FlagsNZ(noC!) "DECrement" 111..... INC mem[address] = mem[address] + 1; FlagsNZ(noC!) "INCrement" ...mmm.. mode address ...000.. #ii PC+ (immediate8) (only for LDX, modifying immediate is senseless) ...001.. ss mem[PC+] (address8 zeropage) ...010.. A A instead of mem[address] (not for DEC (DEX is there!) and INC (NOP is there!)) ...011.. hhll mem[PC++] (address16 absolute) ...101.. ss,X mem[PC+]+X (address8 zeropage +index) (for STX/LDX changed to ss,Y to be more usefull) ...110.. S S instead of mem[address] (only for TXS and TSX) ...111.. hhll,X mem[PC++]+X (address16 absolute +index) (for LDX changed to hhll,X to be more usefull) (but not for STX, is missing entirely, why?) bit test and load/store Y and compare X/Y ooommm00 ooo..... opcode operation 001..... BIT FlagsNV = A bitwise-AND mem[address]; FlagV=bit6(second-N) "BIt Test" 100..... STY mem[address] = Y "STore Y register" = TYA A = Y (= STY A); FlagsNZ (despite store!) "Transfer Y register to Accumulator" 101..... LDY Y = mem[address]; FlagsNZ "LoaD Y register" = TAY Y = A (= LDY A); FlagsNZ "Transfer Accumulator to Y register" 110..... CPY FlagsNZC = Y - mem[address] "ComPare Y register" 111..... CPX FlagsNZC = X - mem[address] "ComPare X register" ...mmm.. mode address (subset of shift/rotate) ...000.. #ii PC+ (immediate8) (not combinable with STY, modifying immed is senseless) (not combinable with BIT, testing const is senseless) ...001.. ss mem[PC+] (address8 zeropage) ...010.. A A instead of mem[address] (only for TAY, not for TYA (DEY is there!)) ...011.. hhll mem[PC++] (address16 absolute) ...101.. ss,X mem[PC+]+X (address8 zeropage +index) (not for BIT, CPY and CPX, are missing, why?) ...110.. A A instead of mem[address] (only for TYA (opcode would be SEV!)) ...111.. hhll,X mem[PC++]+X (address16 absolute +index) (not for BIT, STY and CPY and CPX, are missing, why?) increment/decrement X/Y ooo010o0 ooo...o. opcode operation 100...0. DEY Y = Y - 1; FlagsNZ(noC!) (opcode would be STY A!) "DEcrement Y register" 110...0. INY Y = Y + 1; FlagsNZ(noC!) (opcode would be CPY A!) "INcrement Y register" 110...1. DEX X = X - 1; FlagsNZ(noC!) (opcode would be DEC A!) "DEcrement X register" 111...0. INX X = X + 1; FlagsNZ(noC!) (opcode would be CPX A!) "INcrement X register" stack push/pull 0oo01000 .oo..... opcode operation (push post-decr(!), pull pre-incr(!)) .00..... PHP mem[01,SS-] = PSR "PusH Processor status register" .01..... PLP PSR = mem[01,+SS] "PulL Processor status register" .10..... PHA mem[01,SS-] = A "PusH Accumulator" .11..... PLA A = mem[01,+SS]; FlagsNZ "PulL Accumulator" jumps/subroutines and reset/interrupts oooooooo opcode operation 00000000 BRK mem[01,SS---] = PC,PSR; FlagB=1; FlagI=1 PC = mem[FFFE/FFFF] (as IRQ, just FlagB=1) "BReaK" 00100000 JSR hhll mem[01,SS--] = PC-1; PC = mem[PC++] (address16) "Jump SubRoutine" 01000000 RTI PSR,PC = mem[01,+++SS] "ReTurn from Interrupt" 01001100 JMP hhll PC = mem[PC++] (address16) "JuMP" 01100000 RTS PC = mem[01,++SS]+1 "ReTurn from Subroutine" 01101100 JMP (hhll) PC = mem[mem[PC++]] (address16, indirect16) "JuMP" if [mem[PC++] is hhFF, then the indirect addresses hh part comes from hh00, not (hh+1)00, this is a bug in the processor, it forgets to take over the carry 11101010 NOP do nothing (opcode would be INC A!) "No OPeration" ---- pin RESET FlagI=1; PC = mem[FFFC/FFFD] "RESET" ---- pin NMI mem[01,SS---] = PC,PSR; FlagI=1 PC = mem[FFFA/FFFB] "Non Maskable Interrupt" ---- pin IRQ mem[01,SS---] = PC,PSR; FlagB=0; FlagI=1 PC = mem[FFFE/FFFF] (as BRK, just FlagB=0) "Interrupt ReQuest" ---- pin SEV FlagV=1 (for spinloop CLV; BVC -2) "SEt V flag" branches/conditionals cccooooo opcode operation ...ooooo ...10000 Bcc nn if condition then PC = PC+mem[PC+] (offset8) "Branch cc" ccc..... cc condition 000..... PL N = 0 "PLus" 001..... MI N = 1 "MInus" 010..... VC V = 0 "oVerflow Clear" 011..... VS V = 1 "oVerflow Set" 100..... CC C = 0 "Carry Clear" 101..... CS C = 1 "Carry Set" 110..... NE Z = 0 "Not Equal" 111..... EQ Z = 1 "Equal" flags ffo11000 ff...... f flag 00...... C Carry 01...... I Interrupt 10...... V oVerflow 11...... D Decimal1 ..o..... opcode operation ..0..... CLf Flagf = 0 (not for CLV, TYA is there!) "CLear flag" ..1..... SEf Flagf = 1 (for CLV, FlagV=0, no SEV!) "SEt flag" Instruction Code List: ---------------------- (full machine code bytes, in order: opcode number) 00 BRK 10nn BPL nn 20llhh JSR hhll 30nn BMI nn 01ss ORA (ss,X) 11ss ORA (ss),Y 21ss AND (ss,X) 31ss AND (ss),Y -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - 24ss BIT ss -- - 05ss ORA ss 15ss ORA ss,X 25ss AND ss 35ss AND ss,X 06ss ASL ss 16ss ASL ss,X 26ss ROL ss 36ss ROL ss,X -- -- -- - -- - -- - 08 PHP 18 CLC 28 PLP 38 SEC 09ii ORA #ii 19llhh ORA hhll,Y 29ii AND #ii 39llhh AND hhll,Y 0A ASL A -- - 2A ROL A -- - -- - -- - -- - -- - -- - -- - 2Cllhh BIT hhll -- - 0Dllhh ORA hhll 1Dllhh ORA hhll,X 2Dllhh AND hhll 3Dllhh AND hhll,X 0Ellhh ASL hhll 1Ellhh ASL hhll,X 2Ellhh ROL hhll 3Ellhh ROL hhll,X -- - -- - -- - -- - 02|12|22|32: these 4 unused codes are said to crash the processor even reset will not work, needs to be power off/on to restart 40 RTI 50nn BVC nn 60 RTS 70nn BVS nn 41ss EOR (ss,X) 51ss EOR (ss),Y 61ss ADC (ss,X) 71ss ADC (ss),Y -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - 45ss EOR ss 55ss EOR ss,X 65ss ADC ss 75ss ADC ss,X 46ss LSR ss 56ss LSR ss,X 66ss ROR ss 76ss ROR ss,X -- - -- - -- - -- - 48 PHA 58 CLI 68 PLA 78 SEI 49ii EOR #ii 59llhh EOR hhll,Y 69ii ADC #ii 79llhh ADC hhll,Y 4A LSR A -- - 6A ROR A -- - -- -- - -- - -- - 4Cllhh JMP hhll -- - 6Cllhh JMP (hhll) -- - 4Dllhh EOR hhll 5Dllhh EOR hhll,X 6Dllhh ADC hhll 7Dllhh ADC hhll,X 4Ellhh LSR hhll 5Ellhh LSR hhll,X 6Ellhh ROR hhll 7Ellhh ROR hhll,X -- - -- - -- - -- - 6C: if instr is 6CFFhh then the indirect addr hh comes from hh00, not (hh+1)00 this is a bug in the processor, it forgets to take over the carry -- - 90nn BCC nn A0ii LDY #ii B0nn BCS nn 81ss STA (ss,X) 91ss STA (ss),Y A1ss LDA (ss,X) B1ss LDA (ss),Y -- - -- - A2ii LDX #ii -- - -- - -- - -- - -- - 84ss STY ss 94ss STY ss,X A4ss LDY ss B4ss LDY ss,X 85ss STA ss 95ss STA ss,X A5ss LDA ss B5ss LDA ss,X 86ss STX ss 96ss STX ss,Y A6ss LDX ss B6ss LDX ss,Y -- - -- - -- - -- - 88 DEY 98 TYA A8 TAY B8 CLV -- - 99llhh STA hhll,Y A9ii LDA #ii B9llhh LDA hhll,Y 8A TXA 9A TXS AA TAX BA TSX -- - -- - -- - -- - 8Cllhh STY hhll -- - ACllhh LDY hhll BCllhh LDY hhll,X 8Dllhh STA hhll 9Dllhh STA hhll,X ADllhh LDA hhll BDllhh LDA hhll,X 8Ellhh STX hhll -- - AEllhh LDX hhll BEllhh LDX hhll,Y -- - -- - -- - -- - 88: would be STY A , but used for DEY 89: would be STA #ii , but modifying immediate senseless, so this is no opcode 96: would be STX ss,X , but changed to STX ss,Y to be more usefull 9E: would be STX hhll,X , fairly useless, no opcode, better do ,Y like 96|B6|BE B6: would be LDX ss,X , but changed to LDX ss,Y to be more usefull BE: would be LDX hhll,X , but changed to LDX hhll,Y to be more usefull C0ii CPY #ii D0nn BNE nn E0ii CPX #ii F0nn BEQ nn C1ss CMP (ss,X) D1ss CMP (ss),Y E1ss SBC (ss,X) F1ss SBC (ss),Y -- - -- - -- - -- - -- - -- - -- - -- - C4ss CPY ss -- - E4ss CPX ss -- - C5ss CMP ss D5ss CMP ss,X E5ss SBC ss F5ss SBC ss,X C6ss DEC ss D6ss DEC ss,X E6ss INC ss F6ss INC ss,X -- - -- - -- - -- - C8 INY D8 CLD E8 INX F8 SED C9ii CMP #ii D9llhh CMP hhll,Y E9ii SBC #ii F9llhh SBC hhll,Y CA DEX -- - EA NOP -- - -- - -- - -- - -- - CCllhh CPY hhll -- - ECllhh CPX hhll -- - CDllhh CMP hhll DDllhh CMP hhll,X EDllhh SBC hhll FDllhh SBC hhll,X CEllhh DEC hhll DEllhh DEC hhll,X EEllhh INC hhll FEllhh INC hhll,X -- - -- - -- - -- - C8: would be CPY A ; but used for INY CA: would be DEC A ; but used for DEX E8: would be CPX A ; but used for INX Instruction Code Table: ----------------------- (only opcodes, in order: ver: bit0..1/7..5, hor: bit4..2) + 00 04 08 0C 10 14 18 1C 00 BRK - PHP - BPL - CLC - 20 JSR BIT PLP BIT BMI - SEC - 40 RTI - PHA JMP BVC - CLI - 60 RTS - PLA JMP () BVS - SEI - 80 - STY DEY STY BCC STY ,X TYA - A0 LDY # LDY TAY LDY BCS LDY ,X CLV LDY C0 CPY # CPY INY CPY BNE - CLD - E0 CPX # CPX INX CPX BEQ - SED - 01 ORA (,X) ORA ORA # ORA ORA (),Y ORA ,X ORA ,Y ORA ,X 21 AND (,X) AND AND # AND AND (),Y AND ,X AND ,Y AND ,X 41 EOR (,X) EOR EOR # EOR EOR (),Y EOR ,X EOR ,Y EOR ,X 61 ADC (,X) ADC ADC # ADC ADC (),Y ADC ,X ADC ,Y ADC ,X 81 STA (,X) STA STA # STA STA (),Y STA ,X STA ,Y STA ,X A1 LDA (,X) LDA LDA # LDA LDA (),Y LDA ,X LDA ,Y LDA ,X C1 CMP (,X) CMP CMP # CMP CMP (),Y CMP ,X CMP ,Y CMP ,X E1 SBC (,X) SBC SBC # SBC SBC (),Y SBC ,X SBC ,Y SBC ,X 02 - ASL ASL A ASL - ASL ,X - ASL ,X 22 - ROL ROL A ROL - ROL ,X - ROL ,X 42 - LSR LSR A LSR - LSR ,X - LSR ,X 62 - ROR ROR A ROR - ROR ,X - ROR ,X 82 - STX TXA STX - STX ,Y TXS - A2 LDX # LDX TAX LDX - LDX ,Y TSX LDX ,Y C2 - DEC DEX DEC - DEC ,X - DEC ,X E2 - INC NOP INC - INC ,X - INC ,X