Skip to content

RISC-V指令集手册(非特权架构)

官方网站

模块

包含的模块:

基础指令集版本状态说明
RV32I2.1批准32位基础整数指令集
RV32E2.0批准32位嵌入式基础整数指令集
RV64E2.0批准64位嵌入式基础整数指令集
RV64I2.1批准64位基础整数指令集
RV128I1.7草案128位基础整数指令集(草案)
扩展版本状态说明
Zifencei2.0批准指令获取栅栏
Zicsr2.0批准控制和状态寄存器访问
Zicntr2.0批准计数器指令
Zihintntl1.0批准非时序加载提示
Zihintpause2.0批准暂停提示
Zimop1.0批准用于可能操作
Zicond1.0批准条件分支提示
M2.0批准整数乘法和除法
Zmmul1.0批准仅整数乘法
Zaamo2.1批准原子内存操作
Zalrsc2.1批准加载保留/存储条件指令
A2.1批准原子操作指令
Zawrs1.01批准等待预约设置指令
Zacas1.0批准原子比较并交换
RVWMO2.0批准放松的内存排序
Ztso1.0批准完全存储排序
CMO1.0批准缓存管理操作
F2.2批准单精度浮点指令
D2.2批准双精度浮点指令
Q2.2批准四倍精度浮点指令
Zfh1.0批准半精度浮点指令
Zfhmin1.0批准最小半精度浮点指令
Zfa1.0批准浮点算术指令
Zfinx1.0批准整数寄存器中的单精度浮点指令
Zdinx1.0批准整数寄存器中的双精度浮点指令
Zhinx1.0批准整数寄存器中的半精度浮点指令
Zhinxmin1.0批准最小整数寄存器中的半精度浮点指令
C2.0批准压缩指令
Zce1.0批准嵌入式压缩指令
B1.0批准位操作指令
P0.2草案打包SIMD指令(草案)
V1.0批准矢量扩展
Zbkb1.0批准基本位操作指令
Zbkc1.0批准无进位乘法指令
Zbkx1.0批准位操作扩展
Zk1.0批准加密扩展
Zks1.0批准标量加密指令
Zvbb1.0批准矢量基本位操作指令
Zvbc1.0批准矢量无进位乘法
Zvkg1.0批准矢量加密扩展
Zvkned1.0批准矢量加密非加密数据扩展
Zvknhb1.0批准矢量加密基于哈希的消息认证
Zvksed1.0批准矢量加密对称加密
Zvksh1.0批准矢量加密对称哈希
Zvkt1.0批准矢量加密转换

名称解释

  • IALIGN(以位为单位)来指代实现强制执行的指令地址对齐约束。IALIGN 在基本 ISA 中为 32 位,但某些 ISA 扩展(包括压缩的 ISA 扩展)将 IALIGN 放宽至 16 位。 IALIGN 不得采用 16 或 32 以外的任何值。
  • ILEN(以位为单位)来指代实现支持的最大指令长度,并且它始终是 IALIGN 的倍数。对于仅支持基本指令集的实现,ILEN 是 32 位。支持较长指令的实现具有较大的 ILEN 值。

基本指令格式

RISC-V 所有格式的源(rs1 和 rs2)和目标(rd)寄存器保持在相同位置,以简化解码。除了 CSR 指令中使用的 5 位立即数之外,立即数始终进行符号扩展,并且通常打包到指令中最左边的可用位,并进行分配以降低硬件复杂性。特别是,所有立即数的符号位始终位于指令的位 31 中,以加速符号扩展电路。

R 型指令格式

R 型指令用于寄存器之间的算术和逻辑运算。

31 25 24 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+-------+---------+
| funct7 | rs2 | rs1 | funct3| rd | opcode |
+---------+-------+-------+-------+-------+---------+
  • opcode:操作码,指定指令类型。
  • rd:目标寄存器。
  • funct3:功能码,指定具体操作。
  • rs1:第一个源寄存器。
  • rs2:第二个源寄存器。
  • funct7:功能码,进一步指定具体操作。

I 型指令格式

I 型指令用于立即数运算和内存加载。

31 20 19 15 14 12 11 7 6 0
+----------+-------+-------+-------+-----------------+
|imm[11:0] | rs1 | funct3| rd | opcode |
+----------+-------+-------+-------+-----------------+
  • opcode:操作码。
  • rd:目标寄存器。
  • funct3:功能码。
  • rs1:源寄存器。
  • imm[11:0]:12位的立即数。

S 型指令格式

S 型指令用于内存存储。

31 25 24 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+---------+---------+
| imm[11:5]| rs2 | rs1 | funct3| imm[4:0] | opcode |
+---------+-------+-------+-------+---------+---------+
  • opcode:操作码。
  • imm[4:0]:立即数的低 5 位。
  • funct3:功能码。
  • rs1:第一个源寄存器。
  • rs2:第二个源寄存器。
  • imm[11:5]:立即数的高 7 位。

B 型指令格式

B 型指令用于条件分支。

31 31 30 25 24 20 19 15 14 12 11 7 6 6 0
+---------+-----------+-----+-----+--------+----------+---------+--------+
| imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
+---------+-----------+-----+-----+--------+----------+---------+--------+
  • opcode:操作码。
  • imm[11]:立即数第 11 位。
  • imm[4:1]:立即数的第 4 到第 1 位。
  • funct3:功能码。
  • rs1:第一个源寄存器。
  • rs2:第二个源寄存器。
  • imm[10:5]:立即数的第 10 到第 5 位。
  • imm[12]:立即数的第 12 位。

U 型指令格式

U 型指令用于加载高位立即数。

31 12 11 7 6 0
+------------+-----+---------+
| imm[31:12] | rd | opcode |
+------------+-----+---------+
  • opcode:操作码。
  • rd:目标寄存器。
  • imm[31:12]:立即数的13位到32位。

J 型指令格式

J 型指令用于无条件跳转。

31 31 30 21 20 20 19 12 11 7 6 0
+--------+----------+--------+-----------+----+--------+
|imm[20] |imm[10:1] |imm[11] |imm[19:12] | rd | opcode |
+--------+----------+--------+-----------+----+--------+
  • opcode:操作码。
  • rd:目标寄存器。
  • imm[19:12]:立即数的第19 到第 12 位。
  • imm[11]:立即数的第11 位。
  • imm[10:1]:立即数的第10 到第 1 位。
  • imm[20]:立即数的第20 位。

对比

S 和 B 格式之间的唯一区别在于,B 格式中使用 12 位立即数字段来编码 2 的倍数的分支偏移量。中间位 (imm[10:1]) 和符号位保留在固定位置,而 S 格式中的最低位 (inst[ 7]) 以 B 格式对高位进行编码。

U 和 J 格式之间的唯一区别在于,20 位立即数左移 12 位以形成 U 立即数,左移 1 位以形成 J 立即数。 U 和 J 格式立即数中指令位的位置被选择为最大化与其他格式以及彼此之间的重叠。

RV32I

对于 RV32I,32 个 x 寄存器每个都是 32 位宽 。寄存器 x0 被硬连线,所有位都等于 0。通用寄存器 x1-x31 保存各种指令解释为布尔值集合、或二进制补码有符号二进制整数或无符号二进制的值整数。还有一个程序计数器 pc 保存当前指令的地址。 在基本 RV32I ISA 中,有四种核心指令格式(R/I/S/U),如基本指令格式中所示。所有的长度都是固定的 32 位。基本 ISA 具有 IALIGN=32 ,这意味着指令必须在内存中的四字节边界上对齐。如果目标地址未 IALIGN-bit 对齐,则在执行分支或无条件跳转时会生成指令地址未对齐异常。此异常是在分支或跳转指令上报告的,而不是在目标指令上报告的。对于未采用的条件分支,不会生成指令地址未对齐异常。

可选的压缩 16 位指令格式是围绕以下假设而设计的: x1 是返回地址寄存器, x2 是堆栈指针。使用其他约定的软件将正确运行,但可能具有更大的代码大小。

I 型指令集

主要用于立即数运算和内存加载操作

指令描述opcodefunct3
ADDI加立即数0010011000
SLTI小于立即数置位(有符号)0010011010
SLTIU小于立即数置位(无符号)0010011011
XORI按位异或立即数0010011100
ORI按位或立即数0010011110
ANDI按位与立即数0010011111
SLLI逻辑左移立即数0010011001
SRLI逻辑右移立即数0010011101
SRAI算术右移立即数0010011101
LB加载字节0000011000
LH加载半字0000011001
LW加载字0000011010
LBU加载无符号字节0000011100
LHU加载无符号半字0000011101
JALR跳转并链接寄存器1100111000

ADDI

将符号扩展的12位立即数加上寄存器rs1得值。忽略算术溢出,将结果的低XLEN位保存到寄存器rd。addi rd, rs1, 0实现类似mv rd, rs1汇编伪指令, nop伪指令实现addi x0, x0, 0

SLTI

如果寄存器 rs1 小于符号扩展立即数(且两者均被视为有符号数),则 SLTI(设置小于立即数)将值 1 放入寄存器 rd,否则将 0 写入 rd。

SLTIU

立即数首先被符号扩展为 XLEN 位,然后被视为无符号数, 如果寄存器 rs1 小于立即数(且两者均被视为无符号数),则 SLTI(设置小于立即数)将值 1 放入寄存器 rd,否则将 0 写入 rd。sltiu rd, rs1, 1 如果rs1为0, 则rd设置为1, 实现汇编伪指令seqz rd, rs

ANDI,ORI,XORI

ANDI、ORI、XORI 是逻辑运算,对寄存器 rs1 和符号扩展的 12 位立即数执行按位 AND、OR 和 XOR,并将结果放入 rd。xori rd, rs1, -1将rs1的值取反, 实现汇编伪指令not rd, rs

SLLI,SRLI,SRAI

移位常数被编码为 I 类型格式的特化。要移位的操作数在rs1中,移位量编码在立即数字段的低5位中。右移类型编码在位 30 中(0为SRLI, 1为SRAI)。SLLI 是逻辑左移(零移入低位); SRLI 是逻辑右移(零移入高位); SRAI是算术右移(将原来的符号位复制到空出的高位中)。

LB

lb rd, offset(rs1)从rs1加上立即数的内存地址中加载一个8位值,然后符号扩展为32位,保存到寄存器rd中。

LH

lh rd, offset(rs1)从rs1加上立即数的内存地址中加载一个16位值,然后符号扩展为32位,保存到寄存器rd中。

LW

lw rd, offset(rs1)从rs1加上立即数的内存地址中加载一个32位值,保存到寄存器rd中。

LBU

lbu rd, offset(rs1)从rs1加上立即数的内存地址中加载一个8位值,然后零扩展为32位,保存到寄存器rd中。

LHU

lhu rd, offset(rs1)从rs1加上立即数的内存地址中加载一个16位值,然后零扩展为32位,保存到寄存器rd中。

JALR

过将符号扩展的 12 位立即数与寄存器 rs1 相加,然后将结果的最低有效位设置为零来获得目标地址。返回地址(pc +4)被写入寄存器 rd。如果不需要结果,寄存器 x0 可以用作目标。 LUI 指令可以首先将目标地址的高 20 位装入 rs1,然后 JALR 可以添加低位。类似地,AUIPC 然后 JALR 可以跳转到 32 位 pc 相对地址范围内的任何位置。

U 型指令集

U 型指令格式(U 型指令)在 RISC-V 中用于加载高位立即数到寄存器。

指令描述opcode格式
LUI加载高位立即数0110111U 型
AUIPC加载上半立即数加 PC0010111U 型

LUI

LUI(加载立即数)用于构建32位常量并使用U型格式。 LUI 将 32 位 U 立即值放入目标寄存器 rd,并用零填充最低 12 位。

AUIPC

用于构建 pc 相对地址并使用 U 型格式。 AUIPC 从 U 立即数形成一个 32 位偏移量,用零填充最低 12 位,将该偏移量与 PC 相加,然后将结果放入寄存器 rd 中。

R 型指令集

R 型指令集用于寄存器之间的算术和逻辑运算。每条 R 型指令都使用两个源寄存器和一个目标寄存器,并且有一个功能码(funct3)和一个扩展功能码(funct7)

指令描述funct7funct3opcode
ADD加法00000000000110011
SUB减法01000000000110011
SLL逻辑左移00000000010110011
SRL逻辑右移00000001010110011
SRA算术右移01000001010110011
SLT小于(有符号)00000000100110011
SLTU小于(无符号)00000000110110011
XOR按位异或00000001000110011
OR按位或00000001100110011
AND按位与00000001110110011

ADD

rd = r1 + r2

SUB

rd = r1 - r2溢出被忽略,结果的低 XLEN 位被写入目标 rd。

SLL,SRL,SRA

SLL、SRL 和 SRA 对寄存器 rs1 中的值执行逻辑左移、逻辑右移和算术右移,移位量为寄存器 rs2 低 5 位中保存的移位量。

SLT,SLTU

SLT 和 SLTU 分别执行有符号和无符号比较,如果 rs1 < rs2,则将 1 写入 rd,否则写入 0。

XOR,OR,AND

XOR, OR和AND执行按位逻辑运算。

J 型指令集

J 型指令(Jump 型指令)用于无条件跳转

指令描述opcode格式
JAL跳转和链接0000111J 型

JAL

其中 J 立即数以 2 字节的倍数编码有符号偏移量。将偏移量进行符号扩展并与PC相加,形成跳转目标地址。因此,跳转可以瞄准 ±1 MiB 范围。 JAL将返回地址 (‘pc’+4) 存储到寄存器 rd 中。标准软件调用约定使用“x1”作为返回地址寄存器,使用“x5”作为备用链接寄存器。

B 型指令集

B 型指令(Branch 型指令)用于条件分支跳转。12位立即数以2字节的倍数编码有符号偏移量。偏移量被符号扩展并添加到分支指令的地址以给出目标地址。条件分支范围为±4 KiB。

指令描述funct3opcode
BEQ等于则分支0001100011
BNE不等则分支0011100011
BLT小于则分支1001100011
BGE大于等于则分支1011100011
BLTU无符号小于则分支1101100011
BGEU无符号大于等于则分支1111100011

