根据有符号,无符号,需要前处理,不需要前处理,后处理,等分类
| 指令类型 | 指令示例 | 符号性 | 前处理需求 | 后处理需求 | 特殊说明 |
|---|---|---|---|---|---|
| 乘加指令 | fmadd.d, fmsub.d,fnmsub.d, fnmadd.d | 有符号 | ✔️ | ✔️ | 融合乘加操作,需处理舍入 |
| 基础算术指令 | fadd.d, fsub.d,fmul.d, fdiv.d, fsqrt.d | 有符号 | ✔️ | ✔️ | 需处理NaN/无穷 |
| 符号注入指令 | fsgnj.d, fsgnjn.d,fsgnjx.d | 有符号 | ❌ | ❌ | 直接操作符号位 |
| 比较指令 | feq.d, flt.d, fle.d | 有符号 | ✔️ | ❌ | 需处理NaN比较规则 |
| 极值指令 | fmin.d, fmax.d | 有符号 | ✔️ | ❌ | 需处理NaN和符号 |
| 类型转换指令 | fcvt.s.d, fcvt.d.s,fcvt.w.d, fcvt.wu.d,fcvt.d.w, fcvt.d.wu | 混合 | ✔️ | ✔️ | 整数/浮点互转需舍入 |
| 分类指令 | fclass.d | 有符号 | ✔️ | ❌ | 生成浮点属性掩码 |
| 数据移动指令 | fmv.d.x, fmv.x.d | 无符号 | ❌ | ❌ | 直接位传输 |

一共26条双精度的指令,最近在添加浮点功能,特意了解学习了一下
1.浮点乘加指令
指令:fmadd.d, fmsub.d, fnmadd.d, fnmsub.d

-
功能:执行融合乘加操作
(a × b) ± c,支持取反。 -
操作步骤:
-
输入检查:检测操作数是否为NaN或无穷,若任一操作数为NaN,结果直接为NaN。
-
乘法:计算
a × b,处理中间结果的符号和指数。 -
加法:将乘积与
c相加,处理对齐指数(规格化)。 -
取反:根据指令类型(
fnmadd/fnmsub)对结果符号取反。 -
舍入:根据FRM模式舍入结果,更新
fflags(溢出、精度损失等)。
-
-
规格化需求:是(乘法和加法阶段均需对齐指数)。
-
关键代码:
// 伪代码示例:fmadd.d wire [63:0] product = fp_multiply(a, b); wire [63:0] sum = fp_add(product, c); wire [63:0] result = (opcode == FNMSUB) ? -sum : sum; result = fp_round(result, frm); // 舍入处理
-
异常标志:无效操作(NaN输入)、溢出、下溢、精度损失。
2.基础算数指令
指令:fadd.d, fsub.d, fmul.d, fdiv.d, fsqrt.d

-
功能:双精度浮点加减乘除及平方根。
-
操作步骤:
-
输入规格化:将非规格化数(Denormal)转换为规格化形式。
-
符号处理:
-
fsub.d转换为a + (-b)。 -
fsqrt.d输入为负数时返回NaN(除非输入为-0)。
-
-
运算核心:
-
加减法:对齐指数,尾数加减,规格化结果。
-
乘除法:计算尾数乘积/商,调整指数。
-
平方根:迭代算法(如牛顿-拉夫逊法)或查找表。
-
-
舍入与规格化:对结果舍入并规格化为IEEE 754格式。
-
-
规格化需求:是(输入和输出均需规格化)。
-
关键代码:
wire [63:0] a_norm = normalize(a); wire [63:0] b_norm = normalize(b); wire [63:0] sum = fp_add_core(a_norm, b_norm); sum = fp_round(sum, frm);
-
异常标志:无效操作(如sqrt(-x))、除零、溢出、下溢。
3. 符号注入指令
指令:fsgnj.d, fsgnjn.d, fsgnjx.d

-
功能:直接操作浮点数的符号位,不改变数值。
-
操作步骤:
-
符号位提取:从源操作数获取符号位。
-
符号计算:
-
fsgnj.d:用b的符号替换a的符号。 -
fsgnjn.d:用~b的符号替换a的符号。 -
fsgnjx.d:符号位为a.sign ^ b.sign。
-
-
拼接结果:将新符号与
a的指数和尾数拼接。
-
-
规格化需求:否(符号位直接操作,无需调整数值)。
-
关键代码:
verilog
复制
// 伪代码示例:fsgnjx.d wire new_sign = a[63] ^ b[63]; assign result = {new_sign, a[62:0]}; -
异常标志:无(除非输入为NaN,但符号位仍可操作)。
4. 浮点比较指令
指令:feq.d, flt.d, fle.d

-
功能:比较两个双精度数,结果写入整数寄存器。
-
操作步骤:
-
NaN处理:
-
任一操作数为NaN时,
feq.d返回0,flt.d/fle.d返回0并标记无效操作。
-
-
数值比较:
-
feq.d:a == b。 -
flt.d:a < b(考虑符号)。 -
fle.d:a ≤ b。
-
-
结果写回:比较结果(0或1)写入整数寄存器。
-
-
规格化需求:是(需规格化后比较)。
-
关键代码:
wire is_nan = fp_is_nan(a) || fp_is_nan(b); assign result = is_nan ? 0 : (a == b); fflags.invalid = is_nan; // 标记无效操作
-
异常标志:无效操作(若比较NaN)。
5. 极值指令
指令:fmin.d, fmax.d

