Главная »
RISC-V » 05. Арифметико-логический модуль
Оглавление
§ АЛУ с константой
13 [ALU] rd, rs1, imm
------+-31------------------20-+-19---15-+-14---12-+-11--------7-+-6------0-+
ADDI | imm[11:0] | rs1 | 000 | rd | 001_0011 |
SLTI | imm[11:0] | rs1 | 010 | rd | 001_0011 |
SLTIU | imm[11:0] | rs1 | 011 | rd | 001_0011 |
XORI | imm[11:0] | rs1 | 100 | rd | 001_0011 |
ORI | imm[11:0] | rs1 | 110 | rd | 001_0011 |
ANDI | imm[11:0] | rs1 | 111 | rd | 001_0011 |
------+------------------------+---------+-funct3--+-------------+----------+
Код:
immu = I >> 20
imm = SIGN12(immu)
switch (funct3)
000: regs[rd] = regs[rs1] + imm
010: regs[rd] = regs[rs1] < imm ? 1 : 0
011: regs[rd] = regs[rs1] < immu ? 1 : 0
100: regs[rd] = regs[rs1] ^ imm
110: regs[rd] = regs[rs1] | imm
111: regs[rd] = regs[rs1] & imm
Описание: Производится вычисление нового значения на основе заданного регистра rs1 со знакорасширенным значением константы (12 бит), результат записывается в rd. Если в старшем бите константы будет 1, то он расширяется на все 20 старших битов.
Как можно заметить, нет SUBI – поскольку в качестве операнда принимается значение от -2048 до 2027, то инструкция SUBI автоматически получается при ADDI с отрицательным числом.
Особенность: Интересны две инструкции SLTI (Set Less Than Immediate) и SLTIU – беззнаковый вариант. Они лишь сравнивают два числа и устанавливается либо значение 1, либо 0 в регистр-назначение rd.
§ Сдвиг с константой
13 [SLL|SRL|SRA]I rd,rs1,imm
------+-31--------25-+-24---20-+-19---15-+-14---12-+-11--------7-+-6------0-+
SLLI | 0000000 | сдвиг | rs1 | 001 | rd | 001_0011 |
SRLI | 0000000 | сдвиг | rs1 | 101 | rd | 001_0011 |
SRAI | 0100000 | сдвиг | rs1 | 101 | rd | 001_0011 |
------+-funct7-------+---------+---------+-funct3--+-------------+----------+
Код:
imm = (I >> 20) & 0x1F
switch (funct3)
001: regs[rd] = regs[rs1] << imm
101: if (funct7 == 0) regs[rd] = regs[rs1] >>> imm
101: if (funct7 != 0) regs[rd] = regs[rs1] >> imm
Описание: Инструкции сдвига регистра rs1 на 0..31 битов: SLLI – влево (умножение), SRLI – вправо (деление), SRAI – вправо со знаком. Особенность данной функции в том что для определения SRLI или SRAI задействован параметр funct7. Занимает тот же самый опкод, что и все остальные инструкции, работающие с константами, но используется 5 бит сдвига вместо указателя на регистр rs2.
§ АЛУ с регистрами
33 [ALU] rd, rs1, rs2
------+-31--------25-+-24---20-+-19---15-+-14---12-+-11--------7-+-6------0-+
ADD | 0000000 | rs2 | rs1 | 000 | rd | 011_0011 |
SUB | 0100000 | rs2 | rs1 | 000 | rd | 011_0011 |
SLL | 0000000 | rs2 | rs1 | 001 | rd | 011_0011 |
SLT | 0000000 | rs2 | rs1 | 010 | rd | 011_0011 |
SLTU | 0000000 | rs2 | rs1 | 011 | rd | 011_0011 |
XOR | 0000000 | rs2 | rs1 | 100 | rd | 011_0011 |
SRL | 0000000 | rs2 | rs1 | 101 | rd | 011_0011 |
SRA | 0100000 | rs2 | rs1 | 101 | rd | 011_0011 |
OR | 0000000 | rs2 | rs1 | 110 | rd | 011_0011 |
AND | 0000000 | rs2 | rs1 | 111 | rd | 011_0011 |
------+-funct7-------+---------+---------+-funct3--+-------------+----------+
Код:
v1 = regs[rs1]
v2 = regs[rs2]
sh = v2 & 0x1F
switch (funct3)
000: regs[rd] = funct7 ? v1 - v2 : v1 + v2
001: regs[rd] = v1 << sh
010: regs[rd] = v1 < v2 ? 1 : 0
011: regs[rd] = v1 < v2 ? 1 : 0
100: regs[rd] = v1 ^ v2
101: regs[rd] = funct7 ? v1 >> sh : v1 >>> sh
110: regs[rd] = v1 | v2
111: regs[rd] = v1 & v2
Описание: Это полноценное АЛУ, которое работает с регистрами rs1, rs2 и с записью результата в rd. Поскольку результатов флагов нет, то непосредственно выполняются сами действия. Некоторые вариации меняются при помощи funct7, такие как ADD, SUB и SRL, SRA.