BEQ

如果寄存器 rs1 和 rs2 分别相等,则采取分支。

BNE

如果寄存器 rs1 和 rs2 分别不相等,则采取分支。

BLT

有符号比较, 如果rs1小于rs2, 则采取分支。

BGE

有符号比较, 如果rs1大于rs2, 则采取分支。

BLTU

无符号比较, 如果rs1小于rs2, 则采取分支。

BGEU

无符号比较, 如果rs1大于rs2, 则采取分支。

S 型指令集

S 型指令用于存储数据到内存中。每条 S 型指令使用两个源寄存器,其中一个寄存器提供基地址,另一个寄存器提供存储的数据,以及一个立即数提供偏移量。

以下是 RISC-V 中常见的 S 型指令及其功能描述:

指令描述funct3opcode
SB存储字节0000100011
SH存储半字0010100011
SW存储字0100100011

SB

sb rs2, offset(rs1)rs2的低8位字节存储到以rs1为基地址加上立即数偏移的位置。

SH

sh rs2, offset(rs1)rs2的低16位字节存储到以rs1为基地址加上立即数偏移的位置。

SW

sw rs2, offset(rs1)rs2的32位字节存储到以rs1为基地址加上立即数偏移的位置。

RV32E和RV64E

RV32E和RV64E分别是RV32I和RV64I的缩减版本:唯一的变化是将整数寄存器的数量减少到 16 个( x0-x15 ),其中 x0 是专用零寄存器。

RV64I

提供了其他指令变体来操作 RV64I 中的 32 位值,由操作码后缀“W”表示。这些“*W”指令忽略其输入的高 32 位,并始终生成 32 位有符号值,将它们符号扩展为 64 位,所有 32 位值都以符号扩展格式保存在 64 位寄存器中。即使 32 位无符号整数也会将位 31 扩展到位 63 到 32。因此,无符号和有符号 32 位整数之间的转换是无操作的,就像从有符号 32 位整数到有符号 64 位整数的转换一样。

ADDIW

它将符号扩展的12位立即数与寄存器rs1相加, 结果的低32位符号扩展为64保存到寄存器rd。

SLLI,SRLI,SRAI

SLL、SRL 和 SRA 对寄存器rs1中的值执行逻辑左移、逻辑右移和算术右移,移位量为寄存器rs2低6位中保存的移位量。

SLLIW,SRLIW,SRAIW

与SLLI,SRLI,SRAI类似, 但对32位值进行操作并将其32位结果符号扩展为64位。 imm[5] ≠ 0 的 SLLIW、SRLIW 和 SRAIW 编码被保留。

LUI

使用与 RV32I 相同的操作码。 LUI将32位立即数放入寄存器rd中,并用零填充最低12位。 32位结果被符号扩展为 64 位。

AUIPC

使用与 RV32I相同的操作码。 AUIPC用于构建pc相对地址并使用U型格式。 AUIPC从U立即数形成32位偏移量,用零填充最低12位,将结果符号扩展为 64 位,将其加上PC,然后将结果放入寄存器rd中。

ADDW, SUBW

其定义与 ADD 和 SUB 类似,但对 32 位值进行操作并生成带符号的 32 位结果。溢出被忽略,结果的低 32 位被符号扩展为 64 位并写入目标寄存器。

SLL,SRL,SRA

在RV64I中,仅考虑rs2的低6位作为移位量。

SLLW,SRLW,SRAW

在RV64I中,移位量由 rs2[4:0] 给出。

LD

I 型指令, 将64位值从内存加载到寄存器rd中。

指令描述funct3opcode
LD从内存加载一个 64 位的双字到寄存器0110000011

SD

SD 指令

S 型指令, 将一个 64 位的双字(doubleword)存储到内存中。

指令描述funct3opcode
SD将 64 位双字存储到内存中0110100011

RV128I

RV128I 以与 RV64I 构建于 RV32I 相同的方式构建于 RV64I 之上,其中整数寄存器扩展至 128 位(即 XLEN=128)。大多数整数计算指令都保持不变,因为它们被定义为在 XLEN 位上运行。对寄存器低位中的 32 位值进行操作的 RV64I“*W”整数指令被保留,但现在将其结果从位 31 符号扩展到位 127。添加了一组新的“*D”整数指令,对 128 位整数寄存器的低位中保存的 64 位值进行操作,并将其结果从第 63 位符号扩展到第 127 位。“*D”指令使用两个主要操作码(OP-IMM-64 和 OP-64) )采用标准 32 位编码。

Zifencei拓展

RISC-V 的 Zifencei 扩展增加了指令和内存顺序模型中的 FENCE.I 指令,用于确保指令流在内存模型中的一致性。这在处理自修改代码或共享内存的系统中尤其重要。

作用

FENCE.I(Instruction Fence)是 I 型指令, 指令用于确保在执行该指令之前的所有内存写操作(特别是代码段的写操作)在接下来的指令取指操作之前生效。这在处理自修改代码时非常重要,确保 CPU 知道已经更新了指令并且这些更改在下一次指令取指时生效。

指令描述

指令描述funct3opcode
FENCE.I确保之前的内存写操作在接下来的指令取指之前生效0000001111

示例指令和解释

FENCE.I

  • 描述:确保在执行该指令之前的所有内存写操作在接下来的指令取指操作之前生效。

  • 格式FENCE.I

  • 机器码

    31 20 19 15 14 12 11 7 6 0
    +---------+-------+-----+-----+-------+--------+
    | 000000000000 | 00000 | 000 | 00000 | 0001111 |
    +---------+-------+-----+-----+-------+--------+

示例说明

在某些情况下,例如动态生成代码或修改已经加载的指令,使用 FENCE.I 指令是必需的:

# 修改内存中某个位置的代码
SW x3, 0(x1) # 将寄存器 x3 的值存储到内存地址 x1
# 确保之前的写操作对接下来的指令取指操作可见
FENCE.I
# 从内存中执行刚刚写入的指令
JALR x0, 0(x1)

详细说明

  1. FENCE.I (Instruction Fence)
    • 描述:确保所有先前的内存写操作在任何后续的指令取指操作之前完成。
    • 操作码:0001111
    • 功能码 (funct3):000
    • 使用场景:自修改代码、热补丁、JIT 编译器等需要确保指令流一致性的情况。

应用场景

  • 自修改代码:当程序修改自身的代码段时,需要确保修改后的代码在执行时是最新的。
  • JIT 编译:即时编译器在生成和修改代码后,需要确保 CPU 知道并执行最新的代码。
  • 热补丁:当系统在运行时应用补丁修改指令时,FENCE.I 指令确保新指令被正确执行。

Zicsr拓展

RISC-V 的 Zicsr 扩展增加了对控制状态寄存器(CSR,Control and Status Register)操作的指令集,这些指令用于访问和操作 CPU 内部的控制状态寄存器,以实现各种特权级功能和系统控制功能。

CSR 指令概述

Zicsr 扩展引入了以下指令,CSR 指令是I型指令,用于读写控制状态寄存器:

  1. CSRRW:读写 CSR
  2. CSRRS:读并置位 CSR
  3. CSRRC:读并清零 CSR
  4. CSRRWI:立即数读写 CSR
  5. CSRRSI:立即数读并置位 CSR
  6. CSRRCI:立即数读并清零 CSR

CSR 指令描述

指令描述funct3opcode
CSRRW读写 CSR0011110011
CSRRS读并置位 CSR0101110011
CSRRC读并清零 CSR0111110011
CSRRWI立即数读写 CSR1011110011
CSRRSI立即数读并置位 CSR1101110011
CSRRCI立即数读并清零 CSR1111110011

指令功能

CSRRW(CSR Read and Write)

  • 描述:将 CSR 的值读到寄存器 rd,然后将寄存器 rs1 的值写入 CSR。
  • 格式CSRRW rd, csr, rs1
  • 机器码
    31 20 19 15 14 12 11 7 6 0
    +---------+-------+-----+-----+-------+--------+
    | csr[11:0] | rs1 | 001 | rd | 1110011 |
    +---------+-------+-----+-----+-------+--------+

CSRRS(CSR Read and Set)

  • 描述:将 CSR 的值读到寄存器 rd,然后将寄存器 rs1 的值按位或到 CSR 中。
  • 格式CSRRS rd, csr, rs1
  • 机器码
    31 20 19 15 14 12 11 7 6 0
    +---------+-------+-----+-----+-------+--------+
    | csr[11:0] | rs1 | 010 | rd | 1110011 |
    +---------+-------+-----+-----+-------+--------+

CSRRC(CSR Read and Clear)

  • 描述:将 CSR 的值读到寄存器 rd,然后将寄存器 rs1 的值按位取反并按位与到 CSR 中。
  • 格式CSRRC rd, csr, rs1
  • 机器码
    31 20 19 15 14 12 11 7 6 0
    +---------+-------+-----+-----+-------+--------+
    | csr[11:0] | rs1 | 011 | rd | 1110011 |
    +---------+-------+-----+-----+-------+--------+

CSRRWI(CSR Read and Write Immediate)

  • 描述:将 CSR 的值读到寄存器 rd,然后将立即数 uimm 写入 CSR。
  • 格式CSRRWI rd, csr, uimm
  • 机器码
    31 20 19 15 14 12 11 7 6 0
    +---------+-------+-----+-----+-------+--------+
    | csr[11:0] | uimm | 101 | rd | 1110011 |
    +---------+-------+-----+-----+-------+--------+

CSRRSI(CSR Read and Set Immediate)

  • 描述:将 CSR 的值读到寄存器 rd,然后将立即数 uimm 按位或到 CSR 中。
  • 格式CSRRSI rd, csr, uimm
  • 机器码
    31 20 19 15 14 12 11 7 6 0
    +---------+-------+-----+-----+-------+--------+
    | csr[11:0] | uimm | 110 | rd | 1110011 |
    +---------+-------+-----+-----+-------+--------+

CSRRCI(CSR Read and Clear Immediate)

  • 描述:将 CSR 的值读到寄存器 rd,然后将立即数 uimm 按位取反并按位与到 CSR 中。
  • 格式CSRRCI rd, csr, uimm
  • 机器码
    31 20 19 15 14 12 11 7 6 0
    +---------+-------+-----+-----+-------+--------+
    | csr[11:0] | uimm | 111 | rd | 1110011 |
    +---------+-------+-----+-----+-------+--------+

示例指令和解释

假设我们有一个控制状态寄存器 csr,其地址为 0x300

CSRRW 示例

csrrw x1, 0x300, x2

这条指令会将 CSR 地址 0x300 处的值读到寄存器 x1,然后将寄存器 x2 的值写入 CSR 0x300

CSRRS 示例

csrrs x1, 0x300, x2

这条指令会将 CSR 地址 0x300 处的值读到寄存器 x1,然后将寄存器 x2 的值按位或到 CSR 0x300 中。

CSRRC 示例

csrrc x1, 0x300, x2

这条指令会将 CSR 地址 0x300 处的值读到寄存器 x1,然后将寄存器 x2 的值按位取反并按位与到 CSR 0x300 中。

CSRRWI 示例

csrrwi x1, 0x300, 5

这条指令会将 CSR 地址 0x300 处的值读到寄存器 x1,然后将立即数 5 写入 CSR 0x300

CSRRSI 示例

csrrsi x1, 0x300, 5

这条指令会将 CSR 地址 0x300 处的值读到寄存器 x1,然后将立即数 5 按位或到 CSR 0x300 中。

CSRRCI 示例

csrrci x1, 0x300, 5

这条指令会将 CSR 地址 0x300 处的值读到寄存器 x1,然后将立即数 5 按位取反并按位与到 CSR 0x300 中。

应用场景

  • 系统控制:操作系统内核使用 CSR 指令来配置和控制 CPU 状态。
  • 异常处理:处理器在处理中断和异常时,使用 CSR 指令访问和修改异常状态寄存器。
  • 性能监控:通过 CSR 指令访问和控制性能监控计数器。
  • 调试:调试工具使用 CSR 指令来访问调试控制和状态寄存器。

Zicntr扩展

RISC-V 的 Zicntr 扩展增加了对计数器和定时器的支持。它提供了一组标准的性能计数器和定时器寄存器,这些寄存器可以用来监控和管理处理器的性能。

性能计数器和定时器寄存器

以下是 Zicntr 扩展中定义的标准性能计数器和定时器寄存器:

  1. cycle:用于计数自处理器启动以来的时钟周期数。
  2. time:用于计数自处理器启动以来的定时器时钟周期数。
  3. instret:用于计数自处理器启动以来已执行的指令数。

访问计数器和定时器寄存器

这些寄存器可以通过 CSR 指令(如 CSRR、CSRW、CSRS、CSRC 等)进行访问。

读取计数器寄存器

对于 XLEN≥64 的基本 ISA,CSR 指令可以直接访问完整的 64 位 CSR。使用rdcycle、rdtime 和 rdinstret伪指令读取 cycle 、 time 和 instret 计数器的完整 64 位。对于 XLEN=32 的基本 ISA,Zicntr 扩展允许以 32 位片的形式访问三个64位只读计数器。 rdcycle、rdtime 和 rdinstret伪指令提供各自计数器的低 32 位,rdcycleh、rdtimeh 和 rdinstreth伪指令提供各自计数器的高 32 位。

  • 读取 cycle 寄存器:

    csrrci x1, cycle, 0
    rdcycle x1
  • 读取 time 寄存器:

    csrrci x1, time, 0
    rdtime x1
  • 读取 instret 寄存器:

    csrrci x1, instret, 0
    rdinstret x1

写入计数器寄存器

通常,性能计数器寄存器是只读的,但在某些情况下可以通过操作系统或特权级代码重置这些寄存器。

示例代码

读取 cycle 计数器

csrr x1, cycle # 将cycle计数器的值读入寄存器x1

读取 time 计数器

csrr x1, time # 将time计数器的值读入寄存器x1

读取 instret 计数器

csrr x1, instret # 将instret计数器的值读入寄存器x1

