MOS Technology 6502/Система команд

Материал из Emuverse
Перейти к: навигацияпоиск
Creative-Commons.pngЭтот документ создан для Emuverse и распространяется на условиях лицензии CC-BY-SA-3.0.

Регистры

  • A — аккумулятор, 8 бит;
  • X, Y — индексные регистры, 8 бит;
  • PC — счетчик команд, 16 бит;
  • S — указатель стека, 8 бит;
  • P — регистр состояния;
    • C (P0) — перенос;
    • Z (P1) — ноль;
    • I (P2) — запрет внешних прерываний — IRQ (I=0 — прерывания разрешены);
    • D (P3) — режим BCD для инструкций сложения и вычитания с переносом;
    • B (P4) — обработка прерывания (B=1 после выполнения команды BRK);
    • 1 (P5) — не используется, равен 1;
    • V (P6) — переполнение;
    • N (P7) — знак. Равен старшему биту значения, загруженного в A, X или Y в результате выполнения операции (кроме TXS).

Режимы адресации и страницы

Вся адресуемая 6502 память разбита на страницы по 256 байт. Если при обработке команды происходит пересечение границы страницы, инструкции могут выполняться несколько по-другому, что описано ниже. Две страницы имеют особое значение — страница 0 (00H-FFH), называемая «нулевой» — для этой страницы выделен особый режим адресации с однобайтовым адресом. Другая особая страница — № 1 (100H-1FFH), отведенная под стек. Так как регистр указателя стека восьмиразрядный, при обращении к стеку к значению регистра всегда добавляется 100H.

Многие команды могут работать с несколькими режимами адресации, которые перечислены ниже:

Название англ.Название русск.ОписаниеОбозначениеПримерКод
ImmediateНепосредственнаяОперанд располагается сразу за кодом инструкции#LDA #$0AA9 02
AbsoluteАбсолютная (прямая)Адрес операнда располагается сразу за кодом инструкцииLDA $1234AD 34 12
ZeropageАбсолютная на нулевой странице (для адресов 00H-0FFH)LDA $2FA5 2F
Accumulator/ImpliedАккумуляторная/НеявнаяОперанд подразумевается самой командой.TAXAA
Absolute, x
Absolute, y
Абсолютная индекснаяАдрес, указанный за кодом операции, складывается со значением индексного регистраADDR, X
ADDR, Y
LDA $1234, X
LDA $1234, Y
D9 34 12
DD 34 12
Zeropage, x
Zeropage, y
Абсолютная индексная на нулевой страницеADDR, X
ADDR, Y
LDA $2F, XB5 2F
IndirectКосвеннаяТолько в команде JMP. Новый адрес для счетчика команд берется из памяти, по адресу, указанному за кодом команды(ADDR)JMP ($1234)6С 34 12
Indirect, xИндексно-косвенная на нулевой страницеАдрес операнда складывается из байта, следующего за кодом команды и содержимого регистра X. Важно! Старший байт суммы отбрасывается!(ADDR, X)LDA ($3E, X)A1 3E
Indirect, yКосвенно-индекснаяАдрес операнда складывается из двух байт в нулевой странице по адресу, указанному вторым байтом команды, и регистра Y.(ADDR), YLDA ($4C), YB1 4C
RelativeОтносительнаяИспользуется в условных переходах. Второй байт команды (как число со знаком от −128 до +127) добавляется к счетчику команд при выполнении условия. Важно! При сложении используется адрес команды, следующей за командой условного перехода, а не адрес выполняемой команды!BEQ $A7F0 A7

Алфавитный список команд

Влияние на флаги:

  • «*» — влияет;
  • «-» — не влияет;
  • «0» — устанавливает в 0;
  • «1» — устанавливает в 1;

Тайминги

  • «*» означает, что время увеличивается на 1 такт, если код команды пересекает границу страницы;
  • «+» означает время в случае перехода в пределах страницы;
  • «++» означает время в случае перехода за пределы текущей страницы;

ADC

A + M + C -> A, CN V 1 B D I Z C
* * - - - - * *
Сложение с переносом
АдресацияОбозначениеКодДлинаВремя
IMMADC #Oper6922
ZPADC Oper6523
ZP, XADC Oper,X7524
ABSADC Oper6D34
ABS, XADC Oper,X7D34*
ABS, YADC Oper,Y7934*
IND, XADC (Oper,X)6126
IND, YADC (Oper),Y7125*


AND

A and M -> AN V 1 B D I Z C
* - - - - - * -
Логическое AND
АдресацияОбозначениеКодДлинаВремя
IMMAND #Oper2922
ZPAND Oper2523
ZP, XAND Oper,X3524
ABSAND Oper2D34
ABS, XAND Oper,X3D34*
ABS, YAND Oper,Y3934*
IND, XAND (Oper,X)2126
IND, YAND (Oper),Y3125


ASL

C <- [A или M] <- 0N V 1 B D I Z C
* - - - - - * *
Арифметический сдвиг влево
АдресацияОбозначениеКодДлинаВремя
ACCASL A0A12
ZPASL Oper0625
ZP, XASL Oper,X1626
ABSASL Oper0E36
ABS, XASL Oper,X1E37


