跳到主要内容

RISC-V F 扩展:单精度浮点寄存器、CSR 与指令

RISC-V F 扩展定义符合 IEEE 754-2008 的 32 位单精度浮点运算。它增加 32 个独立的浮点寄存器、浮点控制状态 CSR、单精度访存、算术、融合乘加、格式转换、比较和分类指令。F 依赖 Zicsr,因为软件需要通过 CSR 读取舍入模式和累积异常标志。

只实现 F 时,浮点寄存器宽度 FLEN=32。若处理器同时实现 DQ,同一组 f0f31 会扩宽到 64 或 128 位,单精度值按 NaN-boxing 规则保存于较宽寄存器中。本文先说明 FLEN=32 的 F 基础行为,再指出与较宽扩展及 ABI 相关的差异。

32 个浮点寄存器

浮点寄存器文件与整数寄存器文件相互独立。浮点算术读写 f 寄存器;地址计算、比较结果和浮点/整数转换读写 x 寄存器。FMV.X.WFMV.W.X 用于原样传递 32 位位模式,FCVT 则执行数值转换。

物理寄存器ABI 名称标准用途硬浮点 ABI 下跨调用保留详细说明
f0ft0浮点临时寄存器 0调用者保存。
f1ft1浮点临时寄存器 1调用者保存。
f2ft2浮点临时寄存器 2调用者保存。
f3ft3浮点临时寄存器 3调用者保存。
f4ft4浮点临时寄存器 4调用者保存。
f5ft5浮点临时寄存器 5调用者保存。
f6ft6浮点临时寄存器 6调用者保存。
f7ft7浮点临时寄存器 7调用者保存。
f8fs0浮点保存寄存器 0是*被调用者保存。
f9fs1浮点保存寄存器 1是*被调用者保存。
f10fa0浮点参数 0 / 返回值 0第一个浮点参数和第一个浮点返回值。
f11fa1浮点参数 1 / 返回值 1第二个浮点参数和第二个浮点返回值。
f12fa2浮点参数 2第三个浮点参数。
f13fa3浮点参数 3第四个浮点参数。
f14fa4浮点参数 4第五个浮点参数。
f15fa5浮点参数 5第六个浮点参数。
f16fa6浮点参数 6第七个浮点参数。
f17fa7浮点参数 7第八个浮点参数。
f18fs2浮点保存寄存器 2是*被调用者保存。
f19fs3浮点保存寄存器 3是*被调用者保存。
f20fs4浮点保存寄存器 4是*被调用者保存。
f21fs5浮点保存寄存器 5是*被调用者保存。
f22fs6浮点保存寄存器 6是*被调用者保存。
f23fs7浮点保存寄存器 7是*被调用者保存。
f24fs8浮点保存寄存器 8是*被调用者保存。
f25fs9浮点保存寄存器 9是*被调用者保存。
f26fs10浮点保存寄存器 10是*被调用者保存。
f27fs11浮点保存寄存器 11是*被调用者保存。
f28ft8浮点临时寄存器 8调用者保存。
f29ft9浮点临时寄存器 9调用者保存。
f30ft10浮点临时寄存器 10调用者保存。
f31ft11浮点临时寄存器 11调用者保存。

星号表示只要求保存宽度不超过目标 ABI ABI_FLEN 的值。以 ILP32F 或 LP64F 为例,ABI_FLEN=32fs0fs11 中的 32 位单精度值必须保留。若程序采用纯整数调用约定,即使硬件实现 F,浮点寄存器也可全部视为临时寄存器。

硬浮点调用约定提供八个浮点参数寄存器 fa0fa7,其中 fa0fa1 兼作返回值。可变参数仍按整数调用约定传递。一个聚合对象是否拆分到浮点和整数参数寄存器,取决于其字段组成、字段宽度和可用参数寄存器,具体规则由 psABI 定义。

浮点 CSR 的完整表格