计数器寄存器地址

在 RISC-V 的控制状态寄存器(CSR)地址空间中,以下是一些常见的性能计数器和定时器寄存器地址:

  • cycle:CSR 地址 0xC00
  • time:CSR 地址 0xC01
  • instret:CSR 地址 0xC02

Zihintntl拓展

NTL 指令是 HINT,指示紧随其后的指令(下文称为“目标指令”)的显式内存访问表现出较差的引用时间局部性。 NTL指令不改变体系结构状态,也不改变目标指令的体系结构可见效果。提供四种变体:

  • NTL.P1指令指示目标指令在存储器层次结构中的最内层私有高速缓存的容量内不表现出时间局部性。 NTL.P1 编码为 add x0、x0、x2
  • NTL.PALL指令指示目标指令在存储器层次结构中的任何级别的私有高速缓存的容量内不表现出时间局部性。 NTL.PALL 编码为 add x0、x0、x3
  • NTL.S1指令指示目标指令在存储器层次结构中最内层共享高速缓存的容量内不表现出时间局部性。 NTL.S1 编码为 add x0、x0、x4
  • NTL.ALL指令指示目标指令在存储器层次结构中的任何级高速缓存的容量内不表现出时间局部性。 NTL.ALL 编码为 add x0、x0、x5

Zihintpause扩展

RISC-V 的 Zihintpause 扩展增加了一条用于暂停指令执行的提示指令,旨在优化超线程(SMT,Simultaneous Multithreading)环境下的性能。这条指令为处理器提供了在等待期间暂停执行的提示,允许处理器更高效地调度其他线程,从而提高整体系统性能和能效。

指令概述

Zihintpause 扩展定义了一条提示指令:

  1. PAUSE:提示处理器当前线程可以暂停执行,以便处理器调度其他线程。

PAUSE 指令格式

PAUSE 是一种无操作数的指令,格式如下:

31 25 24 20 19 15 14 12 11 7 6 0
+---------+-------+-----+-----+-------+--------+
| 0000000 | 00000 | 000 | 00000 | 0001011 |
+---------+-------+-----+-----+-------+--------+

Zimop拓展

它引入了可能是操作的指令(MOP)的概念。 MOP 最初定义为简单地将零写入 x[rd] ,但设计为由以后的扩展重新定义以执行某些其他操作。

  1. Zimop 扩展定义了 40 个 MOP 的编码空间。Zimop 扩展定义了 32 个名为 MOP.R.n 的 MOP 指令,其中 n 是 0 到 31 之间的整数(含 0 和 31)。除非由另一个扩展重新定义,否则这些指令只是将 0 写入 x[rd] 。它们的编码允许将来的扩展将它们定义为读取 x[rs1] 以及写入 x[rd] 。

  2. Zimop 扩展另外定义了 8 个名为 MOP.RR.n 的 MOP 指令,其中 n 是 0 到 7 之间的整数(包含 0 和 7)。除非由另一个扩展重新定义,否则这些指令只是将 0 写入 x[rd] 。它们的编码允许将来的扩展将它们定义为读取 x[rs1] 和 x[rs2] 以及写入 x[rd] 。

Zicond拓展

Zicond 扩展定义了一种简单的解决方案,它提供了支持条件算术和条件选择/移动操作所需的大部分好处和所有灵活性,同时保持了 RISC-V 设计理念。这些指令遵循具有 3 个操作数(即 2 个源操作数和 1 个目标操作数)的 R 类型指令的格式。使用这些指令,可以实现无分支序列(通常在两个指令序列中),而不需要指令融合、架构指令解码期间的特殊规定或其他微体系结构规定。

指令描述funct7funct3opcode
czero.eqz如果条件 rs2 等于 0,则将零移至寄存器 rd,否则将 rs1 移至 rd。00001111010110011
czero.nez如果条件 rs2 非零,则将零移至寄存器 rd,否则将 rs1 移至 rd。00001111110110011

M拓展

标准整数乘法和除法指令扩展,包含对两个整数寄存器中保存的值进行乘法或除法的指令。

M 扩展指令表格

以下是 RISC-V M 扩展(整数乘除扩展)的指令表格,包含每条指令的描述、功能码(funct3 和 funct7)、操作码(opcode)以及指令格式。

指令描述funct7funct3opcode格式
MUL有符号整数乘法,结果低位存储到 rd 中00000010000110011MUL rd, rs1, rs2
MULW(RV64)有符号整数低32位乘法,结果低位存储到 rd 中00000010000110011MULH rd, rs1, rs2
MULH高位有符号乘法,结果高位存储到 rd 中00000010010110011MULH rd, rs1, rs2
MULHSU高位有符号和无符号混合乘法,结果高位存储到 rd 中00000010100110011MULHSU rd, rs1, rs2
MULHU高位无符号乘法,结果高位存储到 rd 中00000010110110011MULHU rd, rs1, rs2
DIV有符号整数除法,商存储到 rd 中00000011000110011DIV rd, rs1, rs2
DIVU无符号整数除法,商存储到 rd 中00000011010110011DIVU rd, rs1, rs2
DIVW(RV64)有符号整数除法,只运算低32位商存储到 rd 中00000011000110011DIV rd, rs1, rs2
DIVUW(RV64)无符号整数除法,只运算低32位商存储到 rd 中00000011010110011DIVU rd, rs1, rs2
REM有符号整数取余,余数存储到 rd 中00000011100110011REM rd, rs1, rs2
REMU无符号整数取余,余数存储到 rd 中00000011110110011REMU rd, rs1, rs2
REMW(RV64)有符号整数取余,只运算低32位余数存储到 rd 中00000011100110011REM rd, rs1, rs2
REMUW(RV64)无符号整数取余,只运算低32位余数存储到 rd 中00000011110110011REMU rd, rs1, rs2

Zmmul拓展

Zmmul 扩展实现了 M 扩展的乘法子集。它添加了第 13.1 节中定义的所有指令,即:MUL、MULH、MULHU、MULHSU 和(仅适用于 RV64)MULW。这些编码与相应的 M 扩展指令的编码相同。 M 意味着 Zmmul。

Zaamo拓展

原子内存操作 (AMO) 指令执行读-修改-写操作以实现多处理器同步,并使用 R 型指令格式进行编码。这些 AMO 指令以原子方式从 rs1 中的地址加载数据值,将该值放入寄存器 rd,对加载的值和 rs2 中的原始值应用二元运算符,然后将结果存储回 rs1 中的原始地址。 AMO 可以对双字(仅限 RV64)或内存中的字进行操作。对于 RV64,32 位 AMO 始终对 rd 中的值进行符号扩展,并忽略 rs2 原始值的高 32 位。

指令表格

指令描述funct7funct3opcode格式
AMOADD.Wrs2 的值与内存地址 rs1 的值相加,并将结果写回内存,同时将内存中的原始值存储到 rd000010100101111AMOADD.W rd, rs2, (rs1)
AMOXOR.Wrs2 的值与内存地址 rs1 的值进行异或,并将结果写回内存,同时将内存中的原始值存储到 rd000011000101111AMOXOR.W rd, rs2, (rs1)
AMOAND.Wrs2 的值与内存地址 rs1 的值进行与操作,并将结果写回内存,同时将内存中的原始值存储到 rd000010110101111AMOAND.W rd, rs2, (rs1)
AMOOR.Wrs2 的值与内存地址 rs1 的值进行或操作,并将结果写回内存,同时将内存中的原始值存储到 rd000010100101111AMOOR.W rd, rs2, (rs1)
AMOMIN.Wrs2 和内存地址 rs1 的值比较,取最小值写回内存,同时将内存中的原始值存储到 rd000011000101111AMOMIN.W rd, rs2, (rs1)
AMOMAX.Wrs2 和内存地址 rs1 的值比较,取最大值写回内存,同时将内存中的原始值存储到 rd000011010101111AMOMAX.W rd, rs2, (rs1)
AMOMINU.Wrs2 和内存地址 rs1 的无符号值比较,取最小值写回内存,同时将内存中的原始值存储到 rd000011100101111AMOMINU.W rd, rs2, (rs1)
AMOMAXU.Wrs2 和内存地址 rs1 的无符号值比较,取最大值写回内存,同时将内存中的原始值存储到 rd000011110101111AMOMAXU.W rd, rs2, (rs1)
AMOADD.Drs2 的值与内存地址 rs1 的值相加,并将结果写回内存,同时将内存中的原始值存储到 rd000010110101111AMOADD.D rd, rs2, (rs1)
AMOXOR.Drs2 的值与内存地址 rs1 的值进行异或,并将结果写回内存,同时将内存中的原始值存储到 rd000011110101111AMOXOR.D rd, rs2, (rs1)
AMOAND.Drs2 的值与内存地址 rs1 的值进行与操作,并将结果写回内存,同时将内存中的原始值存储到 rd000010110101111AMOAND.D rd, rs2, (rs1)
AMOOR.Drs2 的值与内存地址 rs1 的值进行或操作,并将结果写回内存,同时将内存中的原始值存储到 rd000010100101111AMOOR.D rd, rs2, (rs1)
AMOMIN.Drs2 和内存地址 rs1 的值比较,取最小值写回内存,同时将内存中的原始值存储到 rd000011000101111AMOMIN.D rd, rs2, (rs1)
AMOMAX.Drs2 和内存地址 rs1 的值比较,取最大值写回内存,同时将内存中的原始值存储到 rd000011010101111AMOMAX.D rd, rs2, (rs1)
AMOMINU.Drs2 和内存地址 rs1 的无符号值比较,取最小值写回内存,同时将内存中的原始值存储到 rd000011100101111AMOMINU.D rd, rs2, (rs1)
AMOMAXU.Drs2 和内存地址 rs1 的无符号值比较,取最大值写回内存,同时将内存中的原始值存储到 rd000011110101111AMOMAXU.D rd, rs2, (rs1)

Zalrsc拓展

用于加载保留/存储条件指令

指令表格

指令描述funct7funct3opcode格式
LR.W加载保留000100110101111LR.W rd, (rs1)
SC.W存储条件000110110101111SC.W rd, rs2, (rs1)
LR.D加载保留双字000100110101111LR.D rd, (rs1)
SC.D存储条件双字000110110101111SC.D rd, rs2, (rs1)

A拓展

包含原子读取-修改-写入内存的指令,以支持在同一内存空间中运行的多个 RISC-V hart 之间的同步。提供的两种形式的原子指令是加载保留/存储条件指令和原子获取和操作存储器指令。这些原子指令都是 R 型指令,两种类型的原子指令都支持各种内存一致性排序,包括无序、获取、释放和顺序一致语义。这些指令允许 RISC-V 支持 RCsc 内存一致性模型。 A 扩展包含 Zaamo 和 Zalrsc 扩展提供的指令。

Zawrs拓展

Zawrs 扩展定义了一对在轮询循环中使用的指令,允许内核进入低功耗状态并等待存储到内存位置。等待内存位置更新是许多用例中的常见模式,例如:

  1. 锁的竞争者等待锁变量被更新。
  2. 消费者在空队列的尾部等待生产者对工作/数据进行排队。生产者可以是在 RISC-V 硬件、加速器设备、外部 I/O 代理上执行的代码。
  3. 代码等待在内存中设置指示事件发生的标志。例如,RISC-V 硬件上的软件可以等待加速器设备在存储器中设置“完成”标志,指示先前提交给设备的作业已完成。
  • WRS.NTO: 将导致 hart 在低功耗状态下暂时停止执行,直到发生对保留集的存储或观察到中断。
  • WRS.STO: 但将停顿持续时间限制为实现定义的短超时,以便在以下情况下在超时时终止停顿:没有发生其他终止失速的条件。然后,使用该指令的程序可以确定是否已达到其最后期限。

软件不是轮询存储到特定内存位置,而是使用LR指令注册包含内存位置所有字节的保留集。Zawrs 扩展中的指令仅在与 LR 指令结合使用时有用,LR 指令由 A 扩展的 Zalrsc 组件提供。

I型指令

指令描述funct12funct3opcode格式
WRS.NTOWRS 无超时011010001110011WRS.NTO
WRS.STO带短超时的 WRS111010001110011WRS.STO

Zacas拓展

当作为硬件指令支持时,比较和交换 (CAS) 提供了一种简单且通常更快的方法来执行线程同步操作。 CAS 通常由无锁和无等待算法使用。此扩展建议使用 CAS 指令来操作 32 位、64 位和 128 位(仅限 RV64)数据值。 CAS指令支持C++11原子比较和交换操作。Zacas 扩展依赖于 Zaamo 扩展。

I型指令

指令描述31-27funct3opcode格式
AMOCAS.W比较和交换011010101110011AMOCAS.W x3, x2, (x1)
AMOCAS.D比较和交换011010111110011AMOCAS.D x3, x2, (x1)
AMOCAS.Q比较和交换011011001110011AMOCAS.Q x3, x2, (x1)

对于 RV32, AMOCAS.W从x1中的地址自动加载32位数据值,将加载的值与x2中保存的32位值进行比较,如果比较按位相等,则将x1地址的数据与寄存器rd的值交换。否则,则将x1地址的数据存值到 rd。

RVWMO拓展

内存一致性模型。内存一致性模型是一组规则,指定内存负载可以返回的值。

RVTSO拓展

RISC-V Total Store Ordering (RVTSO) 内存一致性模型的“Ztso”扩展。 RVTSO 被定义为 RVWMO 的增量,RVTSO 对 RVWMO 进行以下调整:

  • 所有加载操作的行为就好像它们具有 acquire-RCpc 注释一样
  • 所有存储操作的行为就好像它们具有release-RCpc注释一样。
  • 所有 AMO 的行为就好像它们同时具有 acquire-RCsc 和 release-RCsc 注释。

CMO拓展

高速缓存管理操作(或CMO )指令对内存层次结构中的数据副本执行操作。一般来说,CMO 指令对数据的缓存副本进行操作,但在某些情况下,CMO 指令可以直接对内存位置进行操作。此外,CMO 指令按操作分为以下几类:

  • 管理指令针对一组可以访问数据的代理来操作数据的缓存副本
  • 零指令将一系列内存位置清零,可能会在一个或多个高速缓存中分配数据的高速缓存副本
  • 预取指令向硬件指示在不久的将来可以访问给定内存位置处的数据,从而可能在一个或多个高速缓存中分配数据的高速缓存副本