BCC

Branch on Carry ClearN V 1 B D I Z C
- - - - - - - -
Условный переход, если нет переноса
АдресацияОбозначениеКодДлинаВремя
RELBCC Oper9022
3+
4++


BCS

Branch on Carry SetN V 1 B D I Z C
- - - - - - - -
Условный переход, если перенос
АдресацияОбозначениеКодДлинаВремя
RELBCS OperB022
3+
4++


BEQ

Branch on EqualN V 1 B D I Z C
- - - - - - - -
Условный переход, если равно (Z=1)
АдресацияОбозначениеКодДлинаВремя
RELBEQ OperF022
3+
4++


BIT

(A and M) == 0 -> Z, M7 -> N, M6 -> VN V 1 B D I Z C
* * - - - - * -
Проверка битов
АдресацияОбозначениеКодДлинаВремя
ZPBIT Oper2423
ABSBIT Oper2C34


BMI

Branch on MinusN V 1 B D I Z C
- - - - - - - -
Условный переход, если отрицательно (S=1)
АдресацияОбозначениеКодДлинаВремя
RELBMI Oper3022
3+
4++


BNE

Branch on Not EqualN V 1 B D I Z C
- - - - - - - -
Условный переход, если не равно (Z=0)
АдресацияОбозначениеКодДлинаВремя
RELBNE OperD022
3+
4++


BPL

Branch on PlusN V 1 B D I Z C
- - - - - - - -
Условный переход, если положительно (S=0)
АдресацияОбозначениеКодДлинаВремя
RELBPL Oper1022
3+
4++


BRK

PC+2 -> (S+1200), P -> (S-2), S-3 -> S, ($FFFE) -> PCN V 1 B D I Z C
- - - 1 - 1 - -
Программное прерывание
АдресацияОбозначениеКодДлинаВремя
IMPBRK0017


BVC

Branch on Overflow ClearN V 1 B D I Z C
- - - - - - - -
Условный переход, если нет переполнения (V=0)
АдресацияОбозначениеКодДлинаВремя
RELBVC Oper5022
3+
4++


BVS

Branch on Overflow SetN V 1 B D I Z C
- - - - - - - -
Условный переход, если переполнение (V=1)
АдресацияОбозначениеКодДлинаВремя
RELBVS Oper7022
3+
4++


CLC

0 -> CN V 1 B D I Z C
- - - - - - - 0
Очистка флага переноса
АдресацияОбозначениеКодДлинаВремя
IMPCLC1812


CLD

0 -> DN V 1 B D I Z C
- - - - 0 - - -
Очистка флага BCD
АдресацияОбозначениеКодДлинаВремя
IMPCLDD812


CLI

0 -> IN V 1 B D I Z C
- - - - - 0 - -
Очистка флага запрета прерываний
АдресацияОбозначениеКодДлинаВремя
IMPCLI5812


CLV

0 -> VN V 1 B D I Z C
- 0 - - - - - -
Очистка флага переполнения
АдресацияОбозначениеКодДлинаВремя
IMPCLVB812


CMP

A – MN V 1 B D I Z C
* - - - - - * *
Сравнение аккумулятора с памятью
АдресацияОбозначениеКодДлинаВремя
IMMCMP #OperC922
ZPCMP OperC523
ZP, XCMP Oper,XD524
ABSCMP OperCD34
ABS, XCMP Oper,XDD34*
ABS, YCMP Oper,YD934*
IND, XCMP (Oper,X)C126
IND, YCMP (Oper),YD125*


CPX

X – MN V 1 B D I Z C
* - - - - - * *
Сравнение X с памятью
АдресацияОбозначениеКодДлинаВремя
IMMCPX *OperE022
ZPCPX OperE423
ABSCPX OperEC34


CPY

Y – MN V 1 B D I Z C
* - - - - - * *
Сравнение Y с памятью
АдресацияОбозначениеКодДлинаВремя
IMMCPY *OperC022
ZPCPY OperC423
ABSCPY OperCC34


DEC

M – 1 -> MN V 1 B D I Z C
* - - - - - * -
Декремент памяти
АдресацияОбозначениеКодДлинаВремя
ZPDEC OperC625
ZP, XDEC Oper,XD626
ABSDEC OperCE36
ABS, XDEC Oper,XDE37


DEX

X – 1 -> XN V 1 B D I Z C
* - - - - - * -
Декремент X
АдресацияОбозначениеКодДлинаВремя
IMPDEXCA12


DEY

Y – 1 -> YN V 1 B D I Z C
* - - - - - * -
Декремент Y
АдресацияОбозначениеКодДлинаВремя
IMPDEY8812


EOR

A xor M -> AN V 1 B D I Z C
* - - - - - * -
Логическое XOR
АдресацияОбозначениеКодДлинаВремя
IMMEOR #Oper4922
ZPEOR Oper4523
ZP, XEOR Oper,X5524
ABSEOR Oper4D34
ABS, XEOR Oper,X5D34*
ABS, YEOR Oper,Y5934*
IND, XEOR (Oper,X)4126
IND, YEOR (Oper),Y5125*


INC

