Опубликован: 19.01.2025 | Доступ: свободный | Студентов: 4 / 0 | Длительность: 02:34:00
Лекция 4:

Набор непривилегированных инструкций RISC-V

< Лекция 3 || Лекция 4: 12345 || Лекция 5 >

Как уже было показано выше, инструкции этого типа берут непосредственное значение imm, в качестве источника используется регистр rs1, в качестве регистра назначения - rd.

Поскольку инструкция addi rd, rs1, imm использует знаковое непосредственное значение imm, она может сработать как для сложения (если imm меняется от 0 до 2047), так и для вычитания (imm меняется от -2048 до -1).

Инструкции xori, ori и andi rd, rs1, imm выполняют побитовые операции xor (исключающее или), or (логическое сложение) и and (логическое умножение). Например, пусть в регистре x1 лежит значение 0x9, которому в побитовом представлении соответствует число 0b1001, тогда инструкция xori x1, x1, 0x3 выполнит побитовое исключающее или над содержимым регистра x1 и числом 0x3, что можно представить следующим образом:

x1 = x1 xor 0x3 = 0b1001 xor 0b0011 = 0b1010 = 0xa

Инструкции slli, srli, и srai выполняют операции побитового сдвига с использованием непосредственного значения, задающего шаг сдвига. В качестве такого непосредственного значения может выступать положительное пятибитное число, представляющее значения от 0 до 31.

Код операции логического (побитового) сдвига влево синтаксически описывается следующим образом: slli rd, rs1, imm, и в процессе выполнения сдвигает каждый бит регистра, задаваемого как rs1, на imm позиций влево. Результат при этом записывается в регистр rd. При каждом сдвиге на 1 бит младший значащий бит устанавливается в 0, а значение старшего значащего бита теряется.

По аналогии с этим выполняется команда побитового сдвига вправо: srli rd, rs1, imm. Значение регистра rs1 побитового сдвигается вправо, результат записывается в регистр, задаваемый как rd. При этом в старший значащий бит при каждом сдвиге записывается значение 0, а значение младшего значащего бита теряется.

Результат выполнения команды srai в плане заполнение старшего бита отличается для арифметического сдвига вправо для команды srai rd, rs1, imm. Информация о старшем значащем бите для этой операции сохраняется. Если до сдвига он был равен 0, старший бит заполняется 0 после сдвига. Если он был равен 1, он заполняется 1. Такой сдвиг является знакорасширяющим для значений в rs1, которые записаны в дополнительном коде.

Рассмотрим пример. Пусть значение регистра x1 равно 0x9, двоичное представление которого записывается как 0b1001. Тогда в результате выполнения инструкции slli x1, x1, 0x2 выполнится логический сдвиг содержимого регистра x1, который можно описать следующим кодом:

x1 = x1 << 0x2 = 0b1001 << 2 = 0b100100 = 0x24

Оставшиеся две инструкции slti rd, rs1, imm и sltiu rd, rs1, imm сравнивают содержимое регистра-источника с непосредственным значением и устанавливают значение регистра-приёмника в 0 в случае, если значение в регистре-источнике меньше непосредственного значения imm. Отличие между этими двумя командами в том, что команда slti использует значения в дополнительном коде и сравнение происходит со знаком.

Арифметические и логические операции (с регистрами)

Следующая категория R-формата включает в себя арифметические и логические операции, которые используют три регистра: два регистра-источника и регистр-приёмник. Большинство этих инструкций по своему действию аналогичны рассмотренным выше. К этим инструкциям относятся (табл.3.5):

Таблица 3.5.
Инструкция Тип Формат Код funct3 funct7 Описание
Add ADD R 0110011 0x0 0x00 rd = rs1 + rs2
Sub SUB R 0110011 0x0 0x20 rd = rs1 - rs2
Xor XOR R 0110011 0x4 0x00 rd = rs1 ^ rs2
or OR R 0110011 0x6 0x00 rd = rs1 | rs2
and AND R 0110011 0x7 0x00 rd = rs1 & rs2
sll Shift Left Logical R 0110011 0x1 0x00 rd = rs1 << rs2
srl Shift Right Logical R 0110011 0x5 0x00 rd = rs1 >> rs2
sra Set Right Arith. R 0110011 0x5 0x20 rd = rs1 >> rs2
slt Set Less Than R 0110011 0x2 0x00 Rd = (rs1 < rs2)? 0:1
sltu Set Less Than Un. R 0110011 0x3 0x00 rd = (rs1 < rs2)? 0:1

Рассмотрим дополнение предыдущего примера с учётом новых инструкций:

Адрес		Машинный код       Инструкции
0x0		0x00100093		addi x1, x0, 1
0x4		0x00108093		addi x1, x1, 1
0x8		0x00108133		add  x2, x1, x1

В последней строке примера содержимое регистра x1 добавляется к самому себе, результат записывается в регистр x2. В результате выполнения всех операций в регистре x2 содержится число 4.

Все эти инструкции в отдельном рассмотрении не нуждаются, поскольку являются функциональными аналогами операций из предыдущего раздела. Исключением является инструкция sub, но, как нам кажется, её функциональность является очевидной и в рассмотрении не нуждается.

Загрузка и сохранение

Для того, чтобы получить доступ к памяти, реализован ряд инструкций, которые относятся к I-формату и предназначены для загрузки данных из памяти в регистры, а также ряд инструкций, относящихся к S-формату (S-Format, Save) для сохранения данных из регистров в память. Инструкции указаны в таблице 3.6:

Таблица 3.6.
Инструкция Имя Формат Код funct3 Описание
lb Load Byte I 0000011 0x0 rd = M[rs1+imm][7:0]
lh Load Half I 0000011 0x1 rd = M[rs1+imm][15:0]
lw Load Word I 0000011 0x2 rd = M[rs1+imm][31:0]
lbu Load Byte Un. I 0000011 0x0 Rd = M[rs1+imm][7:0]
lhu Load Half Un. I 0010011 0x0 rd = M[rs1+imm][15:0]
sb Store Byte I 0010011 0x0 M[rs1+imm][7:0] = rs2[7:0]
sh Store Half I 0100011 0x1 M[rs1+imm][15:0] = rs2[15:0]
sw Store Word I 0100011 0x2 M[rs1+imm][31:0] = rs2[31:0]

Рассмотрим следующий пример. Предполагается, что в памяти по адресу 0x10000000находится значение 0x02.

Адрес		Машинный код       Значение		
0x0		0x00100093		addi x1, x0, 0x1
0x4		0x01c09093		slli x1, x1, 28
0x8		0x00008103		lb x2, 0(x1)
< Лекция 3 || Лекция 4: 12345 || Лекция 5 >