§ Код на 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(tmp & 0xFF) + 256*read((tmp + 1) & 0xFF);
        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;
    }
}