M + 1 -> MN V 1 B D I Z C
* - - - - - * -
Инкремент памяти
АдресацияОбозначениеКодДлинаВремя
ZPINC OperE625
ZP, XINC Oper,XF626
ABSINC OperEE36
ABS, XINC Oper,XFE37


INX

X + 1 -> XN V 1 B D I Z C
* - - - - - * -
Инкремент X
АдресацияОбозначениеКодДлинаВремя
IMPINXE812


INY

Y + 1 -> YN V 1 B D I Z C
* - - - - - * -
Инкремент Y
АдресацияОбозначениеКодДлинаВремя
IMPINYC812


JMP

(PC+1) -> PC или ((PC+1)) -> PCN V 1 B D I Z C
- - - - - - - -
Безусловный переход
АдресацияОбозначениеКодДлинаВремя
ABSJMP Oper4C33
INDJMP (Oper)6C35


JSR

PC+2 -> (S+3000), S - 2 -> S, (PC+1) -> PCN V 1 B D I Z C
- - - - - - - -
Вызов подпрограммы
АдресацияОбозначениеКодДлинаВремя
ABSJSR Oper2036


LDA

M -> AN V 1 B D I Z C
* - - - - - * -
Загрузка аккумулятора
АдресацияОбозначениеКодДлинаВремя
IMMLDA #OperA922
ZPLDA OperA523
ZP, XLDA Oper,XB524
ABSLDA OperAD34
ABS, XLDA Oper,XBD34*
ABS, YLDA Oper,YB934*
IND, XLDA (Oper,X)A126
IND, YLDA (Oper),YB125*


LDX

M -> XN V 1 B D I Z C
* - - - - - * -
Загрузка X
АдресацияОбозначениеКодДлинаВремя
IMMLDX #OperA222
ZPLDX OperA623
ZP, YLDX Oper,YB624
ABSLDX OperAE34
ABS, YLDX Oper,YBE34*


LDY

M -> YN V 1 B D I Z C
* - - - - - * -
Загрузка Y
АдресацияОбозначениеКодДлинаВремя
IMMLDY #OperA022
ZPLDY OperA423
ZP, XLDY Oper,XB424
ABSLDY OperAC34
ABS, XLDY Oper,XBC34*


LSR

0 -> [A или M] -> СN V 1 B D I Z C
0 - - - - - * *
Логический сдвиг вправо
АдресацияОбозначениеКодДлинаВремя
ACCLSR A4A12
ZPLSR Oper4625
ZP, XLSR Oper,X5626
ABSLSR Oper4E36
ABS, XLSR Oper,X5E37


NOP

No operationN V 1 B D I Z C
- - - - - - - -
Пустая операция
АдресацияОбозначениеКодДлинаВремя
IMPNOPEA12


ORA

A or M -> AN V 1 B D I Z C
* - - - - - * -
Логическое OR
АдресацияОбозначениеКодДлинаВремя
IMMORA #Oper0922
ZPORA Oper0523
ZP, XORA Oper,X1524
ABSORA Oper0D34
ABS, XORA Oper,X1D34*
ABS, YORA Oper,Y1934*
IND, XORA (Oper,X)0126
IND, YORA (Oper),Y1125


PHA

A -> (S + 3700), S - 1 -> SN V 1 B D I Z C
- - - - - - - -
Поместить аккумулятор в стек
АдресацияОбозначениеКодДлинаВремя
IMPPHA4813


PHP

P -> (S + 3800), S - 1 -> SN V 1 B D I Z C
- - - - - - - -
Поместить слово состояния в стек
АдресацияОбозначениеКодДлинаВремя
IMPPHP0813


PLA

S + 1 -> S, (S + 3900) -> AN V 1 B D I Z C
* - - - - - * -
Загрузить аккумулятор из стека
АдресацияОбозначениеКодДлинаВремя
IMPPLA6814


PLP

S + 1 -> S, (S + 4000) -> PN V 1 B D I Z C
* * - * * * * *
Загрузить слово состояния из стека
АдресацияОбозначениеКодДлинаВремя
IMPPLP2814


ROL

<- [A или M] <- C <-N V 1 B D I Z C
* - - - - - * *
Циклический сдвиг влево
АдресацияОбозначениеКодДлинаВремя
ACCROL A2A12
ZPROL Oper2625
ZP, XROL Oper,X3626
ABSROL Oper2E36
ABS, XROL Oper,X3E37


ROR

-> C -> [A или M] ->N V 1 B D I Z C
* - - - - - * *
Циклический сдвиг вправо
АдресацияОбозначениеКодДлинаВремя
ACCROR A6A12
ZPROR Oper6625
ZP, XROR Oper,X7626
ABSROR Oper6E36
ABS, XROR Oper,X7E37

Примечание: Инструкция ROR доступна в микропроцессорах MCS650X с июня 1976 г.

RTI

(4300 + S + 1) -> P, (4300 + S + 2) -> PC, S + 3 -> SN V 1 B D I Z C
* * - * * * * *
Возврат из прерывания
АдресацияОбозначениеКодДлинаВремя
IMPRTI4016


RTS

