RV32FD指令集

Risc-V架构定义了可选的单精度浮点指令(F扩展指令集)和双精度浮点指令(D扩展指令集)。

Risc-V架构规定:处理器可以选择只实现F扩展指令子集而不支持D扩展指令子集;但是如果支持了D扩展指令子集,则必须支持F扩展指令子集。

Risc-V架构规定的浮点数符合IEEE754 2008规则,可以从下面的链接了解浮点数格式的详细信息:

https://www.cnblogs.com/german-iris/p/5759557.html

Risc-V规定,如果支持单精度浮点指令或者双精度浮点指令,则需要增加一组独立的通用浮点寄存器组,包括32个通用浮点寄存器,标号位f0到f31。如果仅支持F扩展指令子集,则每个通用寄存器是32位的,如果支持D扩展那指令子集,则每个通用寄存器是64位的。

Risc-V架构规定,如果支持单精度浮点指令或者双精度浮点指令,需要增加一个浮点控制状态寄存器fcsr,该寄存器是一个可读可写的csr寄存器。

fcsr寄存器包含浮点异常标志域(fflags),不同的标志位表示不同的异常类型。如果浮点运算单元在运算中出现了相应的异常,则会将fcsr寄存器中对应的标志位设置为1,且会一直保持累积。软件可以通过写0的方式单独清除某个异常标志位。

根据IEEE-754标准,浮点运算需要指定舍入模式(rounding mode),Risc-V架构浮点运算的舍入模式可以通过两种方式指定。

使用静态舍入模式,浮点指令编码中有3位作为舍入模式域,不同的舍入模式编码如下图,Risc-V支持5种合法的舍入模式。如果舍入模式编码为101或110,则为非法模式;如果舍入模式编码为111,则意味着使用动态舍入模式。如果使用动态舍入模式,则使用fcsr寄存器中的舍入模式域,舍入模式域定义如上图,如果fcsr寄存器中的舍入模式域指定为非法的舍入模式,则后续浮点指令会产生非法指令异常。


如果处理器不想使用浮点单元,比如把浮点单元关电以节省功耗,可以使用csr写指令将mstatus寄存器的FS域设置成0,将浮点单元的功能予以关闭。当浮点单元功能关闭后,任何访问浮点csr寄存器的操作或者执行浮点指令的行为将会产生非法指令异常

Risc-V规定,对于非规格化数(subnormal Numbers)的处理完全遵循IEEE754定义。

根据IEEE-754标准,在浮点数的表示中,有一类特殊编码数据属于NaN(not a number)类型,且NaN分为Signaling-NaN和Quiet-NAN。

Risc-V架构规定,如果浮点运算的结果是一个NaN数,那么使用一个固定的NaN数,将之命名为Canonical-NaN。单精度浮点对应的Canonical-NaN数值为0x7fc00000,双精度浮点对应Canonical-NaN数值为0x7ff80000_00000000

如果同时支持单精度浮点(F扩展指令子集)和双精度浮点(D扩展指令子集),由于浮点通用寄存器的宽度为64位,Risc-V架构规定单精度浮点指令产生的32位结果写入浮点通用寄存器(64位)时,将结果写入低32位,而高位全部写入数值1,RiscV架构规定此种做法称之为NaN-Boxing。NaN-boxing可以发生在如下情形:

对于单精度浮点数的读(Load)/写(store)指令和传送(Move)指令(包括FLW,FSW,FMV.W.X,FMV.X.W),如果需要将32位的数值写入通用浮点寄存器,则采用NaN-boxing的方式;如果需要将浮点通用寄存器中的数值读出,则仅使用其低32位值。

对于单精度浮点运算(compute)和符号注入(sign-injection)指令,需要判断其操作数浮点寄存器中的值是否为合法的NaN-Boxed值,即高位都是1,如果是,则正常使用其低32位,如果不是,则将此操作数当作Canonical-NaN来使用。

对于整数至单精度的浮点转化指令(比如FCVT.S.X),则采用NaN-boxing的方式写回浮点通用寄存器。对于单精度浮点至整数的转化指令(比如FCVT.X.S),需要判断其操作数浮点寄存器中的值是否为合法的NaN-boxed值(即高位都为1)。如果是,则正常使用其低32位,如果不是,则将此操作数当作Canonical-NaN来使用。

