MOS Technology 6502/Система команд: различия между версиями

Материал из Emuverse
мНет описания правки
Строка 838: Строка 838:


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


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

Версия от 12:19, 13 октября 2009

Этот документ создан для 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 #$0A A9 02
Absolute Абсолютная (прямая) Адрес операнда располагается сразу за кодом инструкции LDA $1234 AD 34 12
Zeropage Абсолютная на нулевой странице (для адресов 00H-0FFH) LDA $2F A5 2F
Accumulator/Implied Аккумуляторная/Неявная Операнд подразумевается самой командой. TAX AA
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, X B5 2F
Indirect Косвенная Только в команде JMP. Новый адрес для счетчика команд берется из памяти, по адресу, указанному за кодом команды (ADDR) JMP ($1234) 6С 34 12
Indirect, x Индексно-косвенная на нулевой странице Адрес операнда складывается из байта, следующего за кодом команды и содержимого регистра X. Важно! Старший байт суммы отбрасывается! (ADDR, X) LDA ($3E, X) A1 3E
Indirect, y Косвенно-индексная Адрес операнда складывается из двух байт в нулевой странице по адресу, указанному вторым байтом команды, и регистра Y. (ADDR), Y LDA ($4C), Y B1 4C
Relative Относительная Используется в условных переходах. Второй байт команды (как число со знаком от −128 до +127) добавляется к счетчику команд при выполнении условия. Важно! При сложении используется адрес команды, следующей за командой условного перехода, а не адрес выполняемой команды! BEQ $A7 F0 A7

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

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

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

Тайминги

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

ADC

A + M + C -> A, C N V 1 B D I Z C
* * - - - - * *
Сложение с переносом
Адресация Обозначение Код Длина Время
IMM ADC #Oper 69 2 2
ZP ADC Oper 65 2 3
ZP, X ADC Oper,X 75 2 4
ABS ADC Oper 6D 3 4
ABS, X ADC Oper,X 7D 3 4*
ABS, Y ADC Oper,Y 79 3 4*
IND, X ADC (Oper,X) 61 2 6
IND, Y ADC (Oper),Y 71 2 5*


AND

A and M -> A N V 1 B D I Z C
* - - - - - * -
Логическое AND
Адресация Обозначение Код Длина Время
IMM AND #Oper 29 2 2
ZP AND Oper 25 2 3
ZP, X AND Oper,X 35 2 4
ABS AND Oper 2D 3 4
ABS, X AND Oper,X 3D 3 4*
ABS, Y AND Oper,Y 39 3 4*
IND, X AND (Oper,X) 21 2 6
IND, Y AND (Oper),Y 31 2 5


ASL

C <- [A или M] <- 0 N V 1 B D I Z C
* - - - - - * *
Арифметический сдвиг влево
Адресация Обозначение Код Длина Время
ACC ASL A 0A 1 2
ZP ASL Oper 06 2 5
ZP, X ASL Oper,X 16 2 6
ABS ASL Oper 0E 3 6
ABS, X ASL Oper,X 1E 3 7


BCC

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


BCS

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


BEQ

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


BIT

(A and M) == 0 -> Z, M7 -> N, M6 -> V N V 1 B D I Z C
* * - - - - * -
Проверка битов
Адресация Обозначение Код Длина Время
ZP BIT Oper 24 2 3
ABS BIT Oper 2C 3 4


BMI

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


BNE

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


BPL

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


BRK

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


BVC

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


BVS

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


CLC

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


CLD

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


CLI

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


CLV

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


CMP

A – M N V 1 B D I Z C
* - - - - - * *
Сравнение аккумулятора с памятью
Адресация Обозначение Код Длина Время
IMM CMP #Oper C9 2 2
ZP CMP Oper C5 2 3
ZP, X CMP Oper,X D5 2 4
ABS CMP Oper CD 3 4
ABS, X CMP Oper,X DD 3 4*
ABS, Y CMP Oper,Y D9 3 4*
IND, X CMP (Oper,X) C1 2 6
IND, Y CMP (Oper),Y D1 2 5*