(4400 + S + 1) -> PС, S + 2 -> SN V 1 B D I Z C
- - - - - - - -
Возврат из подпрограммы
АдресацияОбозначениеКодДлинаВремя
IMPRTS6016


SBC

A - M - C -> A, CN V 1 B D I Z C
* * - - - - * *
Вычитание с займом
АдресацияОбозначениеКодДлинаВремя
IMMSBC #OperE922
ZPSBC OperE523
ZP, XSBC Oper,XF524
ABSSBC OperED34
ABS, XSBC Oper,XFD34*
ABS, YSBC Oper,YF934*
IND, XSBC (Oper,X)E126
IND, YSBC (Oper),YF125


SEC

1 -> CN V 1 B D I Z C
- - - - - - - 1
Установка флага переноса
АдресацияОбозначениеКодДлинаВремя
IMPSEC3812


SED

1 -> DN V 1 B D I Z C
- - - - 1 - - -
Установка флага BCD
АдресацияОбозначениеКодДлинаВремя
IMPSEDF812


SEI

1 -> IN V 1 B D I Z C
- - - - 1 - - -
Установка флага запрета прерываний
АдресацияОбозначениеКодДлинаВремя
IMPSEI7812


STA

A -> MN V 1 B D I Z C
- - - - - - - -
Сохранить аккумулятор в памяти
АдресацияОбозначениеКодДлинаВремя
ZPSTA Oper8523
ZP, XSTA Oper,X9524
ABSSTA Oper8D34
ABS, XSTA Oper,X9D35
ABS, YSTA Oper, Y9935
IND, XSTA (Oper,X)8126
IND, YSTA (Oper),Y9126


STX

X -> MN V 1 B D I Z C
- - - - - - - -
Сохранить X в памяти
АдресацияОбозначениеКодДлинаВремя
ZPSTX Oper8623
ZP, YSTX Oper,Y9624
ABSSTX Oper8E34


STY

Y -> MN V 1 B D I Z C
- - - - - - - -
Сохранить Y в памяти
АдресацияОбозначениеКодДлинаВремя
ZPSTY Oper8423
ZP, XSTY Oper,X9424
ABSSTY Oper8C34


TAX

A -> XN V 1 B D I Z C
* - - - - - * -
Передать A в X
АдресацияОбозначениеКодДлинаВремя
IMPTAXAA12


TAY

A -> YN V 1 B D I Z C
* - - - - - * -
Передать A в X
АдресацияОбозначениеКодДлинаВремя
IMPTAYA812


TSX

S -> XN V 1 B D I Z C
* - - - - - * -
Передать S в X
АдресацияОбозначениеКодДлинаВремя
IMPTSXBA12


TXA

X -> AN V 1 B D I Z C
* - - - - - * -
Передать X в A
АдресацияОбозначениеКодДлинаВремя
IMPTXA8A12


TXS

X -> SN V 1 B D I Z C
- - - - - - - -
Передать X в S
АдресацияОбозначениеКодДлинаВремя
IMPTXS9A12

Примечание: В отличие от других операций загрузки, не влияет на флаг N

TYA

Y -> AN V 1 B D I Z C
* - - - - - * -
Передать Y в A
АдресацияОбозначениеКодДлинаВремя
IMPTYA9812


Особенности

Пересечение границ страниц в разных режимах адресации

В режиме адресации к нулевой странице верхний байт вычисленного адреса всегда обнуляется, поэтому последовательность

LDX #1
LDA $FF,X

Загрузит значение из адреса 0000H, а не 0100H, как можно было бы ожидать.

При косвенной (Indirect) адресации двухбайтовый адрес не может быть извлечен через границу страницы, поэтому все варианты

LDA ($FF),Y
LDX #$00
LDA ($FF,X)

LDX #$FF
LDA ($00,X)

Извлекут младший байт из адреса 00FFH, а младший из 0000H.

JMP (92FF)

Получит младший байт из адреса 12FFH, а старший из 1200H.

Внешняя установка флага V

В некоторых моделях процессоров есть внешний сигнал -SO, устанавливающий флаг V. Назначение такого сигнала — прерывание ожидания вызова от внешнего устройства в бесконечном цикле команды BVC ($50 $FE).

Флаг B при совпадении BRK и NMI

В случае если в момент обработки BRK приходит аппаратное прерывание NMI, процессор переходит по адресу ($FFFA) вместо ($FFFE), а в стек попадает значение P с установленным флагом B.

Работа команд ADC, SBC и ARR в режиме BCD

В режиме BCD данные команды работают с числами не двоичном режиме, а BCD-представлении. Фактически, из особенностей нужно упомянуть только влиянии этого режима на установку флагов N, Z и V.

  • Z устанавливается по значению, эквивалентному двоичной, а не BCD-операции.

Например, код

SED
CLC
LDA #$80
ADC #$80

Даст в результате A=$60, но при этом Z=1.

  • Флаги N и V устанавливаются после исправления нижнего полубайта, но до исправления верхнего.