F 扩展使用三个 U 级可读写 CSR 地址。它们不是三份独立状态:fflagsfrmfcsr 低八位的独立访问视图。

地址CSR权限对应 fcsr作用
0x001fflagsURW[4:0]累积浮点异常标志。软件显式清零前持续保留已经发生的异常。
0x002frmURW[7:5]动态舍入模式。指令 rm=111 时读取该字段。
0x003fcsrURW[7:0]frmfflags 的组合视图;[31:8] 保留给其他标准扩展。

fcsr 固定定义为 32 位,即使 XLEN=64 也不扩宽。未由其他扩展定义的 [31:8] 写入应被忽略并读为 0;通用软件执行读改写时仍应保留这些位,以兼容后续扩展。

fcsr 位字段

字段复位与保存规则说明
[0]NX累积Inexact,舍入结果与无限精度结果不同。
[1]UF累积Underflow,按舍入后 tininess 规则检测下溢。
[2]OF累积Overflow,有限结果超出目标格式范围。
[3]DZ累积Divide by Zero,有限非零数除以零。
[4]NV累积Invalid Operation,例如 0/0、负数开平方或信号 NaN 参与特定操作。
[7:5]frm软件状态动态舍入模式。
[31:8]保留读改写保留当前 F 扩展未使用。

异常标志为粘滞状态。一次运算可同时置多个标志;后续无异常运算不会清零。基础 F 扩展不会因 fflags 置位自动产生 trap,软件需要在适当位置读取和清除。

舍入模式编码

rm/frm 编码助记舍入方式作为指令 rm作为 frm
000RNE最近值,正好居中时取偶数有效有效
001RTZ向零有效有效
010RDN向负无穷有效有效
011RUP向正无穷有效有效
100RMM最近值,正好居中时取绝对值较大者有效有效
101保留保留保留
110保留保留保留
111DYN使用 frm有效保留

执行依赖舍入模式的指令时,如果静态 rm 或动态 frm 使用保留编码,行为属于规范保留范围。写 frm 往往要求处理器串行化部分浮点流水线,因此频繁切换模式时,静态 rm 可减少控制状态相关停顿。

CSR 访问伪指令

伪指令基本效果对应 CSR
frcsr rd读取完整 fcsr 到整数寄存器fcsr
fscsr rd, rs1交换整数寄存器与完整 fcsrfcsr
frrm rd读取 frmfrm
fsrm rd, rs1交换 frmfrm
frflags rd读取 fflagsfflags
fsflags rd, rs1交换 fflagsfflags

这些伪指令最终展开为 CSRRWCSRRS 等 Zicsr 指令。例如,可在一段需要独立统计异常的运算前清除 fflags,运算后再读取:

csrwi fflags, 0      # fflags = 0
fdiv.s fa0, fa1, fa2
csrr a0, fflags # a0[4:0] = 本次及其后续浮点指令累积的标志

F 扩展指令全集

访存、算术和融合乘加

指令操作舍入模式结果位置
flw fd, offset(rs1)x[rs1]+signext(offset) 读取 32 位位模式不适用f[fd]
fsw fs2, offset(rs1)f[fs2] 的低 32 位写入内存不适用内存
fadd.s fd, fs1, fs2fs1 + fs2rmf[fd]
fsub.s fd, fs1, fs2fs1 - fs2rmf[fd]
fmul.s fd, fs1, fs2fs1 × fs2rmf[fd]
fdiv.s fd, fs1, fs2fs1 ÷ fs2rmf[fd]
fsqrt.s fd, fs1sqrt(fs1)rmf[fd]
fmadd.s fd, fs1, fs2, fs3(fs1 × fs2) + fs3,乘加整体只舍入一次rmf[fd]
fmsub.s fd, fs1, fs2, fs3(fs1 × fs2) - fs3,整体只舍入一次rmf[fd]
fnmsub.s fd, fs1, fs2, fs3-(fs1 × fs2) + fs3,整体只舍入一次rmf[fd]
fnmadd.s fd, fs1, fs2, fs3-(fs1 × fs2) - fs3,整体只舍入一次rmf[fd]
fmin.s fd, fs1, fs2选择较小数;-0.0 < +0.0不使用f[fd]
fmax.s fd, fs1, fs2选择较大数;-0.0 < +0.0不使用f[fd]

