Skip to main content

4. 数据类型与舍入 / NaN 口径(勘误 v0.1.2)

整数:二补码,窄结果截断。div/divu/rem/remu 按 RISC-V M 扩展结果(除零、INT_MIN / -1 回绕),永不陷阱——优先于 ISA.md §6 中"除零可产生陷阱"的一般表述。

4.1 MODE 位布局​

位字段说明
[2:0]rmbinary32 舍入
[5:3]rm16binary16 舍入;7 = 动态(跟随 rm)
[8:6]rm64binary64 舍入;7 = 动态(跟随 rm)
[9] / [10]DAZ32 / FTZ32binary32 输入 / 输出冲零
[11] / [12]DAZ16 / FTZ16binary16
[13] / [14]DAZ64 / FTZ64binary64
[20:16]陷阱使能位序同 fflags
其余保留必须为 0

复位值 MODE = 0(IEEE、RNE、保留次正规数、不陷入)。舍入编码 0..4 = RNE/RTZ/RDN/RUP/RMM。任一 rm 字段取 5/6、rm 取 7 或保留位非零:写入触发 IllegalMode(cause 8,trapinfo = 组合后的候选 MODE 值,MODE 不变);指令 rm 操作数取 5/6 触发 IllegalInsn(cause 1,trapinfo = 指令字)。

4.2 舍入模式选择​

  • 显式 rm 操作数优先;dyn(7)或无 rm 操作数的指令按结果宽度选 MODE 字段(binary32 → rm、binary16 → rm16、binary64 → rm64;该字段为 7 时再读 rm)。
  • YAML 中 fcvt.f16.f32.lo/hi 语义写的 "MODE.rm" 是笔误,按勘误应为 MODE.rm16。
  • 舍入不受 rm 影响的指令:ffloor/fceil/ftrunc/frndne(方向固定,不置 NX)、fcvt.i32/u32.f32 与 fcvt.i16/u16.f16(固定 RTZ);.m 变体用显式 rm;fmed3.f32、dot2.f32.f16 用 MODE.rm。

4.3 fflags​

RISC-V 位序:[0] NX、[1] UF、[2] OF、[3] DZ、[4] NV。只累积 EXEC 内活跃 lane 产生的标志;写入只保留 [4:0](高位丢弃,不陷阱)。使能异常(MODE[20:16],位序同 fflags)触发 cause 4:该指令不写回、不排挂起操作,但保留本条新置起的 fflags。

4.4 DAZ / FTZ​

  • DAZ 把次正规输入冲成带符号 0,不置标志;FTZ 把舍入后的次正规结果冲成带符号 0,置 UF|NX(精确的次正规结果同样冲零;FTZ 关时按 RISC-V 规则:tiny 且不精确才置 UF)。
  • 转换指令:DAZ 看源宽度、FTZ 看结果宽度(如 fcvt.f16.f32.* 用 DAZ32 + FTZ16,dot2.f32.f16 的 f16 源用 DAZ16、s3 用 DAZ32、结果 FTZ32)。
  • min/max/med3/fsat 不做 FTZ(结果是某个输入本身,不经过舍入)。
  • 符号注入(fsgnj*)、neg/abs 修饰、move 和 fclass 不受 DAZ/FTZ 影响;fsgnj* 与 cmp.class.* 虽带 fp_mode 标志仍按此处理(标志规则优先)。
  • 不带 fp_mode 的指令不做 DAZ/FTZ:cmp.*.f64(标志与使能陷阱照常)、frexp.exp.f32;rcp/rsq.f64 固定 RNE 且不做 DAZ/FTZ。

4.5 NaN 与比较​

  • 算术结果的 NaN 为规范 quiet NaN:f32 0x7FC00000、f16 0x7E00、f64 0x7FF8000000000000;sNaN 输入置 NV。
  • 比较谓词:有序 lt/le/gt/ge 为 signaling(任一操作数 NaN——含 qNaN——置 NV);eq/ne、o/u 与无序 equ/neu/ltu/leu/gtu/geu 为 quiet(只有 sNaN 置 NV)。f16/f32/f64 一致。cmp.ne = "有序且不等"(任一 NaN → false),不是 eq 的取反;"无序或不等"是 neu。
  • fmin/fmax(三种宽度)与浮点原子 fmin/fmax:IEEE 754-2019 minimumNumber/maximumNumber——单 NaN 返回另一操作数、双 NaN 返回规范 NaN、-0 < +0。
  • fmed3 遇 NaN 返回非 NaN 值的 min3(AMD 风格),不按字面 fmin/fmax 组合。
  • frexp.mant(三种宽度)对 NaN/inf 原样透传(保留 payload)、不置任何标志(sNaN 也不置 NV);frexp.exp 对 0/inf/NaN 返回 0、从不置标志。
  • 取整类(floor/ceil/trunc/rndne)不置 NX(对应 RISC-V fround);ffract 结果钳到 < 1.0 的最大值(f32 0x3F7FFFFF、f16 0x3BFF),±inf 输入得规范 NaN 并置 NV;sat 修饰把 -0 变 +0;pkcvt.unorm8* 为 RNE;snorm 转换把 -1 编为 -32767。
  • fadd/pkadd 等 H 格式 16 位运算只写 rd 所选半;移位量取低 4 位。

4.6 SFU 数值定义(A 档)​

  • 近似 SFU(exp2/log2/sin/cos/rsq)内部以 binary64 RNE 计算(vendored SoftFloat;多项式系数为 mpmath 200-bit 精确值的 RNE binary64),最后按目标 rm 舍入一次。
  • 非 RNE 模式下结果是忠实舍入(真值两相邻可表示数之一,< 1 ulp),不保证方向正确;实测 RNE ≤ 0.5 ulp、其他 rm ≤ 1 ulp。
  • sin/cos 输入单位是圈(sin(2*pi*x));rcp/sqrt/fsqrt/fdiv 正确舍入;rsq 为两步 RNE(rcp/rsq.f64 恒 RNE,≥ 26 正确位);整数 div/divu/rem/remu 见 §4 开头。
  • approx 指令标志口径:数学结果 ≠ 所得位模式时置 NX(次正规或为零再加 UF);特殊操作数置 NV/DZ(rcp/rsq 的 ±0 → DZ;log2(±0) → DZ、负数/-inf → NV;rsq(负) → NV;sin/cos(±inf) → NV)。