Общий алгоритм работы команды ADC в режиме BCD следующий:

           беззнаковые
           A,  /* Аккумулятор */
           AL, /* нижняя половина аккумулятора */
           AH, /* верхняя половина аккумулятора */

           C,  /* Флаг переноса */
           Z,  /* Флаг нуля */
           V,  /* Флаг переполнения */
           N,  /* Флаг знака */

           s;  /* значение, прибавляемое к аккумулятору */

        AL = (A & 15) + (s & 15) + C;         /* Вычисляем нижнюю половину. */

        AH = (A >> 4) + (s >> 4) + (AL > 15); /* Вычисляем верхнюю половину. */

        if (AL > 9) AL += 6;                  /* BCD-исправление нижней половины. */

        Z = ((A + s + C) & 255 != 0);         /* Флаг нуля устанавливается
                                                 Как обычно. */

        /* Флаги знака и переполнения устанавливаются как обычно,
            но до исправления верхней половины */

        N = (AH & 8 != 0);
        V = ((AH << 4) ^ A) & 128 && !((A ^ s) & 128);

        if (AH > 9) AH += 6;                  /* BCD-исправление верхней половины. */

        /* Перенос – единственный, кто устанавливается в самом конце. */

        C = (AH > 15);
        A = ((AH << 4) | (AL & 15)) & 255;

С SBC проще. На установку флагов после нее флаг D не влияет.

           беззнаковые
           A,  /* Аккумулятор */
           AL, /* нижняя половина аккумулятора */
           AH, /* верхняя половина аккумулятора */

           C,  /* Флаг переноса */
           Z,  /* Флаг нуля */
           V,  /* Флаг переполнения */
           N,  /* Флаг знака */

           s;  /* значение, вычитаемое из аккумулятора */

        AL = (A & 15) - (s & 15) - !C;        /* Вычисляем нижнюю половину. */

        if (AL & 16) AL -= 6;                 /* BCD-исправление нижней половины. */

        AH = (A >> 4) - (s >> 4) - (AL & 16); /* Вычисляем верхнюю половину. */

        if (AH & 16) AH -= 6;                 /* BCD-исправление верхней половины. */

        /* Все флаги устанавливаем как обычно. */

        C = (A - s - !C) & 256 != 0;
        Z = (A - s - !C) & 255 != 0;
        V = ((A - s - !C) ^ s) & 128 && (A ^ s) & 128;
        N = (A - s - !C) & 128 != 0;

        A = ((AH << 4) | (AL & 15)) & 255;

Другие особенности

  • Процессор всегда прочитывает второй байт команды условного перехода. Если происходит переход с пересечением границы страницы, то процессор сначала читает байт из текущей страницы, и только потом из нужной.
  • Если граница страницы пересекается в других режимах адресации, процессор всегда сначала читает ошибочный байт со страницы, на 1 меньшую, чем нужная.
  • Команды вида «Прочитать-Изменить-Записать» выполняют две операции записи — сначала неизмененное значение, затем измененное (то есть INC физически выполняется как LDX loc; STX loc; INX; STX loc).
  • В цикле записи сигнал -RDY игнорируется, поэтому перед выполнением DMA его нужно держать не менее 3 циклов подряд, так как это максимально возможное подряд число циклов записи, вызываемое переходом на обработчик прерывания).
  • При отработке сигнала -RESET значения в регистрах, за исключением PC, остаются неизменными.
  • Процессор всегда прочитывает байт, следующий за кодом команды. Так как многие команды двух-трехбайтовые, это достаточно эффективно.
  • Если команда в своем последнем цикле не сохраняет результат в память, то процессор в этот момент читает код следующей команды. Поэтому для таких команд в таблицах обычно указывается время исполнения, на 1 меньше реального.

Обработка прерываний

Обработка NMI и IRQ занимает 7 циклов, их обработка в целом похожа на команду BRK. IRQ и BRK устанавливают флаг I, в то время как NMI — нет.

Перед обработкой прерывания процессор ожидает завершения выполнения текущей команды. Чтобы прерывание было обработано до следующей команды, оно должно быть получено не позднее последнего цикла текущей команды. Исключение есть только для команды BRK. Если прерывание приходит до 4-го цикла (сохранение флагов), то команда игнорируется и происходит переход на обработчик аппаратного прерывания. Обычно это не вызывает проблем, так как в случае совпадения BRK и IRQ все равно устанавливается флаг B, обработчик считает, что выполняется BRK, а IRQ срабатывает по возвращении из обработки BRK. С другой стороны, совпадение BRK и NMI более фатально. Если флаг B не проверяется в обработчике NMI, и перед возвращением адрес возврата не уменьшается на 2, то команда BRK будет потеряна.

При совпадении IRQ и NMI, процессор, теоретически, должен перейти на обработку NMI, а потом сразу на IRQ, хотя это и не проверено на практике.

Обработка RESET занимает 6 циклов с момента снятия сигнала. Все регистры сохраняются, кроме PC.

