mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-10 10:29:43 +00:00
Add some documentation (!) for undocumented 6502 instructions.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
847e07be86
commit
ffb945a46d
642
M6502/documentation/6502-NMOS.extra.opcodes.txt
Normal file
642
M6502/documentation/6502-NMOS.extra.opcodes.txt
Normal file
@ -0,0 +1,642 @@
|
||||
|
||||
"Extra Instructions Of The 65XX Series CPU"
|
||||
|
||||
By: Adam Vardy (abe0084@infonet.st-johns.nf.ca)
|
||||
|
||||
|
||||
[File created: 22, Aug. 1995... 27, Sept. 1996]
|
||||
|
||||
The following is a list of 65XX/85XX extra opcodes. The operation codes
|
||||
for the 6502 CPU fit in a single byte; out of 256 possible combinations,
|
||||
only 151 are "legal." This text describes the other 256-151= 105 operation
|
||||
codes. These opcodes are not generally recognized as part of the 6502
|
||||
instruction set. They are also referred to as undefined opcodes or
|
||||
undocumented opcodes or non-standard opcodes or unofficial opcodes. In
|
||||
"The Commodore 64 Programmer's Reference Guide" their hexadecimal values
|
||||
are simply marked as future expansion. This list of opcodes was compiled
|
||||
with help from "The Complete Inner Space Anthology" by Karl J. H. Hildon.
|
||||
|
||||
I have marked off the beginning of the description of each opcode with a
|
||||
few asterisks. At times, I also included an alternate name in parenthesis.
|
||||
All opcode values are given in hexadecimal. These hexadecimal values are
|
||||
listed immediately to the right of any sample code. The lowercase letters
|
||||
found in these examples represent the hex digits that you must provide as
|
||||
the instruction's immediate byte value or as the instruction's destination
|
||||
or source address. Thus immediate values and zero page addresses are
|
||||
referred to as 'ab'. For absolute addressing mode the two bytes of an
|
||||
absolute address are referred to as 'cd' and 'ab'.
|
||||
|
||||
Execution times for all opcodes are given alongside to the very right of
|
||||
any sample code. A number of the opcodes described here combine the
|
||||
operation of two regular 6502 instructions. You can refer to a book on the
|
||||
6502 instruction set for more information, such as which flags a particular
|
||||
instruction affects.
|
||||
|
||||
|
||||
ASO *** (SLO)
|
||||
This opcode ASLs the contents of a memory location and then ORs the result
|
||||
with the accumulator.
|
||||
|
||||
Supported modes:
|
||||
|
||||
ASO abcd ;0F cd ab ;No. Cycles= 6
|
||||
ASO abcd,X ;1F cd ab ; 7
|
||||
ASO abcd,Y ;1B cd ab ; 7
|
||||
ASO ab ;07 ab ; 5
|
||||
ASO ab,X ;17 ab ; 6
|
||||
ASO (ab,X) ;03 ab ; 8
|
||||
ASO (ab),Y ;13 ab ; 8
|
||||
|
||||
(Sub-instructions: ORA, ASL)
|
||||
|
||||
Here is an example of how you might use this opcode:
|
||||
|
||||
ASO $C010 ;0F 10 C0
|
||||
|
||||
Here is the same code using equivalent instructions.
|
||||
|
||||
ASL $C010
|
||||
ORA $C010
|
||||
|
||||
RLA ***
|
||||
RLA ROLs the contents of a memory location and then ANDs the result with
|
||||
the accumulator.
|
||||
|
||||
Supported modes:
|
||||
|
||||
RLA abcd ;2F cd ab ;No. Cycles= 6
|
||||
RLA abcd,X ;3F cd ab ; 7
|
||||
RLA abcd,Y ;3B cd ab ; 7
|
||||
RLA ab ;27 ab ; 5
|
||||
RLA ab,X ;37 ab ; 6
|
||||
RLA (ab,X) ;23 ab ; 8
|
||||
RLA (ab),Y ;33 ab ; 8
|
||||
|
||||
(Sub-instructions: AND, ROL)
|
||||
|
||||
Here's an example of how you might write it in a program.
|
||||
|
||||
RLA $FC,X ;37 FC
|
||||
|
||||
Here's the same code using equivalent instructions.
|
||||
|
||||
ROL $FC,X
|
||||
AND $FC,X
|
||||
|
||||
LSE *** (SRE)
|
||||
LSE LSRs the contents of a memory location and then EORs the result with
|
||||
the accumulator.
|
||||
|
||||
Supported modes:
|
||||
|
||||
LSE abcd ;4F cd ab ;No. Cycles= 6
|
||||
LSE abcd,X ;5F cd ab ; 7
|
||||
LSE abcd,Y ;5B cd ab ; 7
|
||||
LSE ab ;47 ab ; 5
|
||||
LSE ab,X ;57 ab ; 6
|
||||
LSE (ab,X) ;43 ab ; 8
|
||||
LSE (ab),Y ;53 ab ; 8
|
||||
|
||||
(Sub-instructions: EOR, LSR)
|
||||
|
||||
Example:
|
||||
|
||||
LSE $C100,X ;5F 00 C1
|
||||
|
||||
Here's the same code using equivalent instructions.
|
||||
|
||||
LSR $C100,X
|
||||
EOR $C100,X
|
||||
|
||||
RRA ***
|
||||
RRA RORs the contents of a memory location and then ADCs the result with
|
||||
the accumulator.
|
||||
|
||||
Supported modes:
|
||||
|
||||
RRA abcd ;6F cd ab ;No. Cycles= 6
|
||||
RRA abcd,X ;7F cd ab ; 7
|
||||
RRA abcd,Y ;7B cd ab ; 7
|
||||
RRA ab ;67 ab ; 5
|
||||
RRA ab,X ;77 ab ; 6
|
||||
RRA (ab,X) ;63 ab ; 8
|
||||
RRA (ab),Y ;73 ab ; 8
|
||||
|
||||
(Sub-instructions: ADC, ROR)
|
||||
|
||||
Example:
|
||||
|
||||
RRA $030C ;6F 0C 03
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
ROR $030C
|
||||
ADC $030C
|
||||
|
||||
AXS *** (SAX)
|
||||
AXS ANDs the contents of the A and X registers (without changing the
|
||||
contents of either register) and stores the result in memory.
|
||||
AXS does not affect any flags in the processor status register.
|
||||
|
||||
Supported modes:
|
||||
|
||||
AXS abcd ;8F cd ab ;No. Cycles= 4
|
||||
AXS ab ;87 ab ; 3
|
||||
AXS ab,Y ;97 ab ; 4
|
||||
AXS (ab,X) ;83 ab ; 6
|
||||
|
||||
(Sub-instructions: STA, STX)
|
||||
|
||||
Example:
|
||||
|
||||
AXS $FE ;87 FE
|
||||
|
||||
Here's the same code using equivalent instructions.
|
||||
|
||||
STX $FE
|
||||
PHA
|
||||
AND $FE
|
||||
STA $FE
|
||||
PLA
|
||||
|
||||
LAX ***
|
||||
This opcode loads both the accumulator and the X register with the contents
|
||||
of a memory location.
|
||||
|
||||
Supported modes:
|
||||
|
||||
LAX abcd ;AF cd ab ;No. Cycles= 4
|
||||
LAX abcd,Y ;BF cd ab ; 4*
|
||||
LAX ab ;A7 ab ;*=add 1 3
|
||||
LAX ab,Y ;B7 ab ;if page 4
|
||||
LAX (ab,X) ;A3 ab ;boundary 6
|
||||
LAX (ab),Y ;B3 ab ;is crossed 5*
|
||||
|
||||
(Sub-instructions: LDA, LDX)
|
||||
|
||||
Example:
|
||||
|
||||
LAX $8400,Y ;BF 00 84
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
LDA $8400,Y
|
||||
LDX $8400,Y
|
||||
|
||||
DCM *** (DCP)
|
||||
This opcode DECs the contents of a memory location and then CMPs the result
|
||||
with the A register.
|
||||
|
||||
Supported modes:
|
||||
|
||||
DCM abcd ;CF cd ab ;No. Cycles= 6
|
||||
DCM abcd,X ;DF cd ab ; 7
|
||||
DCM abcd,Y ;DB cd ab ; 7
|
||||
DCM ab ;C7 ab ; 5
|
||||
DCM ab,X ;D7 ab ; 6
|
||||
DCM (ab,X) ;C3 ab ; 8
|
||||
DCM (ab),Y ;D3 ab ; 8
|
||||
|
||||
(Sub-instructions: CMP, DEC)
|
||||
|
||||
Example:
|
||||
|
||||
DCM $FF ;C7 FF
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
DEC $FF
|
||||
CMP $FF
|
||||
|
||||
INS *** (ISC)
|
||||
This opcode INCs the contents of a memory location and then SBCs the result
|
||||
from the A register.
|
||||
|
||||
Supported modes:
|
||||
|
||||
INS abcd ;EF cd ab ;No. Cycles= 6
|
||||
INS abcd,X ;FF cd ab ; 7
|
||||
INS abcd,Y ;FB cd ab ; 7
|
||||
INS ab ;E7 ab ; 5
|
||||
INS ab,X ;F7 ab ; 6
|
||||
INS (ab,X) ;E3 ab ; 8
|
||||
INS (ab),Y ;F3 ab ; 8
|
||||
|
||||
(Sub-instructions: SBC, INC)
|
||||
|
||||
Example:
|
||||
|
||||
INS $FF ;E7 FF
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
INC $FF
|
||||
SBC $FF
|
||||
|
||||
ALR ***
|
||||
This opcode ANDs the contents of the A register with an immediate value and
|
||||
then LSRs the result.
|
||||
|
||||
One supported mode:
|
||||
|
||||
ALR #ab ;4B ab ;No. Cycles= 2
|
||||
|
||||
Example:
|
||||
|
||||
ALR #$FE ;4B FE
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
AND #$FE
|
||||
LSR A
|
||||
|
||||
ARR ***
|
||||
This opcode ANDs the contents of the A register with an immediate value and
|
||||
then RORs the result.
|
||||
|
||||
One supported mode:
|
||||
|
||||
ARR #ab ;6B ab ;No. Cycles= 2
|
||||
|
||||
Here's an example of how you might write it in a program.
|
||||
|
||||
ARR #$7F ;6B 7F
|
||||
|
||||
Here's the same code using equivalent instructions.
|
||||
|
||||
AND #$7F
|
||||
ROR A
|
||||
|
||||
XAA ***
|
||||
XAA transfers the contents of the X register to the A register and then
|
||||
ANDs the A register with an immediate value.
|
||||
|
||||
One supported mode:
|
||||
|
||||
XAA #ab ;8B ab ;No. Cycles= 2
|
||||
|
||||
Example:
|
||||
|
||||
XAA #$44 ;8B 44
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
TXA
|
||||
AND #$44
|
||||
|
||||
OAL ***
|
||||
This opcode ORs the A register with #$EE, ANDs the result with an immediate
|
||||
value, and then stores the result in both A and X.
|
||||
|
||||
One supported mode:
|
||||
|
||||
OAL #ab ;AB ab ;No. Cycles= 2
|
||||
|
||||
Here's an example of how you might use this opcode:
|
||||
|
||||
OAL #$AA ;AB AA
|
||||
|
||||
Here's the same code using equivalent instructions:
|
||||
|
||||
ORA #$EE
|
||||
AND #$AA
|
||||
TAX
|
||||
|
||||
SAX ***
|
||||
SAX ANDs the contents of the A and X registers (leaving the contents of A
|
||||
intact), subtracts an immediate value, and then stores the result in X.
|
||||
... A few points might be made about the action of subtracting an immediate
|
||||
value. It actually works just like the CMP instruction, except that CMP
|
||||
does not store the result of the subtraction it performs in any register.
|
||||
This subtract operation is not affected by the state of the Carry flag,
|
||||
though it does affect the Carry flag. It does not affect the Overflow
|
||||
flag.
|
||||
|
||||
One supported mode:
|
||||
|
||||
SAX #ab ;CB ab ;No. Cycles= 2
|
||||
|
||||
Example:
|
||||
|
||||
SAX #$5A ;CB 5A
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
STA $02
|
||||
TXA
|
||||
AND $02
|
||||
SEC
|
||||
SBC #$5A
|
||||
TAX
|
||||
LDA $02
|
||||
|
||||
Note: Memory location $02 would not be altered by the SAX opcode.
|
||||
|
||||
NOP ***
|
||||
NOP performs no operation. Opcodes: 1A, 3A, 5A, 7A, DA, FA.
|
||||
Takes 2 cycles to execute.
|
||||
|
||||
SKB ***
|
||||
SKB stands for skip next byte.
|
||||
Opcodes: 80, 82, C2, E2, 04, 14, 34, 44, 54, 64, 74, D4, F4.
|
||||
Takes 2, 3, or 4 cycles to execute.
|
||||
|
||||
SKW ***
|
||||
SKW skips next word (two bytes).
|
||||
Opcodes: 0C, 1C, 3C, 5C, 7C, DC, FC.
|
||||
Takes 4 cycles to execute.
|
||||
|
||||
To be dizzyingly precise, SKW actually performs a read operation. It's
|
||||
just that the value read is not stored in any register. Further, opcode 0C
|
||||
uses the absolute addressing mode. The two bytes which follow it form the
|
||||
absolute address. All the other SKW opcodes use the absolute indexed X
|
||||
addressing mode. If a page boundary is crossed, the execution time of one
|
||||
of these SKW opcodes is upped to 5 clock cycles.
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The following opcodes were discovered and named exclusively by the author.
|
||||
(Or so it was thought before.)
|
||||
|
||||
HLT ***
|
||||
HLT crashes the microprocessor. When this opcode is executed, program
|
||||
execution ceases. No hardware interrupts will execute either. The author
|
||||
has characterized this instruction as a halt instruction since this is the
|
||||
most straightforward explanation for this opcode's behaviour. Only a reset
|
||||
will restart execution. This opcode leaves no trace of any operation
|
||||
performed! No registers affected.
|
||||
|
||||
Opcodes: 02, 12, 22, 32, 42, 52, 62, 72, 92, B2, D2, F2.
|
||||
|
||||
TAS ***
|
||||
This opcode ANDs the contents of the A and X registers (without changing
|
||||
the contents of either register) and transfers the result to the stack
|
||||
pointer. It then ANDs that result with the contents of the high byte of
|
||||
the target address of the operand +1 and stores that final result in
|
||||
memory.
|
||||
|
||||
One supported mode:
|
||||
|
||||
TAS abcd,Y ;9B cd ab ;No. Cycles= 5
|
||||
|
||||
(Sub-instructions: STA, TXS)
|
||||
|
||||
Here is an example of how you might use this opcode:
|
||||
|
||||
TAS $7700,Y ;9B 00 77
|
||||
|
||||
Here is the same code using equivalent instructions.
|
||||
|
||||
STX $02
|
||||
PHA
|
||||
AND $02
|
||||
TAX
|
||||
TXS
|
||||
AND #$78
|
||||
STA $7700,Y
|
||||
PLA
|
||||
LDX $02
|
||||
|
||||
Note: Memory location $02 would not be altered by the TAS opcode.
|
||||
|
||||
Above I used the phrase 'the high byte of the target address of the operand
|
||||
+1'. By the words target address, I mean the unindexed address, the one
|
||||
specified explicitly in the operand. The high byte is then the second byte
|
||||
after the opcode (ab). So we'll shorten that phrase to AB+1.
|
||||
|
||||
SAY ***
|
||||
This opcode ANDs the contents of the Y register with <ab+1> and stores the
|
||||
result in memory.
|
||||
|
||||
One supported mode:
|
||||
|
||||
SAY abcd,X ;9C cd ab ;No. Cycles= 5
|
||||
|
||||
Example:
|
||||
|
||||
SAY $7700,X ;9C 00 77
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
PHA
|
||||
TYA
|
||||
AND #$78
|
||||
STA $7700,X
|
||||
PLA
|
||||
|
||||
XAS ***
|
||||
This opcode ANDs the contents of the X register with <ab+1> and stores the
|
||||
result in memory.
|
||||
|
||||
One supported mode:
|
||||
|
||||
XAS abcd,Y ;9E cd ab ;No. Cycles= 5
|
||||
|
||||
Example:
|
||||
|
||||
XAS $6430,Y ;9E 30 64
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
PHA
|
||||
TXA
|
||||
AND #$65
|
||||
STA $6430,Y
|
||||
PLA
|
||||
|
||||
AXA ***
|
||||
This opcode stores the result of A AND X AND the high byte of the target
|
||||
address of the operand +1 in memory.
|
||||
|
||||
Supported modes:
|
||||
|
||||
AXA abcd,Y ;9F cd ab ;No. Cycles= 5
|
||||
AXA (ab),Y ;93 ab ; 6
|
||||
|
||||
Example:
|
||||
|
||||
AXA $7133,Y ;9F 33 71
|
||||
|
||||
Equivalent instructions:
|
||||
|
||||
STX $02
|
||||
PHA
|
||||
AND $02
|
||||
AND #$72
|
||||
STA $7133,Y
|
||||
PLA
|
||||
LDX $02
|
||||
|
||||
Note: Memory location $02 would not be altered by the AXA opcode.
|
||||
|
||||
|
||||
The following notes apply to the above four opcodes: TAS, SAY, XAS, AXA.
|
||||
|
||||
None of these opcodes affect the accumulator, the X register, the Y
|
||||
register, or the processor status register!
|
||||
The author has no explanation for the complexity of these
|
||||
instructions. It is hard to comprehend how the microprocessor could handle
|
||||
the convoluted sequence of events which appears to occur while executing
|
||||
one of these opcodes. A partial explanation for what is going on is that
|
||||
these instructions appear to be corruptions of other instructions. For
|
||||
example, the opcode SAY would have been one of the addressing modes of the
|
||||
standard instruction STY (absolute indexed X) were it not for the fact that
|
||||
the normal operation of this instruction is impaired in this particular
|
||||
instance.
|
||||
|
||||
One irregularity uncovered is that sometimes the actual value is stored in
|
||||
memory, and the AND with <ab+1> part drops off (ex. SAY becomes true STY).
|
||||
This happens very infrequently. The behaviour appears to be connected with
|
||||
the video display. For example, it never seems to occur if either the
|
||||
screen is blanked or C128 2MHz mode is enabled.
|
||||
|
||||
--- Imported example ---
|
||||
Here is a demo program to illustrate the above effect. SYS 8200 to try it.
|
||||
There is no exit, so you'll have to hit Stop-Restore to quit. And you may
|
||||
want to clear the screen before running it. For contrast, there is a
|
||||
second routine which runs during idle state display. Use SYS 8211 for it.
|
||||
After trying the second routine, check it out again using POKE 53269,255 to
|
||||
enable sprites.
|
||||
|
||||
begin 640 say->sty
|
||||
D"""B`*`@G``%Z$P,("P1T##[+!'0$/NB`*`@G``%Z-#Z3!,@
|
||||
`
|
||||
end
|
||||
|
||||
--- Text import end ---
|
||||
|
||||
WARNING: If the target address crosses a page boundary because of indexing,
|
||||
the instruction may not store at the intended address. It may end up
|
||||
storing in zero page, or another address altogether (page=value stored).
|
||||
Apparently certain internal 65XX registers are being overridden. The whole
|
||||
scheme behind this erratic behaviour is very complex and strange.
|
||||
|
||||
|
||||
And continuing with the list...
|
||||
|
||||
ANC ***
|
||||
ANC ANDs the contents of the A register with an immediate value and then
|
||||
moves bit 7 of A into the Carry flag. This opcode works basically
|
||||
identically to AND #immed. except that the Carry flag is set to the same
|
||||
state that the Negative flag is set to.
|
||||
|
||||
One supported mode:
|
||||
|
||||
ANC #ab ;2B ab ;No. Cycles= 2
|
||||
ANC #ab ;0B ab
|
||||
|
||||
(Sub-instructions: AND, ROL)
|
||||
|
||||
OPCODE 89
|
||||
Opcode 89 is another SKB instruction. It requires 2 cycles to execute.
|
||||
|
||||
LAS ***
|
||||
This opcode ANDs the contents of a memory location with the contents of the
|
||||
stack pointer register and stores the result in the accumulator, the X
|
||||
register, and the stack pointer. Affected flags: N Z.
|
||||
|
||||
One supported mode:
|
||||
|
||||
LAS abcd,Y ;BB cd ab ;No. Cycles= 4*
|
||||
|
||||
OPCODE EB
|
||||
Opcode EB seems to work exactly like SBC #immediate. Takes 2 cycles.
|
||||
|
||||
That is the end of the list.
|
||||
|
||||
This list is a full and complete list of all undocumented opcodes, every
|
||||
last hex value. It provides complete and thorough information and it also
|
||||
corrects some incorrect information found elsewhere. The opcodes MKA and
|
||||
MKX (also known as TSTA and TSTX) as described in "The Complete Commodore
|
||||
Inner Space Anthology" do not exist. Also, it is erroneously indicated
|
||||
there that the instructions ASO, RLA, LSE, RRA have an immediate addressing
|
||||
mode. (RLA #ab would be ANC #ab.)
|
||||
|
||||
[Recent additions to this text file]
|
||||
|
||||
Here are some other more scrutinizing observations.
|
||||
|
||||
The opcode ARR operates more complexily than actually described in the list
|
||||
above. Here is a brief rundown on this. The following assumes the decimal
|
||||
flag is clear. You see, the sub-instruction for ARR ($6B) is in fact ADC
|
||||
($69), not AND. While ADC is not performed, some of the ADC mechanics are
|
||||
evident. Like ADC, ARR affects the overflow flag. The following effects
|
||||
occur after ANDing but before RORing. The V flag is set to the result of
|
||||
exclusive ORing bit 7 with bit 6. Unlike ROR, bit 0 does not go into the
|
||||
carry flag. The state of bit 7 is exchanged with the carry flag. Bit 0 is
|
||||
lost. All of this may appear strange, but it makes sense if you consider
|
||||
the probable internal operations of ADC itself.
|
||||
|
||||
SKB opcodes 82, C2, E2 may be HLTs. Since only one source claims this, and
|
||||
no other sources corroborate this, it must be true on very few machines.
|
||||
On all others, these opcodes always perform no operation.
|
||||
|
||||
LAS is suspect. This opcode is possibly unreliable.
|
||||
|
||||
OPCODE BIT-PATTERN: 10x0 1011
|
||||
Now it is time to discuss XAA ($8B) and OAL ($AB). A fair bit of
|
||||
controversy has surrounded these two opcodes. There are two good reasons
|
||||
for this. 1 - They are rather weird in operation. 2 - They do operate
|
||||
differently on different machines. Highly variable.
|
||||
|
||||
Here is the basic operation.
|
||||
OAL
|
||||
This opcode ORs the A register with #xx, ANDs the result with an immediate
|
||||
value, and then stores the result in both A and X.
|
||||
|
||||
On my 128, xx may be EE,EF,FE, OR FF. These possibilities appear to depend
|
||||
on three factors: the X register, PC, and the previous instruction
|
||||
executed. Bit 0 is ORed from x, and also from PCH. As for XAA, on my 128
|
||||
this opcode appears to work exactly as described in the list.
|
||||
|
||||
On my 64, OAL produces all sorts of values for xx: 00,04,06,80, etc... A
|
||||
rough scenario I worked out to explain this is here. The constant value EE
|
||||
disappears entirely. Instead of ORing with EE, the accumulator is ORed
|
||||
with certain bits of X and also ORed with certain bits of another
|
||||
"register" (nature unknown, whether it be the data bus, or something else).
|
||||
However, if OAL is preceded by certain other instructions like NOP, the
|
||||
constant value EE reappears and the foregoing does not take place.
|
||||
|
||||
On my 64, XAA works like this. While X is transfered to A, bit 0 and bit 4
|
||||
are not. Instead, these bits are ANDed with those bits from A, and the
|
||||
result is stored in A.
|
||||
|
||||
There may be many variations in the behaviour of both opcodes. XAA #$00 or
|
||||
OAL #$00 are likely quite reliable in any case. It seems clear that the
|
||||
video chip (i.e., VIC-II) bears responsibility for some small part of the
|
||||
anomalousness, at least. Beyond that, the issue is unclear.
|
||||
|
||||
One idea I'll just throw up in the air about why the two opcodes behave as
|
||||
they do is this observation. While other opcodes like 4B and 6B perform
|
||||
AND as their first step, 8B and AB do not. Perhaps this difference leads
|
||||
to some internal conflict in the microprocessor. Besides being subject to
|
||||
"noise", the actual base operations do not vary.
|
||||
|
||||
All of the opcodes in this list (at least up to the dividing line) use the
|
||||
naming convention from the CCISA Anthology book. There is another naming
|
||||
convention used, for example in the first issue of C=Hacking. The only
|
||||
assembler I know of that supports undocumented opcodes is Power Assembler.
|
||||
And it uses the same naming conventions as used here.
|
||||
|
||||
One note on a different topic. A small error has been pointed out in the
|
||||
64 Programmers Reference Guide with the instruction set listing. In the
|
||||
last row, in the last column of the two instructions AND and ORA there
|
||||
should be an asterisk, just as there is with ADC. That is the indirect,Y
|
||||
addressing mode. In another table several pages later correct information
|
||||
is given.
|
||||
|
||||
(A correction: There was one error in this document originally. One
|
||||
addressing mode for LAX was given as LAX ab,X. This should have been
|
||||
LAX ab,Y (B7). Also note that Power Assembler apparently has this same
|
||||
error, likely because both it and this document derive first from the same
|
||||
source as regards these opcodes. Coding LAX $00,X is accepted and
|
||||
produces the output B7 00.)
|
||||
|
||||
References
|
||||
|
||||
o Joel Shepherd. "Extra Instructions" COMPUTE!, October 1983.
|
||||
|
||||
o Jim Butterfield. "Strange Opcodes" COMPUTE, March 1993.
|
||||
|
||||
o Raymond Quirling. "6510 Opcodes" The Transactor, March 1986.
|
||||
|
||||
o John West, Marko Mäkelä. '64doc' file, 1994/06/03.
|
433
M6502/documentation/undocumented_opcodes.txt
Normal file
433
M6502/documentation/undocumented_opcodes.txt
Normal file
@ -0,0 +1,433 @@
|
||||
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
|
Loading…
x
Reference in New Issue
Block a user