CPX

X – M N V 1 B D I Z C
* - - - - - * *
Сравнение X с памятью
Адресация Обозначение Код Длина Время
IMM CPX *Oper E0 2 2
ZP CPX Oper E4 2 3
ABS CPX Oper EC 3 4


CPY

Y – M N V 1 B D I Z C
* - - - - - * *
Сравнение Y с памятью
Адресация Обозначение Код Длина Время
IMM CPY *Oper C0 2 2
ZP CPY Oper C4 2 3
ABS CPY Oper CC 3 4


DEC

M – 1 -> M N V 1 B D I Z C
* - - - - - * -
Декремент памяти
Адресация Обозначение Код Длина Время
ZP DEC Oper C6 2 5
ZP, X DEC Oper,X D6 2 6
ABS DEC Oper CE 3 6
ABS, X DEC Oper,X DE 3 7


DEX

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


DEY

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


EOR

A xor M -> A N V 1 B D I Z C
* - - - - - * -
Логическое XOR
Адресация Обозначение Код Длина Время
IMM EOR #Oper 49 2 2
ZP EOR Oper 45 2 3
ZP, X EOR Oper,X 55 2 4
ABS EOR Oper 4D 3 4
ABS, X EOR Oper,X 5D 3 4*
ABS, Y EOR Oper,Y 59 3 4*
IND, X EOR (Oper,X) 41 2 6
IND, Y EOR (Oper),Y 51 2 5*


INC

M + 1 -> M N V 1 B D I Z C
* - - - - - * -
Инкремент памяти
Адресация Обозначение Код Длина Время
ZP INC Oper E6 2 5
ZP, X INC Oper,X F6 2 6
ABS INC Oper EE 3 6
ABS, X INC Oper,X FE 3 7


INX

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


INY

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


JMP

(PC+1) -> PC или ((PC+1)) -> PC N V 1 B D I Z C
- - - - - - - -
Безусловный переход
Адресация Обозначение Код Длина Время
ABS JMP Oper 4C 3 3
IND JMP (Oper) 6C 3 5


JSR

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


LDA

M -> A N V 1 B D I Z C
* - - - - - * -
Загрузка аккумулятора
Адресация Обозначение Код Длина Время
IMM LDA #Oper A9 2 2
ZP LDA Oper A5 2 3
ZP, X LDA Oper,X B5 2 4
ABS LDA Oper AD 3 4
ABS, X LDA Oper,X BD 3 4*
ABS, Y LDA Oper,Y B9 3 4*
IND, X LDA (Oper,X) A1 2 6
IND, Y LDA (Oper),Y B1 2 5*


LDX

M -> X N V 1 B D I Z C
* - - - - - * -
Загрузка X
Адресация Обозначение Код Длина Время
IMM LDX #Oper A2 2 2
ZP LDX Oper A6 2 3
ZP, Y LDX Oper,Y B6 2 4
ABS LDX Oper AE 3 4
ABS, Y LDX Oper,Y BE 3 4*


LDY

M -> Y N V 1 B D I Z C
* - - - - - * -
Загрузка Y
Адресация Обозначение Код Длина Время
IMM LDY #Oper A0 2 2
ZP LDY Oper A4 2 3
ZP, X LDY Oper,X B4 2 4
ABS LDY Oper AC 3 4
ABS, X LDY Oper,X BC 3 4*


LSR

0 -> [A или M] -> С N V 1 B D I Z C
0 - - - - - * *
Логический сдвиг вправо
Адресация Обозначение Код Длина Время
ACC LSR A 4A 1 2
ZP LSR Oper 46 2 5
ZP, X LSR Oper,X 56 2 6
ABS LSR Oper 4E 3 6
ABS, X LSR Oper,X 5E 3 7


NOP

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


ORA