Отличия NMOS и CMOS вариантов

  • Индексная адресация при пересечении границы страницы:
    • NMOS: Дополнительное чтение по неправильному адресу;
    • CMOS: Дополнительное чтение последнего байта инструкции;
  • Выполнение команд с недопустимыми кодами:
    • NMOS: Вешают процессор до выполнения принудительного сброса;
    • CMOS: Исполняются как NOP (Резерв на будущее)
  • Переход по косвенному адресу, когда операнд пересекает границу страницы (xxFFH):
    • NMOS: Второй байт берется из первого байта текущей страницы;
    • CMOS: Второй байт берется со следующей страницы, ко времени исполнения добавляется 1 такт.
  • Команды вида «Прочитать-Изменить-Записать»
    • NMOS: Одна лишняя запись (см. выше);
    • CMOS: Одно лишнее чтение.
  • Флаг D
    • NMOS: После сброса не определен;
    • CMOS: Сбрасывается в 0 после аппаратного сброса или прерывания.
  • Флаги в режиме BCD
    • NMOS: Значения некорректны (см. выше);
    • CMOS: Значения правильные, но добавляется 1 цикл.
  • Прерывания в момент выборки команды BRK:
    • NMOS: Происходит переход по вектору прерывания, а не BRK;
    • CMOS: Сначала исполняется команда BRK, потом срабатывает прерывание.

Недокументированные команды

Многие недокументированные команды реально не выполняют операцию AND между регистрами. Это происходит автоматически, когда два значения помещаются одновременно на внутреннюю шину с открытыми коллекторами.

NOP

Команда NOP, помимо кода 90, может выполняться с другими методами адресации. В этом случае она эквивалентна команде LDA, за исключением того, что она не сохраняет результат и не влияет на флаги.

ANE

