Опубликован: 17.03.2025 | Доступ: свободный | Студентов: 0 / 0 | Длительность: 07:30:00
Лекция 7:

Архитектура процессоров

Набор инструкций RISC-V

Подход создания базового набора инструкций с выбором необходимых расширений в RISC-V позволяет беспрепятственно развивать архитектуру без затруднений для обратной совместимости. Также обеспечивается возможность производить на единой архитектуре чипы с одинаковой эффективностью, предназначенные для различных сегментов, например, встраиваемых системы где делается упор на энергоэффективность и цену, либо пользовательские решения, где важна производительность.

Как и в остальных архитектурах, операции в RISC-V кодируются в особый формат, однако (за исключением особого расширения сжатых инструкций), инструкции имеют всегда одинаковую длину кодировки (32 бит) вне зависимости от разрядности процессора. Такой подход существенно упрощает декодирование инструкций, работу с памятью и повторное использование частей расширения непосредственно в реализациях других процессоров.

Ниже перечислены базовые инструкции работы процессора RISC-V RVI32, необходимые для собственной реализации ядра процессора:

1. Арифметические инструкции

ADD: сложение.

Пример: ADD x3, x1, x2 - сложение значений в регистрах x1 и x2, результат записывается в x3.

SUB: вычитание.

Пример: SUB x3, x1, x2 - вычитание значения x2 из x1, результат записывается в x3.

2. Логические инструкции

AND: логическое И.

Пример: AND x3, x1, x2 - побитовое И значений в регистрах x1 и x2, результат записывается в x3.

OR: логическое ИЛИ.

Пример: OR x3, x1, x2 - побитовое ИЛИ значений в регистрах x1 и x2, результат записывается в x3.

XOR: исключающее ИЛИ.

Пример: XOR x3, x1, x2 - побитовое исключающее ИЛИ, результат записывается в x3.

3. Инструкции для работы с памятью

LW: загрузка слова из памяти.

Пример: LW x3, 0(x1) - загрузка 32-битного слова из адреса, основанного на значении в x1, в регистр x3.

SW: запись слова в память.

Пример: SW x3, 0(x1) - запись 32-битного слова из x3 по адресу, основанному на значении в x1.

4. Управление потоком выполнения

JAL: переход с сохранением адреса возврата.

Пример: JAL x1, label - переход к метке label, адрес возврата сохраняется в x1.

LUI: загрузка верхней части значения.

Пример: LUI x1, 0x12345 - загрузка значения 0x12345000 в регистр x1.

BEQ: условный переход (если равно)

Пример: BEQ x1, x2, label - переход к метке label, если значения в x1 и x2 равны.

JALR: переход по адресу в регистре с сохранением адреса возврата.

Пример: JALR x1, 0(x5) # Переход к адресу, указанному в x5. Возврат по выполнении по адресу, сохраненному в x1.

AUIPC: добавление адреса текущей инструкции.

Пример: AUIPC x1, 0x10 - добавляет к адресу текущей инструкции значение 0x10, результат помещается в x1.

BNE: условный переход (если не равно).

Пример: BNE x1, x2, label - переход к метке label, если значения в x1 и x2 не равны.

5. Инструкции для работы с непосредственными данными

ADDI: сложение с немедленным значением.

Пример: ADDI x3, x1, 10 - сложение значения в x1 с 10, результат записывается в x3.

SLTI: сравнение меньше с немедленным значением.

Пример: SLTI x3, x1, 10 - x3 будет равно 1, если x1 < 10, иначе 0.

6. Инструкции для операций с битами

SLL: сдвиг влево.

Пример: SLL x3, x1, 2 - сдвиг значения в x1 на 2 бита влево, результат записывается в x3.

SRL: логический сдвиг вправо.

Пример: SRL x3, x1, 2 - логический сдвиг значения в x1 на 2 бита вправо.