A or M -> A N V 1 B D I Z C
* - - - - - * -
Логическое OR
Адресация Обозначение Код Длина Время
IMM ORA #Oper 09 2 2
ZP ORA Oper 05 2 3
ZP, X ORA Oper,X 15 2 4
ABS ORA Oper 0D 3 4
ABS, X ORA Oper,X 1D 3 4*
ABS, Y ORA Oper,Y 19 3 4*
IND, X ORA (Oper,X) 01 2 6
IND, Y ORA (Oper),Y 11 2 5


PHA

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


PHP

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


PLA

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


PLP

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


ROL

<- [A или M] <- C <- N V 1 B D I Z C
* - - - - - * *
Циклический сдвиг влево
Адресация Обозначение Код Длина Время
ACC ROL A 2A 1 2
ZP ROL Oper 26 2 5
ZP, X ROL Oper,X 36 2 6
ABS ROL Oper 2E 3 6
ABS, X ROL Oper,X 3E 3 7


ROR

-> C -> [A или M] -> N V 1 B D I Z C
* - - - - - * *
Циклический сдвиг вправо
Адресация Обозначение Код Длина Время
ACC ROR A 6A 1 2
ZP ROR Oper 66 2 5
ZP, X ROR Oper,X 76 2 6
ABS ROR Oper 6E 3 6
ABS, X ROR Oper,X 7E 3 7

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

RTI

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


RTS

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


SBC

A - M - C -> A, C N V 1 B D I Z C
* * - - - - * *
Вычитание с займом
Адресация Обозначение Код Длина Время
IMM SBC #Oper E9 2 2
ZP SBC Oper E5 2 3
ZP, X SBC Oper,X F5 2 4
ABS SBC Oper ED 3 4
ABS, X SBC Oper,X FD 3 4*
ABS, Y SBC Oper,Y F9 3 4*
IND, X SBC (Oper,X) E1 2 6
IND, Y SBC (Oper),Y F1 2 5


SEC

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


SED

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


SEI

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


STA

A -> M N V 1 B D I Z C
- - - - - - - -
Сохранить аккумулятор в памяти
Адресация Обозначение Код Длина Время
ZP STA Oper 85 2 3
ZP, X STA Oper,X 95 2 4
ABS STA Oper 8D 3 4
ABS, X STA Oper,X 9D 3 5
ABS, Y STA Oper, Y 99 3 5
IND, X STA (Oper,X) 81 2 6
IND, Y STA (Oper),Y 91 2 6


STX

X -> M N V 1 B D I Z C
- - - - - - - -
Сохранить X в памяти
Адресация Обозначение Код Длина Время
ZP STX Oper 86 2 3
ZP, Y STX Oper,Y 96 2 4
ABS STX Oper 8E 3 4


STY

Y -> M N V 1 B D I Z C
- - - - - - - -
Сохранить Y в памяти
Адресация Обозначение Код Длина Время
ZP STY Oper 84 2 3
ZP, X STY Oper,X 94 2 4
ABS STY Oper 8C 3 4


TAX

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


TAY

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


TSX

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


TXA

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


TXS

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

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

TYA

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


Особенности

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

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

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 -> A N V 1 B D I Z C
* - - - - - * -
Адресация Обозначение Код Длина Время
IMM ANE #byte 8B 2  ?

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

ANC

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


ANC?

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


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
* * - - - - * *
Адресация Обозначение Код Длина Время
IMM ARR #byte 6B 2?  ?

Примечание: Алгоритм для 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 A N V 1 B D I Z C
* - - - - - * *
Адресация Обозначение Код Длина Время
IMM ASR #Oper 4B 2  ?


DCP (DEC + CMP)

M + 1 -> M, A – M N V 1 B D I Z C
* - - - - - * *
Адресация Обозначение Код Длина Время
ZP DCP Oper C7 2  ?
ZP, X DCP Oper,X D7 2  ?
ABS DCP Oper CF 3  ?
ABS, X DCP Oper,X DF 3  ?
ABS, Y DCP Oper, Y DB 3  ?
IND, X DCP (Oper,X) C3 2  ?
IND, Y DCP (Oper),Y D3 2  ?



