§ Код на Verilog
В 6502 процессоре все методы адресации описываются очень простым способом
1casex (data)
2
3 8'bxxx_000_x1: cpu_state <= NDX;
4 8'bxxx_010_x1,
5 8'b1xx_000_x0: cpu_state <= IMM;
6 8'bxxx_100_x1: cpu_state <= NDY;
7 8'bxxx_110_x1: cpu_state <= ABY;
8 8'bxxx_001_xx: cpu_state <= ZP;
9 8'bxxx_011_xx,
10 8'b001_000_00: cpu_state <= ABS;
11 8'b10x_101_1x: cpu_state <= ZPY;
12 8'bxxx_101_xx: cpu_state <= ZPX;
13 8'b10x_111_1x: cpu_state <= ABY;
14 8'bxxx_111_xx: cpu_state <= ABX;
15 8'bxxx_100_00: cpu_state <= REL;
16 8'b0xx_010_10: cpu_state <= ACC;
17 default: cpu_state <= IMP;
18
19endcase
§ Расшифровка методов адресации
- АСС - аккумуляторная, подразумевает наличие операнда в регистре 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
1
2switch (operand_type) {
3
4
5
6 case NDX: {
7
8 tmp = read(addr);
9 tmp = (tmp + reg.x) & 0xff;
10 return read(tmp) + ((read((1 + tmp) & 0xff) << 8));
11 }
12
13
14 case NDY: {
15
16 tmp = read(addr);
17 rt = read(tmp & 0xFF) + 256*read((tmp + 1) & 0xFF);
18 pt = rt;
19 rt = (rt + reg.y) & 0xFFFF;
20
21 if ((pt & 0xFF00) != (rt & 0xFF00))
22 cycles_ext++;
23
24 return rt;
25 }
26
27
28 case ZP: return read( addr );
29
30
31 case ZPX: return (read(addr) + reg.x) & 0x00ff;
32
33
34 case ZPY: return (read(addr) + reg.y) & 0x00ff;
35
36
37 case ABS: return readw(addr);
38
39
40 case ABX: {
41
42 pt = readw(addr);
43 rt = pt + reg.x;
44
45 if ((pt & 0xff00) != (rt & 0xff00))
46 cycles_ext++;
47
48 return rt & 0xffff;
49 }
50
51
52 case ABY: {
53
54 pt = readw(addr);
55 rt = pt + reg.y;
56
57 if ((pt & 0xff00) != (rt & 0xff00))
58 cycles_ext++;
59
60 return rt & 0xFFFF;
61 }
62
63
64 case IND: {
65
66 addr = readw(addr);
67 iaddr = read(addr) + 256*read((addr & 0xFF00) + ((addr + 1) & 0x00FF));
68 return iaddr;
69 }
70
71
72 case REL: {
73
74 iaddr = read(addr);
75 return (iaddr + addr + 1 + (iaddr < 128 ? 0 : -256)) & 0xffff;
76 }
77}