RISC-V指令集手册(非特权架构)
模块
包含的模块:
基础指令集 | 版本 | 状态 | 说明 |
---|---|---|---|
RV32I | 2.1 | 批准 | 32位基础整数指令集 |
RV32E | 2.0 | 批准 | 32位嵌入式基础整数指令集 |
RV64E | 2.0 | 批准 | 64位嵌入式基础整数指令集 |
RV64I | 2.1 | 批准 | 64位基础整数指令集 |
RV128I | 1.7 | 草案 | 128位基础整数指令集(草案) |
扩展 | 版本 | 状态 | 说明 |
---|---|---|---|
Zifencei | 2.0 | 批准 | 指令获取栅栏 |
Zicsr | 2.0 | 批准 | 控制和状态寄存器访问 |
Zicntr | 2.0 | 批准 | 计数器指令 |
Zihintntl | 1.0 | 批准 | 非时序加载提示 |
Zihintpause | 2.0 | 批准 | 暂停提示 |
Zimop | 1.0 | 批准 | 用于可能操作 |
Zicond | 1.0 | 批准 | 条件分支提示 |
M | 2.0 | 批准 | 整数乘法和除法 |
Zmmul | 1.0 | 批准 | 仅整数乘法 |
Zaamo | 2.1 | 批准 | 原子内存操作 |
Zalrsc | 2.1 | 批准 | 加载保留/存储条件指令 |
A | 2.1 | 批准 | 原子操作指令 |
Zawrs | 1.01 | 批准 | 等待预约设置指令 |
Zacas | 1.0 | 批准 | 原子比较并交换 |
RVWMO | 2.0 | 批准 | 放松的内存排序 |
Ztso | 1.0 | 批准 | 完全存储排序 |
CMO | 1.0 | 批准 | 缓存管理操作 |
F | 2.2 | 批准 | 单精度浮点指令 |
D | 2.2 | 批准 | 双精度浮点指令 |
Q | 2.2 | 批准 | 四倍精度浮点指令 |
Zfh | 1.0 | 批准 | 半精度浮点指令 |
Zfhmin | 1.0 | 批准 | 最小半精度浮点指令 |
Zfa | 1.0 | 批准 | 浮点算术指令 |
Zfinx | 1.0 | 批准 | 整数寄存器中的单精度浮点指令 |
Zdinx | 1.0 | 批准 | 整数寄存器中的双精度浮点指令 |
Zhinx | 1.0 | 批准 | 整数寄存器中的半精度浮点指令 |
Zhinxmin | 1.0 | 批准 | 最小整数寄存器中的半精度浮点指令 |
C | 2.0 | 批准 | 压缩指令 |
Zce | 1.0 | 批准 | 嵌入式压缩指令 |
B | 1.0 | 批准 | 位操作指令 |
P | 0.2 | 草案 | 打包SIMD指令(草案) |
V | 1.0 | 批准 | 矢量扩展 |
Zbkb | 1.0 | 批准 | 基本位操作指令 |
Zbkc | 1.0 | 批准 | 无进位乘法指令 |
Zbkx | 1.0 | 批准 | 位操作扩展 |
Zk | 1.0 | 批准 | 加密扩展 |
Zks | 1.0 | 批准 | 标量加密指令 |
Zvbb | 1.0 | 批准 | 矢量基本位操作指令 |
Zvbc | 1.0 | 批准 | 矢量无进位乘法 |
Zvkg | 1.0 | 批准 | 矢量加密扩展 |
Zvkned | 1.0 | 批准 | 矢量加密非加密数据扩展 |
Zvknhb | 1.0 | 批准 | 矢量加密基于哈希的消息认证 |
Zvksed | 1.0 | 批准 | 矢量加密对称加密 |
Zvksh | 1.0 | 批准 | 矢量加密对称哈希 |
Zvkt | 1.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 型指令用于寄存器之间的算术和逻辑运算。
opcode
:操作码,指定指令类型。rd
:目标寄存器。funct3
:功能码,指定具体操作。rs1
:第一个源寄存器。rs2
:第二个源寄存器。funct7
:功能码,进一步指定具体操作。
I 型指令格式
I 型指令用于立即数运算和内存加载。
opcode
:操作码。rd
:目标寄存器。funct3
:功能码。rs1
:源寄存器。imm[11:0]
:12位的立即数。
S 型指令格式
S 型指令用于内存存储。
opcode
:操作码。imm[4:0]
:立即数的低 5 位。funct3
:功能码。rs1
:第一个源寄存器。rs2
:第二个源寄存器。imm[11:5]
:立即数的高 7 位。
B 型指令格式
B 型指令用于条件分支。
opcode
:操作码。imm[11]
:立即数第 11 位。imm[4:1]
:立即数的第 4 到第 1 位。funct3
:功能码。rs1
:第一个源寄存器。rs2
:第二个源寄存器。imm[10:5]
:立即数的第 10 到第 5 位。imm[12]
:立即数的第 12 位。
U 型指令格式
U 型指令用于加载高位立即数。
opcode
:操作码。rd
:目标寄存器。imm[31:12]
:立即数的13位到32位。
J 型指令格式
J 型指令用于无条件跳转。
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 型指令集
主要用于立即数运算和内存加载操作
指令 | 描述 | opcode | funct3 |
---|---|---|---|
ADDI | 加立即数 | 0010011 | 000 |
SLTI | 小于立即数置位(有符号) | 0010011 | 010 |
SLTIU | 小于立即数置位(无符号) | 0010011 | 011 |
XORI | 按位异或立即数 | 0010011 | 100 |
ORI | 按位或立即数 | 0010011 | 110 |
ANDI | 按位与立即数 | 0010011 | 111 |
SLLI | 逻辑左移立即数 | 0010011 | 001 |
SRLI | 逻辑右移立即数 | 0010011 | 101 |
SRAI | 算术右移立即数 | 0010011 | 101 |
LB | 加载字节 | 0000011 | 000 |
LH | 加载半字 | 0000011 | 001 |
LW | 加载字 | 0000011 | 010 |
LBU | 加载无符号字节 | 0000011 | 100 |
LHU | 加载无符号半字 | 0000011 | 101 |
JALR | 跳转并链接寄存器 | 1100111 | 000 |
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 | 加载高位立即数 | 0110111 | U 型 |
AUIPC | 加载上半立即数加 PC | 0010111 | U 型 |
LUI
LUI(加载立即数)用于构建32位常量并使用U型格式。 LUI 将 32 位 U 立即值放入目标寄存器 rd,并用零填充最低 12 位。
AUIPC
用于构建 pc 相对地址并使用 U 型格式。 AUIPC 从 U 立即数形成一个 32 位偏移量,用零填充最低 12 位,将该偏移量与 PC 相加,然后将结果放入寄存器 rd 中。
R 型指令集
R 型指令集用于寄存器之间的算术和逻辑运算。每条 R 型指令都使用两个源寄存器和一个目标寄存器,并且有一个功能码(funct3)和一个扩展功能码(funct7)
指令 | 描述 | funct7 | funct3 | opcode |
---|---|---|---|---|
ADD | 加法 | 0000000 | 000 | 0110011 |
SUB | 减法 | 0100000 | 000 | 0110011 |
SLL | 逻辑左移 | 0000000 | 001 | 0110011 |
SRL | 逻辑右移 | 0000000 | 101 | 0110011 |
SRA | 算术右移 | 0100000 | 101 | 0110011 |
SLT | 小于(有符号) | 0000000 | 010 | 0110011 |
SLTU | 小于(无符号) | 0000000 | 011 | 0110011 |
XOR | 按位异或 | 0000000 | 100 | 0110011 |
OR | 按位或 | 0000000 | 110 | 0110011 |
AND | 按位与 | 0000000 | 111 | 0110011 |
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 | 跳转和链接 | 0000111 | J 型 |
JAL
其中 J 立即数以 2 字节的倍数编码有符号偏移量。将偏移量进行符号扩展并与PC相加,形成跳转目标地址。因此,跳转可以瞄准 ±1 MiB 范围。 JAL将返回地址 (‘pc’+4) 存储到寄存器 rd 中。标准软件调用约定使用“x1”作为返回地址寄存器,使用“x5”作为备用链接寄存器。
B 型指令集
B 型指令(Branch 型指令)用于条件分支跳转。12位立即数以2字节的倍数编码有符号偏移量。偏移量被符号扩展并添加到分支指令的地址以给出目标地址。条件分支范围为±4 KiB。
指令 | 描述 | funct3 | opcode |
---|---|---|---|
BEQ | 等于则分支 | 000 | 1100011 |
BNE | 不等则分支 | 001 | 1100011 |
BLT | 小于则分支 | 100 | 1100011 |
BGE | 大于等于则分支 | 101 | 1100011 |
BLTU | 无符号小于则分支 | 110 | 1100011 |
BGEU | 无符号大于等于则分支 | 111 | 1100011 |
BEQ
如果寄存器 rs1 和 rs2 分别相等,则采取分支。
BNE
如果寄存器 rs1 和 rs2 分别不相等,则采取分支。
BLT
有符号比较, 如果rs1小于rs2, 则采取分支。
BGE
有符号比较, 如果rs1大于rs2, 则采取分支。
BLTU
无符号比较, 如果rs1小于rs2, 则采取分支。
BGEU
无符号比较, 如果rs1大于rs2, 则采取分支。
S 型指令集
S 型指令用于存储数据到内存中。每条 S 型指令使用两个源寄存器,其中一个寄存器提供基地址,另一个寄存器提供存储的数据,以及一个立即数提供偏移量。
以下是 RISC-V 中常见的 S 型指令及其功能描述:
指令 | 描述 | funct3 | opcode |
---|---|---|---|
SB | 存储字节 | 000 | 0100011 |
SH | 存储半字 | 001 | 0100011 |
SW | 存储字 | 010 | 0100011 |
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中。
指令 | 描述 | funct3 | opcode |
---|---|---|---|
LD | 从内存加载一个 64 位的双字到寄存器 | 011 | 0000011 |
SD
SD 指令
S 型指令, 将一个 64 位的双字(doubleword)存储到内存中。
指令 | 描述 | funct3 | opcode |
---|---|---|---|
SD | 将 64 位双字存储到内存中 | 011 | 0100011 |
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 知道已经更新了指令并且这些更改在下一次指令取指时生效。
指令描述
指令 | 描述 | funct3 | opcode |
---|---|---|---|
FENCE.I | 确保之前的内存写操作在接下来的指令取指之前生效 | 000 | 0001111 |
示例指令和解释
FENCE.I
-
描述:确保在执行该指令之前的所有内存写操作在接下来的指令取指操作之前生效。
-
格式:
FENCE.I
-
机器码:
示例说明
在某些情况下,例如动态生成代码或修改已经加载的指令,使用 FENCE.I
指令是必需的:
详细说明
- 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型指令,用于读写控制状态寄存器:
- CSRRW:读写 CSR
- CSRRS:读并置位 CSR
- CSRRC:读并清零 CSR
- CSRRWI:立即数读写 CSR
- CSRRSI:立即数读并置位 CSR
- CSRRCI:立即数读并清零 CSR
CSR 指令描述
指令 | 描述 | funct3 | opcode |
---|---|---|---|
CSRRW | 读写 CSR | 001 | 1110011 |
CSRRS | 读并置位 CSR | 010 | 1110011 |
CSRRC | 读并清零 CSR | 011 | 1110011 |
CSRRWI | 立即数读写 CSR | 101 | 1110011 |
CSRRSI | 立即数读并置位 CSR | 110 | 1110011 |
CSRRCI | 立即数读并清零 CSR | 111 | 1110011 |
指令功能
CSRRW(CSR Read and Write)
- 描述:将 CSR 的值读到寄存器
rd
,然后将寄存器rs1
的值写入 CSR。 - 格式:
CSRRW rd, csr, rs1
- 机器码:
CSRRS(CSR Read and Set)
- 描述:将 CSR 的值读到寄存器
rd
,然后将寄存器rs1
的值按位或到 CSR 中。 - 格式:
CSRRS rd, csr, rs1
- 机器码:
CSRRC(CSR Read and Clear)
- 描述:将 CSR 的值读到寄存器
rd
,然后将寄存器rs1
的值按位取反并按位与到 CSR 中。 - 格式:
CSRRC rd, csr, rs1
- 机器码:
CSRRWI(CSR Read and Write Immediate)
- 描述:将 CSR 的值读到寄存器
rd
,然后将立即数uimm
写入 CSR。 - 格式:
CSRRWI rd, csr, uimm
- 机器码:
CSRRSI(CSR Read and Set Immediate)
- 描述:将 CSR 的值读到寄存器
rd
,然后将立即数uimm
按位或到 CSR 中。 - 格式:
CSRRSI rd, csr, uimm
- 机器码:
CSRRCI(CSR Read and Clear Immediate)
- 描述:将 CSR 的值读到寄存器
rd
,然后将立即数uimm
按位取反并按位与到 CSR 中。 - 格式:
CSRRCI rd, csr, uimm
- 机器码:
示例指令和解释
假设我们有一个控制状态寄存器 csr
,其地址为 0x300
。
CSRRW 示例
这条指令会将 CSR 地址 0x300
处的值读到寄存器 x1
,然后将寄存器 x2
的值写入 CSR 0x300
。
CSRRS 示例
这条指令会将 CSR 地址 0x300
处的值读到寄存器 x1
,然后将寄存器 x2
的值按位或到 CSR 0x300
中。
CSRRC 示例
这条指令会将 CSR 地址 0x300
处的值读到寄存器 x1
,然后将寄存器 x2
的值按位取反并按位与到 CSR 0x300
中。
CSRRWI 示例
这条指令会将 CSR 地址 0x300
处的值读到寄存器 x1
,然后将立即数 5
写入 CSR 0x300
。
CSRRSI 示例
这条指令会将 CSR 地址 0x300
处的值读到寄存器 x1
,然后将立即数 5
按位或到 CSR 0x300
中。
CSRRCI 示例
这条指令会将 CSR 地址 0x300
处的值读到寄存器 x1
,然后将立即数 5
按位取反并按位与到 CSR 0x300
中。
应用场景
- 系统控制:操作系统内核使用 CSR 指令来配置和控制 CPU 状态。
- 异常处理:处理器在处理中断和异常时,使用 CSR 指令访问和修改异常状态寄存器。
- 性能监控:通过 CSR 指令访问和控制性能监控计数器。
- 调试:调试工具使用 CSR 指令来访问调试控制和状态寄存器。
Zicntr扩展
RISC-V 的 Zicntr 扩展增加了对计数器和定时器的支持。它提供了一组标准的性能计数器和定时器寄存器,这些寄存器可以用来监控和管理处理器的性能。
性能计数器和定时器寄存器
以下是 Zicntr 扩展中定义的标准性能计数器和定时器寄存器:
- cycle:用于计数自处理器启动以来的时钟周期数。
- time:用于计数自处理器启动以来的定时器时钟周期数。
- 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
寄存器: -
读取
time
寄存器: -
读取
instret
寄存器:
写入计数器寄存器
通常,性能计数器寄存器是只读的,但在某些情况下可以通过操作系统或特权级代码重置这些寄存器。
示例代码
读取 cycle
计数器
读取 time
计数器
读取 instret
计数器
计数器寄存器地址
在 RISC-V 的控制状态寄存器(CSR)地址空间中,以下是一些常见的性能计数器和定时器寄存器地址:
cycle
:CSR 地址 0xC00time
:CSR 地址 0xC01instret
: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 扩展定义了一条提示指令:
- PAUSE:提示处理器当前线程可以暂停执行,以便处理器调度其他线程。
PAUSE 指令格式
PAUSE 是一种无操作数的指令,格式如下:
Zimop拓展
它引入了可能是操作的指令(MOP)的概念。 MOP 最初定义为简单地将零写入 x[rd] ,但设计为由以后的扩展重新定义以执行某些其他操作。
-
Zimop 扩展定义了 40 个 MOP 的编码空间。Zimop 扩展定义了 32 个名为 MOP.R.n 的 MOP 指令,其中 n 是 0 到 31 之间的整数(含 0 和 31)。除非由另一个扩展重新定义,否则这些指令只是将 0 写入 x[rd] 。它们的编码允许将来的扩展将它们定义为读取 x[rs1] 以及写入 x[rd] 。
-
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 类型指令的格式。使用这些指令,可以实现无分支序列(通常在两个指令序列中),而不需要指令融合、架构指令解码期间的特殊规定或其他微体系结构规定。
指令 | 描述 | funct7 | funct3 | opcode |
---|---|---|---|---|
czero.eqz | 如果条件 rs2 等于 0,则将零移至寄存器 rd,否则将 rs1 移至 rd。 | 0000111 | 101 | 0110011 |
czero.nez | 如果条件 rs2 非零,则将零移至寄存器 rd,否则将 rs1 移至 rd。 | 0000111 | 111 | 0110011 |
M拓展
标准整数乘法和除法指令扩展,包含对两个整数寄存器中保存的值进行乘法或除法的指令。
M 扩展指令表格
以下是 RISC-V M 扩展(整数乘除扩展)的指令表格,包含每条指令的描述、功能码(funct3 和 funct7)、操作码(opcode)以及指令格式。
指令 | 描述 | funct7 | funct3 | opcode | 格式 |
---|---|---|---|---|---|
MUL | 有符号整数乘法,结果低位存储到 rd 中 | 0000001 | 000 | 0110011 | MUL rd, rs1, rs2 |
MULW | (RV64)有符号整数低32位乘法,结果低位存储到 rd 中 | 0000001 | 000 | 0110011 | MULH rd, rs1, rs2 |
MULH | 高位有符号乘法,结果高位存储到 rd 中 | 0000001 | 001 | 0110011 | MULH rd, rs1, rs2 |
MULHSU | 高位有符号和无符号混合乘法,结果高位存储到 rd 中 | 0000001 | 010 | 0110011 | MULHSU rd, rs1, rs2 |
MULHU | 高位无符号乘法,结果高位存储到 rd 中 | 0000001 | 011 | 0110011 | MULHU rd, rs1, rs2 |
DIV | 有符号整数除法,商存储到 rd 中 | 0000001 | 100 | 0110011 | DIV rd, rs1, rs2 |
DIVU | 无符号整数除法,商存储到 rd 中 | 0000001 | 101 | 0110011 | DIVU rd, rs1, rs2 |
DIVW | (RV64)有符号整数除法,只运算低32位商存储到 rd 中 | 0000001 | 100 | 0110011 | DIV rd, rs1, rs2 |
DIVUW | (RV64)无符号整数除法,只运算低32位商存储到 rd 中 | 0000001 | 101 | 0110011 | DIVU rd, rs1, rs2 |
REM | 有符号整数取余,余数存储到 rd 中 | 0000001 | 110 | 0110011 | REM rd, rs1, rs2 |
REMU | 无符号整数取余,余数存储到 rd 中 | 0000001 | 111 | 0110011 | REMU rd, rs1, rs2 |
REMW | (RV64)有符号整数取余,只运算低32位余数存储到 rd 中 | 0000001 | 110 | 0110011 | REM rd, rs1, rs2 |
REMUW | (RV64)无符号整数取余,只运算低32位余数存储到 rd 中 | 0000001 | 111 | 0110011 | REMU 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 位。
指令表格
指令 | 描述 | funct7 | funct3 | opcode | 格式 |
---|---|---|---|---|---|
AMOADD.W | 将 rs2 的值与内存地址 rs1 的值相加,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 010 | 0101111 | AMOADD.W rd, rs2, (rs1) |
AMOXOR.W | 将 rs2 的值与内存地址 rs1 的值进行异或,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 100 | 0101111 | AMOXOR.W rd, rs2, (rs1) |
AMOAND.W | 将 rs2 的值与内存地址 rs1 的值进行与操作,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 011 | 0101111 | AMOAND.W rd, rs2, (rs1) |
AMOOR.W | 将 rs2 的值与内存地址 rs1 的值进行或操作,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 010 | 0101111 | AMOOR.W rd, rs2, (rs1) |
AMOMIN.W | 将 rs2 和内存地址 rs1 的值比较,取最小值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 100 | 0101111 | AMOMIN.W rd, rs2, (rs1) |
AMOMAX.W | 将 rs2 和内存地址 rs1 的值比较,取最大值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 101 | 0101111 | AMOMAX.W rd, rs2, (rs1) |
AMOMINU.W | 将 rs2 和内存地址 rs1 的无符号值比较,取最小值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 110 | 0101111 | AMOMINU.W rd, rs2, (rs1) |
AMOMAXU.W | 将 rs2 和内存地址 rs1 的无符号值比较,取最大值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 111 | 0101111 | AMOMAXU.W rd, rs2, (rs1) |
AMOADD.D | 将 rs2 的值与内存地址 rs1 的值相加,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 011 | 0101111 | AMOADD.D rd, rs2, (rs1) |
AMOXOR.D | 将 rs2 的值与内存地址 rs1 的值进行异或,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 111 | 0101111 | AMOXOR.D rd, rs2, (rs1) |
AMOAND.D | 将 rs2 的值与内存地址 rs1 的值进行与操作,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 011 | 0101111 | AMOAND.D rd, rs2, (rs1) |
AMOOR.D | 将 rs2 的值与内存地址 rs1 的值进行或操作,并将结果写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 010 | 0101111 | AMOOR.D rd, rs2, (rs1) |
AMOMIN.D | 将 rs2 和内存地址 rs1 的值比较,取最小值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 100 | 0101111 | AMOMIN.D rd, rs2, (rs1) |
AMOMAX.D | 将 rs2 和内存地址 rs1 的值比较,取最大值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 101 | 0101111 | AMOMAX.D rd, rs2, (rs1) |
AMOMINU.D | 将 rs2 和内存地址 rs1 的无符号值比较,取最小值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 110 | 0101111 | AMOMINU.D rd, rs2, (rs1) |
AMOMAXU.D | 将 rs2 和内存地址 rs1 的无符号值比较,取最大值写回内存,同时将内存中的原始值存储到 rd 中 | 00001 | 111 | 0101111 | AMOMAXU.D rd, rs2, (rs1) |
Zalrsc拓展
用于加载保留/存储条件指令
指令表格
指令 | 描述 | funct7 | funct3 | opcode | 格式 |
---|---|---|---|---|---|
LR.W | 加载保留 | 00010 | 011 | 0101111 | LR.W rd, (rs1) |
SC.W | 存储条件 | 00011 | 011 | 0101111 | SC.W rd, rs2, (rs1) |
LR.D | 加载保留双字 | 00010 | 011 | 0101111 | LR.D rd, (rs1) |
SC.D | 存储条件双字 | 00011 | 011 | 0101111 | SC.D rd, rs2, (rs1) |
A拓展
包含原子读取-修改-写入内存的指令,以支持在同一内存空间中运行的多个 RISC-V hart 之间的同步。提供的两种形式的原子指令是加载保留/存储条件指令和原子获取和操作存储器指令。这些原子指令都是 R 型指令,两种类型的原子指令都支持各种内存一致性排序,包括无序、获取、释放和顺序一致语义。这些指令允许 RISC-V 支持 RCsc 内存一致性模型。 A 扩展包含 Zaamo 和 Zalrsc 扩展提供的指令。
Zawrs拓展
Zawrs 扩展定义了一对在轮询循环中使用的指令,允许内核进入低功耗状态并等待存储到内存位置。等待内存位置更新是许多用例中的常见模式,例如:
- 锁的竞争者等待锁变量被更新。
- 消费者在空队列的尾部等待生产者对工作/数据进行排队。生产者可以是在 RISC-V 硬件、加速器设备、外部 I/O 代理上执行的代码。
- 代码等待在内存中设置指示事件发生的标志。例如,RISC-V 硬件上的软件可以等待加速器设备在存储器中设置“完成”标志,指示先前提交给设备的作业已完成。
- WRS.NTO: 将导致 hart 在低功耗状态下暂时停止执行,直到发生对保留集的存储或观察到中断。
- WRS.STO: 但将停顿持续时间限制为实现定义的短超时,以便在以下情况下在超时时终止停顿:没有发生其他终止失速的条件。然后,使用该指令的程序可以确定是否已达到其最后期限。
软件不是轮询存储到特定内存位置,而是使用LR指令注册包含内存位置所有字节的保留集。Zawrs 扩展中的指令仅在与 LR 指令结合使用时有用,LR 指令由 A 扩展的 Zalrsc 组件提供。
I型指令
指令 | 描述 | funct12 | funct3 | opcode | 格式 |
---|---|---|---|---|---|
WRS.NTO | WRS 无超时 | 01101 | 000 | 1110011 | WRS.NTO |
WRS.STO | 带短超时的 WRS | 11101 | 000 | 1110011 | WRS.STO |
Zacas拓展
当作为硬件指令支持时,比较和交换 (CAS) 提供了一种简单且通常更快的方法来执行线程同步操作。 CAS 通常由无锁和无等待算法使用。此扩展建议使用 CAS 指令来操作 32 位、64 位和 128 位(仅限 RV64)数据值。 CAS指令支持C++11原子比较和交换操作。Zacas 扩展依赖于 Zaamo 扩展。
I型指令
指令 | 描述 | 31-27 | funct3 | opcode | 格式 |
---|---|---|---|---|---|
AMOCAS.W | 比较和交换 | 01101 | 010 | 1110011 | AMOCAS.W x3, x2, (x1) |
AMOCAS.D | 比较和交换 | 01101 | 011 | 1110011 | AMOCAS.D x3, x2, (x1) |
AMOCAS.Q | 比较和交换 | 01101 | 100 | 1110011 | AMOCAS.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 指令按操作分为以下几类:
- 管理指令针对一组可以访问数据的代理来操作数据的缓存副本
- 零指令将一系列内存位置清零,可能会在一个或多个高速缓存中分配数据的高速缓存副本
- 预取指令向硬件指示在不久的将来可以访问给定内存位置处的数据,从而可能在一个或多个高速缓存中分配数据的高速缓存副本
指令 | 描述 | funct7 | funct3 | rs2 | opcode | 格式 |
---|---|---|---|---|---|---|
CBO.CLEAN | 清理缓存行,将缓存数据写回主存但不失效 | 0000001 | 001 | 00000 | 1111111 | CBO.CLEAN rs1 |
CBO.FLUSH | 刷新缓存行,将缓存数据写回主存并失效 | 0000001 | 101 | 00000 | 1111111 | CBO.FLUSH rs1 |
CBO.INVAL | 使缓存行无效 | 0000010 | 110 | 00000 | 1111111 | CBO.INVAL rs1 |
CBO.ZERO | 将缓存行清零 | 0000011 | 111 | 00000 | 1111111 | CBO.ZERO rs1 |
PREFETCH.I | 预取指令缓存行 | 0000100 | 000 | 00000 | 1111111 | PREFETCH.I rs1 |
PREFETCH.R | 预取数据缓存行进行读取 | 0000101 | 000 | 00000 | 1111111 | PREFETCH.R rs1 |
PREFETCH.W | 预取数据缓存行进行写入 | 0000110 | 000 | 00000 | 1111111 | PREFETCH.W rs1 |
F拓展
F扩展增加了32个浮点寄存器f0-f31 ,每个32位宽,以及一个浮点控制和状态寄存器fcsr ,其中包含浮点单元的操作模式和异常状态。
FCSR 寄存器结构
FCSR 是一个 32 位寄存器,具体结构如下:
- fflags(5 位):浮点异常标志,记录浮点运算过程中产生的异常。
- frm(3 位):浮点舍入模式,指定浮点运算的舍入模式。
- Reserved(24 位):保留位,未使用。
fflags(浮点异常标志)
fflags 字段记录了浮点运算过程中产生的五种异常。每个异常占一位,如果产生相应的异常,该位将被置位。
位 | 名称 | 描述 |
---|---|---|
0 | NV(Invalid Operation) | 无效操作异常,如 0/0 或 sqrt(负数) |
1 | DZ(Divide by Zero) | 除以零异常,例如 非零数 / 0 |
2 | OF(Overflow) | 溢出异常,例如结果超出浮点数范围,趋向于无穷大 |
3 | UF(Underflow) | 下溢异常,例如结果非常接近于零,但非零 |
4 | NX(Inexact) | 不精确异常,例如结果不能精确表示,需要舍入 |
frm(浮点舍入模式)
frm 字段指定了浮点运算的舍入模式,共有以下五种模式:
值 | 舍入模式 | 描述 |
---|---|---|
000 | Round to Nearest, ties to Even | 向最接近的偶数舍入(默认模式) |
001 | Round towards Zero | 向零方向舍入(截断) |
010 | Round Down (towards -∞) | 向负无穷方向舍入 |
011 | Round Up (towards +∞) | 向正无穷方向舍入 |
100 | Round to Nearest, ties to Max Magnitude | 向最接近的数舍入,遇到平局时向最大幅值舍入 |
101-111 | Reserved | 保留,未定义 |
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
将 FCSR 寄存器的值读入整数寄存器 x1。
设置 FCSR
将整数寄存器 x1 的值写入 FCSR 寄存器。
设置浮点舍入模式
将整数寄存器 x1 的值写入 frm(浮点舍入模式)寄存器,同时将原 frm 的值写入 x0。
检查浮点异常
将 FCSR 寄存器的值读入整数寄存器 x1,然后通过 AND 操作取出 fflags 字段(低 5 位)的值,存入 x2。
FLW(Floating-Point Load Word)
FLW 指令用于从内存加载一个 32 位的单精度浮点数到浮点寄存器。
指令格式
FLW 指令属于 I 型指令,格式如下:
- imm:12 位立即数,表示内存地址偏移量。
- rs1:基地址寄存器。
- funct3:功能码,固定为
010
。 - rd:目标浮点寄存器。
- opcode:操作码,固定为
0000111
。
示例
将内存地址 x2 + 4
处的 32 位单精度浮点数加载到浮点寄存器 f1
中。
FSW(Floating-Point Store Word)
FSW 指令用于将一个 32 位的单精度浮点数从浮点寄存器存储到内存中。
指令格式
FSW 指令属于 S 型指令,格式如下:
- imm:12 位立即数,分为高 7 位(imm[11:5])和低 5 位(imm[4:0]),表示内存地址偏移量。
- rs2:源浮点寄存器。
- rs1:基地址寄存器。
- funct3:功能码,固定为
010
。 - opcode:操作码,固定为
0100111
。
示例
将浮点寄存器 f1
中的 32 位单精度浮点数存储到内存地址 x2 + 4
处。
指令表格
R型指令
指令 | 描述 | funct7 | rs2 | rs1 | funct3 | rd | opcode | 格式 |
---|---|---|---|---|---|---|---|---|
FADD.S | 单精度浮点数加法 | 0000000 | rs2 | rs1 | 000 | rd | 1010011 | FADD.S rd, rs1, rs2 |
FSUB.S | 单精度浮点数减法 | 0000100 | rs2 | rs1 | 000 | rd | 1010011 | FSUB.S rd, rs1, rs2 |
FMUL.S | 单精度浮点数乘法 | 0001000 | rs2 | rs1 | 000 | rd | 1010011 | FMUL.S rd, rs1, rs2 |
FDIV.S | 单精度浮点数除法 | 0001100 | rs2 | rs1 | 000 | rd | 1010011 | FDIV.S rd, rs1, rs2 |
FSQRT.S | 单精度浮点数平方根 | 0101100 | 00000 | rs1 | 000 | rd | 1010011 | FSQRT.S rd, rs1 |
FSGNJ.S | 单精度浮点数符号复制 | 0010000 | rs2 | rs1 | 000 | rd | 1010011 | FSGNJ.S rd, rs1, rs2 |
FSGNJN.S | 单精度浮点数符号取反 | 0010000 | rs2 | rs1 | 001 | rd | 1010011 | FSGNJN.S rd, rs1, rs2 |
FSGNJX.S | 单精度浮点数符号异或 | 0010000 | rs2 | rs1 | 010 | rd | 1010011 | FSGNJX.S rd, rs1, rs2 |
FMIN.S | 单精度浮点数最小值 | 0010100 | rs2 | rs1 | 000 | rd | 1010011 | FMIN.S rd, rs1, rs2 |
FMAX.S | 单精度浮点数最大值 | 0010100 | rs2 | rs1 | 001 | rd | 1010011 | FMAX.S rd, rs1, rs2 |
FCVT.W.S | 单精度浮点数转换为有符号整数(舍入到零) | 1100000 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.W.S rd, rs1 |
FCVT.WU.S | 单精度浮点数转换为无符号整数(舍入到零) | 1100000 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.WU.S rd, rs1 |
FMV.X.W | 单精度浮点数按位复制到整数寄存器 | 1110000 | 00000 | rs1 | 000 | rd | 1010011 | FMV.X.W rd, rs1 |
FEQ.S | 单精度浮点数比较(等于) | 1010000 | rs2 | rs1 | 010 | rd | 1010011 | FEQ.S rd, rs1, rs2 |
FLT.S | 单精度浮点数比较(小于) | 1010000 | rs2 | rs1 | 001 | rd | 1010011 | FLT.S rd, rs1, rs2 |
FLE.S | 单精度浮点数比较(小于等于) | 1010000 | rs2 | rs1 | 000 | rd | 1010011 | FLE.S rd, rs1, rs2 |
FCLASS.S | 分类单精度浮点数值 | 1110000 | 00000 | rs1 | 001 | rd | 1010011 | FCLASS.S rd, rs1 |
FMV.W.X | 整数寄存器按位复制到单精度浮点数寄存器 | 1111000 | 00000 | rs1 | 000 | rd | 1010011 | FMV.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 型指令,格式如下:
- imm:12 位立即数,表示内存地址偏移量。
- rs1:基地址寄存器。
- funct3:功能码,固定为
011
。 - rd:目标浮点寄存器。
- opcode:操作码,固定为
0000111
。
示例
将内存地址 x2 + 8
处的 64 位双精度浮点数加载到浮点寄存器 f1
中。
FSD(Floating-Point Store Double)
FSD 指令用于将一个 64 位的双精度浮点数从浮点寄存器存储到内存中。
指令格式
FSD 指令属于 S 型指令,格式如下:
- imm:12 位立即数,分为高 7 位(imm[11:5])和低 5 位(imm[4:0]),表示内存地址偏移量。
- rs2:源浮点寄存器。
- rs1:基地址寄存器。
- funct3:功能码,固定为
011
。 - opcode:操作码,固定为
0100111
。
示例
将浮点寄存器 f1
中的 64 位双精度浮点数存储到内存地址 x2 + 8
处。
指令表格
指令 | 描述 | funct7 | rs2 | rs1 | funct3 | rd | opcode | 格式 |
---|---|---|---|---|---|---|---|---|
FADD.D | 双精度浮点数加法 | 0000001 | rs2 | rs1 | 000 | rd | 1010011 | FADD.D rd, rs1, rs2 |
FSUB.D | 双精度浮点数减法 | 0000101 | rs2 | rs1 | 000 | rd | 1010011 | FSUB.D rd, rs1, rs2 |
FMUL.D | 双精度浮点数乘法 | 0001001 | rs2 | rs1 | 000 | rd | 1010011 | FMUL.D rd, rs1, rs2 |
FDIV.D | 双精度浮点数除法 | 0001101 | rs2 | rs1 | 000 | rd | 1010011 | FDIV.D rd, rs1, rs2 |
FSQRT.D | 双精度浮点数平方根 | 0101101 | 00000 | rs1 | 000 | rd | 1010011 | FSQRT.D rd, rs1 |
FSGNJ.D | 双精度浮点数符号复制 | 0010001 | rs2 | rs1 | 000 | rd | 1010011 | FSGNJ.D rd, rs1, rs2 |
FSGNJN.D | 双精度浮点数符号取反 | 0010001 | rs2 | rs1 | 001 | rd | 1010011 | FSGNJN.D rd, rs1, rs2 |
FSGNJX.D | 双精度浮点数符号异或 | 0010001 | rs2 | rs1 | 010 | rd | 1010011 | FSGNJX.D rd, rs1, rs2 |
FMIN.D | 双精度浮点数最小值 | 0010101 | rs2 | rs1 | 000 | rd | 1010011 | FMIN.D rd, rs1, rs2 |
FMAX.D | 双精度浮点数最大值 | 0010101 | rs2 | rs1 | 001 | rd | 1010011 | FMAX.D rd, rs1, rs2 |
FCVT.S.D | 双精度浮点数转换为单精度浮点数 | 0100001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.S.D rd, rs1 |
FCVT.D.S | 单精度浮点数转换为双精度浮点数 | 0100000 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.D.S rd, rs1 |
FEQ.D | 双精度浮点数比较(等于) | 1010001 | rs2 | rs1 | 010 | rd | 1010011 | FEQ.D rd, rs1, rs2 |
FLT.D | 双精度浮点数比较(小于) | 1010001 | rs2 | rs1 | 001 | rd | 1010011 | FLT.D rd, rs1, rs2 |
FLE.D | 双精度浮点数比较(小于等于) | 1010001 | rs2 | rs1 | 000 | rd | 1010011 | FLE.D rd, rs1, rs2 |
FCLASS.D | 分类双精度浮点数值 | 1110001 | 00000 | rs1 | 001 | rd | 1010011 | FCLASS.D rd, rs1 |
FCVT.W.D | 双精度浮点数转换为有符号整数(舍入到零) | 1100001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.W.D rd, rs1 |
FCVT.WU.D | 双精度浮点数转换为无符号整数(舍入到零) | 1100001 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.WU.D rd, rs1 |
FCVT.D.W | 有符号整数转换为双精度浮点数 | 1101001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.D.W rd, rs1 |
FCVT.D.WU | 无符号整数转换为双精度浮点数 | 1101001 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.D.WU rd, rs1 |
FMV.X.D | 双精度浮点数按位复制到整数寄存器 | 1110001 | 00000 | rs1 | 000 | rd | 1010011 | FMV.X.D rd, rs1 |
FMV.D.X | 整数寄存器按位复制到双精度浮点数寄存器 | 1111001 | 00000 | rs1 | 000 | rd | 1010011 | FMV.D.X rd, rs1 |
Q拓展
FLQ(Floating-Point Load Quad)
FLQ 指令用于从内存加载一个 128 位的四倍精度浮点数到浮点寄存器。
指令格式
FLQ 指令属于 I 型指令,格式如下:
- imm:12 位立即数,表示内存地址偏移量。
- rs1:基地址寄存器。
- funct3:功能码,固定为
011
。 - rd:目标浮点寄存器。
- opcode:操作码,固定为
0000111
。
示例
将内存地址 x2 + 16
处的 128 位四倍精度浮点数加载到浮点寄存器 f1
中。
FSQ(Floating-Point Store Quad)
FSQ 指令用于将一个 128 位的四倍精度浮点数从浮点寄存器存储到内存中。
指令格式
FSQ 指令属于 S 型指令,格式如下:
- imm:12 位立即数,分为高 7 位(imm[11:5])和低 5 位(imm[4:0]),表示内存地址偏移量。
- rs2:源浮点寄存器。
- rs1:基地址寄存器。
- funct3:功能码,固定为
011
。 - opcode:操作码,固定为
0100111
。
示例
将浮点寄存器 f1
中的 128 位四倍精度浮点数存储到内存地址 x2 + 16
处。
指令表格
指令 | 描述 | funct7 | rs2 | rs1 | funct3 | rd | opcode | 格式 |
---|---|---|---|---|---|---|---|---|
FADD.Q | 四倍精度浮点数加法 | 0000001 | rs2 | rs1 | 000 | rd | 1010011 | FADD.Q rd, rs1, rs2 |
FSUB.Q | 四倍精度浮点数减法 | 0000101 | rs2 | rs1 | 000 | rd | 1010011 | FSUB.Q rd, rs1, rs2 |
FMUL.Q | 四倍精度浮点数乘法 | 0001001 | rs2 | rs1 | 000 | rd | 1010011 | FMUL.Q rd, rs1, rs2 |
FDIV.Q | 四倍精度浮点数除法 | 0001101 | rs2 | rs1 | 000 | rd | 1010011 | FDIV.Q rd, rs1, rs2 |
FSQRT.Q | 四倍精度浮点数平方根 | 0101101 | 00000 | rs1 | 000 | rd | 1010011 | FSQRT.Q rd, rs1 |
FSGNJ.Q | 四倍精度浮点数符号复制 | 0010001 | rs2 | rs1 | 000 | rd | 1010011 | FSGNJ.Q rd, rs1, rs2 |
FSGNJN.Q | 四倍精度浮点数符号取反 | 0010001 | rs2 | rs1 | 001 | rd | 1010011 | FSGNJN.Q rd, rs1, rs2 |
FSGNJX.Q | 四倍精度浮点数符号异或 | 0010001 | rs2 | rs1 | 010 | rd | 1010011 | FSGNJX.Q rd, rs1, rs2 |
FMIN.Q | 四倍精度浮点数最小值 | 0010101 | rs2 | rs1 | 000 | rd | 1010011 | FMIN.Q rd, rs1, rs2 |
FMAX.Q | 四倍精度浮点数最大值 | 0010101 | rs2 | rs1 | 001 | rd | 1010011 | FMAX.Q rd, rs1, rs2 |
FCVT.S.Q | 四倍精度浮点数转换为单精度浮点数 | 0100001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.S.Q rd, rs1 |
FCVT.Q.S | 单精度浮点数转换为四倍精度浮点数 | 0100000 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.Q.S rd, rs1 |
FCVT.D.Q | 四倍精度浮点数转换为双精度浮点数 | 0100001 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.D.Q rd, rs1 |
FCVT.Q.D | 双精度浮点数转换为四倍精度浮点数 | 0100000 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.Q.D rd, rs1 |
FEQ.Q | 四倍精度浮点数比较(等于) | 1010001 | rs2 | rs1 | 010 | rd | 1010011 | FEQ.Q rd, rs1, rs2 |
FLT.Q | 四倍精度浮点数比较(小于) | 1010001 | rs2 | rs1 | 001 | rd | 1010011 | FLT.Q rd, rs1, rs2 |
FLE.Q | 四倍精度浮点数比较(小于等于) | 1010001 | rs2 | rs1 | 000 | rd | 1010011 | FLE.Q rd, rs1, rs2 |
FCLASS.Q | 分类四倍精度浮点数值 | 1110001 | 00000 | rs1 | 001 | rd | 1010011 | FCLASS.Q rd, rs1 |
FCVT.W.Q | 四倍精度浮点数转换为有符号整数(舍入到零) | 1100001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.W.Q rd, rs1 |
FCVT.WU.Q | 四倍精度浮点数转换为无符号整数(舍入到零) | 1100001 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.WU.Q rd, rs1 |
FCVT.Q.W | 有符号整数转换为四倍精度浮点数 | 1101001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.Q.W rd, rs1 |
FCVT.Q.WU | 无符号整数转换为四倍精度浮点数 | 1101001 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.Q.WU rd, rs1 |
Zfh拓展
RISC-V 的 Zfh 扩展(Half-Precision Floating-Point Extension)增加了一组用于半精度浮点数(16 位)运算的指令。这些指令允许处理器执行半精度浮点数的算术、比较、转换和其他操作,从而提高系统在需要高效且快速处理浮点数据的应用中的性能,例如图形处理和机器学习。
指令表格
指令 | 描述 | funct7 | rs2 | rs1 | funct3 | rd | opcode | 格式 |
---|---|---|---|---|---|---|---|---|
FADD.H | 半精度浮点数加法 | 0000101 | rs2 | rs1 | 000 | rd | 1010011 | FADD.H rd, rs1, rs2 |
FSUB.H | 半精度浮点数减法 | 0001101 | rs2 | rs1 | 000 | rd | 1010011 | FSUB.H rd, rs1, rs2 |
FMUL.H | 半精度浮点数乘法 | 0010101 | rs2 | rs1 | 000 | rd | 1010011 | FMUL.H rd, rs1, rs2 |
FDIV.H | 半精度浮点数除法 | 0011101 | rs2 | rs1 | 000 | rd | 1010011 | FDIV.H rd, rs1, rs2 |
FSQRT.H | 半精度浮点数平方根 | 0101101 | 00000 | rs1 | 000 | rd | 1010011 | FSQRT.H rd, rs1 |
FSGNJ.H | 半精度浮点数符号复制 | 0110001 | rs2 | rs1 | 000 | rd | 1010011 | FSGNJ.H rd, rs1, rs2 |
FSGNJN.H | 半精度浮点数符号取反 | 0110001 | rs2 | rs1 | 001 | rd | 1010011 | FSGNJN.H rd, rs1, rs2 |
FSGNJX.H | 半精度浮点数符号异或 | 0110001 | rs2 | rs1 | 010 | rd | 1010011 | FSGNJX.H rd, rs1, rs2 |
FMIN.H | 半精度浮点数最小值 | 0110101 | rs2 | rs1 | 000 | rd | 1010011 | FMIN.H rd, rs1, rs2 |
FMAX.H | 半精度浮点数最大值 | 0110101 | rs2 | rs1 | 001 | rd | 1010011 | FMAX.H rd, rs1, rs2 |
FCVT.S.H | 半精度浮点数转换为单精度浮点数 | 1000001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.S.H rd, rs1 |
FCVT.H.S | 单精度浮点数转换为半精度浮点数 | 1000000 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.H.S rd, rs1 |
FEQ.H | 半精度浮点数比较(等于) | 1010001 | rs2 | rs1 | 010 | rd | 1010011 | FEQ.H rd, rs1, rs2 |
FLT.H | 半精度浮点数比较(小于) | 1010001 | rs2 | rs1 | 001 | rd | 1010011 | FLT.H rd, rs1, rs2 |
FLE.H | 半精度浮点数比较(小于等于) | 1010001 | rs2 | rs1 | 000 | rd | 1010011 | FLE.H rd, rs1, rs2 |
FCLASS.H | 分类半精度浮点数值 | 1100001 | 00000 | rs1 | 001 | rd | 1010011 | FCLASS.H rd, rs1 |
FCVT.W.H | 半精度浮点数转换为有符号整数(舍入到零) | 1100001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.W.H rd, rs1 |
FCVT.WU.H | 半精度浮点数转换为无符号整数(舍入到零) | 1100001 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.WU.H rd, rs1 |
FCVT.H.W | 有符号整数转换为半精度浮点数 | 1101001 | 00000 | rs1 | 000 | rd | 1010011 | FCVT.H.W rd, rs1 |
FCVT.H.WU | 无符号整数转换为半精度浮点数 | 1101001 | 00000 | rs1 | 001 | rd | 1010011 | FCVT.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 格式用于带立即数的操作指令。
- 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 格式用于跳转指令。
- 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 格式用于加载指令。
- 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 格式用于存储指令。
- 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 格式用于分支指令。
- 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 格式用于寄存器到寄存器的操作指令。
- 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 格式用于存储到堆栈指令。
- 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 格式用于加载立即数宽指令。
- C.ADDI4SPN: 它将按 4 缩放的零扩展非零立即数添加到堆栈指针 x2 ,并将结果写入 rd′ 。该指令用于生成指向堆栈分配变量的指针,并扩展为
addi rd, x2, nzuimm[9:2]
。
9. CA 格式
- 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 Number | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
---|---|---|---|---|---|---|---|---|
Integer Register Number | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15 |
Integer Register ABI Name | s0 | s1 | a0 | a1 | a2 | a3 | a4 | a5 |
Floating-Point Register Number | f8 | f9 | f10 | f11 | f12 | f13 | f14 | f15 |
Floating-Point Register ABI Name | fs0 | fs1 | fa0 | fa1 | fa2 | fa3 | fa4 | fa5 |
Zc*拓展
Zc* 是一组扩展,定义现有 C 扩展的子集(Zca、Zcd、Zcf)和仅包含 16 位编码的新扩展。
指令 | Zca | Zcf | Zcd | Zcb | Zcmp | Zcmt |
---|---|---|---|---|---|---|
Zca 扩展用于引用 C 扩展中的指令,这些指令不包括浮点加载和存储 | ||||||
C 排除 c.f* | 是 | |||||
Zcf 扩展用于引用压缩的单精度浮点加载/存储 | ||||||
c.flw | rv32 | |||||
c.flwsp | rv32 | |||||
c.fsw | rv32 | |||||
c.fswsp | rv32 | |||||
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
该指令从通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址加载一个字节。结果字节被零扩展到 XLEN 位并写入 rd。
CLH
c.lhu: 该指令从通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址加载半字。所得半字被零扩展到 XLEN 位并写入 rd。 c.lh: 该指令从通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址加载半字。所得半字被零扩展到 XLEN 位并写入 rd。
CSB
该指令将 rs2 的最低有效字节存储到通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址。
CSH
该指令将 rs2 的最低有效半字存储到通过将 rs1 添加到零扩展立即数 uimm 形成的内存地址。
CU
- 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
该指令将 rs1 和 rs2 中的源操作数的 XLEN 位相乘,并将结果的最低 XLEN 位写入 rd。
CMPP
- 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
- cm.mvsa01: 将a0-a1移动到s0-s7的两个寄存器中。
- cm.mvsa01s: 将两个s0-s7寄存器移入a0-a1。
CMJT
- cm.jt: 通过表跳转
- cm.jalt: 通过带有可选链接的表格跳转
B拓展
B 标准扩展包括 Zba、Zbb 和 Zbs 扩展提供的指令。
RV32 | RV64 | Mnemonic | Instruction | Zba | Zbb | Zbc | Zbs |
---|---|---|---|---|---|---|---|
✓ | add.uw rd, rs1, rs2 | Add unsigned word | ✓ | ||||
✓ | ✓ | andn rd, rs1, rs2 | AND with inverted operand | ✓ | |||
✓ | ✓ | clmul rd, rs1, rs2 | Carry-less multiply (low-part) | ✓ | |||
✓ | ✓ | clmulh rd, rs1, rs2 | Carry-less multiply (high-part) | ✓ | |||
✓ | ✓ | clmulr rd, rs1, rs2 | Carry-less multiply (reversed) | ✓ | |||
✓ | ✓ | clz rd, rs | Count leading zero bits | ✓ | |||
✓ | clzw rd, rs | Count leading zero bits in word | ✓ | ||||
✓ | ✓ | cpop rd, rs | Count set bits | ✓ | |||
✓ | cpopw rd, rs | Count set bits in word | ✓ | ||||
✓ | ✓ | ctz rd, rs | Count trailing zero bits | ✓ | |||
✓ | ctzw rd, rs | Count trailing zero bits in word | ✓ | ||||
✓ | ✓ | max rd, rs1, rs2 | Maximum | ✓ | |||
✓ | ✓ | maxu rd, rs1, rs2 | Unsigned maximum | ✓ | |||
✓ | ✓ | min rd, rs1, rs2 | Minimum | ✓ | |||
✓ | ✓ | minu rd, rs1, rs2 | Unsigned minimum | ✓ | |||
✓ | ✓ | orc.b rd, rs1, rs2 | Bitwise OR-Combine, byte granule | ✓ | |||
✓ | ✓ | orn rd, rs1, rs2 | OR with inverted operand | ✓ | |||
✓ | ✓ | rev8 rd, rs | Byte-reverse register | ✓ | |||
✓ | ✓ | rol rd, rs1, rs2 | Rotate left (Register) | ✓ | |||
✓ | rolw rd, rs1, rs2 | Rotate Left Word (Register) | ✓ | ||||
✓ | ✓ | ror rd, rs1, rs2 | Rotate right (Register) | ✓ | |||
✓ | ✓ | rori rd, rs1, shamt | Rotate right (Immediate) | ✓ | |||
✓ | roriw rd, rs1, shamt | Rotate right Word (Immediate) | ✓ | ||||
✓ | rorw rd, rs1, rs2 | Rotate right Word (Register) | ✓ | ||||
✓ | ✓ | bclr rd, rs1, rs2 | Single-Bit Clear (Register) | ✓ | |||
✓ | ✓ | bclri rd, rs1, imm | Single-Bit Clear (Immediate) | ✓ | |||
✓ | ✓ | bext rd, rs1, rs2 | Single-Bit Extract (Register) | ✓ | |||
✓ | ✓ | bexti rd, rs1, imm | Single-Bit Extract (Immediate) | ✓ | |||
✓ | ✓ | binv rd, rs1, rs2 | Single-Bit Invert (Register) | ✓ | |||
✓ | ✓ | binvi rd, rs1, imm | Single-Bit Invert (Immediate) | ✓ | |||
✓ | ✓ | bset rd, rs1, rs2 | Single-Bit Set (Register) | ✓ | |||
✓ | ✓ | bseti rd, rs1, imm | Single-Bit Set (Immediate) | ✓ | |||
✓ | ✓ | sext.b rd, rs | Sign-extend byte | ✓ | |||
✓ | ✓ | sext.h rd, rs | Sign-extend halfword | ✓ | |||
✓ | ✓ | sh1add rd, rs1, rs2 | Shift left by 1 and add | ✓ | |||
✓ | sh1add.uw rd, rs1, rs2 | Shift unsigned word left by 1 and add | ✓ | ||||
✓ | ✓ | sh2add rd, rs1, rs2 | Shift left by 2 and add | ✓ | |||
✓ | sh2add.uw rd, rs1, rs2 | Shift unsigned word left by 2 and add | ✓ | ||||
✓ | ✓ | sh3add rd, rs1, rs2 | Shift left by 3 and add | ✓ | |||
✓ | sh3add.uw rd, rs1, rs2 | Shift unsigned word left by 3 and add | ✓ | ||||
✓ | slli.uw rd, rs1, imm | Shift-left unsigned word (Immediate) | ✓ | ||||
✓ | ✓ | xnor rd, rs1, rs2 | Exclusive NOR | ✓ | |||
✓ | ✓ | zext.h rd, rs | Zero-extend halfword | ✓ |
Zba
- 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
- 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
- clmul: 产生 2*XLEN 无携带产品的下半部分。
- clmulh: 生产 2·XLEN 无携带产品的上半部分。
- clmulr: 生成 2·XLEN 无进位乘积的位 2·XLEN−2:XLEN-1。
Zbs
- 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
- 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
- clmul: 产生 2*XLEN 无携带产品的下半部分。
- clmulh: 生产 2·XLEN 无携带产品的上半部分。
Zbkx
- 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)。
Address | Privilege | Name | Description |
---|---|---|---|
0x008 | URW | vstart | Vector start position |
0x009 | URW | vxsat | Fixed-Point Saturate Flag |
0x00A | URW | vxrm | Fixed-Point Rounding Mode |
0x00F | URW | vcsr | Vector control and status register |
0xC20 | URO | vl | Vector length |
0xC21 | URO | vtype | Vector data type register |
0xC22 | URO | vlenb | VLEN/8 (vector register length in bytes) |