§ Код на Verilog
В 6502 процессоре все методы адресации описываются очень простым способомcasex (data) 8'bxxx_000_x1: cpu_state <= NDX; 8'bxxx_010_x1, 8'b1xx_000_x0: cpu_state <= IMM; 8'bxxx_100_x1: cpu_state <= NDY; 8'bxxx_110_x1: cpu_state <= ABY; 8'bxxx_001_xx: cpu_state <= ZP; 8'bxxx_011_xx, 8'b001_000_00: cpu_state <= ABS; 8'b10x_101_1x: cpu_state <= ZPY; 8'bxxx_101_xx: cpu_state <= ZPX; 8'b10x_111_1x: cpu_state <= ABY; 8'bxxx_111_xx: cpu_state <= ABX; 8'bxxx_100_00: cpu_state <= REL; 8'b0xx_010_10: cpu_state <= ACC; default: cpu_state <= IMP; endcase
§ Расшифровка методов адресации
- АСС - аккумуляторная, подразумевает наличие операнда в регистре A процессора (что требуется указать в мнемонике).
- IMM - непосредственная, 8-разрядный операнд расположен сразу за кодом команды (в мнемонической записи перед непосредственным операндом ставится символ «#»).
- ABS - прямая, в команде указывается полный 16-разрядный адрес операнда:
- ABS, X (ABX) - индексированная по X, указывается базовый 16-разрядный адрес, к которому прибавляется смещение из регистра X;
- ABS, Y (ABY) - индексированная по Y, указывается базовый 16-разрядный адрес, к которому прибавляется смещение из регистра Y.
- IMPL - неявная (указывается лишь мнемоника), операнды не указываются - жесткая логика работы инструкции.
- IND - косвенная, задается адрес ячейки памяти, в которой хранится адрес операнда - бывает следующих видов: NDX, NDY.
- IND, X (NDX) - индексно-косвенная, указывается 8-разрядный адрес в нулевой странице (в квадратных скобках), к которому прибавляется содержимое регистра X, после чего из ячейки памяти с вычисленным адресом и следующей за ней извлекается полный 16-разрядный адрес операнда (в мнемонике после адреса через запятую ставится и "X"). Другими словами - в области нулевой страницы создается таблица адресов, а при помощи переменной в регистре "X" можно по ним "бегать";
- IND, Y (NDY) - косвенно-индексная, указывается 8-разрядный адрес в нулевой странице (в квадратных скобках), после чего из заданной ячейки памяти и следующей за ней считывается 16-разрядный базовый адрес, к которому прибавляется содержимое регистра Y, и из ячейки с вычисленным адресом извлекается операнд (в мнемонике после адреса через запятую ставится и "Y"). В данном случае переменная в регистре "Y" играет роль смещения относительно адреса базы, хранящегося в нулевой странице;
- REL - относительная, в команде указывается 8-разрядное смещение относительно содержимого счетчика команд PC;
- ZP - адресация нулевой страницы, в команде задается 8-разрядный адрес, определяющий ячейку памяти нулевой страницы, где хранится операнд;
- ZP, X (ZPX) - индексированная по X адресация нулевой страницы, указывается 8-разрядный базовый адрес в нулевой странице, к которому прибавляется содержимое регистра X, и из ячейки памяти с вычисленным адресом извлекается операнд;
- ZP, Y (ZPY) - индексированная по Y адресация нулевой страницы, в нулевой странице указывается 8-разрядный базовый адрес, к которому прибавляется содержимое регистра Y, и из ячейки памяти с вычисленным адресом извлекается операнд.
§ Декодирование метода адресации на JS
// Разобрать операнд switch (operand_type) { // PEEK( PEEK( (arg + X) % 256) + PEEK((arg + X + 1) % 256) * 256 // Indirect, X (b8,X) case NDX: { tmp = read( addr ); tmp = (tmp + reg.x) & 0xff; return read( tmp ) + ((read((1 + tmp) & 0xff) << 8)); } // Indirect, Y (b8),Y case NDY: { tmp = read(addr); rt = read(0xff & tmp); rt |= read(0xff & (tmp + 1)) << 8; pt = rt; rt = (rt + reg.y) & 0xffff; if ((pt & 0xff00) !== (rt & 0xff00)) cycles_ext++; return rt; } // Zero Page case ZP: return read( addr ); // Zero Page, X case ZPX: return (read(addr) + reg.x) & 0x00ff; // Zero Page, Y case ZPY: return (read(addr) + reg.y) & 0x00ff; // Absolute case ABS: return readw(addr); // Absolute, X case ABX: { pt = readw(addr); rt = pt + reg.x; if ((pt & 0xff00) !== (rt & 0xff00)) cycles_ext++; return rt & 0xffff; } // Absolute, Y case ABY: { pt = readw(addr); rt = pt + reg.y; if ((pt & 0xff00) !== (rt & 0xff00)) cycles_ext++; return rt & 0xffff; } // Indirect case IND: { addr = readw(addr); iaddr = read(addr) + 256*read((addr & 0xFF00) + ((addr + 1) & 0x00FF)); return iaddr; } // Relative case REL: { iaddr = read(addr); return (iaddr + addr + 1 + (iaddr < 128 ? 0 : -256)) & 0xffff; } }
6 мая, 2020
© 2007-2023 Психичная мышь шила