§ Код на 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    // PEEK( PEEK( (arg + X) % 256) + PEEK((arg + X + 1) % 256) * 256
5    // Indirect, X (b8,X)
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    // Indirect, Y (b8),Y
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    // Zero Page
28    case ZP:  return read( addr );
29
30    // Zero Page, X
31    case ZPX: return (read(addr) + reg.x) & 0x00ff;
32
33    // Zero Page, Y
34    case ZPY: return (read(addr) + reg.y) & 0x00ff;
35
36    // Absolute
37    case ABS: return readw(addr);
38
39    // Absolute, X
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    // Absolute, Y
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    // Indirect
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    // Relative
72    case REL: {
73
74        iaddr = read(addr);
75        return (iaddr + addr + 1 + (iaddr < 128 ? 0 : -256)) & 0xffff;
76    }
77}