-
功能:返回两个浮点数的最小值或最大值(按数值,非信号)。
-
操作步骤:
-
NaN处理:若任一操作数为NaN,返回非NaN数;若均为NaN,返回NaN。
-
符号与数值比较:
-
负数小于正数。
-
fmin.d选择更小的数值(考虑符号)。
-
-
返回结果:选择后的值直接输出,无需舍入。
-
-
规格化需求:是(需规格化后比较)。
-
关键代码:
if (a is NaN) result = b; else if (b is NaN) result = a; else result = (a < b) ? a : b;
-
异常标志:无效操作(若输入为NaN)
6. 类型转换指令
指令:fcvt.s.d, fcvt.d.s, fcvt.w.d, fcvt.wu.d, fcvt.d.w, fcvt.d.wu


-
功能:单/双精度浮点与整数(有/无符号)相互转换。
-
操作步骤:
-
整数转浮点:
-
符号扩展(有符号整数)或零扩展(无符号整数)。
-
规格化整数为浮点格式。
-
-
浮点转整数:
-
处理溢出(超出整数范围时返回最大/最小值)。
-
根据舍入模式(FRM)截断或舍入。
-
-
单双精度互转:
-
扩展或截断尾数,调整指数偏置。
-
-
-
规格化需求:是(转换过程需规格化)。
-
关键代码:
integer_t int_val; if (fp_val >= 2^31-1) int_val = 0x7FFFFFFF; else if (fp_val <= -2^31) int_val = 0x80000000; else int_val = (fp_val >= 0) ? floor(fp_val) : ceil(fp_val);
-
异常标志:无效操作(NaN输入)、溢出(超出整数范围)。
7. 分类指令
指令:fclass.d
![]()
-
功能:生成描述浮点数值类别的10位掩码。
-
操作步骤:
-
位检查:分析符号位、指数、尾数。
-
生成掩码:
-
每位对应一种类别(如负无穷、负规格化数、正零等)。
-
-
-
规格化需求:否(直接检查位模式)。
-
关键代码:
verilog
复制
// 伪代码示例:fclass.d wire is_neg_inf = (exp == 0x7FF) && (sign == 1) && (frac == 0); wire is_pos_zero = (exp == 0) && (sign == 0) && (frac == 0); assign mask = {is_snan, is_qnan, is_neg_inf, ..., is_pos_zero}; -
异常标志:无。
8.load与store指令

fld(Load Double)指令
功能:
将内存中的 64位双精度浮点数 加载到目标浮点寄存器 f[rd] 中。
指令格式:
复制
fld rd, offset(rs1)
-
rs1:基址寄存器(整数寄存器),存储内存地址。
-
offset:12位有符号立即数偏移量(字节寻址)。
-
rd:目标浮点寄存器(需为偶数编号,因占用两个单精度寄存器空间)。
操作步骤:
-
地址计算:
-
计算有效地址:
effective_addr = reg[rs1] + sign_extend(offset)。 -
检查地址是否 对齐到8字节(若未对齐,触发 地址不对齐异常
misaligned exception)。
-
-
内存读取:
-
从
effective_addr读取 64位数据(大端或小端由系统决定)。 -
若内存访问越界或权限不足,触发 Load Page Fault 异常。
-
-
数据写入寄存器:
-
将读取的64位数据直接写入浮点寄存器
f[rd](无需格式转换)。 -
若实现为单精度寄存器组(如RV32),需占用
f[rd]和f[rd+1]两个连续寄存器。
-
-
异常处理:
-
地址不对齐:若
effective_addr % 8 != 0,触发异常。 -
缺页异常:访问无效内存地址时触发。
-
-
寄存器编号对齐:在RV32中,
rd必须为偶数(如f0,f2),因为双精度数占用两个寄存器。原子性要求:64位加载在RV32中可能需要两次32位内存访问,需确保原子性(避免中间状态被中断)。
fsd(Store Double)指令
功能:
将浮点寄存器 f[rs2] 中的 64位双精度浮点数 存储到内存中。
指令格式:
复制
fsd rs2, offset(rs1)
-
rs1:基址寄存器(整数寄存器),存储内存地址。
-
offset:12位有符号立即数偏移量(字节寻址)。
-
rs2:源浮点寄存器(需为偶数编号)。
操作步骤:
-
地址计算:
-
计算有效地址:
effective_addr = reg[rs1] + sign_extend(offset)。 -
检查地址是否 对齐到8字节(若未对齐,触发 地址不对齐异常)。
-
-
寄存器数据读取:
-
从浮点寄存器
f[rs2]读取64位数据(RV32中需组合f[rs2]和f[rs2+1])。
-
-
内存写入:
-
将64位数据写入
effective_addr指向的内存位置。 -
若内存访问越界或权限不足,触发 Store Page Fault 异常。
-
-
异常处理:
-
地址不对齐:若
effective_addr % 8 != 0,触发异常。 -
缺页异常:访问无效内存地址时触发。
-




被折叠的 条评论
为什么被折叠?