指令描述funct7funct3rs2opcode格式
CBO.CLEAN清理缓存行,将缓存数据写回主存但不失效0000001001000001111111CBO.CLEAN rs1
CBO.FLUSH刷新缓存行,将缓存数据写回主存并失效0000001101000001111111CBO.FLUSH rs1
CBO.INVAL使缓存行无效0000010110000001111111CBO.INVAL rs1
CBO.ZERO将缓存行清零0000011111000001111111CBO.ZERO rs1
PREFETCH.I预取指令缓存行0000100000000001111111PREFETCH.I rs1
PREFETCH.R预取数据缓存行进行读取0000101000000001111111PREFETCH.R rs1
PREFETCH.W预取数据缓存行进行写入0000110000000001111111PREFETCH.W rs1

F拓展

F扩展增加了32个浮点寄存器f0-f31 ,每个32位宽,以及一个浮点控制和状态寄存器fcsr ,其中包含浮点单元的操作模式和异常状态。

FCSR 寄存器结构

FCSR 是一个 32 位寄存器,具体结构如下:

31 8 7 5 4 0
+-----------+-----------+-----------+
| Reserved | frm[2:0] | fflags[4:0]|
+-----------+-----------+-----------+
  • fflags(5 位):浮点异常标志,记录浮点运算过程中产生的异常。
  • frm(3 位):浮点舍入模式,指定浮点运算的舍入模式。
  • Reserved(24 位):保留位,未使用。

fflags(浮点异常标志)

fflags 字段记录了浮点运算过程中产生的五种异常。每个异常占一位,如果产生相应的异常,该位将被置位。

名称描述
0NV(Invalid Operation)无效操作异常,如 0/0 或 sqrt(负数)
1DZ(Divide by Zero)除以零异常,例如 非零数 / 0
2OF(Overflow)溢出异常,例如结果超出浮点数范围,趋向于无穷大
3UF(Underflow)下溢异常,例如结果非常接近于零,但非零
4NX(Inexact)不精确异常,例如结果不能精确表示,需要舍入

frm(浮点舍入模式)

frm 字段指定了浮点运算的舍入模式,共有以下五种模式:

舍入模式描述
000Round to Nearest, ties to Even向最接近的偶数舍入(默认模式)
001Round towards Zero向零方向舍入(截断)
010Round Down (towards -∞)向负无穷方向舍入
011Round Up (towards +∞)向正无穷方向舍入
100Round to Nearest, ties to Max Magnitude向最接近的数舍入,遇到平局时向最大幅值舍入
101-111Reserved保留,未定义

FCSR 寄存器的操作

RISC-V 提供了一些指令来访问和操作 FCSR 寄存器。

  • FRCSR(Floating-Point Read Control and Status Register):读取 FCSR 寄存器的值。
  • FSCSR(Floating-Point Set Control and Status Register):设置 FCSR 寄存器的值。
  • FSCXR(Floating-Point Control and Status Register Exchange):交换寄存器值。

示例

读取 FCSR

FRCSR x1

将 FCSR 寄存器的值读入整数寄存器 x1。

设置 FCSR

FSCSR x1

将整数寄存器 x1 的值写入 FCSR 寄存器。

设置浮点舍入模式

CSRRW x0, frm, x1

将整数寄存器 x1 的值写入 frm(浮点舍入模式)寄存器,同时将原 frm 的值写入 x0。

检查浮点异常

FRCSR x1
ANDI x2, x1, 0x1F # 取出 fflags 的值

将 FCSR 寄存器的值读入整数寄存器 x1,然后通过 AND 操作取出 fflags 字段(低 5 位)的值,存入 x2。

FLW(Floating-Point Load Word)

FLW 指令用于从内存加载一个 32 位的单精度浮点数到浮点寄存器。

指令格式

FLW 指令属于 I 型指令,格式如下:

31 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+-----+--------+
| imm | rs1 | funct3| rd | opcode|
+---------+-------+-------+-------+-----+--------+
  • imm:12 位立即数,表示内存地址偏移量。
  • rs1:基地址寄存器。
  • funct3:功能码,固定为 010
  • rd:目标浮点寄存器。
  • opcode:操作码,固定为 0000111

示例

FLW f1, 4(x2)

将内存地址 x2 + 4 处的 32 位单精度浮点数加载到浮点寄存器 f1 中。

FSW(Floating-Point Store Word)

FSW 指令用于将一个 32 位的单精度浮点数从浮点寄存器存储到内存中。

指令格式

FSW 指令属于 S 型指令,格式如下:

31 25 24 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+-------+--------+
| imm[11:5] | rs2 | rs1 | funct3| imm[4:0]| opcode|
+---------+-------+-------+-------+-------+--------+
  • imm:12 位立即数,分为高 7 位(imm[11:5])和低 5 位(imm[4:0]),表示内存地址偏移量。
  • rs2:源浮点寄存器。
  • rs1:基地址寄存器。
  • funct3:功能码,固定为 010
  • opcode:操作码,固定为 0100111

示例

FSW f1, 4(x2)

将浮点寄存器 f1 中的 32 位单精度浮点数存储到内存地址 x2 + 4 处。

指令表格

R型指令

指令描述funct7rs2rs1funct3rdopcode格式
FADD.S单精度浮点数加法0000000rs2rs1000rd1010011FADD.S rd, rs1, rs2
FSUB.S单精度浮点数减法0000100rs2rs1000rd1010011FSUB.S rd, rs1, rs2
FMUL.S单精度浮点数乘法0001000rs2rs1000rd1010011FMUL.S rd, rs1, rs2
FDIV.S单精度浮点数除法0001100rs2rs1000rd1010011FDIV.S rd, rs1, rs2
FSQRT.S单精度浮点数平方根010110000000rs1000rd1010011FSQRT.S rd, rs1
FSGNJ.S单精度浮点数符号复制0010000rs2rs1000rd1010011FSGNJ.S rd, rs1, rs2
FSGNJN.S单精度浮点数符号取反0010000rs2rs1001rd1010011FSGNJN.S rd, rs1, rs2
FSGNJX.S单精度浮点数符号异或0010000rs2rs1010rd1010011FSGNJX.S rd, rs1, rs2
FMIN.S单精度浮点数最小值0010100rs2rs1000rd1010011FMIN.S rd, rs1, rs2
FMAX.S单精度浮点数最大值0010100rs2rs1001rd1010011FMAX.S rd, rs1, rs2
FCVT.W.S单精度浮点数转换为有符号整数(舍入到零)110000000000rs1000rd1010011FCVT.W.S rd, rs1
FCVT.WU.S单精度浮点数转换为无符号整数(舍入到零)110000000000rs1001rd1010011FCVT.WU.S rd, rs1
FMV.X.W单精度浮点数按位复制到整数寄存器111000000000rs1000rd1010011FMV.X.W rd, rs1
FEQ.S单精度浮点数比较(等于)1010000rs2rs1010rd1010011FEQ.S rd, rs1, rs2
FLT.S单精度浮点数比较(小于)1010000rs2rs1001rd1010011FLT.S rd, rs1, rs2
FLE.S单精度浮点数比较(小于等于)1010000rs2rs1000rd1010011FLE.S rd, rs1, rs2
FCLASS.S分类单精度浮点数值111000000000rs1001rd1010011FCLASS.S rd, rs1
FMV.W.X整数寄存器按位复制到单精度浮点数寄存器111100000000rs1000rd1010011FMV.W.X rd, rs1

D拓展

D 扩展将 32 个浮点寄存器f0-f31扩展至 64 位(表 24中的 FLEN=64)。f现在可以保存 32 位或 64 位浮点值

FLD(Floating-Point Load Double)

FLD 指令用于从内存加载一个 64 位的双精度浮点数到浮点寄存器。

指令格式

FLD 指令属于 I 型指令,格式如下:

31 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+-----+--------+
| imm | rs1 | funct3| rd | opcode|
+---------+-------+-------+-------+-----+--------+
  • imm:12 位立即数,表示内存地址偏移量。
  • rs1:基地址寄存器。
  • funct3:功能码,固定为 011
  • rd:目标浮点寄存器。
  • opcode:操作码,固定为 0000111

示例

FLD f1, 8(x2)

将内存地址 x2 + 8 处的 64 位双精度浮点数加载到浮点寄存器 f1 中。

FSD(Floating-Point Store Double)

FSD 指令用于将一个 64 位的双精度浮点数从浮点寄存器存储到内存中。

指令格式

FSD 指令属于 S 型指令,格式如下:

31 25 24 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+-------+--------+
| imm[11:5] | rs2 | rs1 | funct3| imm[4:0]| opcode|
+---------+-------+-------+-------+-------+--------+
  • imm:12 位立即数,分为高 7 位(imm[11:5])和低 5 位(imm[4:0]),表示内存地址偏移量。
  • rs2:源浮点寄存器。
  • rs1:基地址寄存器。
  • funct3:功能码,固定为 011
  • opcode:操作码,固定为 0100111

示例

FSD f1, 8(x2)

将浮点寄存器 f1 中的 64 位双精度浮点数存储到内存地址 x2 + 8 处。

指令表格

指令描述funct7rs2rs1funct3rdopcode格式
FADD.D双精度浮点数加法0000001rs2rs1000rd1010011FADD.D rd, rs1, rs2
FSUB.D双精度浮点数减法0000101rs2rs1000rd1010011FSUB.D rd, rs1, rs2
FMUL.D双精度浮点数乘法0001001rs2rs1000rd1010011FMUL.D rd, rs1, rs2
FDIV.D双精度浮点数除法0001101rs2rs1000rd1010011FDIV.D rd, rs1, rs2
FSQRT.D双精度浮点数平方根010110100000rs1000rd1010011FSQRT.D rd, rs1
FSGNJ.D双精度浮点数符号复制0010001rs2rs1000rd1010011FSGNJ.D rd, rs1, rs2
FSGNJN.D双精度浮点数符号取反0010001rs2rs1001rd1010011FSGNJN.D rd, rs1, rs2
FSGNJX.D双精度浮点数符号异或0010001rs2rs1010rd1010011FSGNJX.D rd, rs1, rs2
FMIN.D双精度浮点数最小值0010101rs2rs1000rd1010011FMIN.D rd, rs1, rs2
FMAX.D双精度浮点数最大值0010101rs2rs1001rd1010011FMAX.D rd, rs1, rs2
FCVT.S.D双精度浮点数转换为单精度浮点数010000100000rs1000rd1010011FCVT.S.D rd, rs1
FCVT.D.S单精度浮点数转换为双精度浮点数010000000000rs1000rd1010011FCVT.D.S rd, rs1
FEQ.D双精度浮点数比较(等于)1010001rs2rs1010rd1010011FEQ.D rd, rs1, rs2
FLT.D双精度浮点数比较(小于)1010001rs2rs1001rd1010011FLT.D rd, rs1, rs2
FLE.D双精度浮点数比较(小于等于)1010001rs2rs1000rd1010011FLE.D rd, rs1, rs2
FCLASS.D分类双精度浮点数值111000100000rs1001rd1010011FCLASS.D rd, rs1
FCVT.W.D双精度浮点数转换为有符号整数(舍入到零)110000100000rs1000rd1010011FCVT.W.D rd, rs1
FCVT.WU.D双精度浮点数转换为无符号整数(舍入到零)110000100000rs1001rd1010011FCVT.WU.D rd, rs1
FCVT.D.W有符号整数转换为双精度浮点数110100100000rs1000rd1010011FCVT.D.W rd, rs1
FCVT.D.WU无符号整数转换为双精度浮点数110100100000rs1001rd1010011FCVT.D.WU rd, rs1
FMV.X.D双精度浮点数按位复制到整数寄存器111000100000rs1000rd1010011FMV.X.D rd, rs1
FMV.D.X整数寄存器按位复制到双精度浮点数寄存器111100100000rs1000rd1010011FMV.D.X rd, rs1

Q拓展

FLQ(Floating-Point Load Quad)

FLQ 指令用于从内存加载一个 128 位的四倍精度浮点数到浮点寄存器。

指令格式

FLQ 指令属于 I 型指令,格式如下:

31 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+-----+--------+
| imm | rs1 | funct3| rd | opcode|
+---------+-------+-------+-------+-----+--------+
  • imm:12 位立即数,表示内存地址偏移量。
  • rs1:基地址寄存器。
  • funct3:功能码,固定为 011
  • rd:目标浮点寄存器。
  • opcode:操作码,固定为 0000111

示例

FLQ f1, 16(x2)

将内存地址 x2 + 16 处的 128 位四倍精度浮点数加载到浮点寄存器 f1 中。

FSQ(Floating-Point Store Quad)

FSQ 指令用于将一个 128 位的四倍精度浮点数从浮点寄存器存储到内存中。

指令格式

FSQ 指令属于 S 型指令,格式如下:

31 25 24 20 19 15 14 12 11 7 6 0
+---------+-------+-------+-------+-------+--------+
| imm[11:5] | rs2 | rs1 | funct3| imm[4:0]| opcode|
+---------+-------+-------+-------+-------+--------+
  • imm:12 位立即数,分为高 7 位(imm[11:5])和低 5 位(imm[4:0]),表示内存地址偏移量。
  • rs2:源浮点寄存器。
  • rs1:基地址寄存器。
  • funct3:功能码,固定为 011
  • opcode:操作码,固定为 0100111

示例

FSQ f1, 16(x2)

将浮点寄存器 f1 中的 128 位四倍精度浮点数存储到内存地址 x2 + 16 处。

指令表格

