| Этот документ создан для 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
Источники
Комментариев нет:
Отправить комментарий