EightBit/M6502/documentation/undocumented_opcodes.txt
Adrian Conlon ffb945a46d Add some documentation (!) for undocumented 6502 instructions.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
2018-01-07 23:48:27 +00:00

433 lines
12 KiB
Plaintext

6502 Undocumented Opcodes
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
Based on the Atari 8-bit 6502
Version 3.0, 5/17/1997
By Freddy Offenga (offen300@hio.tem.nhl.nl)
This version is a direct follow up of the illegal opcode list by Joakim
Atterhal (WosFilm) and me which was published in the Atari 8-bit disk
magazine "Mega Maga-zine" issue #6. Most opcode names in this list
originated from a disassembler for the Atari (The Symbolic
Disas-sem-bler by HiasSoft).
Credits:
- Joakim Atterhal
- Adam Vardy
- Craig Taylor
References:
1. Illegal opcodes, WosFilm and Frankenstein,
Mega Magazine #2, December 1991
2. Illegal opcodes v2, WosFilm and Fran-ken-stein,
Mega Maga-zine #6, October 1993
3. Illegal Opcodes der 65xx-CPU, Frank Leiprecht,
ABBUC Sondermagazin 10, Top-Maga-zin Oktober 1991
4. Erg=E4nzung zu den Illegalen OP-Codes, Peter W=F6tzel,
Top-M-ag-azin Januar 1992.
5. 6502 Opcodes and Quasi-Opcodes, Craig Taylor, 1992
6. Extra Instructions Of The 65XX Series CPU, Adam Vardy,
27 Sept. 1996
Changes since Version 2.0:
Version 2.0 was compared with two Commodore 8-bit based lists found on
the inter-net. There were some diffe-rences in opcode names, so I
included the other names too. Names between curly brackets are the names
taken from the list compiled by Craig Taylor. Names between square
brackets are the names taken from the list by Adam Vardy.
The old list was also compared with two other Atari 8-bit based lists
(by Frank Leiprecht and Peter W=F6tzel). No new things were found on thes=
e
lists.
The timing values (clock cycles) from all the opcodes were compared with
the values on the list by Adam Vardy. There were no differen-ces.
The addressing modes for the "DOP" (double nop) and "TOP" instructions
were copied from Craig Taylor's list. The reason for this is that the
different addressing modes explain the differences in the timing values.
Opcode $8B was removed from the "AAX" table. The behaviour of this
opcode seems to be comlex (as noted by several peop-le). Maybe there
will be more information in the next version of this document. For now
this opcode is called "XAA".
The addressing mode for opcode $A3 (LAX) was false on the previous list.
Changed to (indi-rect,x).
The addressing modes for opcodes $13 and $03 (SLO) were swit-ched.
Corrected in this version.
Addressing mode for opcode $B7 (LAX) was "zero-page,x", but should be
"zero-page,y". Corrected.
Changed the suspicious opcode $93. This one was called "DOP", but is in
fact another "AXA" instruction.
Tested the behaviour of $9E (SXA), $9C (SYA) and $9B (XAS). There static
AND with 7 mentioned in the old list was false. The observation of the
function 'AND with the high byte of the argument + 1' (from Adam Vardy's
list) seems to be correct.
Opc : opcode in hexadecimal
Sz : size in bytes
n : number of clock cycles
* : add one cycle when page boundary is crossed
AAC (ANC) [ANC]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND byte with accumulator. If result is negative then carry is set.
Status flags: N,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Immediate |AAC #arg |$0B| 2 | 2
Immediate |AAC #arg |$2B| 2 | 2
AAX (SAX) [AXS]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND X register with accumulator and store result in memory. Status
flags: N,Z
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |AAX arg |$87| 2 | 3
Zero Page,Y |AAX arg,Y |$97| 2 | 4
(Indirect,X)|AAX (arg,X)|$83| 2 | 6
Absolute |AAX arg |$8F| 3 | 4
ARR (ARR) [ARR]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND byte with accumulator, then rotate one bit right in accu-mulator and
check bit 5 and 6:
If both bits are 1: set C, clear V.
If both bits are 0: clear C and V.
If only bit 5 is 1: set V, clear C.
If only bit 6 is 1: set C and V.
Status flags: N,V,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Immediate |ARR #arg |$6B| 2 | 2
ASR (ASR) [ALR]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND byte with accumulator, then shift right one bit in accumu-lator.
Status flags: N,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Immediate |ASR #arg |$4B| 2 | 2
ATX (LXA) [OAL]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND byte with accumulator, then transfer accumulator to X register.
Status flags: N,Z
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Immediate |ATX #arg |$AB| 2 | 2
AXA (SHA) [AXA]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND X register with accumulator then AND result with 7 and store in
memory. Status flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Absolute,Y |AXA arg,Y |$9F| 3 | 5
(Indirect),Y|AXA arg |$93| 2 | 6
AXS (SBX) [SAX]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND X register with accumulator and store result in X regis-ter, then
subtract byte from X register (without borrow).
Status flags: N,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Immediate |AXS #arg |$CB| 2 | 2
DCP (DCP) [DCM]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Subtract 1 from memory (without borrow).
Status flags: C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |DCP arg |$C7| 2 | 5
Zero Page,X |DCP arg,X |$D7| 2 | 6
Absolute |DCP arg |$CF| 3 | 6
Absolute,X |DCP arg,X |$DF| 3 | 7
Absolute,Y |DCP arg,Y |$DB| 3 | 7
(Indirect,X)|DCP (arg,X)|$C3| 2 | 8
(Indirect),Y|DCP (arg),Y|$D3| 2 | 8
DOP (NOP) [SKB]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
No operation (double NOP). The argument has no signifi-cance. Status
flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |DOP arg |$04| 2 | 3
Zero Page,X |DOP arg,X |$14| 2 | 4
Zero Page,X |DOP arg,X |$34| 2 | 4
Zero Page |DOP arg |$44| 2 | 3
Zero Page,X |DOP arg,X |$54| 2 | 4
Zero Page |DOP arg |$64| 2 | 3
Zero Page,X |DOP arg,X |$74| 2 | 4
Immediate |DOP #arg |$80| 2 | 2
Immediate |DOP #arg |$82| 2 | 2
Immediate |DOP #arg |$89| 2 | 2
Immediate |DOP #arg |$C2| 2 | 2
Zero Page,X |DOP arg,X |$D4| 2 | 4
Immediate |DOP #arg |$E2| 2 | 2
Zero Page,X |DOP arg,X |$F4| 2 | 4
ISC (ISB) [INS]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Increase memory by one, then subtract memory from accu-mulator (with
borrow). Status flags: N,V,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |ISC arg |$E7| 2 | 5
Zero Page,X |ISC arg,X |$F7| 2 | 6
Absolute |ISC arg |$EF| 3 | 6
Absolute,X |ISC arg,X |$FF| 3 | 7
Absolute,Y |ISC arg,Y |$FB| 3 | 7
(Indirect,X)|ISC (arg,X)|$E3| 2 | 8
(Indirect),Y|ISC (arg),Y|$F3| 2 | 8
KIL (JAM) [HLT]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Stop program counter (processor lock up).
Status flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Implied |KIL |$02| 1 | -
Implied |KIL |$12| 1 | -
Implied |KIL |$22| 1 | -
Implied |KIL |$32| 1 | -
Implied |KIL |$42| 1 | -
Implied |KIL |$52| 1 | -
Implied |KIL |$62| 1 | -
Implied |KIL |$72| 1 | -
Implied |KIL |$92| 1 | -
Implied |KIL |$B2| 1 | -
Implied |KIL |$D2| 1 | -
Implied |KIL |$F2| 1 | -
LAR (LAE) [LAS]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND memory with stack pointer, transfer result to accu-mulator, X
register and stack pointer.
Status flags: N,Z
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Absolute,Y |LAR arg,Y |$BB| 3 | 4 *
LAX (LAX) [LAX]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Load accumulator and X register with memory.
Status flags: N,Z
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |LAX arg |$A7| 2 | 3
Zero Page,Y |LAX arg,Y |$B7| 2 | 4
Absolute |LAX arg |$AF| 3 | 4
Absolute,Y |LAX arg,Y |$BF| 3 | 4 *
(Indirect,X)|LAX (arg,X)|$A3| 2 | 6
(Indirect),Y|LAX (arg),Y|$B3| 2 | 5 *
NOP (NOP) [NOP]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
No operation
Status flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Implied |NOP |$1A| 1 | 2
Implied |NOP |$3A| 1 | 2
Implied |NOP |$5A| 1 | 2
Implied |NOP |$7A| 1 | 2
Implied |NOP |$DA| 1 | 2
Implied |NOP |$FA| 1 | 2
RLA (RLA) [RLA]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Rotate one bit left in memory, then AND accumulator with memory. Status
flags: N,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |RLA arg |$27| 2 | 5
Zero Page,X |RLA arg,X |$37| 2 | 6
Absolute |RLA arg |$2F| 3 | 6
Absolute,X |RLA arg,X |$3F| 3 | 7
Absolute,Y |RLA arg,Y |$3B| 3 | 7
(Indirect,X)|RLA (arg,X)|$23| 2 | 8
(Indirect),Y|RLA (arg),Y|$33| 2 | 8
RRA (RRA) [RRA]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Rotate one bit right in memory, then add memory to accumulator (with
carry).
Status flags: N,V,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |RRA arg |$67| 2 | 5
Zero Page,X |RRA arg,X |$77| 2 | 6
Absolute |RRA arg |$6F| 3 | 6
Absolute,X |RRA arg,X |$7F| 3 | 7
Absolute,Y |RRA arg,Y |$7B| 3 | 7
(Indirect,X)|RRA (arg,X)|$63| 2 | 8
(Indirect),Y|RRA (arg),Y|$73| 2 | 8
SBC (SBC) [SBC]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
The same as the legal opcode $E9 (SBC #byte)
Status flags: N,V,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Immediate |SBC #byte |$EB| 2 | 2
SLO (SLO) [ASO]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Shift left one bit in memory, then OR accumulator with memory. =
Status flags: N,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |SLO arg |$07| 2 | 5
Zero Page,X |SLO arg,X |$17| 2 | 6
Absolute |SLO arg |$0F| 3 | 6
Absolute,X |SLO arg,X |$1F| 3 | 7
Absolute,Y |SLO arg,Y |$1B| 3 | 7
(Indirect,X)|SLO (arg,X)|$03| 2 | 8
(Indirect),Y|SLO (arg),Y|$13| 2 | 8
SRE (SRE) [LSE]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Shift right one bit in memory, then EOR accumulator with memory. Status
flags: N,Z,C
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Zero Page |SRE arg |$47| 2 | 5
Zero Page,X |SRE arg,X |$57| 2 | 6
Absolute |SRE arg |$4F| 3 | 6
Absolute,X |SRE arg,X |$5F| 3 | 7
Absolute,Y |SRE arg,Y |$5B| 3 | 7
(Indirect,X)|SRE (arg,X)|$43| 2 | 8
(Indirect),Y|SRE (arg),Y|$53| 2 | 8
SXA (SHX) [XAS]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND X register with the high byte of the target address of the argument
+ 1. Store the result in memory.
M =3D X AND HIGH(arg) + 1
Status flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Absolute,Y |SXA arg,Y |$9E| 3 | 5
SYA (SHY) [SAY]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND Y register with the high byte of the target address of the argument
+ 1. Store the result in memory.
M =3D Y AND HIGH(arg) + 1
Status flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Absolute,X |SYA arg,X |$9C| 3 | 5
TOP (NOP) [SKW]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
No operation (tripple NOP). The argument has no signifi-cance. Status
flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Absolute |TOP arg |$0C| 3 | 4
Absolute,X |TOP arg,X |$1C| 3 | 4 *
Absolute,X |TOP arg,X |$3C| 3 | 4 *
Absolute,X |TOP arg,X |$5C| 3 | 4 *
Absolute,X |TOP arg,X |$7C| 3 | 4 *
Absolute,X |TOP arg,X |$DC| 3 | 4 *
Absolute,X |TOP arg,X |$FC| 3 | 4 *
XAA (ANE) [XAA]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Exact operation unknown. Read the referenced documents for more
information and observations.
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Immediate |XAA #arg |$8B| 2 | 2
XAS (SHS) [TAS]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
AND X register with accumulator and store result in stack pointer, then
AND stack pointer with the high byte of the target address of the
argument + 1. Store result in memory.
S =3D X AND A, M =3D S AND HIGH(arg) + 1
Status flags: -
Addressing |Mnemonics |Opc|Sz | n
------------|-----------|---|---|---
Absolute,Y |XAS arg,Y |$9B| 3 | 5