We wszystkich komputerach Atari serii XL/XE instalowany był procesor 6502C SALLY. Interesującą cechą tego procesora jest obecność na jego liście rozkazów nieudokumentowanych. Listę kodów nieudokumentowanych czasem mylnie zwanych nielegalnymi lub niepublikowanymi można podzielić na trzy grupy:
- Kody stabilne działają na wszystkich komputerach Atari serii XL/XE i większości modeli 400/800, w której montowano procesor 6502C SALLY,
- Kody niestabilne działają w sposób niżej opisany tylko na procesorach 6502C niektórych producentów. Rozkazy te mogą zawsze prawidłowo zachowywać się w brzegowych sytuacjach. Niestabilność może polegać na nieprawidłowym stanie znaczników procesora po wykonaniu instrukcji, miejscu w którym ustalana jest wartość znaczników np. na wyniku cząstkowym, w najgorszym przypadku na zawartości rejestrów i/lub pamięci po wykonaniu instrukcji.
- Kody Crash IMmediately blokują procesor do sygnału reset.
Należy pamiętać, że rozkazy nieudokumentowane (w szczególności ANE i ANX) mogą działać inaczej na procesorach z rodziny 65xx montowanych w C64 np. 6510.
KOD | +00 | +01 | +02 | +03 | +04 | +05 | +06 | +07 | +08 | +09 | +0A | +0B | +0C | +0D | +0E | +0F |
+00 | CIM | ASO (Z,X) | DOP Z | ASO Z | ANC #n | TOP Q | ASO Q | |||||||||
+10 | CIM | ASO (Z),Y | DOP Z,X | ASO Z,X | NPO | ASO Q,Y | TOP Q,X | ASO Q,X | ||||||||
+20 | CIM | RLN (Z,X) | RLN Z | ANC #n | RLN Q | |||||||||||
+30 | CIM | RLN (Z),Y | DOP Z,X | RLN Z,X | NPO | RLN Q,Y | TOP Q,X | RLN Q,X | ||||||||
+40 | CIM | LSE (Z,X) | DOP Z | LSE Z | ALR #n | LSE Q | ||||||||||
+50 | CIM | LSE (Z),Y | DOP Z,X | LSE Z,X | NPO | LSE Q,Y | TOP Q,X | LSE Q,X | ||||||||
+60 | CIM | RRD (Z,X) | DOP Z | RRD Z | ARR #n | RRD Q | ||||||||||
+70 | CIM | RRD (Z),Y | DOP Z,X | RRD Z,X | NPO | RRD Q,Y | TOP Q,X | RRD Q,X | ||||||||
+80 | DOP #n | DOP #n | SAX (Z,X) | SAX Z | DOP #n | ANE #n | SAX Q | |||||||||
+90 | CIM | SHA (Z),Y | SAX Z,Y | SHS Q,Y | SHY Q,X | SHX Q,Y | SHA Q,Y | |||||||||
+A0 | LAX (Z,X) | LAX Z | ANX #n | LAX Q | ||||||||||||
+B0 | CIM | LAX (Z),Y | LAX Z,Y | LAS Q,Y | LAX Q,Y | |||||||||||
+C0 | DOP #n | DCP (Z,X) | DCP Z | SBX #n | DCP Q | |||||||||||
+D0 | CIM | DCP (Z),Y | DOP Z,X | DCP Z,X | NPO | DCP Q,Y | TOP Q,X | DCP Q,X | ||||||||
+E0 | DOP #n | ISB (Z,X) | ISB Z | SBC #n | ISB Q | |||||||||||
+F0 | CIM | ISB (Z),Y | DOP Z,X | ISB Z,X | NPO | ISB Q,Y | TOP Q,X | ISB Q,X |
Legenda:
n – dane w trybie natychmiastowym,
Q – adres dwubajtowy,
Z – adres jednobajtowy danych lub adresu pośredniego,
* – dodać cykl przy zmianie strony.
ANC
Wykonuje AND na A i danej. Znacznik C ustawiany tak jak N.
Znaczniki: N,Z,C
Assembler | kod | dł. | cykle |
ANC #n | $0B | 2 | 2 |
ANC #n | $2B | 2 | 2 |
SAX
Wykonuje AND pomiędzy A i rejestrem X, wynik zapisuje w pamięci. Rejestry A i X pozostają niezmienione.
Znaczniki: –
Assembler | kod | dł. | cykle |
SAX Z | $87 | 2 | 3 |
SAX Z,Y | $97 | 2 | 4 |
SAX (Z,X) | $83 | 2 | 6 |
SAX Q | $8F | 3 | 4 |
ALR
Wykonuje AND na A i danej, następnie LSR @.
Znaczniki: N,Z,C
Assembler | kod | dł. | cykle |
ALR #n | $4B | 2 | 2 |
SBX
Wykonuje AND pomiędzy rejestrem X i A, wynik w rejestrze X.
Znacznik C ustawiany gdy zawartość rejestru X jest większa lub równa danej.
Od rejestru X odejmuje daną (bez pożyczki).
Znaczniki: N,Z,C
Assembler | kod | dł. | cykle |
SBX #n | $CB | 2 | 2 |
DCM / DCP
Zmniejsza o jeden wartość bajtu pamięci następnie wykonuje CMP na A i tej wartości.
Znaczniki: N,Z,C
Assembler | kod | dł. | cykle |
DCP Z | $C7 | 2 | 5 |
DCP Z,X | $D7 | 2 | 6 |
DCP Q | $CF | 3 | 6 |
DCP Q,X | $DF | 3 | 7 |
DCP Q,Y | $DB | 3 | 7 |
DCP (Z,X) | $C3 | 2 | 8 |
DCP (Z),Y | $D3 | 2 | 8 |
INS / ISB
Zwiększa o jeden zawartość pamięci. Od A odejmuje wartość pamięci (z pożyczką).
Znaczniki: N,V,Z,C
Assembler | kod | dł. | cykle |
ISB Z | $E7 | 2 | 5 |
ISB Z,X | $F7 | 2 | 6 |
ISB Q | $EF | 3 | 6 |
ISB Q,X | $FF | 3 | 7 |
ISB Q,Y | $FB | 3 | 7 |
ISB (Z,X) | $E3 | 2 | 8 |
ISB (Z),Y | $F3 | 2 | 8 |
NPO
Niepublikowany NOP
Znaczniki: –
Assembler | kod | dł. | cykle |
NPO | $1A | 1 | 2 |
NPO | $3A | 1 | 2 |
NPO | $5A | 1 | 2 |
NPO | $7A | 1 | 2 |
NPO | $DA | 1 | 2 |
NPO | $FA | 1 | 2 |
DOP
Dwubajtowy NOP
Znaczniki: –
Assembler | kod | dł. | cykle |
DOP Z | $04 | 2 | 3 |
DOP Z,X | $14 | 2 | 4 |
DOP Z,X | $34 | 2 | 4 |
DOP Z | $44 | 2 | 3 |
DOP Z,X | $54 | 2 | 4 |
DOP Z | $64 | 2 | 3 |
DOP Z,X | $74 | 2 | 4 |
DOP #n | $80 | 2 | 2 |
DOP #n | $82 | 2 | 2 |
DOP #n | $89 | 2 | 2 |
DOP #n | $C2 | 2 | 2 |
DOP Z,X | $D4 | 2 | 4 |
DOP #n | $E2 | 2 | 2 |
DOP Z,X | $F4 | 2 | 4 |
TOP
Trzybajtowy NOP
Znaczniki: –
Assembler | kod | dł. | cykle |
TOP Q | $0C | 3 | 4 |
TOP Q,X | $1C | 3 | 4* |
TOP Q,X | $3C | 3 | 4* |
TOP Q,X | $5C | 3 | 4* |
TOP Q,X | $7C | 3 | 4* |
TOP Q,X | $DC | 3 | 4* |
TOP Q,X | $FC | 3 | 4* |
SBC
Niepublikowany SBC #n.
Znaczniki: N,V,Z,C
Assembler | kod | dł. | cykle |
SBC #n | $EB | 2 | 2 |
LAX
Załaduje daną do A i rejestru X.
Znaczniki: N,Z
Assembler | kod | dł. | cykle |
LAX Z | $A7 | 2 | 3 |
LAX Z,Y | $B7 | 2 | 4 |
LAX Q | $AF | 3 | 4 |
LAX Q,Y | $BF | 3 | 4* |
LAX (Z,X) | $A3 | 2 | 6 |
LAX (Z),Y | $B3 | 2 | 5* |
RLA / RLN
Wykonuje ROL na pamięci, następnie AND z A (wynik w A).
Znaczniki: N,Z,C
Assembler | kod | dł. | cykle |
RLN Z | $27 | 2 | 5 |
RLN Z,X | $37 | 2 | 6 |
RLN Q | $2F | 3 | 6 |
RLN Q,X | $3F | 3 | 7 |
RLN Q,Y | $3B | 3 | 7 |
RLN (Z,X) | $23 | 2 | 8 |
RLN (Z),Y | $33 | 2 | 8 |
RRA / RRD
Wykonuje ROR na pamięci, następnie ADC z A (wynik w A).
Znaczniki: N,V,Z,C
Assembler | kod | dł. | cykle |
RRD Z | $67 | 2 | 5 |
RRD Z,X | $77 | 2 | 6 |
RRD Q | $6F | 3 | 6 |
RRD Q,X | $7F | 3 | 7 |
RRD Q,Y | $7B | 3 | 7 |
RRD (Z,X) | $63 | 2 | 8 |
RRD (Z),Y | $73 | 2 | 8 |
ASO
Wykonuje ASL na pamięci, następnie ORA z A (wynik w A).
Znaczniki: N,Z,C
Assembler | kod | dł. | cykle |
ASO Z | $07 | 2 | 5 |
ASO Z,X | $17 | 2 | 6 |
ASO Q | $0F | 3 | 6 |
ASO Q,X | $1F | 3 | 7 |
ASO Q,Y | $1B | 3 | 7 |
ASO (Z,X) | $03 | 2 | 8 |
ASO (Z),Y | $13 | 2 | 8 |
LSE
Wykonuje LSR na pamięci, następnie EOR z A (wynik w A).
Znaczniki: N,Z,C
Assembler | kod | dł. | cykle |
LSE Z | $47 | 2 | 5 |
LSE Z,X | $57 | 2 | 6 |
LSE Q | $4F | 3 | 6 |
LSE Q,X | $5F | 3 | 7 |
LSE Q,Y | $5B | 3 | 7 |
LSE (Z,X) | $43 | 2 | 8 |
LSE (Z),Y | $53 | 2 | 8 |
SHX
Do starszego bajtu adresu dodaje jeden i wykonuje AND z rejestrem X.
Tak otrzymaną wartość zapisuje w pamięci.
Jeśli nastąpiło przekroczenie granicy strony zapis wykona pod adresem
którego starszy bajt jest równy otrzymanej wartości.
Znaczniki: –
Assembler | kod | dł. | cykle |
SHX Q,Y | $9E | 3 | 5 |
SHY
Do starszego bajtu adresu dodaje jeden i wykonuje AND z rejestrem Y.
Tak otrzymana wartość zapisuje w pamięci.
Jeśli nastąpiło przekroczenie granicy strony zapis wykona pod adresem
którego starszy bajt jest równy otrzymanej wartości.
Znaczniki: –
Assembler | kod | dł. | cykle |
SHY Q,X | $9C | 3 | 5 |
ARR
Gdy znacznik D=0 rozkaz działa następująco:
Wykonuje AND na A i danej po czym ROR.
Znacznik C wpisuje do b7, b6 do znacznika C, do V b6 EOR b5.
Gdy znacznik D=1 rozkaz:
Wykonuje AND na A i danej (cząstkowy wynik w postaci młodszego i starszego nibbla przechowuje) następnie wykonuje ROR @.
Jeśli wartość młodszego nibbla cząstkowego wyniku powiększona o jego b0 będzie większa lub równa od 5 to
młodszy nibbel wyniku w A zostanie zwiększony o 6, przy czym cząstkowe przeniesienie do starszego nibbla zostanie utracone.
Podobnie starszy nibbel cząstkowego wyniku, jeśli wartość po zwiększeniu o b0 będzie większa lub równa 5
to starszy nibbel wyniku w A zwiększony będzie o 6 a dodatkowo znacznik C zostanie ustawiony, jeśli nie było korekty starszego nibbla wyniku znacznik C będzie skasowany.
Flaga V ustawiona gdy w b6 zmieni swoj stan po AND i ROR, kasowany w przeciwnym wypadku.
Znaczniki: N,V,Z,C
Assembler | kod | dł. | cykle |
ARR #n | $6B | 2 | 2 |
SHA
Do starszego bajtu adresu dodaje jeden i wykonuje AND z A, następnie AND z rejestrem X.
Tak otrzymaną wartość zapisuje w pamięci.
Jeśli nastąpi przekroczenie granicy strony zapis wykona pod adresem
którego starszy bajt jest równy otrzymanej wartości.
Znaczniki: –
Assembler | kod | dł. | cykle |
SHA Q,Y | $9F | 3 | 5 |
SHA (Z),Y | $93 | 2 | 6 |
SHS
Do rejestru S zapisuje wynik operacji A AND X następnie do starszego bajtu adresu dodaje
jeden, wykonuje AND z S i zapisuje wynik w pamięci.
Jeśli nastąpi przekroczenie granicy strony zapis wykona pod adresem
którego starszy bajt jest równy otrzymanej wartości.
Znaczniki: –
# Wynik w S jest stabilny, w pamięci nie.
Assembler | kod | dł. | cykle |
SHS Q,Y | $9B | 3 | 5 |
LAS
Wykonuje AND na zawartości pamięci i rejestru S, wynik zapisuje w rejestrach A, X, S.
Znaczniki: N,Z
# Wyniki w A, X, S, N są stabilne, w Z nie.
Assembler | kod | dł. | cykle |
LAS Q,Y | $BB | 3 | 4* |
ANE
Znaczniki procesora ustawiane są wg. operacji argument AND A.
Rozkaz najpierw wykonuje sumę logiczną argumentu i wartości $EF, następnie operacji AND na rejestrze X i wyniku. W kolejnym kroku z tak otrzymaną wartością wykona AND z A. Wynik w A.
Znaczniki: N,Z
Assembler | kod | dł. | cykle |
ANE #n | $8B | 2 | 2 |
ANX
Wykonuje operację argument AND A, wynik zapisuje w A oraz rejetrze X.
Znaczniki: N,Z
Assembler | kod | dł. | cykle |
ANX #n | $AB | 2 | 2 |
CIM
Blokuje procesor.
Znaczniki: –
Assembler | kod | dł. | cykle |
CIM | $02 | 1 | – |
CIM | $12 | 1 | – |
CIM | $22 | 1 | – |
CIM | $32 | 1 | – |
CIM | $42 | 1 | – |
CIM | $52 | 1 | – |
CIM | $62 | 1 | – |
CIM | $72 | 1 | – |
CIM | $92 | 1 | – |
CIM | $B2 | 1 | – |
CIM | $D2 | 1 | – |
CIM | $F2 | 1 | – |
CIEKAWOSTKI
- Rozkazy nieudokumentowane stabilne użyte zostały w:
- grach: Alex, Alley Cat, Bosconian, Crownland, Firebal 1K, Flinstone’s Adventures, Gallahad, Ghastly Night, Indiana Jones – The Last Crusade, Jurassic Park, Landscape, Leader Board, Nexuss, Prince of Persia, Rainbow Walker, Riot, SOS Saturn, Terminator, Vanguard
- programach: Deary, Film Editor, Platfus Demo, Rolex, Rolex 2, Rolex 3, Rolex IV, Szczemp Sex Demo, Turbo SPEEDER 1400
- Rozkazy nieudokumentowane niestabilne użyte zostały w:
- grach: G.I.L.P.
- programach: 6502 Illegal Codes Test (Krógera)
Bracia Selinger używali nieudokumentowanych rozkazów we wszystkich swoich grach.