指令描述funct7rs2rs1funct3rdopcode格式
FADD.Q四倍精度浮点数加法0000001rs2rs1000rd1010011FADD.Q rd, rs1, rs2
FSUB.Q四倍精度浮点数减法0000101rs2rs1000rd1010011FSUB.Q rd, rs1, rs2
FMUL.Q四倍精度浮点数乘法0001001rs2rs1000rd1010011FMUL.Q rd, rs1, rs2
FDIV.Q四倍精度浮点数除法0001101rs2rs1000rd1010011FDIV.Q rd, rs1, rs2
FSQRT.Q四倍精度浮点数平方根010110100000rs1000rd1010011FSQRT.Q rd, rs1
FSGNJ.Q四倍精度浮点数符号复制0010001rs2rs1000rd1010011FSGNJ.Q rd, rs1, rs2
FSGNJN.Q四倍精度浮点数符号取反0010001rs2rs1001rd1010011FSGNJN.Q rd, rs1, rs2
FSGNJX.Q四倍精度浮点数符号异或0010001rs2rs1010rd1010011FSGNJX.Q rd, rs1, rs2
FMIN.Q四倍精度浮点数最小值0010101rs2rs1000rd1010011FMIN.Q rd, rs1, rs2
FMAX.Q四倍精度浮点数最大值0010101rs2rs1001rd1010011FMAX.Q rd, rs1, rs2
FCVT.S.Q四倍精度浮点数转换为单精度浮点数010000100000rs1000rd1010011FCVT.S.Q rd, rs1
FCVT.Q.S单精度浮点数转换为四倍精度浮点数010000000000rs1000rd1010011FCVT.Q.S rd, rs1
FCVT.D.Q四倍精度浮点数转换为双精度浮点数010000100000rs1001rd1010011FCVT.D.Q rd, rs1
FCVT.Q.D双精度浮点数转换为四倍精度浮点数010000000000rs1001rd1010011FCVT.Q.D rd, rs1
FEQ.Q四倍精度浮点数比较(等于)1010001rs2rs1010rd1010011FEQ.Q rd, rs1, rs2
FLT.Q四倍精度浮点数比较(小于)1010001rs2rs1001rd1010011FLT.Q rd, rs1, rs2
FLE.Q四倍精度浮点数比较(小于等于)1010001rs2rs1000rd1010011FLE.Q rd, rs1, rs2
FCLASS.Q分类四倍精度浮点数值111000100000rs1001rd1010011FCLASS.Q rd, rs1
FCVT.W.Q四倍精度浮点数转换为有符号整数(舍入到零)110000100000rs1000rd1010011FCVT.W.Q rd, rs1
FCVT.WU.Q四倍精度浮点数转换为无符号整数(舍入到零)110000100000rs1001rd1010011FCVT.WU.Q rd, rs1
FCVT.Q.W有符号整数转换为四倍精度浮点数110100100000rs1000rd1010011FCVT.Q.W rd, rs1
FCVT.Q.WU无符号整数转换为四倍精度浮点数110100100000rs1001rd1010011FCVT.Q.WU rd, rs1

Zfh拓展

RISC-V 的 Zfh 扩展(Half-Precision Floating-Point Extension)增加了一组用于半精度浮点数(16 位)运算的指令。这些指令允许处理器执行半精度浮点数的算术、比较、转换和其他操作,从而提高系统在需要高效且快速处理浮点数据的应用中的性能,例如图形处理和机器学习。

指令表格

指令描述funct7rs2rs1funct3rdopcode格式
FADD.H半精度浮点数加法0000101rs2rs1000rd1010011FADD.H rd, rs1, rs2
FSUB.H半精度浮点数减法0001101rs2rs1000rd1010011FSUB.H rd, rs1, rs2
FMUL.H半精度浮点数乘法0010101rs2rs1000rd1010011FMUL.H rd, rs1, rs2
FDIV.H半精度浮点数除法0011101rs2rs1000rd1010011FDIV.H rd, rs1, rs2
FSQRT.H半精度浮点数平方根010110100000rs1000rd1010011FSQRT.H rd, rs1
FSGNJ.H半精度浮点数符号复制0110001rs2rs1000rd1010011FSGNJ.H rd, rs1, rs2
FSGNJN.H半精度浮点数符号取反0110001rs2rs1001rd1010011FSGNJN.H rd, rs1, rs2
FSGNJX.H半精度浮点数符号异或0110001rs2rs1010rd1010011FSGNJX.H rd, rs1, rs2
FMIN.H半精度浮点数最小值0110101rs2rs1000rd1010011FMIN.H rd, rs1, rs2
FMAX.H半精度浮点数最大值0110101rs2rs1001rd1010011FMAX.H rd, rs1, rs2
FCVT.S.H半精度浮点数转换为单精度浮点数100000100000rs1000rd1010011FCVT.S.H rd, rs1
FCVT.H.S单精度浮点数转换为半精度浮点数100000000000rs1000rd1010011FCVT.H.S rd, rs1
FEQ.H半精度浮点数比较(等于)1010001rs2rs1010rd1010011FEQ.H rd, rs1, rs2
FLT.H半精度浮点数比较(小于)1010001rs2rs1001rd1010011FLT.H rd, rs1, rs2
FLE.H半精度浮点数比较(小于等于)1010001rs2rs1000rd1010011FLE.H rd, rs1, rs2
FCLASS.H分类半精度浮点数值110000100000rs1001rd1010011FCLASS.H rd, rs1
FCVT.W.H半精度浮点数转换为有符号整数(舍入到零)110000100000rs1000rd1010011FCVT.W.H rd, rs1
FCVT.WU.H半精度浮点数转换为无符号整数(舍入到零)110000100000rs1001rd1010011FCVT.WU.H rd, rs1
FCVT.H.W有符号整数转换为半精度浮点数110100100000rs1000rd1010011FCVT.H.W rd, rs1
FCVT.H.WU无符号整数转换为半精度浮点数110100100000rs1001rd1010011FCVT.H.WU rd, rs1

Zfhmin拓展

为 16 位半精度二进制浮点指令提供最低限度的支持。 Zfhmin 扩展是 Zfh 扩展的子集,仅包含数据传输和转换指令。与 Zfh 一样,Zfhmin 扩展依赖于单精度浮点扩展 F。预期 Zfhmin 软件主要使用半精度格式进行存储,以更高精度执行大多数计算。

Zfa拓展

添加了立即加载、IEEE 754-2019 最小和最大运算、舍入到整数运算和安静浮点比较的指令。对于 RV32D,Zfa 扩展还添加了用于在整数寄存器之间传输双精度浮点值的指令,对于 RV64Q,它添加了用于四精度浮点值的类似指令。 Zfa 扩展取决于 F 扩展。

Zfinx,Zdinx,Zhinx,Zhinxmin

“Zfinx”扩展(发音为“zf-in-x”),它提供与单精度浮点指令的标准浮点 F 扩展中的指令类似的指令,但它在x寄存器上操作,而不是在f寄存器上操作。 f寄存器。本章还定义了“Zdinx”、“Zhinx”和“Zhinxmin”扩展,它们为其他浮点精度提供类似的指令。Zfinx 扩展添加了 F 扩展添加的所有指令,但传输指令 FLW、FSW、FMV.WX、FMV.XW、C.FLW[SP] 和 C.FSW[SP]除外。

这些 F 扩展指令的 Zfinx 变体具有相同的语义,只是每当此类指令访问f寄存器时,它都会访问具有相同编号的x寄存器。

Zfinx 扩展依赖于“Zicsr”扩展来进行控制和状态寄存器访问。

C拓展

通过为常见操作添加短的 16 位指令编码来减少静态和动态代码大小。 C 扩展可以添加到任何基本 ISA(RV32、RV64、RV128)中,我们使用通用术语“RVC”来涵盖其中任何一个。通常,程序中 50%-60% 的 RISC-V 指令可以替换为 RVC 指令,从而使代码大小减少 25%-30%。RVC 使用简单的压缩方案,在以下情况下提供常见 32 位 RISC-V 指令的较短 16 位版本:

  • 立即数或地址偏移量很小
  • 其中一个寄存器是零寄存器 ( x0 )、ABI 链接寄存器 ( x1 ) 或 ABI 堆栈指针 ( x2 )
  • 目标寄存器和第一个源寄存器相同
  • 使用的寄存器是 8 个最常用的寄存器。

1. CI 格式(Compressed Immediate)

CI 格式用于带立即数的操作指令。

15 13 12 12 11 7 6 2 1 0
----------+-------------------+--------------+---------------+-------------------+-------+
cmd | funct3 | imm | rd/rs1 | imm | opcode|
----------+-------------------+--------------+---------------+-------------------+-------+
C.LWSP | 010 | offset[5] | dest!=0 | offset[4:2|7:6] | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.LDSP | 011 | offset[5] | dest!=0 | offset[4:3|8:6] | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.FLWSP | 011 | offset[5] | dest!=0 | offset[4|9:6] | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.FLDSP | 001 | offset[5] | dest | offset[4:2|7:6] | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.LQSP | 001 | offset[5] | dest | offset[4:3|8:6] | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.LI | 010 | imm[5] | dest!=0 | imm[4:0] | 01 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.LUI | 011 | nzimm[17] | dest!={0,2}| imm[16:12] | 01 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.ADDI | 000 | nzimm[5] | dest!=0 | nzimm[4:0] | 01 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.ADDIW | 001 | imm[5] | dest!=0 | imm[4:0] | 01 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.ADDI16SP| 011 | nzimm[9] | 2 | nzimm[4|6|8:7|5] | 01 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.SLLI | 000 | shamt[5] | dest!=0 | shamt[4:0] | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.NOP | 000 | 0 | 0 | 0 | 01 |
----------+-------------------+--------------+---------------+-------------------+-------+
  • C.LWSP: 将内存中的32位值加载到寄存器rd中。它通过将按4缩放的零扩展偏移量添加到堆栈指针x2来计算有效地址。它扩展为 lw rd, offset(x2)
  • C.LDSP: 是仅 RV64C/RV128C 的指令,它将 64 位值从内存加载到寄存器 rd 中。它通过将按 8 缩放的零扩展偏移量添加到堆栈指针 x2 来计算其有效地址。它扩展为 ld rd, offset(x2) 。 C.LDSP仅在rd!=x0时有效,rd=x0的码点被保留。
  • C.FLWSP: 是仅 RV128C 的指令,它将 128 位值从内存加载到寄存器 rd 中。它通过将按 16 缩放的零扩展偏移量添加到堆栈指针 x2 来计算其有效地址。它扩展为 lq rd, offset(x2) 。 C.LQSP仅当rd≠x0时有效,rd=x0的码点被保留。
  • C.FLDSP: 仅 RV32FC 的指令,它将单精度浮点值从内存加载到浮点寄存器 rd 中。它通过将按 4 缩放的零扩展偏移量添加到堆栈指针 x2 来计算其有效地址。它扩展为 flw rd, offset(x2)
  • C.LQSP: 仅 RV32DC/RV64DC 指令,它将双精度浮点值从内存加载到浮点寄存器 rd 中。它通过将按 8 缩放的零扩展偏移量添加到堆栈指针 x2 来计算其有效地址。它扩展为 fld rd, offset(x2)
  • C.LI: 将符号扩展的 6 位立即数 imm 加载到寄存器 rd 中。 C.LI 扩展为 addi rd, x0, imm
  • C.LUI: 将非零 6 位立即数字段加载到目标寄存器的位 17-12,清除底部 12 位,并将位 17 符号扩展到目标寄存器的所有较高位。 C.LUI 扩展为 lui rd, imm
  • C.ADDI: 将非零符号扩展 6 位立即数与寄存器 rd 中的值相加,然后将结果写入 rd。 C.ADDI 扩展为addi rd, rd, imm
  • C.ADDIW: RV64C/RV128C 的指令,它执行相同的计算,但生成 32 位结果,然后将结果符号扩展为 64 位。 C.ADDIW 扩展为addiw rd, rd, imm
  • C.ADDI16SP: 将非零符号扩展 6 位立即数添加到堆栈指针 ( sp=x2 ) 中的值,其中立即数被缩放以表示范围 (-512,496) 内 16 的倍数。 C.ADDI16SP 用于调整程序序言和尾声中的堆栈指针。它扩展为addi x2, x2, nzimm[9:4]
  • C.SLLI: 对寄存器 rd 中的值执行逻辑左移,然后将结果写入 rd。移位量在 shamt 字段中编码。对于 RV128C,移位量为零用于编码 64 的移位。C.SLLI 扩展为 slli rd, rd, shamt[5:0],但 RV128C 除外,其 shamt=0,扩展为 slli rd, rd, 64。对于 RV32C,shamt[5] 必须为零;shamt[5]=1 的代码点指定用于自定义扩展。对于 RV32C 和 RV64C,移位量必须非零;shamt=0 的代码点是 HINT。对于所有基本 ISA,rd=x0 的代码点都是 HINT,RV32C 中 shamt[5]=1 的代码点除外。
  • C.NOP: 除了推进pc 和增加任何适用的性能计数器外,它不会改变任何用户可见的状态。C.NOP 扩展为nop

2. CJ 格式(Compressed Jump)

CJ 格式用于跳转指令。

15 2 1 0
----------+-------------------+-----------------------------------------------------------+-------+
cmd | funct3 | imm | opcode|
----------+-------------------+-----------------------------------------------------------+-------+
C.J | 101 | offset[11|4|9:8|10|6|7|3:1|5] | 01 |
----------+-------------------+-----------------------------------------------------------+-------+
C.JAL | 001 | offset[11|4|9:8|10|6|7|3:1|5] | 01 |
----------+-------------------+-----------------------------------------------------------+-------+
  • C.J: 执行无条件控制传输。偏移量经过符号扩展并添加到pc以形成跳转目标地址。因此,C.J 可以定位 ±2 KiB 范围。C.J 扩展为 jal x0,offset
  • C.JAL: RV32C 专用指令,执行与 C.J 相同的操作,但另外将跳转(pc+2)后的指令地址写入链接寄存器 x1。C.JAL 扩展为 jal x1,offset

3. CL 格式(Compressed Load)

CL 格式用于加载指令。

