Лисья Нора

§ Описание кодов

В данной таблице приведены все документированные инструкции процессора 6502 с описанием алгоритма на Си для помощи в создании эмулятора.
КОДОписаниеIMMZPZPXABSABXABYINXINYIMPRELACCIND
ADCСложение с учетом флага переноса: А + d8 + С. Результат в аккумуляторе А и флаге переноса C6965756D7D7961
unsigned int temp = src + AC + (IF_CARRY() ? 1 : 0);
/* This is not valid in decimal mode */
SET_ZERO(temp & 0xFF);
if (IF_DECIMAL()) {
if (((AC & 0x0F) + (src & 0x0F) + (IF_CARRY() ? 1 : 0)) > 9) temp += 6;
SET_SIGN(temp);
SET_OVERFLOW(((AC ^ src ^ 0x80) & 0x80) && ((AC ^ temp) & 0x80) );
if (temp > 0x99) temp += 96;
SET_CARRY(temp > 0x99);
} else {
SET_SIGN(temp);
SET_OVERFLOW(((AC ^ src ^ 0x80) & 0x80) && ((AC ^ temp) & 0x80) );
SET_CARRY(temp > 0xFF);
}
AC = ((BYTE) temp);
ANDПоразрядное логическое И аккумулятора и операнда292535...2D3D392131.........
src &= AC;
SET_SIGN(src);
SET_ZERO(src);
AC = src;
ASLАрифметический сдвиг операнда влево (умножение на 2)...0616...0E1E...............0A
SET_CARRY(src & 0x80);
src <<= 1;
src &= 0xFF;
SET_SIGN(src);
SET_ZERO(src);
STORE src /* в память или аккумулятор, зависит от метода адресации */
BCCПереход, если флаг C = 0..............................90...
if (!IF_CARRY()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
BCSПереход, если флаг C = 1..............................B0...
if (IF_CARRY()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
BEQПереход, если флаг Z = 1..............................F0...
if (IF_ZERO()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
BITУстановка флагов в соответствии с результатом выполнения поразрядного логического И над содержимым аккумулятора и операнда. Бит 6 результата копируется во флаг V, а бит 7 - во флаг N...24......2C.....................
SET_SIGN(src);
SET_OVERFLOW(0x40 & src); /* Копированиь бит 6 в OVERFLOW флаг. */
SET_ZERO(src & AC);
BMIПереход, если флаг N = 1..............................30...
if (IF_SIGN()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
BNEПереход, если флаг Z = 0..............................D0...
if (!IF_ZERO()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
BPLПереход, если флаг N = 0..............................10...
if (!IF_SIGN()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
BRKПрограммное прерывание...........................00......
PC += 2
PUSH((PC >> 8) & 0xFF); /* Вставка обратного адреса в стек */
PUSH(PC & 0xFF);
SET_BREAK(1); /* Установить BFlag перед вставкой */
PUSH(SR);
SET_INTERRUPT(1);
PC = (LOAD(0xFFFE) | (LOAD(0xFFFF) << 8));
BVCПереход, если флаг V = 0..............................50...
if (!IF_OVERFLOW()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
BVSПереход, если флаг V = 1..............................70...
if (IF_OVERFLOW()) {
clk += ((PC & 0xFF00) != (REL_ADDR(PC, src) & 0xFF00) ? 2 : 1);
PC = REL_ADDR(PC, src);
}
CLCСброс флага C...........................18......
SET_CARRY(0);
CLDСброс флага D...........................D8......
SET_DECIMAL(0);
CLIСброс флага I (разрешение прерываний)...........................58......
SET_INTERRUPT(0);
CLVСброс флага V...........................B8......
SET_OVERFLOW(0);
CMPУстановка флагов в соответствии с результатом вычитания операнда из содержимого аккумулятораC9C5D5...CDDDD9C1D1.........
/* CF=1, если AC > src */
src = (AC - src);
SET_CARRY(src >= 0);
SET_SIGN(src);
SET_ZERO(src & 0xFF);
CPXУстановка флагов в соответствии с результатом вычитания операнда из содержимого регистра XE0E4......EC.....................
/* CF=1, если X > src */
src = (XR - src);
SET_CARRY(src >= 0);
SET_SIGN(src);
SET_ZERO(src & 0xFF);
CPYУстановка флагов в соответствии с результатом вычитания операнда из содержимого регистра YC0C4......CC.....................
/* CF=1, если Y > src */
src = (YR - src);
SET_CARRY(src >= 0);
SET_SIGN(src);
SET_ZERO(src & 0xFF);
DECУменьшение операнда на 1...C6D6...CEDE..................
src = (src - 1) & 0xFF;
SET_SIGN(src);
SET_ZERO(src);
STORE(address, (src));
DEXХ = Х-1...........................CA......
unsigned src = XR;
src = (src - 1) & 0xFF;
SET_SIGN(src);
SET_ZERO(src);
XR = (src);
DEYY = Y-1...........................88......
unsigned src = YR;
src = (src - 1) & 0xFF;
SET_SIGN(src);
SET_ZERO(src);
YR = (src);
EORПоразрядное Исключающее ИЛИ содержимого аккумулятора и операнда494555...4D5D594151.........
src ^= AC;
SET_SIGN(src);
SET_ZERO(src);
AC = src;
INCУвеличение операнда на 1...E6F6...EEFE..................
src = (src + 1) & 0xFF;
SET_SIGN(src);
SET_ZERO(src);
STORE(address, (src));
INXХ = X+1...........................E8......
unsigned src = XR;
src = (src + 1) & 0xFF;
SET_SIGN(src);
SET_ZERO(src);
XR = (src);
INYY = Y+1...........................C8......
unsigned src = YR;
src = (src + 1) & 0xFF;
SET_SIGN(src);
SET_ZERO(src);
YR = (src);
JMPПереход по указанному адресу............4C.....................
PC = (src)
JMPНепрямой переход по адресу....................................
unsigned address = read_word()
PC = memory[ address ] + 256*memory[ (address & 0xFF00) + ((address+1)&0x00FF) ];
JSRВызов подпрограммы с указанным адресом. В стеке сохраняется только адрес возврата............20.....................
PC--;
PUSH((PC >> 8) & 0xFF); /* Вставка обратного адреса в стек. */
PUSH(PC & 0xFF);
PC = (src);
LDAЗагрузка операнда в аккумуляторA9A5B5...ADBDB9A1B1.........
SET_SIGN(src);
SET_ZERO(src);
AC = (src);
LDXЗагрузка операнда в регистр XA2A6...B6AE...BE...............
SET_SIGN(src);
SET_ZERO(src);
XR = (src);
LDYЗагрузка операнда в регистр YA0A4B4...ACBC..................
SET_SIGN(src);
SET_ZERO(src);
YR = (src);
LSRЛогический сдвиг операнда вправо (деление на 2)...4656...4E5E...............4A
SET_CARRY(src & 0x01);
src >>= 1;
SET_SIGN(src);
SET_ZERO(src);
STORE src /* в память или аккумулятор, зависит от метода адресации */
NOPНет операции
Ничего не выполняется
ORAПоразрядное логическое ИЛИ содержимого аккумулятора и операнда090515...0D1D190111.........
src |= AC;
SET_SIGN(src);
SET_ZERO(src);
AC = src;
PHAПомещение содержимого аккумулятора в стек...........................48......
src = AC;
PUSH(src);
PHPПомещение регистра состояния в стек...........................08......
src = GET_SR | 0x30;
PUSH(src);
PLAПомещение байта с вершины стека в аккумулятор...........................68......
src = PULL();
SET_SIGN(src);
SET_ZERO(src);
PLPПомещение байта с вершины стека в регистр состояния...........................28......
src = PULL();
SET_SR((src));
ROLЦиклический сдвиг операнда влево...2636...2E3E...............2A
src <<= 1;
if (IF_CARRY()) src |= 0x1;
SET_CARRY(src > 0xFF);
src &= 0xFF;
SET_SIGN(src);
SET_ZERO(src);
STORE src /* в память или аккумулятор, зависит от метода адресации */
RORЦиклический сдвиг операнда вправо...6676...6E7E...............6A
if (IF_CARRY()) src |= 0x100;
SET_CARRY(src & 0x01);
src >>= 1;
SET_SIGN(src);
SET_ZERO(src);
STORE src /* в память или аккумулятор, зависит от метода адресации */
RTIВозврат из прерывания...........................40......
src = PULL();
SET_SR(src);
src = PULL();
src |= (PULL() << 8); /* Загрузка адреса из стека */
PC = (src);
RTSВозврат из подпрограммы...........................60......
src = PULL();
src += ((PULL()) << 8) + 1; /* Загрузить адрес из стека и добавить + 1 */
PC = (src);
SBCВычитание операнда из содержимого аккумулятора с учетом флага переносаE9E5F5...EDFDF9E1F1.........
unsigned int temp = AC - src - (IF_CARRY() ? 0 : 1);
SET_SIGN(temp);
SET_ZERO(temp & 0xFF); /* Sign и Zero неверны в Decimal mode */
SET_OVERFLOW(((AC ^ temp) & 0x80) && ((AC ^ src) & 0x80));
if (IF_DECIMAL()) {
if ( ((AC & 0xf) - (IF_CARRY() ? 0 : 1)) < (src & 0xf)) /* EP */ temp -= 6;
if (temp > 0x99) temp -= 0x60;
}
SET_CARRY(temp >= 0x00);
AC = (temp & 0xFF);
SECУстановка флага C...........................38......
SET_CARRY(1);
SEDУстановка флага D...........................F8......
SET_DECIMAL(1);
SEIУстановка флага I (запрещение прерываний)...........................78......
SET_INTERRUPT(1);
STAЗапись содержимого аккумулятора в память...8595...8D9D998191.........
STORE(address, (src));
STXЗапись содержимого регистра X в память...86...968E.....................
STORE(address, XR);
STYЗапись содержимого регистра Y в память...8494...8C.....................
STORE(address, YR);
TAXПересылка содержимого аккумулятора в регистр X...........................AA......
unsigned src = AC;
SET_SIGN(src);
SET_ZERO(src);
XR = (src);
TAYПересылка содержимого аккумулятора в регистр Y...........................A8......
unsigned src = AC;
SET_SIGN(src);
SET_ZERO(src);
YR = (src);
TSXПересылка содержимого указателя стека в регистр X...........................BA......
unsigned src = SP;
SET_SIGN(src);
SET_ZERO(src);
XR = (src);
TXAПересылка содержимого регистра X в аккумулятор...........................8A......
unsigned src = XR;
SET_SIGN(src);
SET_ZERO(src);
AC = (src);
TXSПересылка содержимого регистра X в указатель стека...........................9A......
unsigned src = XR;
SP = (src);
TYAПересылка содержимого регистра Y в аккумулятор...........................98......
unsigned src = YR;
SET_SIGN(src);
SET_ZERO(src);
AC = (src);