Undocumented 6502C

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.


KODY STABILNE

    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

KODY NIESTABILNE

    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

KODY CRASH

    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, Crownland, Firebal 1K, Flinstone’s Adventures, Gallahad, Ghastly Night, Indiana Jones – The Last Crusade, Jurassic Park, Landscape, Leader Board, Nexuss, 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.