15 13 12 10 9 7 6 5 4 2 1 0
----------+-------------------+--------------+---------------+------------------+---------+-------+
cmd | funct3 | imm | rs1 | imm | rd | opcode|
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.LW | 010 | offset[5:3] | base | offset[2|6] | dest | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.LD | 011 | offset[5:3] | base | offset[7:6] | dest | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.LQ | 001 | offset[5|4|8]| base | offset[7:6] | dest | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.FLW | 011 | offset[5:3] | base | offset[2|6] | dest | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.FLD | 001 | offset[5:3] | base | offset[7:6] | dest | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
  • C.LW: 将内存中的 32 位值加载到寄存器 rd 中。它通过将零扩展偏移量(按 4 缩放)添加到寄存器 rs1 中的基地址来计算有效地址。它扩展为 lw rd,offset(rs1)
  • C.LD: RV64C/RV128C 专用指令,它将内存中的 64 位值加载到寄存器 rd 中。它通过将零扩展偏移量(按 8 缩放)添加到寄存器 rs1中的基地址来计算有效地址。它扩展为 ld rd, offset(rs1)
  • C.LQ: RV128C 专用指令,它将 128 位值从内存加载到寄存器 rd 中。它通过将零扩展偏移量(按 16 缩放)添加到寄存器 rs1 中的基址来计算有效地址。它扩展为lq rd′, offset(rs1′)
  • C.FLW: RV32FC 的指令,它将单精度浮点值从内存加载到浮点寄存器 rd 中。它通过将按 4 缩放的零扩展偏移量添加到寄存器 rs1 中的基地址来计算有效地址。它扩展为 flw rd, offset(rs1)
  • C.FLD: RV32DC/RV64DC 指令,它将双精度浮点值从内存加载到浮点寄存器 rd 中。它通过将按 8 缩放的零扩展偏移量与寄存器 rs1中的基地址相加来计算有效地址。它扩展为fld rd, offset(rs1)

4. CS 格式(Compressed Store)

CS 格式用于存储指令。

15 13 12 10 9 7 6 5 4 2 1 0
----------+-------------------+--------------+---------------+------------------+---------+-------+
cmd | funct3 | imm | rs1 | imm | rs2 | opcode|
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.SW | 110 | offset[5:3] | base | offset[2|6] | src | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.SD | 111 | offset[5:3] | base | offset[7:6] | src | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.SQ | 101 | offset[5|4|8]| base | offset[7:6] | src | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.FSW | 111 | offset[5:3] | base | offset[2|6] | src | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
C.FSD | 101 | offset[5:3] | base | offset[7:6] | src | 00 |
----------+-------------------+--------------+---------------+------------------+---------+-------+
  • C.SW: 将寄存器 rs2 中的 32 位值存储到内存中。它通过将零扩展偏移量(按 4 缩放)添加到寄存器 rs1 中的基地址来计算有效地址。它扩展为sw rs2,offset(rs1)
  • C.SD: RV64C/RV128C 专用指令,它将寄存器 rs2 中的 64 位值存储到内存中。它通过将零扩展偏移量(按 8 缩放)添加到寄存器 rs1 中的基地址来计算有效地址。它扩展为sd rs2, offset(rs1)
  • C.SQ: RV128C 专用指令,它将寄存器 rs2 中的 128 位值存储到内存中。它通过将零扩展偏移量(按 16 缩放)添加到寄存器 rs1 中的基地址来计算有效地址。它扩展为sq rs2, offset(rs1)
  • C.FSW: RV32FC 专用指令,将浮点寄存器 rs2 中的单精度浮点值存储到内存中。它通过将零扩展偏移量(按 4 缩放)添加到寄存器 rs1 中的基地址来计算有效地址。它扩展为fsw rs2, offset(rs1)
  • C.FSD: RV32DC/RV64DC 专用指令,将浮点寄存器 rs2 中的双精度浮点值存储到内存中。它通过将零扩展偏移量(按 8 缩放)添加到寄存器 rs1 中的基地址来计算有效地址。它扩展为fsd rs2, offset(rs1)

5. CB 格式(Compressed Branch)

CB 格式用于分支指令。

15 13 12 10 9 7 6 2 1 0
----------+-------------------+------------------+--------------+--------------------+-------+
cmd | funct3 | imm | rs1 | imm | opcode|
----------+-------------------+------------------+--------------+--------------------+-------+
C.BEQZ | 110 | offset[8|4:3] | src | offset[7:6|2:1|5] | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
C.BNEZ | 111 | offset[8|4:3] | src | offset[7:6|2:1|5] | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
15 13 12 12 11 10 9 7 6 2 1 0
----------+-------------------+-----------+----------+--------------+--------------------+-------+
cmd | funct3 | imm | funct2 | rd/rs1 | imm | opcode|
----------+-------------------+-----------+----------+--------------+--------------------+-------+
C.SRLI | 100 | shamt[5] | 00 | dest | shamt[4:0] | 01 |
----------+-------------------+-----------+----------+--------------+--------------------+-------+
C.SRAI | 100 | shamt[5] | 01 | dest | shamt[4:0] | 01 |
----------+-------------------+-----------+----------+--------------+--------------------+-------+
C.ANDI | 100 | imm[5] | 10 | dest | imm[4:0] | 01 |
----------+-------------------+-----------+----------+--------------+--------------------+-------+
  • C.BEQZ: 执行条件控制传输。偏移量经过符号扩展并添加到 pc 以形成分支目标地址。因此,它可以定位 ±256 B 范围。如果寄存器 rs1 中的值为零,则 C.BEQZ 进行分支。它扩展为 beq rs1, x0, offset
  • C.BNEZ: C.BEQZ 的定义类似,但如果 rs1 包含非零值,则进行分支。它扩展为bne rs1′, x0, offset
  • C.SRLI: 对寄存器 rd 中的值执行逻辑右移,然后将结果写入 rd。移位量被编码在 shamt 字段中。对于RV128C,使用移位量0来编码64的移位。此外,对于RV128C,移位量被符号扩展,因此合法的移位量为1-31、64和96-127。 C.SRLI 扩展为 srli rd, rd, shamt ,但 shamt=0 的 RV128C 除外,它扩展为 srli rd, rd, 64 。对于RV32C,shamt[5]必须为零; shamt[5]=1 的代码点指定用于自定义扩展。对于RV32C和RV64C,移位量必须非零; shamt=0 的代码点是提示。
  • C.SRAI: 与 C.SRLI 类似,但执行算术右移。 C.SRAI 扩展为 srai rd、rd、shamt
  • C.ANDI: 计算寄存器 rd 中的值与符号扩展的 6 位立即数按位与,然后将结果写入 rd。 C.ANDI 扩展为 andi rd, rd, imm

6. CR 格式(Compressed Register)

CR 格式用于寄存器到寄存器的操作指令。

15 12 11 7 6 2 1 0
----------+-------------------+-------------------------+---------------------------------+-------+
cmd | funct4 | rs1 | rs2 | opcode|
----------+-------------------+-------------------------+---------------------------------+-------+
C.JR | 1000 | src!=0 | 0 | 10 |
----------+-------------------+-------------------------+---------------------------------+-------+
C.JALR | 1001 | src!=0 | 0 | 10 |
----------+-------------------+-------------------------+---------------------------------+-------+
C.MV | 1000 | dest!=0 | src!=0 | 10 |
----------+-------------------+-------------------------+---------------------------------+-------+
C.ADD | 1001 | dest!=0 | src!=0 | 10 |
----------+-------------------+-------------------------+---------------------------------+-------+
C.EBREAK | 1001 | 0 | 0 | 10 |
----------+-------------------+-------------------------+---------------------------------+-------+
  • C.JR: 执行无条件控制传输到寄存器 rs1 中的地址。C.JR 扩展为 jalr x0, 0(rs1)。C.JR 仅在以下情况下有效rs1!=0
  • C.JALR: 执行与 C.JR 相同的操作,但另外将跳转(pc+2)之后的指令的地址写入链接寄存器 x1。C.JALR 扩展为 jalr x1, 0(rs1)。C.JALR 仅在以下情况下有效rs1!=0
  • C.MV: 将寄存器 rs2 中的值复制到寄存器 rd 中。C.MV 扩展为 add rd, x0, rs2
  • C.ADD: 将寄存器 rd 和 rs2 中的值相加,并将结果写入寄存器 rd。C.ADD 扩展为add rd, rd, rs2

7. CSS 格式(Compressed Stack Store)

CSS 格式用于存储到堆栈指令。

15 13 12 7 6 2 1 0
----------+-------------------+------------------------------+-------------------+-------+
cmd | funct3 | imm | rs2 | opcode|
----------+-------------------+--------------+---------------+-------------------+-------+
C.SWSP | 110 | offset[5:2|7:6] | src | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.SDSP | 111 | offset[5:3|8:6] | src | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.SQSP | 101 | offset[5:4|9:6] | src | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.FSWSP | 111 | offset[5:2|7:6] | src | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
C.FSDSP | 101 | offset[5:3|8:6] | src | 10 |
----------+-------------------+--------------+---------------+-------------------+-------+
  • C.SWSP: 将寄存器 rs2 中的 32 位值存储到内存中。它通过将按 4 缩放的零扩展偏移量添加到堆栈指针 x2 来计算有效地址。它扩展为 sw rs2, offset(x2) 。
  • C.SDSP: 仅 RV64C/RV128C 的指令,它将寄存器 rs2 中的 64 位值存储到内存。它通过将按 8 缩放的零扩展偏移量添加到堆栈指针 x2 来计算有效地址。它扩展为 sd rs2, offset(x2) 。
  • C.SQSP: 仅 RV128C 的指令,它将寄存器 rs2 中的 128 位值存储到内存。它通过将按 16 缩放的零扩展偏移量添加到堆栈指针 x2 来计算有效地址。它扩展为 sq rs2, offset(x2) 。
  • C.FSWSP: 仅 RV32FC 指令,它将浮点寄存器 rs2 中的单精度浮点值存储到内存。它通过将按 4 缩放的零扩展偏移量添加到堆栈指针 x2 来计算有效地址。它扩展为 fsw rs2, offset(x2) 。
  • C.FSDSP: 仅 RV32DC/RV64DC 指令,它将浮点寄存器 rs2 中的双精度浮点值存储到内存。它通过将按 8 缩放的零扩展偏移量添加到堆栈指针 x2 来计算有效地址。它扩展为 fsd rs2, offset(x2)。

8. CIW 格式(Compressed Immediate Wide)

CIW 格式用于加载立即数宽指令。

15 13 12 5 4 2 1 0
----------+-------------------+------------------------------+-------------------+-------+
cmd | funct3 | imm | rd | opcode|
----------+-------------------+--------------+---------------+-------------------+-------+
C.ADDI4SPN| 000 | nzuimm[5:4|9:6|2|3] | dest | 00 |
----------+-------------------+--------------+---------------+-------------------+-------+
  • C.ADDI4SPN: 它将按 4 缩放的零扩展非零立即数添加到堆栈指针 x2 ,并将结果写入 rd′ 。该指令用于生成指向堆栈分配变量的指针,并扩展为addi rd, x2, nzuimm[9:2]

9. CA 格式

15 10 9 7 6 5 4 2 1 0
----------+-------------------+------------------+--------------+--------------------+-------+
cmd | funct6 | rd/rs1 | funct2 | rs2 | opcode|
----------+-------------------+------------------+--------------+--------------------+-------+
C.AND | 100011 | dest | 11 | src | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
C.OR | 100011 | dest | 10 | src | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
C.XOR | 100011 | dest | 01 | src | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
C.SUB | 100011 | dest | 00 | src | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
C.ADDW | 100111 | dest | 01 | src | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
C.SUBW | 100111 | dest | 00 | src | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+
  • C.AND: 计算寄存器 rd 和 rs2 中值的按位与,然后将结果写入寄存器rd。C.AND 扩展为 and rd, rd, rs2
  • C.OR: 计算寄存器 rd 和 rs2 中值的按位或,然后将结果写入寄存器 rd。C.OR 扩展为 or rd, rd, rs2
  • C.XOR: 计算寄存器 rd 和 rs2 中值的按位异或,然后将结果写入寄存器rd。扩展为 xor rd, rd, rs2
  • C.SUB: 从寄存器 rd 中的值中减去寄存器 rs2 中的值,然后将结果写入寄存器rd。C.SUB 扩展为 sub rd、rd′、rs2
  • C.ADDW: RV64C/RV128C 专用指令,它将寄存器 rd 和 rs2 中的值相加,然后对和的低 32 位进行符号扩展,然后将结果写入寄存器 rd扩展为addw rd、rd、rs2
  • C.SUBW:RV64C/RV128C 专用指令,它将寄存器 rd 中的值中减去寄存器 rs2 中的值,然后对差值的低 32 位进行符号扩展,然后将结果写入寄存器 rd。扩展为 subw rd、rd、rs2

寄存器

CIW、CL、CS、CA 和 CB 格式的三位 rs1'、rs2' 和 rd' 字段指定的寄存器

RVC Register Number000001010011100101110111
Integer Register Numberx8x9x10x11x12x13x14x15
Integer Register ABI Names0s1a0a1a2a3a4a5
Floating-Point Register Numberf8f9f10f11f12f13f14f15
Floating-Point Register ABI Namefs0fs1fa0fa1fa2fa3fa4fa5

Zc*拓展

Zc* 是一组扩展,定义现有 C 扩展的子集(Zca、Zcd、Zcf)和仅包含 16 位编码的新扩展。

指令ZcaZcfZcdZcbZcmpZcmt
Zca 扩展用于引用 C 扩展中的指令,这些指令不包括浮点加载和存储
C 排除 c.f*
Zcf 扩展用于引用压缩的单精度浮点加载/存储
c.flwrv32
c.flwsprv32
c.fswrv32
c.fswsprv32
Zcd 扩展用于引用压缩的双精度浮点加载/存储
c.fld
c.fldsp
c.fsd
c.fsdsp
适用于所有架构的简单操作
c.lbu
c.lh
c.lhu
c.sb
c.sh
c.zext.b
c.sext.b
c.zext.h
c.sext.h
c.zext.w
c.mul
c.not
与 c.fsdsp 重叠的 PUSH/POP 和双重移动。用于嵌入式 CPU 的复杂操作
cm.push
cm.pop
cm.popret
cm.popretz
cm.mva01s
cm.mvsa01
与 c.fsdsp 重叠的表跳转。用于嵌入式 CPU 的复杂操作
cm.jt
cm.jalt

