首页/指令库/双精度融合乘减
FMSUB.D

RISC-V FMSUB.D 指令详解

指令手册R4-type

双精度浮点融合乘减:rd = (rs1 * rs2) - rs3,融合操作只在最终按 rm 舍入一次。

指令语法

fmsub.d rd, rs1, rs2, rs3[, rm]
操作数说明
rd、rs1、rs2、rs3:浮点寄存器 f0–f31 或对应 ABI 名称;f0 可写,源重叠时使用写回前的同一初始值。
rm 为可选的小写汇编操作数,省略时为 dyn;rm=111 使用 frm。静态 101/110 和动态 frm=101–111 的行为保留。
D浮点运算

指令行为说明

FMSUB.D 使用 R4 型四寄存器格式执行 双精度浮点融合乘减。rs1 与 rs2 的乘积不会先舍入或写回中间结果,而是与 rs3 组成一个融合表达式,最终按 rm 舍入一次并写入 rd。

FMSUB.D 指令解析与执行动画

展示 D 扩展双精度 R4 融合乘减 指令的 ISA 可见流程:解析编码字段,读取浮点寄存器,执行 FMSUB 语义并写回 rd。

rd
rs1
rs2
rs3
rm
fmsub.d
,
,
,
,

rm 可留空:按汇编默认 dyn 编码,并使用下方 fcsr.frm。

执行环境
FLEN>=64 / fmt=D (01)
舍入: RNE 最近偶数
fflags: 初始 0
31..27
26..25
24..20
19..15
14..12
11..7
6..0
01101
rs3
01
fmt=D
01100
rs2
01011
rs1
000
rm
01010
rd
1000111
MSUB
执行数据路径
instruction
0x6AC58547
opcode
1000111 -> MSUB
rs3/fmt
fa3(f13) + D(01) -> R4 FMSUB
rm
000 -> RNE 最近偶数
rd/rs
fa0(f10) / fa1(f11) / fa2(f12) / fa3(f13)
read
尚未读取源寄存器
fused op
等待 Execute 计算
write
尚未写回;初始 fflags=0
当前步骤

Fetch:展示 32-bit R4 编码

机器码按 R4-type 字段切分;FMSUB.D 使用专用 major opcode 1000111,不是普通 OP-FP opcode。

encoding: 0x6AC58547
syntax : fmsub.d fa0(f10), fa1(f11), fa2(f12), fa3(f13), rne
result : 尚未写回;初始 fflags=0

默认示例 (1.5 * 2.0) - 1.0 = 2.0 可精确核算;融合操作只在最终按 rm 舍入一次,因此示例 fflags 保持 0。

双精度计算视图
rs1
fa1(f11) = 1.5
rs2
fa2(f12) = 2.0
rs3
fa3(f13) = 1.0
结果
等待 Execute 计算

默认示例 (1.5 * 2.0) - 1.0 = 2.0 可精确核算;融合操作只在最终按 rm 舍入一次,因此示例 fflags 保持 0。

假定扩展可用、FS 已启用、输入已正确 NaN-boxed、初始 fflags=0。仅接受非零有限精确白名单输入和非零白名单结果;零与舍入/异常边界不在动画范围内。同一源寄存器须有同一初始值;rd 可与源重叠,f0 可正常写回。步骤是教学视图。

该动画只展示 RISC-V D 扩展的 ISA 可见 R4 编码、示例数值结果和 fflags 关系;不模拟具体 FPU 流水线、延迟、完整 IEEE 754 边界组合或微架构实现。

快速理解与检索要点

FMSUB.D 的学习重点是 R4 编码和 fused 语义:rs3 是真实第三个源寄存器,乘积与加/减项形成一个精确中间表达式,最后只舍入一次。

RV32/RV64 D(依赖 F),需启用浮点状态;32 位 R4 编码的 opcode=1000111,fmt=01 选择 64 位双精度。
编码字段顺序为 rs3 | fmt | rs2 | rs1 | rm | rd | opcode;这与普通 OP-FP R-type 不同。
语义表达式为 rd = (rs1 * rs2) - rs3,融合操作只在最终按 rm/frm 舍入一次;静态或动态保留 rm/frm 编码的行为不可假定。
rm 为可选汇编操作数,须小写;省略时为 dyn。FLEN>64 时源须正确 NaN-boxed,否则按规范 NaN 处理;窄结果高位写全 1。动画仅执行非零有限精确白名单输入及非零白名单结果;异常与舍入边界见静态说明。

常见使用场景

浮点融合运算

假定 RV32/RV64 D、浮点状态启用,f1=1.5、f2=2、f3=1 均为双精度(更宽 FLEN 时正确 NaN-boxed),初始 fflags=0:fmsub.d f0, f1, f2, f3, rne 写 f0=(1.5×2)-1=2,结果精确,fflags 仍为 0。

数值计算

假定 RV32/RV64 D、浮点状态启用,f1=1.5、f2=2、f3=1 均为双精度(更宽 FLEN 时正确 NaN-boxed),初始 fflags=0:fmsub.d f0, f1, f2, f3, rne 写 f0=(1.5×2)-1=2,结果精确,fflags 仍为 0。

使用前检查清单

语法检查
  • rd、rs1、rs2、rs3:浮点寄存器 f0–f31 或对应 ABI 名称;f0 可写,源重叠时使用写回前的同一初始值。
  • rm 为可选的小写汇编操作数,省略时为 dyn;rm=111 使用 frm。静态 101/110 和动态 frm=101–111 的行为保留。
语义检查
  • 确认 rs3 参与融合操作,结果只在最终舍入一次。
  • 确认负形式 FNMADD/FNMSUB 的符号规则与预期一致。

容易混淆 / 常见误区

FMSUB.D 是融合操作,不等同于 FMUL 后接 FADD/FSUB 的两次舍入序列。
R4 编码的 bits 31..27 是 rs3 字段;不要按普通 OP-FP R-type 的 funct5 字段解读。
rm 控制最终一次舍入;rm=101 或 110,以及 rm=111 且 frm=101..111 时的行为均为保留,不能把它们当作固定舍入模式。
FMA 的乘数分别为无穷和零时必须设置 NV,即使 rs3 是 quiet NaN;适用异常为 NV、OF、UF、NX,累积到 fflags,置位本身不会触发 trap。NaN 结果遵循通用规范 NaN 规则。
FNMSUB/FNMADD 的负号规则容易混淆:FNMSUB 为 -(rs1*rs2)+rs3,FNMADD 为 -(rs1*rs2)-rs3。

常见问题

FMSUB.D 和 FMUL 后接加减有什么不同?

FMSUB.D 是融合操作,乘积不会先舍入成中间浮点结果;整个表达式只在最终按 rm 舍入一次。

FMSUB.D 为什么是 R4-type?

它需要 rd、rs1、rs2、rs3 和 rm 字段,bits 31..27 存放 rs3,而不是普通 R-type 的 funct5。

FMSUB.D 会设置 fflags 吗?

会在适用情况下按官方浮点规则设置异常标志,例如非精确、上溢、下溢或无效操作;默认动画示例选择精确有限值,因此显示 fflags 保持 0。