ISB (INC + SBC)

M + 1 -> M, A – M -> A N V 1 B D I Z C
* * - - - - * *
Адресация Обозначение Код Длина Время
ZP ISB Oper E7 2  ?
ZP, X ISB Oper,X F7 2  ?
ABS ISB Oper EF 3  ?
ABS, X ISB Oper,X FF 3  ?
ABS, Y ISB Oper, Y FB 3  ?
IND, X ISB (Oper,X) E3 2  ?
IND, Y ISB (Oper),Y F3 2  ?



LAS

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


LAX

M -> A, X N V 1 B D I Z C
* - - - - - * -
Адресация Обозначение Код Длина Время
ZP LAX Oper A7 2  ?
ZP, Y! LAX Oper,Y B7 2  ?
ABS LAX Oper AF 3  ?
ABS, Y LAX Oper,Y BF 3  ?
IND, X LAX (Oper,Y) A3 2  ?
IND, Y LAX (Oper),Y B3 2  ?


LXA

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



RLA

ROL M, A and M -> A N V 1 B D I Z C
* - - - - - * *
Адресация Обозначение Код Длина Время
ZP RLA Oper 27 2  ?
ZP, X RLA Oper,X 37 2  ?
ABS RLA Oper 2F 3  ?
ABS, X RLA Oper,X 3F 3  ?
ABS, Y RLA Oper, Y 3B 3  ?
IND, X RLA (Oper,X) 23 2  ?
IND, Y RLA (Oper),Y 33 2  ?


RRA

ROR M, ADC(A, M) -> A N V 1 B D I Z C
* * - - - - * *
Адресация Обозначение Код Длина Время
ZP RRA Oper 67 2  ?
ZP, X RRA Oper,X 77 2  ?
ABS RRA Oper 6F 3  ?
ABS, X RRA Oper,X 7F 3  ?
ABS, Y RRA Oper, Y 7B 3  ?
IND, X RRA (Oper,X) 63 2  ?
IND, Y RRA (Oper),Y 73 2  ?


SAX

A and X -> M N V 1 B D I Z C
- - - - - - - -
Адресация Обозначение Код Длина Время
ZP SAX Oper 87 2  ?
ZP, Y! SAX Oper,Y 97 2  ?
ABS SAX Oper 8F 3  ?
IND, X SAX (Oper,X) 83 2  ?



SBX (CMP + DEX)

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

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

SHA

A & X & (ADDR_HI + 1)) -> M N V 1 B D I Z C
- - - - - - - -
Адресация Обозначение Код Длина Время
IND, Y SHA (Oper),Y 93 2  ?
ABS, Y SHA Oper,Y 9F 3  ?

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

SHS

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

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

SHX

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


SHY

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

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

SLO (ASL + ORA)

ASL M -> M, A or M -> A N V 1 B D I Z C
* - - - - - * *
Адресация Обозначение Код Длина Время
ZP SLO Oper 07 2  ?
ZP, X SLO Oper,X 17 2  ?
ABS SLO Oper 0F 3  ?
ABS, X SLO Oper,X 1F 3  ?
ABS, Y SLO Oper, Y 1B 3  ?
IND, X SLO (Oper,X) 03 2  ?
IND, Y SLO (Oper),Y 13 2  ?


SRE

LSR M -> M, A xor M -> A N V 1 B D I Z C
* - - - - - * *
Адресация Обозначение Код Длина Время
ZP SRE Oper 47 2  ?
ZP, X SRE Oper,X 57 2  ?
ABS SRE Oper 4F 3  ?
ABS, X SRE Oper,X 5F 3  ?
ABS, Y SRE Oper, Y 5B 3  ?
IND, X SRE (Oper,X) 43 2  ?
IND, Y SRE (Oper),Y 53 2  ?


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

Любую команду 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

Источники