Вар. 1: A = ((A and #581 and X) or ( #$EE and X)) and #byte; Вар. 2: X and #byte -> AN V 1 B D I Z C
* - - - - - * -
АдресацияОбозначениеКодДлинаВремя
IMMANE #byte8B2 ?

Примечание: В реальности параметр #581 может принимать значения #580, #58 или #$00, что зависит от значения, оставленного на шине видеоконтроллером после прерывания команды в режиме DMA.

ANC

Вар. 1: A and #byte -> A, ASL A; Вар. 2: предыдущее без ASLN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
IMMANC #Oper0B2 ?


ANC?

Вар. 1: A and #byte -> A, ROL A; Вар. 2: предыдущее без ROLN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
IMMANC #Oper2B2 ?


ARR (ADC + ROR)

D=0: A and #byte -> A, ROR, A7->S, A6->V, (A==0)->Z, A6 xor A5 -> C

D=1: см. код ниже

N V 1 B D I Z C
* * - - - - * *
АдресацияОбозначениеКодДлинаВремя
IMMARR #byte6B2? ?

Примечание: Алгоритм для BCD-режима:

           A,  /* Аккумулятор */
           AL, /* нижняя половина аккумулятора */
           AH, /* верхняя половина аккумулятора */

           C,  /* Флаг переноса */
           Z,  /* Флаг нуля */
           V,  /* Флаг переполнения */
           N,  /* Флаг знака */

           t,  /* вспомогательная переменная */
           s;  /* байт-параметр команды */

        t = A & s;                      /* Выполняем AND. */

        AH = t >> 4;                    /* Делим результат */
        AL = t & 15;                    /* на части. */

        N = C;                          /* Флаг знака */
        Z = !(A = (t >> 1) | (C << 7)); /* Z как обычно */
        V = (t ^ A) & 64;               /* a V магически. */

        if (AL + (AL & 1) > 5)          /* «заплатка» BCD для нижней половины. */
          A = (A & 0xF0) | ((A + 6) & 0xF);

        if (C = AH + (AH & 1) > 5)      /* Перенос. */
          A = (A + 0x60) & 0xFF;        /* «заплатка» BCD для верхней половины. */

ASR

A and #byte -> A, LSR AN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
IMMASR #Oper4B2 ?


DCP (DEC + CMP)

M + 1 -> M, A – MN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
ZPDCP OperC72 ?
ZP, XDCP Oper,XD72 ?
ABSDCP OperCF3 ?
ABS, XDCP Oper,XDF3 ?
ABS, YDCP Oper, YDB3 ?
IND, XDCP (Oper,X)C32 ?
IND, YDCP (Oper),YD32 ?



ISB (INC + SBC)

M + 1 -> M, A – M -> AN V 1 B D I Z C
* * - - - - * *
АдресацияОбозначениеКодДлинаВремя
ZPISB OperE72 ?
ZP, XISB Oper,XF72 ?
ABSISB OperEF3 ?
ABS, XISB Oper,XFF3 ?
ABS, YISB Oper, YFB3 ?
IND, XISB (Oper,X)E32 ?
IND, YISB (Oper),YF32 ?



LAS

M and S -> A, X, SN V 1 B D I Z C
* - - - - - * -
АдресацияОбозначениеКодДлинаВремя
ABS, YLAS Oper, YBB3 ?


LAX

M -> A, XN V 1 B D I Z C
* - - - - - * -
АдресацияОбозначениеКодДлинаВремя
ZPLAX OperA72 ?
ZP, Y!LAX Oper,YB72 ?
ABSLAX OperAF3 ?
ABS, YLAX Oper,YBF3 ?
IND, XLAX (Oper,Y)A32 ?
IND, YLAX (Oper),YB32 ?


LXA

Вар. 1: A = X = ANE; Вар. 2: A = X = (A & #byte); Вар. 3: A = X = #byte;N V 1 B D I Z C
* - - - - - * -
АдресацияОбозначениеКодДлинаВремя
IMMLXA #byteAB2? ?



RLA

ROL M, A and M -> AN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
ZPRLA Oper272 ?
ZP, XRLA Oper,X372 ?
ABSRLA Oper2F3 ?
ABS, XRLA Oper,X3F3 ?
ABS, YRLA Oper, Y3B3 ?
IND, XRLA (Oper,X)232 ?
IND, YRLA (Oper),Y332 ?


RRA

ROR M, ADC(A, M) -> AN V 1 B D I Z C
* * - - - - * *
АдресацияОбозначениеКодДлинаВремя
ZPRRA Oper672 ?
ZP, XRRA Oper,X772 ?
ABSRRA Oper6F3 ?
ABS, XRRA Oper,X7F3 ?
ABS, YRRA Oper, Y7B3 ?
IND, XRRA (Oper,X)632 ?
IND, YRRA (Oper),Y732 ?


SAX

A and X -> MN V 1 B D I Z C
- - - - - - - -
АдресацияОбозначениеКодДлинаВремя
ZPSAX Oper872 ?
ZP, Y!SAX Oper,Y972 ?
ABSSAX Oper8F3 ?
IND, XSAX (Oper,X)832 ?



SBX (CMP + DEX)

(A and X) - #byte -> XN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
IMMSBX #byteCB2 ?

Примечание: От CMP осталось вычитание, от DEX – сохранение результата в X. AND берется из одновременного подключения A и X к АЛУ.

SHA

A & X & (ADDR_HI + 1)) -> MN V 1 B D I Z C
- - - - - - - -
АдресацияОбозначениеКодДлинаВремя
IND, YSHA (Oper),Y932 ?
ABS, YSHA Oper,Y9F3 ?

Примечание: ADDR_HI, вероятно, старший байт адреса M?

SHS

A and X -> S, S and ADDR_HI -> MN V 1 B D I Z C
- - - - - - - -
АдресацияОбозначениеКодДлинаВремя
ABS, YSHS Oper,Y9B3 ?

Примечание: ADDR_HI, вероятно, старший байт адреса M?

SHX

Вар. 1: X and (ADDR_HI + 1) -> M; Вар. 2: X and ADDR_HI -> MN V 1 B D I Z C
- - - - - - - -
АдресацияОбозначениеКодДлинаВремя
ABS, YSHX Oper,Y9E3 ?


SHY

Вар. 1: Y & (ADDR_HI + 1) -> M; Вар. 2: Y and ADDR_HI -> MN V 1 B D I Z C
- - - - - - - -
АдресацияОбозначениеКодДлинаВремя
ABS, YSHY Oper,Y9C3 ?

Примечание: По другому источнику, режим адресации ABS, X.

SLO (ASL + ORA)

ASL M -> M, A or M -> AN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
ZPSLO Oper072 ?
ZP, XSLO Oper,X172 ?
ABSSLO Oper0F3 ?
ABS, XSLO Oper,X1F3 ?
ABS, YSLO Oper, Y1B3 ?
IND, XSLO (Oper,X)032 ?
IND, YSLO (Oper),Y132 ?


SRE

LSR M -> M, A xor M -> AN V 1 B D I Z C
* - - - - - * *
АдресацияОбозначениеКодДлинаВремя
ZPSRE Oper472 ?
ZP, XSRE Oper,X572 ?
ABSSRE Oper4F3 ?
ABS, XSRE Oper,X5F3 ?
ABS, YSRE Oper, Y5B3 ?
IND, XSRE (Oper,X)432 ?
IND, YSRE (Oper),Y532 ?


Порядок декодирования команд

Любую команду 6502 можно представить следующим образом:

XXXYYYZZ
└┬┘└┬┘└┤
 │  │  └── Группа команд
 │  └───── Режим адресации
 └──────── Код команды

Таким образом, для уменьшения сравнений можно использовать следующий алгоритм:

swith ZZ:
          case 0:
                 switch XXX:
                            case 0:
                                   //Команды 000yyy00
                                   Do_Command_0(yyy);
                            break;
                            case 1:
                                   //Команды 001yyy00
                                   Do_Command_1(yyy);
                            break;
                            // etc
                 end;
          case 1:
                 switch XXX:
                            case 0:
                                   //Команды 000yyy01
                                   Do_Command_2(yyy);
                            break;
                            case 1:
                                   //Команды 001yyy01
                                   Do_Command_3(yyy);
                            break;
                            // etc
                 end;
          break
end;     

Далее все команды сгруппированы по этому принципу.

  • «*» отмечены недокументированные команды)
  • HALT обозначает зависание процессора
  • «*NOP mode» обозначает, что команда эквивалента «LDA mode», но результат не сохраняется и флаги не меняются.
??? 000xxx00
       000   BRK
       001   *NOP zp
       010   PHP
       011   *NOP abs
       100   BPL
       101   *NOP zp,x
       110   CLC
       111   *NOP abs,x

??? 001xxx00
       000   JSR
       001   BIT zp
       010   PLP impl
       011   BIT abs
       100   BMI rel
       101   *NOP zp,x
       110   SEC impl
       111   *NOP abs,x
 
??? 010xxx00
       000   RTI
       001   *NOP zp
       010   PHA impl
       011   JMP abs
       100   BVC rel
       101   *NOP zp,x
       110   CLI impl
       111   *NOP abs,x

??? 011xxx00
       000   RTS
       001   *NOP zp
       010   PLA impl
       011   JMP (abs)
       100   BVS rel
       101   *NOP zp,x
       110   SEI impl
       111   *NOP abs,x

??? 100xxx00
       000   *NOP
       001   STY zp
       010   DEY impl
       011   STY abs
       100   BCC rel
       101   STY zp,x
       110   TYA impl
       111   *SHY abs,x

??? 101xxx00
       000   LDY
       001   LDY zp
       010   TAY impl
       011   LDY abs
       100   BCS rel
       101   LDY zp,x
       110   CLV impl
       111   LDY abs,x

??? 110xxx00
       000   CPY
       001   CPY zp
       010   INY impl
       011   CPY abs
       100   BNE rel
       101   *NOP zp,x
       110   CLD impl
       111   *NOP abs,x

??? 111xxx00
       000   CPX
       001   CPX zp
       010   INX impl
       011   CPX abs
       100   BEQ rel
       101   *NOP zp,x
       110   SED impl
       111   *NOP abs,x

ORA 000xxx01
       000   ind,x
       001   zp
       010   immed
       011   abs
       100   ind,y
       101   zp,x
       110   abs,y
       111   abs,x

AND 001xxx01
EOR 010xxx01
ADC 011xxx01
STA 100xxx01
LDA 101xxx01
CMP 110xxx01
SBC 111xxx01

ASL 000xxx10
       000   *HALT
       001   zp
       010   accum
       011   abs
       100   *HALT
       101   zp,x
       110   *NOP
       111   abs,x

ROL 001xxx10
       000   *HALT
       001   zp
       010   accum
       011   abs
       100   *HALT
       101   zp,x
       110   *NOP
       111   abs,x

LSR 010xxx10
       000   *HALT
       001   zp
       010   accum
       011   abs
       100   *HALT
       101   zp,x
       110   *NOP
       111   abs,x

ROR 011xxx10
       000   *HALT
       001   zp
       010   accum
       011   abs
       100   *HALT
       101   zp,x
       110   *NOP
       111   abs,x

STX 100xxx10
       000   *NOP(HALT)
       001   zp
       010   TXA (accum)
       011   abs
       100   *HALT
       101   zp,y
       110   TXS
       111   *SHX**y)