RV32FM主要包括以下指令:

Category Fmt RV32F   machine code(bin) comment float read/write instruction     flw rd offset[11:0](RS1) [31-20, imm[11:0]][19-15,rs1]010[11-7, rd]‘0000111 rd=mem[rs1+offset], offset是一个12位符号数,所以加法操作时候,需要符号位扩展。flw指令从存储器中读回一个单精度浮点数,写回寄存器rd。     fsw rd2 offset[11:0](RS1) [31-25, imm[11:5]][24-20,rs2][19-15,rs1]010[11-7, imm[4:0]]‘0100111 mem[rs1+offset]=rd2, offset是一个12位符号数,所以加法操作时候,需要符号位扩展。Fsw指令将操作数寄存器rs2中的单精度浮点数写回存储器中。     fld rd offset[11:0](RS1) [31-20, imm[11:0]][19-15,rs1]011 [11-7, rd]‘0000111 rd=mem[rs1+offset], offset是一个12位符号数,所以加法操作时候,需要符号位扩展。flw指令从存储器中读回一个双精度浮点数,写回寄存器rd。     fsd rd2 offset[11:0](RS1) [31-25, imm[11:5]][24-20,rs2][19-15,rs1]011 [11-7, imm[4:0]]‘0100111 mem[rs1+offset]=rd2, offset是一个12位符号数,所以加法操作时候,需要符号位扩展。Fsw指令将操作数寄存器rs2中的双精度浮点数写回存储器中。 float compute instruciton     fadd.s rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的单精度浮点数进行加法操作,结果返回rd     fsub.s rd, rs1, rs2 0000100[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的单精度浮点数进行减法操作,结果返回rd     fmul.s rd, rs1, rs2 0001000[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的单精度浮点数进行乘法操作,结果返回rd     fdiv.s rd, rs1, rs2 0001100[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的单精度浮点数进行除法操作,结果返回rd     fsqrt.s rd, rs1 010110000000 [19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的单精度浮点数进行平方根操作,结果返回rd     fadd.d rd, rs1, rs2 0000001[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的双精度浮点数进行加法操作,结果返回rd     fsub.d rd, rs1, rs2 0000101[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的双精度浮点数进行加法操作,结果返回rd     fmul.d rd, rs1, rs2 0001001[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的双精度浮点数进行加法操作,结果返回rd     fdiv.d rd, rs1, rs2 0001101[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的双精度浮点数进行加法操作,结果返回rd     fsqrt.d rd, rs1 010110100000 [19-15,rs1][14-12,rm][11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的双精度浮点数进行平方根操作,结果返回rd min/max     fmin.s rd, rs1, rs2 0010100[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的单精度浮点数进行比较操作,将数字小的一方写回rd     fmax.s rd, rs1, rs2 0010100[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的单精度浮点数进行比较操作,将数字大的一方写回rd     fmin.d rd, rs1, rs2 0010101[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的双精度浮点数进行比较操作,将数字小的一方写回rd     fmax.d rd, rs1, rs2 0010101[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 将操作数寄存器rs1和rs2中的双精度浮点数进行比较操作,将数字大的一方写回rd 乘加指令     fmadd.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000011 将操作数寄存器rs1,rs2和rs3中的单精度浮点数进行rd=rs1*rs2+r3操作     fmsub.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000111 将操作数寄存器rs1,rs2和rs3中的单精度浮点数进行rd=rs1*rs2-r3操作     fnmadd.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001011 将操作数寄存器rs1,rs2和rs3中的单精度浮点数进行rd=-rs1*rs2-r3操作     fnmsub.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001111 将操作数寄存器rs1,rs2和rs3中的单精度浮点数进行rd=-rs1*rs2+r3操作     fmadd.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000011 将操作数寄存器rs1,rs2和rs3中的双精度浮点数进行rd=rs1*rs2+r3操作     fmsub.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000111 将操作数寄存器rs1,rs2和rs3中的双精度浮点数进行rd=rs1*rs2-r3操作     fnmadd.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001011 将操作数寄存器rs1,rs2和rs3中的双精度浮点数进行rd=-rs1*rs2-r3操作     fnmsub.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001111 将操作数寄存器rs1,rs2和rs3中的双精度浮点数进行rd=-rs1*rs2+r3操作 浮点数格式转化指令     fcvt.w.s rd, rs1 110000000000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用浮点寄存器rs1中的单精度浮点数转化成有符号整数,写入rd     fcvt.s.w rd, rs1 110100000000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用整数寄存器rs1中的有符号整数转化成单精度浮点数,写入rd     fcvt.uw.s rd, rs1 110000000001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用浮点寄存器rs1中的单精度浮点数转化成无符号整数,写入rd     fcvt.s.uw rd, rs1 110100000001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用整数寄存器rs1中的无符号整数转化成单精度浮点数,写入rd     fcvt.w.d rd, rs1 110000100000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用浮点寄存器rs1中的双精度浮点数转化成有符号整数,写入rd     fcvt.d.w rd, rs1 110100100000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用整数寄存器rs1中的有符号整数转化成双精度浮点数,写入rd     fcvt.uw.d rd, rs1 110000100001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用浮点寄存器rs1中的双精度浮点数转化成无符号整数,写入rd     fcvt.d.uw rd, rs1 110100100001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用整数寄存器rs1中的无符号整数转化成双精度浮点数,写入rd     fct.s.d rd, rs1 010000000001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用浮点寄存器rs1中的双精度浮点数转化成单精度浮点数,写入rd     fct.d.s rd, rs1 010000100001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 将通用浮点寄存器rs1中的单精度浮点数转化成双精度浮点数,写入rd 浮点数符号注入指令     fsgnj.s rd, rs1, rs2 0010000[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 操作数均为单精度浮点数,结果的符号位来自rs2,其它位来自rs1,结果写回rd     fsgnjn.s rd, rs1, rs2 0010000[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 操作数均为单精度浮点数,结果的符号位来自rs2符号取反,其它位来自rs1,结果写回rd     fsgnjx.s rd, rs1, rs2 0010000[24-20,rs2][19-15,rs1]010[11-7,rd]‘1010011 操作数均为单精度浮点数,结果的符号位来自rs2符号与rs1符号xor操作,其它位来自rs1,结果写回rd     fsgnj.d rd, rs1, rs2 0010001[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 操作数均为双精度浮点数,结果的符号位来自rs2,其它位来自rs1,结果写回rd     fsgnjn.d rd, rs1, rs2 0010001[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 操作数均为双精度浮点数,结果的符号位来自rs2符号取反,其它位来自rs1,结果写回rd     fsgnjx.d rd, rs1, rs2 0010001[24-20,rs2][19-15,rs1]010[11-7,rd]‘1010011 操作数均为双精度浮点数,结果的符号位来自rs2符号与rs1符号xor操作,其它位来自rs1,结果写回rd 浮点与整数互搬指令     fmv.x.w rd, rs1 111000000000 [19-15,rs1]000[11-7,rd]‘1010011 将通用浮点寄存器中的rs1读出,写回通用整数寄存器rd中。     fmv.w.x rd, rs1 111100000000 [19-15,rs1]000[11-7,rd]‘1010011 将通用整数寄存器中的rs1读出,写回通用浮点寄存器rd中。 浮点数比较指令     flt.s rd, rs1, rs2 1010000[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 如果通用浮点寄存器rs1中的单精度值小于rs2中的值,则结果为1,否则为0,结果写回整数寄存器rd     fle.s rd, rs1, rs2 1010000[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 如果通用浮点寄存器rs1中的单精度值小于等于rs2中的值,则结果为1,否则为0,结果写回整数寄存器rd     feq.s rd, rs1, rs2 1010000[24-20,rs2][19-15,rs1]010[11-7,rd]‘1010011 如果通用浮点寄存器rs1中的单精度值等于rs2中的值,则结果为1,否则为0,结果写回整数寄存器rd     flt.d rd, rs1, rs2 1010001[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 如果通用浮点寄存器rs1中的双精度值小于rs2中的值,则结果为1,否则为0,结果写回整数寄存器rd     fle.d rd, rs1, rs2 1010001[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 如果通用浮点寄存器rs1中的双精度值小于等于rs2中的值,则结果为1,否则为0,结果写回整数寄存器rd     feq.d rd, rs1, rs2 1010001[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 如果通用浮点寄存器rs1中的双精度值等于rs2中的值,则结果为1,否则为0,结果写回整数寄存器rd 浮点数分类指令     fclass.s rd, rs1 111000000000 [19-15,rs1]010[11-7,rd]‘1010011 对通用浮点寄存器rs1中的单精度浮点数进行判断,根据其所属的类型,生成一个10位的独热码(one-hot)结果,结果的每一位对应一种类型。     fclass.d rd, rs1 111000100000 [19-15,rs1]010[11-7,rd]‘1010011 对通用浮点寄存器rs1中的双精度浮点数进行判断,根据其所属的类型,生成一个10位的独热码(one-hot)结果,结果的每一位对应一种类型。


image

image


对于FMAX和FMIN指令,注意一下特殊情况:

1. 如果指令的两个操作数都是NaN,那么结果为Canonical-NaN。

2. 如果只有一个操作数位NaN,则结果为非NaN的另外一个操作数。

3. 如果任意一个操作数属于Signaling-NaN,则需要在fcsr寄存器中产生NV异常标志。

4. 由于浮点数可以表示两个0值,分别是-0.0和+0.0,对于FMAX和FMIN指令而言,-0.0被认为比+0.0小。


由于浮点数的表示范围远远大于整数的表示范围,且浮点数存在某些特殊的类型(无穷大或者NaN),因此将浮点数换成整数的过程中存在诸多特殊情况,将其转化成整数的过程如下图所示:

clip_image007


浮点分类指令的分类结果(10位的独热码):

image

转载于:https://www.cnblogs.com/mikewolf2002/p/9878603.html

### RV32I指令集定义与特性 #### 定义 RV32I 是 RISC-V 指令集架构 (ISA) 的一种基本整数指令集,专为 32 位系统设计。它是一个简单的、固定长度的指令集,每条指令都是 32 位宽[^1]。该指令集旨在提供基础的整数运算能力,适用于通用计算场景。 #### 特性 以下是 RV32I 指令集主要特性: 1. **寄存器配置** - RV32I 配备了 32 个通用寄存器,每个寄存器宽度为 32 位(XLEN=32)。其中 `x0` 被硬连线为零值,而其他寄存器 (`x1` 至 `x31`) 可存储布尔值或以二进制补码形式表示的有符号/无符号整数值[^4]。 2. **指令种类** - 支持多种类型的指令包括加载(Load)、存储(Store)、算术(Arithmetic)、逻辑(Logical)以及分支(Branch)和跳转(Jump)等操作。 - 指令格式主要包括 R 型(寄存器到寄存器操作)、I 型(立即数操作)、S 型(存储操作)、B 型(分支操作)和 U/J 型(绝对跳跃和偏移量操作)[^5]。 3. **编码效率** - RV32I 设计时预留了大量的编码空间以便未来扩展 ISA 功能。其操作码分配经过精心规划,使得具有相似数据路径特性的指令共享更多相同的比特模式,从而简化硬件控制逻辑的设计[^5]。 4. **程序计数器管理** - 使用专门的非特权寄存器——程序计数器(PC),用于跟踪当前执行指令的位置并支持相对寻址机制下的分支与跳转功能。 5. ** immediates 处理方式** - 对于 B 类型和 J 类型指令中的目标地址字段进行了特殊处理:通过将其左移一位来扩大可达范围;同时调整 immediate 字段内部 bit 排列顺序减少多路复用成本提升性能表现。 6. **适用领域** - 主要应用于资源有限但需要高效能比的小型设备或者作为更大规模处理器的基础组成部分之一[^2]。 ```python # 示例 Python 实现部分核心概念模拟 class RegisterFile: def __init__(self): self.registers = [0]*32 def read(self, reg_num:int)->int: return self.registers[reg_num] def write(self, reg_num:int,value:int): if reg_num !=0: # x0 is hardwired to zero. self.registers[reg_num]=value register_file =RegisterFile() print(register_file.read(1)) # Output will be initial value of register x1 which should default as per specifcation rules above . ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值