首页/指令库/半精度融合负乘加
FNMADD.H

RISC-V FNMADD.H 指令详解

指令手册R4-type

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

指令语法

fnmadd.h rd, rs1, rs2, rs3[, rm]
操作数说明
rd、rs1、rs2、rs3:浮点 f0–f31 或对应 ABI 名称;f0 可写,rd 可与源重叠,同名源读取同一初值。
rm 是可选小写操作数,省略为 dyn;rm=111 使用 frm,静态 101/110 与动态 frm=101–111 的行为保留。
Zfh浮点运算

指令行为说明

FNMADD.H 使用 R4 四寄存器格式计算 -(rs1×rs2)-rs3。乘积不先舍入;整个融合表达式只在最终按 rm 舍入为 16 位半精度结果并写入浮点寄存器 rd。它适用于支持 Zfh 且浮点状态已启用的 RV32/RV64。

FNMADD.H 指令解析与执行动画

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

rd
rs1
rs2
rs3
rm
fnmadd.h
,
,
,
,

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

执行环境
FLEN>=32 / fmt=H (10)
舍入: RNE 最近偶数
fflags: 初始 0
31..27
26..25
24..20
19..15
14..12
11..7
6..0
01101
rs3
10
fmt=H
01100
rs2
01011
rs1
000
rm
01010
rd
1001111
NMADD
执行数据路径
instruction
0x6CC5854F
opcode
1001111 -> NMADD
rs3/fmt
fa3(f13) + H(10) -> R4 FNMADD
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 字段切分;FNMADD.H 使用专用 major opcode 1001111,不是普通 OP-FP opcode。

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

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

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

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

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

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

快速理解与检索要点

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

需要 RV32/RV64 Zfh 和已启用的浮点状态;半精度操作数及结果宽度为 16 位。Zfh 依赖 F;仅 Zfhmin 不包含本计算指令。
32 位 R4:rs3[31:27] | fmt=10[26:25] | rs2[24:20] | rs1[19:15] | rm[14:12] | rd[11:7] | opcode=1001111[6:0]。
rd、rs1、rs2、rs3 均选择浮点寄存器 f0–f31;f0 可写。rs3 是第三个源,不是 rd 的隐含旧值。
rm 可省略,默认 dyn;000/001/010/011/100 分别为 rne/rtz/rdn/rup/rmm,111 使用 frm。静态 101/110 与动态 frm=101–111 的行为保留。
操作数窄于 FLEN 时必须正确 NaN-boxed;否则按该格式的规范 NaN 处理。较窄结果的高 FLEN 位写 1。
适用的 NV、OF、UF、NX 累积到 fflags,置位本身不产生浮点异常陷阱。∞×0 必须置 NV,即使 rs3 是 quiet NaN;NaN 结果默认使用规范 NaN。
负号作用于乘积,再减 rs3;不要通过“先融合相加、再取反”的两步过程推断有符号零或定向舍入结果。动画仅接受输入及非零结果均在精确白名单中的有限示例,假定正确 NaN-boxing、初始 fflags=0。

常见使用场景

浮点融合运算

假定所需扩展与浮点状态已启用,f1=1.5、f2=2、f3=0.5 均为本指令格式(窄于 FLEN 时正确 NaN-boxed),初始 fflags=0:示例精确写 f0=-(1.5×2)-0.5=-3.5,fflags 仍为 0。

数值计算

假定所需扩展与浮点状态已启用,f1=1.5、f2=2、f3=0.5 均为本指令格式(窄于 FLEN 时正确 NaN-boxed),初始 fflags=0:示例精确写 f0=-(1.5×2)-0.5=-3.5,fflags 仍为 0。

使用前检查清单

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

容易混淆 / 常见误区

FNMADD.H 是融合操作,不等同于 FMUL 后接 FADD/FSUB 的两次舍入序列。
R4 编码的 bits 31..27 是 rs3 字段;不要按普通 OP-FP R-type 的 funct5 字段解读。
rm 控制最终一次舍入;非精确、上溢、下溢、无效操作或特殊值路径按官方浮点异常标志规则记录。
FNMSUB/FNMADD 的负号规则容易混淆:FNMSUB 为 -(rs1*rs2)+rs3,FNMADD 为 -(rs1*rs2)-rs3。

常见问题

FNMADD.H 和 FMUL 后接加减有什么不同?

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

FNMADD.H 为什么是 R4-type?

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

FNMADD.H 会设置 fflags 吗?

会按条件累积 NV、OF、UF、NX;不会自动清除已有标志。∞×0 必须置 NV,即使第三源为 quiet NaN。默认精确示例假定初始 fflags=0,所以最终仍为 0。