LDX 101xxx10
       000   imm
       001   zp
       010   TAX (accum)
       011   abs
       100   *HALT
       101   zp,y
       110   TSX
       111   *y)

DEC 110xxx10
       000   *NOP(HALT)
       001   zp
       010   DEX (impl)
       011   abs
       100   *HALT
       101   zp,x
       110   *NOP
       111   abs,x

INC 111xxx10
       000   *NOP(HALT)
       001   zp
       010   NOP (impl)
       011   abs
       100   *HALT
       101   zp,x
       110   *NOP
       111   abs,x

*SLO 000xxx11
       000   *SLO ind,x
       001   *SLO zp
       010   *ANC imm
       011   *SLO abs
       100   *SLO ind,y
       101   *SLO zp,x
       110   *SLO abs,y
       111   *SLO abs,x

*RLA 001xxx11
       000   *RLA ind,x
       001   *RLA zp
       010   *ANC imm
       011   *RLA abs
       100   *RLA ind,y
       101   *RLA zp,x
       110   *RLA abs,y
       111   *RLA abs,x

*SRE 010xxx11
       000   *SRE ind,x
       001   *SRE zp
       010   *ASR imm
       011   *SRE abs
       100   *SRE ind,y
       101   *SRE zp,x
       110   *SRE abs,y
       111   *SRE abs,x

*RRA 011xxx11
       000   *RRA ind,x
       001   *RRA zp
       010   *ARR imm
       011   *RRA abs
       100   *RRA ind,y
       101   *RRA zp,x
       110   *RRA abs,y
       111   *RRA abs,x

*??? 100xxx11
        000   *SAX ind,x
        001   *SAX zp
        010   *ANE imm
        011   *SAX abs
        100   *SHA ind,y
        101   *SAX* y)
        110   *SHS abs,y
        111   *SHA**y)

*??? 101xxx11
        000   *LAX ind,x
        001   *LAX zp
        010   *LXA imm
        011   *LAX abs
        100   *LAX ind,y
        101   *LAX* y)
        110   *LAS abs,y
        111   *LAX* y)

*DCP 110xxx11
       000   *DCP ind,x
       001   *DCP zp
       010   *SBX imm
       011   *DCP abs
       100   *DCP ind,y
       101   *DCP zp,x
       110   *DCP abs,y
       111   *DCP abs,x

*ISB 111xxx11
       000   *ISB ind,x
       001   *IBS zp
       010   *SBC imm
       011   *ISB abs
       100   *ISB ind,y
       101   *ISB zp,x
       110   *ISB abs,y
       111   *ISB abs,x

Источники