flwfsw 原样传输 32 位,不规范化 NaN,因此 NaN payload 会保留。只有自然对齐地址保证原子访问;非对齐访问由执行环境决定是透明处理还是产生 trap。

四条融合乘加使用三个源寄存器和一个目的寄存器。中间乘积不单独舍入,因此结果可能与先执行 fmul.s 再执行 fadd.s 不同。∞ × 0 即使与 quiet NaN 相加,也必须置 NV

符号注入与位模式移动

指令位级行为是否设置 fflags常见伪指令
fsgnj.s fd, fs1, fs2数值位来自 fs1,符号位来自 fs2fmv.s fd, fs1 在两个源相同时成立
fsgnjn.s fd, fs1, fs2数值位来自 fs1,符号位为 fs2 符号取反fneg.s fd, fs1
fsgnjx.s fd, fs1, fs2数值位来自 fs1,符号位为两个源符号异或fabs.s fd, fs1
fmv.x.w rd, fs1将 32 位浮点位模式复制到整数寄存器低 32 位无数值转换
fmv.w.x fd, rs1将整数寄存器低 32 位复制到浮点寄存器无数值转换

RV64 执行 fmv.x.w 时,整数目的寄存器高 32 位用浮点源的符号位填充。两条 FMV 均不解释数值,也不改变非规范 NaN 的 payload。

浮点与整数转换

指令源类型目的类型RV32/RV64说明
fcvt.w.s rd, fs1, rmFP32有符号 32 位整数RV32/RV64RV64 将 32 位结果符号扩展到 XLEN。
fcvt.wu.s rd, fs1, rmFP32无符号 32 位整数RV32/RV64RV64 仍按规范将 32 位结果符号扩展到 XLEN。
fcvt.l.s rd, fs1, rmFP32有符号 64 位整数仅 RV64超出范围时按规定值截取并置 NV
fcvt.lu.s rd, fs1, rmFP32无符号 64 位整数仅 RV64超出范围时按规定值截取并置 NV
fcvt.s.w fd, rs1, rm有符号 32 位整数FP32RV32/RV64rm 舍入。
fcvt.s.wu fd, rs1, rm无符号 32 位整数FP32RV32/RV64rm 舍入。
fcvt.s.l fd, rs1, rm有符号 64 位整数FP32仅 RV64rm 舍入。
fcvt.s.lu fd, rs1, rm无符号 64 位整数FP32仅 RV64rm 舍入。

浮点转整数时,先按 rm 舍入,再检查目的类型范围。结果不可表示时置 NV,并输出规范规定的端点值;此时不再同时置 NX。结果可表示但发生舍入时置 NX

输入情况fcvt.w.sfcvt.wu.sfcvt.l.sfcvt.lu.s
最小有效值-2^310-2^630
最大有效值2^31-12^32-12^63-12^64-1
负向越界或 -∞-2^310-2^630
正向越界2^31-12^32-12^63-12^64-1
+∞ 或 NaN2^31-12^32-12^63-12^64-1

比较指令

指令条件整数结果NaN 与 NV
feq.s rd, fs1, fs2fs1 == fs2条件成立写 1,否则写 0任一源为 NaN 时结果为 0;仅 signaling NaN 置 NV
flt.s rd, fs1, fs2fs1 < fs2条件成立写 1,否则写 0任一源为 NaN 时结果为 0,并置 NV
fle.s rd, fs1, fs2fs1 ≤ fs2条件成立写 1,否则写 0任一源为 NaN 时结果为 0,并置 NV