Все инструкции в RISC-V разделены на 6 типов:

  1. R - операции АЛУ типа регистр - регистр;
  2. I - операции АЛУ с непосредственным значением в команде;
  3. S - операции загрузки/сохранения;
  4. B - условная передача управления;
  5. U - операции с расширенным непосредственным значением;
  6. J - безусловная передача управления.

Форматы типов инструкций представлены на рисунке 7.9 и определены в "The RISC-V Instruction Set Manual " [6]. В приложении Б приведен перечень инструкции для базовой версии RV32I


Рис. 7.9.

Рассмотрим пример кодировки инструкции add - инструкции суммирования содержимого двух регистров и записи результата в третий регистр. На рисунке 7.10 представлен пример кодировки соответствующей инструкции.


Рис. 7.10.

Первая строчка отображает то, как будет записана типовая инструкция в данном расширении. Opcode - номер операции, который описан в документации на каждую инструкцию константным значением. В случае с инструкцией add это будет 0110011, rd - номер регистра назначения результата. Funct3 - указатель дешифратору операций, какую операцию реализовывать, на случай если opcode инструкций одинаковы, rs1 - номер первого операнда. rs2 - номер второго операнда. Оставшаяся часть заполняется нулями. При детальном рассмотрении типовой кодировки и кодировки конкретной инструкции можно заметить, что у нас отсутствует imm(произвольная константа), которая занимает 12 бит. Это связано с тем, что логика инструкции сделана так, что никаких констант не требуется. Освободившееся место использовано для второго операнда, положение которого не стандартизировано в типовой кодировке. Если бы у нас была константа, но не было нужды в номере регистра второго операнда, то операнд находился именно в поле с 31 по20-ый бит. Таким образом, при сложении r1 и r2 с записью результата в r3, кодировка будет иметь следующий вид: 0000000_00010_00001_000_00011_0110011.

При изучении и в сравнении с другими системами ISA можно заметить, что процессоры RISC-V на уровне микроархитектуры в силу упрощения и повышения быстродействия не реализуют множество инструкций, характерных для других решений. Поэтому в компиляторы ассемблера заложены псевдо-инструкции, которые может применять программист, а они в свою очередь будут транслированы в инструкции, реализуемые процессором. В таблицу 7.2 сведены псевдо-инструкции, транслируемые в инструкции процессоров RISC-V.

Таблица 7.2.
Псевдо-инструкция Инструкция RISC-V Описание
nop addi zero,zero,0 нет операции
mv rd, rs1 addi rd, rs, 0 Копирование между регистрами rs в rd
not rd, rs1 xori rd, rs, -1 Запись в rd логической инверсии RS (все биты проходят операцию XOR с 1)
neg rd, rs1 sub rd, x0, rs Запись в rd числа в обратном коде rs
seqz rd, rs1 sltiu rd, rs, 1 Устанавливает результат в 1 если rs <1
snez rd, rs1 sltu rd, x0, rs Устанавливает результат в 1 если rs не равен 0
sltz rd, rs1 slt rd, rs, x0 Устанавливает результат в 1 если rs < 0
sgtz rd, rs1 slt rd, x0, rs Устанавливает результат в 1 если rs >0
beqz rs1, offset beq rs, x0, offset Переход если равно 0
bnez rs1, offset bne rs, x0, offset Переход если не равно 0
blez rs1, offset bge x0, rs, offset Переход если меньше или равно 0
bgez rs1, offset bge rs, x0, offset Переход если больше или равно 0
bltz rs1, offset blt rs, x0, offset Переход если меньше 0
bgtz rs1, offset blt x0, rs, offset Переход если больше 0
bgt rs, rt, offset blt rt, rs, offset Переход если больше
ble rs, rt, offset bge rt, rs, offset Переход если меньше или равно
bgtu rs, rt, offset bltu rt, rs, offset Условный переход сравнить два беззнаковых числа. Если rs >rt переход по адресу offset
j offset jal x0, offset безусловный переход
jr offset jal x1, offset Безусловный переход по адресу, адрес возврата в x1
ret jalr x0, x1, 0 Возврат из функции