C

C 扩展是以下扩展的超集:

  • Zca
  • Zcf 如果指定了 F(仅限 RV32)
  • Zcd(如果指定了 D)

由于 C 定义了与 Zca、Zcf 和 Zcd 相同的指令,因此规则是:

  • C 总是意味Zca
  • C+F 意味着 Zcf(仅限 RV32)
  • C+D 意味着Zcd

Zce

Zce 扩展旨在用于微控制器,并包括所有相关的 Zc 扩展。

  • 在不带 F 的 RV32 上指定 Zce 包括 Zca、Zcb、Zcmp、Zcmt。
  • 在 RV32 上用 F 指定 Zce 包括 Zca、Zcb、Zcmp、Zcmt 和 Zcf。
  • 在 RV64 上指定 Zce 始终包括 Zca、Zcb、Zcmp、Zcmt。 RV64 不存在 Zcf。

MISA.C

如果选择以下扩展名,则设置 MISA.C:

  • Zca 而不是 F
  • 指定Zca、Zcf 和F(仅限RV32)。
  • Zca、Zcf 和 Zcd(如果指定了 D)(仅限 RV32)。此配置不包括 Zcmp、Zcmt。
  • Zca、Zcd(如果指定了 D)(仅限 RV64)此配置不包括 Zcmp、Zcmt。

Zca

Zca 扩展是为了引用 C 扩展中不包括浮点加载和存储的指令。因此,它排除了所有 16 位浮点加载和存储:c.flw、c.flwsp、c.fsw、c.fswsp、c.fld、c.fldsp、c.fsd、c.fsdsp。

Zcf

Zcf 是现有的一组压缩单精度浮点加载和存储:c.flw、c.flwsp、c.fsw、c.fswsp。

Zcd

Zcd 是现有的一组压缩双精度浮点加载和存储:c.fld、c.fldsp、c.fsd、c.fsdsp。

Zcb

Zcb 具有简单的代码大小节省指令,很容易在所有 CPU 上实现。目前所有编码都为所有架构保留,并且与任何现有扩展没有冲突。

Zcmp

Zcmp 扩展是一组指令,可以作为一系列现有 32 位 RISCV 指令执行。此扩展重用了 c.fsdsp 中的一些编码。因此,它与 Zcd 不兼容,当 C 和 D 扩展同时存在时,Zcd 也会被包含在内。

Zcmt

Zcmt添加了表跳转指令,还添加了jvt CSR。此扩展重用了 c.fsdsp 中的一些编码。因此,它与 Zcd 不兼容,当 C 和 D 扩展同时存在时,Zcd 也会被包含在内。Zcmt 扩展依赖于 Zca 和 Zicsr 扩展。

Zc指令格式

CLB

15 10 9 7 6 5 4 2 1 0
----------+-------------------+--------------+---------------+-------------------+-------+
cmd | funct6 | rs1 | uimm | rd | opcode|
----------+-------------------+--------------+---------------+-------------------+-------+
c.lbu | 100000 | x8-x15 | uimm[0|1] | x8-x15 | 00 |
----------+-------------------+--------------+---------------+-------------------+-------+

该指令从通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址加载一个字节。结果字节被零扩展到 XLEN 位并写入 rd。

CLH

15 10 9 7 6 6 5 5 4 2 1 0
----------+-------------------+--------------+------+---------+-------------------+-------+
cmd | funct6 | rs1 | uimm | rd | opcode|
----------+-------------------+--------------+------+---------+-------------------+-------+
c.lhu | 100001 | x8-x15 | 0 |uimm[1] | x8-x15 | 00 |
----------+-------------------+--------------+----------------+-------------------+-------+
c.lh | 100001 | x8-x15 | 1 |uimm[1] | x8-x15 | 00 |
----------+-------------------+--------------+----------------+-------------------+-------+

c.lhu: 该指令从通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址加载半字。所得半字被零扩展到 XLEN 位并写入 rd。 c.lh: 该指令从通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址加载半字。所得半字被零扩展到 XLEN 位并写入 rd。

CSB

15 10 9 7 6 5 4 2 1 0
----------+-------------------+--------------+---------------+-------------------+-------+
cmd | funct6 | rs1 | uimm | rs2 | opcode|
----------+-------------------+--------------+---------------+-------------------+-------+
c.sb | 100010 | x8-x15 | uimm[0|1] | x8-x15 | 00 |
----------+-------------------+--------------+---------------+-------------------+-------+

该指令将 rs2 的最低有效字节存储到通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址。

CSH

15 10 9 7 6 6 5 5 4 2 1 0
----------+-------------------+--------------+------+---------+-------------------+-------+
cmd | funct6 | rs1 | uimm | rs2 | opcode|
----------+-------------------+--------------+------+---------+-------------------+-------+
c.sh | 100011 | x8-x15 | 0 |uimm[1] | x8-x15 | 00 |
----------+-------------------+--------------+----------------+-------------------+-------+

该指令将 rs2 的最低有效半字存储到通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址。

CU

15 10 9 7 6 2 1 0
----------+-------------------+--------------+------------------------+-------+
cmd | funct6 | rd/rs1 | funct5 | opcode|
----------+-------------------+--------------+------------------------+-------+
c.zext.b | 100111 | x8-x15 | 11000 | 01 |
----------+-------------------+--------------+------------------------+-------+
c.sext.b | 100111 | x8-x15 | 11001 | 01 |
----------+-------------------+--------------+------------------------+-------+
c.zext.h | 100111 | x8-x15 | 11010 | 01 |
----------+-------------------+--------------+------------------------+-------+
c.sext.h | 100111 | x8-x15 | 11011 | 01 |
----------+-------------------+--------------+------------------------+-------+
c.zext.w | 100111 | x8-x15 | 11100 | 01 |
----------+-------------------+--------------+------------------------+-------+
c.not | 100111 | x8-x15 | 11101 | 01 |
----------+-------------------+--------------+------------------------+-------+
  • c.zext.b: 该指令采用单个源/目标操作数。它通过将零插入到所有比 7 更重要的位中,将操作数的最低有效字节零扩展到 XLEN 位。
  • c.sext.b: 该指令采用单个源/目标操作数。它通过将字节中的最高有效位(即位 7)复制到所有较高有效位,将操作数中的最低有效字节符号扩展为 XLEN 位。
  • c.zext.h: 该指令采用单个源/目标操作数。通过将零插入到所有高于 15 的位中,它将操作数的最低有效半字零扩展到 XLEN 位。
  • c.sext.h: 该指令采用单个源/目标操作数。它通过将半字中的最高有效位(即位 15)复制到所有较高有效位,将操作数中的最低有效半字符号扩展为 XLEN 位。
  • c.zext.w: 该指令采用单个源/目标操作数。通过将零插入到所有高于 31 的位中,它将操作数的最低有效字零扩展到 XLEN 位。
  • c.not: 该指令取 rd/rs1 的反码并将结果写入同一寄存器。

CA

15 10 9 7 6 5 4 2 1 0
----------+-------------------+------------------+--------------+--------------------+-------+
cmd | funct6 | rd/rs1 | funct2 | rs2 | opcode|
----------+-------------------+------------------+--------------+--------------------+-------+
c.mul | 100111 | x8-x15 | 10 | x8-x15 | 01 |
----------+-------------------+------------------+--------------+--------------------+-------+

该指令将 rs1 和 rs2 中的源操作数的 XLEN 位相乘,并将结果的最低 XLEN 位写入 rd。

CMPP

15 10 9 8 7 2 1 0
----------+-------------------+--------------+-----------------------+----------------+-------+
cmd | funct6 | funct2 | urlist | spimm | opcode|
----------+-------------------+--------------+-----------------------+----------------+-------+
cm.push | 101110 | 00 | rlist | spimm[5:4] | 10 |
----------+-------------------+--------------+-----------------------+----------------+-------+
cm.pop | 101110 | 10 | rlist | spimm[5:4] | 10 |
----------+-------------------+--------------+-----------------------+----------------+-------+
cm.popretz| 101111 | 00 | rlist | spimm[5:4] | 10 |
----------+-------------------+--------------+-----------------------+----------------+-------+
cm.popret | 101111 | 10 | rlist | spimm[5:4] | 10 |
----------+-------------------+--------------+-----------------------+----------------+-------+
cm.mvsa01 | 101011 | 01 | rlist | spimm[5:4] | 10 |
----------+-------------------+--------------+-----------------------+----------------+-------+
cm.mvsa01s| 101111 | 00 | rlist | spimm[5:4] | 10 |
----------+-------------------+--------------+-----------------------+----------------+-------+
  • cm.push: 将 ra 和 0 到 12 个保存的寄存器存储到堆栈帧,可选择分配额外的堆栈空间。
  • cm.pop: 从堆栈帧加载ra和0到12保存的寄存器,释放堆栈帧。
  • cm.popretz: 从堆栈帧加载ra和0到12个保存的寄存器,释放堆栈帧,将零移入a0,返回到ra。
  • cm.popret: 从堆栈帧加载ra和0到12个保存的寄存器,释放堆栈帧,返回ra。
  • cm.mvsa01: 将a0-a1移动到s0-s7的两个寄存器中。

CMMV

15 10 9 7 6 5 4 2 1 0
----------+-------------------+--------------+----------------+-------------------+-------+
cmd | funct6 | rs1 | funct2 | rs2 | opcode|
----------+-------------------+--------------+----------------+-------------------+-------+
cm.mvsa01 | 101011 | | 01 | | 10 |
----------+-------------------+--------------+----------------+-------------------+-------+
cm.mvsa01s| 101011 | | 11 | | 10 |
----------+-------------------+--------------+----------------+-------------------+-------+
  • cm.mvsa01: 将a0-a1移动到s0-s7的两个寄存器中。
  • cm.mvsa01s: 将两个s0-s7寄存器移入a0-a1。

CMJT

15 10 9 2 1 0
----------+-------------------+-----------------------------------------------+-------+
cmd | funct6 | index | opcode|
----------+-------------------+-----------------------------------------------+-------+
cm.jt | 101000 | | 10 |
----------+-------------------+-----------------------------------------------+-------+
cm.jalt | 101000 | | 10 |
----------+-------------------+-----------------------------------------------+-------+
  • cm.jt: 通过表跳转
  • cm.jalt: 通过带有可选链接的表格跳转

B拓展

B 标准扩展包括 Zba、Zbb 和 Zbs 扩展提供的指令。

RV32RV64MnemonicInstructionZbaZbbZbcZbs
add.uw rd, rs1, rs2Add unsigned word
andn rd, rs1, rs2AND with inverted operand
clmul rd, rs1, rs2Carry-less multiply (low-part)
clmulh rd, rs1, rs2Carry-less multiply (high-part)
clmulr rd, rs1, rs2Carry-less multiply (reversed)
clz rd, rsCount leading zero bits
clzw rd, rsCount leading zero bits in word
cpop rd, rsCount set bits
cpopw rd, rsCount set bits in word
ctz rd, rsCount trailing zero bits
ctzw rd, rsCount trailing zero bits in word
max rd, rs1, rs2Maximum
maxu rd, rs1, rs2Unsigned maximum
min rd, rs1, rs2Minimum
minu rd, rs1, rs2Unsigned minimum
orc.b rd, rs1, rs2Bitwise OR-Combine, byte granule
orn rd, rs1, rs2OR with inverted operand
rev8 rd, rsByte-reverse register
rol rd, rs1, rs2Rotate left (Register)
rolw rd, rs1, rs2Rotate Left Word (Register)
ror rd, rs1, rs2Rotate right (Register)
rori rd, rs1, shamtRotate right (Immediate)
roriw rd, rs1, shamtRotate right Word (Immediate)
rorw rd, rs1, rs2Rotate right Word (Register)
bclr rd, rs1, rs2Single-Bit Clear (Register)
bclri rd, rs1, immSingle-Bit Clear (Immediate)
bext rd, rs1, rs2Single-Bit Extract (Register)
bexti rd, rs1, immSingle-Bit Extract (Immediate)
binv rd, rs1, rs2Single-Bit Invert (Register)
binvi rd, rs1, immSingle-Bit Invert (Immediate)
bset rd, rs1, rs2Single-Bit Set (Register)
bseti rd, rs1, immSingle-Bit Set (Immediate)
sext.b rd, rsSign-extend byte
sext.h rd, rsSign-extend halfword
sh1add rd, rs1, rs2Shift left by 1 and add
sh1add.uw rd, rs1, rs2Shift unsigned word left by 1 and add
sh2add rd, rs1, rs2Shift left by 2 and add
sh2add.uw rd, rs1, rs2Shift unsigned word left by 2 and add
sh3add rd, rs1, rs2Shift left by 3 and add
sh3add.uw rd, rs1, rs2Shift unsigned word left by 3 and add
slli.uw rd, rs1, immShift-left unsigned word (Immediate)
xnor rd, rs1, rs2Exclusive NOR
zext.h rd, rsZero-extend halfword

Zba

31 25 24 20 19 15 14 12 11 7 6 0
----------+-------------------+-------------+----------------+--------+---------+---------+
cmd | funct7 | rs2 | rs1 | funct3 | rd | opcode |
----------+-------------------+-------------+----------------+--------+---------+---------+
add.uw | 0000100 | | | 000 | | 0111011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sh1add | 0000100 | | | 010 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sh1add.uw | 0010000 | | | 010 | | 0111011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sh2add | 0010000 | | | 100 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sh2add.uw | 0010000 | | | 100 | | 0111011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sh3add | 0010000 | | | 110 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sh3add.uw | 0010000 | | | 110 | | 0111011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
slli.uw | 0000010 | | | 001 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
  • add.uw: 在 rs2 和 rs1 的零扩展最低有效字之间执行 XLEN 范围的加法。
  • sh1add: 将 rs1 左移 1 位并添加到 rs2 中。
  • sh1add.uw: 执行两个加数的 XLEN 范围加法。第一个加数是 rs2。第二个加数是提取 rs1 的最低有效字并向左移动 1 位形成的无符号值。
  • sh2add: 将 rs1 左移 2 位并添加到 rs2 中。
  • sh2add.uw: 执行两个加数的 XLEN 范围加法。第一个加数是 rs2。第二个加数是提取 rs1 的最低有效字并向左移动 2 位形成的无符号值。
  • sh3add: 将 rs1 左移 3 位并添加到 rs2 中。
  • sh3add.uw: 执行两个加数的 XLEN 范围加法。第一个加数是 rs2。第二个加数是提取 rs1 的最低有效字并向左移动 3 位形成的无符号值。
  • slli.uw: 采用 rs1 的最低有效字,对其进行零扩展,并将其左移立即数。