比较结果直接写入整数寄存器,因此整数分支可以紧随其后执行。FLT.SFLE.S 是 signaling comparison,FEQ.S 是 quiet comparison。

fclass.s 分类结果

fclass.s rd, fs1 不执行数值比较,而是在整数寄存器中返回 10 位 one-hot 分类结果。它不设置浮点异常标志。

rd浮点类别
0负无穷 -∞
1负正规数
2负次正规数
3负零 -0
4正零 +0
5正次正规数
6正正规数
7正无穷 +∞
8signaling NaN
9quiet NaN

NaN、次正规数和异常结果

除各指令另有规定外,浮点运算产生 NaN 时返回规范 NaN。FP32 规范 NaN 的位模式为 0x7fc00000:符号为正,指数全 1,quiet bit 为 1,其余尾数位为 0。F 扩展允许实现提供非标准 NaN payload 传播模式,但规范 NaN 行为必须可用并作为标准软件可依赖的行为。

FLWFSWFMVFSGNJ* 属于位模式传输或符号操作,不把输入 NaN 改成规范 NaN。普通算术、比较、最小/最大值及格式转换按各自规则处理 quiet NaN 与 signaling NaN。

F 扩展要求按 IEEE 754 处理次正规数,不允许默认 flush-to-zero。tininess 在舍入后检测。下溢通常与非精确同时发生,但是否置 UF 仍由 IEEE 754 的下溢条件决定。

mstatus.FS 与上下文切换

特权架构在 mstatus[14:13] 定义 FSsstatus 提供相同状态的受限视图。它记录浮点上下文是否启用以及是否可能被修改。

FS状态执行含义
00Off执行浮点指令或访问浮点 CSR 产生非法指令异常。
01Initial浮点状态已启用,可按初始状态处理。
10Clean自上次保存后未发现浮点状态修改。
11Dirtyf0f31fcsr 可能已修改,上下文切换需要保存。

FS=Dirty 时,mstatus.SD 也为 1。操作系统可先读取 SD/FS,仅在需要时保存 32 个浮点寄存器和 fcsr。实现允许较保守地把 Initial 或 Clean 提前改为 Dirty,因此软件可以用 Dirty 判断“必须保存”,不能用 Clean 证明任务从未执行过浮点指令。

fcsr 属于线程状态。任务切换、信号处理、调试器和虚拟机监控程序需要与浮点寄存器一起保存和恢复,否则动态舍入模式或异常标志会在不同线程之间相互影响。

RTL 数据通路与控制要求

  • 浮点寄存器文件与整数寄存器文件分离后,FCVTFMV 和比较指令需要跨寄存器文件传输数据或写回结果。
  • FMADD.S 等 R4 型指令有三个浮点源操作数,寄存器文件端口、操作数旁路和相关检测需要覆盖第三源。
  • fcsr 写入与浮点流水线中尚未退休的指令存在顺序要求;动态舍入模式修改不能越过依赖旧模式的运算。
  • fflags 是多个异常位的按位累积结果。CSR 软件写、浮点指令置位、流水线清除和 trap 重放同时出现时,必须保证已退休指令的标志不丢失,未退休指令不产生可见更新。
  • FMVFLW/FSWFSGNJ* 必须保留位模式;算术单元内部即使使用重编码格式,也要在架构写回时满足标准编码。
  • FP32 加减、乘法、除法、平方根和 FMA 的特殊值处理不同,不能由统一的“NaN/无穷”旁路覆盖全部情况。
  • 只有自然对齐的 FLW/FSW 保证原子性;非对齐策略由执行环境规定,异常必须保持精确。
  • FS 状态更新属于架构状态提交的一部分。被清除的指令、推测执行或重放失败不能错误地使软件观察到浮点结果或异常标志。

参考:RISC-V F 2.2 规范RISC-V psABI 浮点寄存器约定Machine-Level ISA 的 FS 状态