Zbb

31 25 24 20 19 15 14 12 11 7 6 0
----------+-------------------+-------------+----------------+--------+---------+---------+
cmd | funct7 | funct5/rs2 | rs1 | funct3 | rd | opcode |
----------+-------------------+-------------+----------------+--------+---------+---------+
andn | 0100000 | rs2 | | 111 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
clz | 0110000 | 00000 | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
clzw | 0110000 | 00000 | | 001 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
cpop | 0110000 | 00010 | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
cpopw | 0010000 | 00010 | | 001 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
ctz | 0110000 | 00001 | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
ctzw | 0110000 | 00001 | | 001 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
max | 0000101 | rs2 | | 001 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
maxu | 0000101 | rs2 | | 111 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
min | 0000101 | rs2 | | 101 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
minu | 0000101 | rs2 | | 100 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
orc.b | 0010100 | 00111 | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
orn | 0100000 | rs2 | | 111 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rev8 | 0110100 | rs2 | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rol | 0110000 | rs2 | | 001 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rolw | 0110000 | rs2 | | 001 | | 0111011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
ror | 0110000 | rs2 | | 101 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rori | 0110000 | shamt | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
roriw | 0110000 | shamt | | 101 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rorw | 0110000 | shamt | | 101 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sext.b | 0110000 | 00100 | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
sext.h | 0110000 | 00101 | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
xnor | 0100000 | rs2 | | 100 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
zext.h | 0000100 | 00000 | | 100 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
  • andn: 在 rs1 和 rs2 的按位取反之间执行按位逻辑与运算。
  • clz: 计算第一个 1 之前 0 的数量,从最高有效位(即 XLEN-1)开始一直到位 0。因此,如果输入为 0,则输出为 XLEN,如果最高有效位为 0,则输出为 XLEN。输入的有效位为 1,输出为 0。
  • clzw: 从位 31 开始计算第一个 1 之前的 0 数量,一直到位 0。因此,如果最低有效字为 0,则输出为 32,如果该字的最高有效位(即,位 31) 为 1,则输出为 0。
  • cpop: 计算源寄存器中 1(即设置位)的数量。
  • cpopw: 计算源寄存器最低有效字中 1(即设置位)的数量。
  • ctz: 计算第一个 1 之前 0 的数量,从最低有效位(即 0)开始一直到最高有效位(即 XLEN-1)。因此,如果输入为 0,则输出为 XLEN,如果输入的最低有效位为 1,则输出为 0。
  • ctzw: 计算第一个 1 之前 0 的数量,从最低有效位(即 0)开始,一直到最低有效字的最高有效位(即 31)。因此,如果最低有效字为 0,则输出为 32,如果输入的最低有效位为 1,则输出为 0。
  • max: 返回两个有符号整数中较大的一个。
  • maxu: 返回两个无符号整数中较大的一个。
  • min: 返回两个有符号整数中较小的一个。
  • minu: 返回两个无符号整数中较小的一个。
  • orc.b: 使用按位逻辑或组合每个字节内的位。如果 rs 的相应字节内没有设置任何位,则将结果 rd 中每个字节的位设置为全零;如果设置了 rs 的相应字节内的任何位,则将结果 rd 中每个字节的位设置为全 1。
  • orn: 在 rs1 和 rs2 的按位取反之间执行按位逻辑或运算。
  • rev8: 颠倒 rs 中字节的顺序。
  • rol: 反转寄存器每个字节中的位顺序。
  • rolw: 对 rs1 的最低有效字执行左循环 rs2 的最低有效 5 位的量。通过将位 31 复制到所有更高有效位来对所得字值进行符号扩展。
  • ror: 按 rs2 的最低有效 log2(XLEN) 位中的量执行 rs1 的右循环。
  • rori: 按 shamt 的最低有效 log2(XLEN) 位中的量对 rs1 执行右循环。对于RV32,保留shamt[5]=1对应的编码。
  • roriw: 按 shamt 的最低有效 log2(XLEN) 位中的量对 rs1 执行右循环。对于RV32,保留shamt[5]=1对应的编码。
  • rorw: 对 rs1 的最低有效字执行右循环,旋转次数为 rs2 的最低有效 5 位。通过将第 31 位复制到所有较高有效位,对结果字进行符号扩展。
  • sext.b: 通过将字节中的最高有效位(即位 7)复制到所有较高有效位,将源中的最低有效字节符号扩展为 XLEN。
  • sext.h: 通过将半字中的最高有效位(即位 15)复制到所有较高有效位,将 rs 中的最低有效半字符号扩展为 XLEN。
  • xnor: 对 rs1 和 rs2 执行按位异或非运算。
  • zext.h: 通过将 0 插入所有高于 15 的位,将源的最低有效半字零扩展到 XLEN。

Zbc

31 25 24 20 19 15 14 12 11 7 6 0
----------+-------------------+-------------+----------------+--------+---------+---------+
cmd | funct7 | rs2 | rs1 | funct3 | rd | opcode |
----------+-------------------+-------------+----------------+--------+---------+---------+
clmul | 0000101 | rs2 | | 001 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
clmulh | 0000101 | rs2 | | 011 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
clmulr | 0000101 | rs2 | | 010 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
  • clmul: 产生 2*XLEN 无携带产品的下半部分。
  • clmulh: 生产 2·XLEN 无携带产品的上半部分。
  • clmulr: 生成 2·XLEN 无进位乘积的位 2·XLEN−2:XLEN-1。

Zbs

31 25 24 20 19 15 14 12 11 7 6 0
----------+-------------------+-------------+----------------+--------+---------+---------+
cmd | funct7 | rs2 | rs1 | funct3 | rd | opcode |
----------+-------------------+-------------+----------------+--------+---------+---------+
bclr | 0100100 | rs2 | | 001 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
bclri | 0100100 | shamt | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
bext | 0100100 | rs2 | | 101 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
bexti | 0100100 | shamt | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
binv | 0110100 | rs2 | | 001 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
binvi | 0110100 | shamt | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
bset | 0010100 | rs2 | | 001 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
bseti | 0010100 | shamt | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
  • bclr: 返回 rs1,并在 rs2 中指定的索引处清除了一位。该索引是从 rs2 的低 log2(XLEN) 位读取的。
  • bclri: 返回 rs1,并在 shamt 中指定的索引处清除了一位。该索引是从 shamt 的低 log2(XLEN) 位读取的。对于RV32,保留shamt[5]=1对应的编码。
  • bext: 返回从 rs1 中提取的单个位,该位位于 rs2 中指定的索引处。该索引是从 rs2 的低 log2(XLEN) 位读取的。
  • bexti: 返回从 rs1 中提取的单个位,该位位于 rs2 中指定的索引处。该索引是从 shamt 的低 log2(XLEN) 位读取的。对于RV32,保留shamt[5]=1对应的编码。
  • binv: 返回 rs1,并在 rs2 中指定的索引处反转一位。该索引是从 rs2 的低 log2(XLEN) 位读取的。
  • binvi: 返回 rs1,其中一位在 shamt 中指定的索引处反转。该索引是从 shamt 的低 log2(XLEN) 位读取的。对于RV32,保留shamt[5]=1对应的编码。
  • bset: 该返回 rs1,并在 rs2 中指定的索引处设置了一个位。该索引是从 rs2 的低 log2(XLEN) 位读取的。
  • bseti: 返回 rs1,并在 shamt 中指定的索引处设置了一个位。该索引是从 shamt 的低 log2(XLEN) 位读取的。对于RV32,保留shamt[5]=1对应的编码。

Zbkb

31 25 24 20 19 15 14 12 11 7 6 0
----------+-------------------+-------------+----------------+--------+---------+---------+
cmd | funct7 | funct5/rs2 | rs1 | funct3 | rd | opcode |
----------+-------------------+-------------+----------------+--------+---------+---------+
rol | 0110000 | rs2 | | 001 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rolw | 0110000 | rs2 | | 001 | | 0111011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
ror | 0110000 | rs2 | | 101 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rori | 0110000 | shamt | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
roriw | 0110000 | shamt | | 101 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rorw | 0110000 | shamt | | 101 | | 0011011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
andn | 0100000 | rs2 | | 111 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
orn | 0100000 | rs2 | | 111 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
xnor | 0100000 | rs2 | | 100 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
pack | 0000100 | rs2 | | 100 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
packh | 0000100 | rs2 | | 111 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
packw | 0000100 | rs2 | | 100 | | 0111011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rev.b | 0110100 | 00111 | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
rev8 | 0110100 | rs2 | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
zip | 0000100 | 11110 | | 001 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
unzip | 0000100 | 11111 | | 101 | | 0010011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
  • rol: 反转寄存器每个字节中的位顺序。
  • rolw: 对 rs1 的最低有效字执行左循环 rs2 的最低有效 5 位的量。通过将位 31 复制到所有更高有效位来对所得字值进行符号扩展。
  • ror: 按 rs2 的最低有效 log2(XLEN) 位中的量执行 rs1 的右循环。
  • rori: 按 shamt 的最低有效 log2(XLEN) 位中的量对 rs1 执行右循环。对于RV32,保留shamt[5]=1对应的编码。
  • roriw: 按 shamt 的最低有效 log2(XLEN) 位中的量对 rs1 执行右循环。对于RV32,保留shamt[5]=1对应的编码。
  • rorw: 对 rs1 的最低有效字执行右循环,旋转次数为 rs2 的最低有效 5 位。通过将第 31 位复制到所有较高有效位,对结果字进行符号扩展。
  • andn: 在 rs1 和 rs2 的按位取反之间执行按位逻辑与运算。
  • orn: 在 rs1 和 rs2 的按位取反之间执行按位逻辑或运算。
  • xnor: 对 rs1 和 rs2 执行按位异或非运算。
  • pack: 将rs1和rs2的XLEN/2位下半部分打包到rd中,其中rs1在下半部分,rs2在上半部分。
  • packh: 将 rs1 和 rs2 的最低有效字节打包到 rd 的 16 个最低有效位中,零扩展 rd 的其余部分。
  • packw: 将 rs1 和 rs2 的低 16 位打包到 rd 的 32 个最低有效位中,将 32 位结果符号扩展到 rd 的其余部分。该指令仅存在于基于 RV64 的系统上。
  • rev.b: 反转寄存器每个字节中的位顺序。
  • rev8: 颠倒 rs 中字节的顺序。
  • zip: 将源字的所有奇数位和偶数位分散到目标字的高半部分和低半部分中。它是解压缩指令的逆指令。该指令仅适用于 RV32。
  • unzip: 将源字的高半部分和低半部分中的位收集到目标字中的奇数/偶数位位置。它是 zip 指令的逆指令。该指令仅适用于 RV32。

Zbkc

31 25 24 20 19 15 14 12 11 7 6 0
----------+-------------------+-------------+----------------+--------+---------+---------+
cmd | funct7 | rs2 | rs1 | funct3 | rd | opcode |
----------+-------------------+-------------+----------------+--------+---------+---------+
clmul | 0000101 | rs2 | | 001 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
clmulh | 0000101 | rs2 | | 011 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
  • clmul: 产生 2*XLEN 无携带产品的下半部分。
  • clmulh: 生产 2·XLEN 无携带产品的上半部分。

Zbkx

31 25 24 20 19 15 14 12 11 7 6 0
----------+-------------------+-------------+----------------+--------+---------+---------+
cmd | funct7 | rs2 | rs1 | funct3 | rd | opcode |
----------+-------------------+-------------+----------------+--------+---------+---------+
xperm.b | 0010100 | rs2 | | 100 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
xperm.n | 0010100 | rs2 | | 010 | | 0110011 |
----------+-------------------+-------------+----------------+--------+---------+---------+
  • xperm.b: rs1 寄存器包含 XLEN/8 8 位元素的向量。 rs2 寄存器包含 XLEN/8 8 位索引向量。结果是 rs2 中的每个元素都被 rs1 中的索引元素替换,如果 rs2 的索引超出范围,则结果为零。
  • xperm.n: rs1 寄存器包含 XLEN/4 4 位元素的向量。 rs2 寄存器包含 XLEN/4 4 位索引的向量。结果是 rs2 中的每个元素都被 rs1 中的索引元素替换,如果 rs2 的索引超出范围,则结果为零。

V拓展

RISC-V的向量扩展(RISC-V Vector Extension,简称V扩展)是RISC-V指令集架构的一个重要扩展,用于高效处理向量计算任务。这些任务在科学计算、多媒体处理和机器学习等领域中非常常见。

  • 向量元素的最大大小(ELEN): ELEN ≥ 8,它必须是 2 的幂。
  • 单个向量寄存器的位数(VLEN): VLEN ≥ ELEN,必须是 2 的幂,且不得大于 2^16。

向量扩展向基本标量 RISC-V ISA 添加了 32 个向量寄存器(v0-v31)和 7 个非特权 CSR(vstart、vxsat、vxrm、vcsr、vtype、vl、vlenb)。

AddressPrivilegeNameDescription
0x008URWvstartVector start position
0x009URWvxsatFixed-Point Saturate Flag
0x00AURWvxrmFixed-Point Rounding Mode
0x00FURWvcsrVector control and status register
0xC20UROvlVector length
0xC21UROvtypeVector data type register
0xC22UROvlenbVLEN/8 (vector register length in bytes)