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)结果,结果的每一位对应一种类型。 | |||
对于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),因此将浮点数换成整数的过程中存在诸多特殊情况,将其转化成整数的过程如下图所示:
浮点分类指令的分类结果(10位的独热码):

RV32FD指令集的更多相关文章
- Risc-V指令集
https://riscv.org/specifications/ Risc-V文档包括:用户层指令集文档和特权架构文档,下面这两个文件的官网链接. User-Level ISA Specificat ...
- SSE指令集学习:Compiler Intrinsic
大多数的函数是在库中,Intrinsic Function却内嵌在编译器中(built in to the compiler). 1. Intrinsic Function Intrinsic Fun ...
- ARM-汇编指令集(总结)
ARM汇编指令集 指令.伪指令 (汇编)指令: 是机器码的助记符,经过汇编器编译后,由CPU执行. (汇编)伪指令:用来指导指令执行,是汇编器的产物,最终不会生成机器码. 有两种不同风格的ARM指 ...
- iOS------苹果设备处理器指令集(iPhone初代到iPhone5s)
(via 雅香小筑) Arm处理器,因为其低功耗和小尺寸而闻名,几乎所有的手机处理器都基于arm,其在嵌入式系统中的应用非常广泛,它的性能在同等功耗产品中也很出色. Armv6.armv7.armv7 ...
- SSE指令集优化学习:双线性插值
对SSE的学习总算迈出了第一步,用2天时间对双线性插值的代码进行了优化,现将实现的过程梳理以下,算是对这段学习的一个总结. 1. 什么是SSE 说到SSE,首先要弄清楚的一个概念是SIMD(单指令多数 ...
- RISC指令集的五个周期
RISC指令集的五个周期 RISC(reduced instruction set computer,精简指令集计算机)简称为精简指令集.RISC把执行指令的精力主要放在了经常使用的指令上面.本文主要 ...
- x86指令集同频性能提升
x86近5000条指令,迄今为止最复杂的指令集.这里不研究CISC & RISC,也不考虑process制程变化,主要是看最近几代IA架构对于同频率下性能的提升. x86指令集nasm文档 h ...
- CPU指令集
cpu作为一台电脑中的核心,它的作用是无法替代的.而cpu本身只是在块硅晶片上所集成的超大规模的集成电路,集成的晶体管数量可达到上亿个,是由非常先进复杂的制造工艺制造出来的,拥有相当高的科技含量. C ...
- 在UWP应用中加入Cortana语音指令集
本文介绍小娜语音指令集的使用场景,如何将UWP应用接入小娜的语音指令集,使用户直接通过小娜启动应用并使用应用中 一些轻量级的功能.文中以必应词典作为实例讲解必应词典UWP版本是如何接入小娜语音功能的. ...
随机推荐
- 本机Tomcat启动myeclipse,用Jmeter录制脚本端口冲突解决办法
今天用jmeter 录制脚本与已经启动的Tomcat端口冲突,无法启动工作台的http代理服务器, 如果两个的端口一样,则http代理服务器启动就会提示端口被占用 所以先把Tomcat端口和http代 ...
- 004.SMB之guest级别配置
一 配置文件修改 注意: 1 share级别权限访问即,无任何验证共享,对guest开放. 2 新版samba4已取消share级别,可使用user级别配置成无验证共享. 1.1 全局配置文件修改 [ ...
- 初识thinkphp(5)
这次主要内容是模型的基本操作 0x01:什么是模型 通过手册的阅览,笼统的说就是,把打开数据库等操作在另一个php文件中进行 以及对变量的规则具体细节,查询,取值等操作进行定义,方便在控制器中直接使用 ...
- OSI 7层 TCP/IP 4层
在网络层有{ IP协议:IP协议是用于将多个包交换网络连接起来的,它在源地址和目的地址之间传送一种称之为数据包的东西,它还提供对数据大小的重新组装功能,以适应不同网络对包大小的要求. ICMP协议:I ...
- luogu P1663 山
题目链接 luogu P1663 山 题解 只需要求出下凸包的最低点就好了 显然是由两个斜率相反的直线相交来的 盼下最低点为直线的情况 代码 #include<cstdio> #inclu ...
- Android activity之间数据传递和共享的方式之Application
1.基于消息的通信机制 Intent ---bundle ,extra 数据类型有限,比如遇到不可序列化的数据Bitmap,InputStream,或者LinkedList链表等等数据类型就不太好用 ...
- [CQOI2007]涂色
[CQOI2007]涂色 题目大意: 假设你有一条长度为\(n\)的木版,初始时没有涂过任何颜色.每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色.问达到给定的目标至少要多少次操 ...
- [POI2013]Morskie opowieści
[POI2013]Morskie opowieści 题目大意: 一个\(n(n\le5000)\)点\(m(m\le5000)\)边无向图,边权均为\(1\),有\(k(k\le10^6)\)个询问 ...
- Dell H300/6i/6iR/H700/H800阵列卡配置(转)
说明:其实Dell系列的阵列卡基本都是同一个套路和界面,包括操作步骤,不同的是不同的卡性能和支持Raid模式不一样而已. 名称解释: Disk Group:磁盘组,这里相当于是阵列,例如配置了一个RA ...
- Software UART, Timer, PWM, External Interrupt
How can you add extra hardware UARTs to a 32bit TMS470 ARM7-based microcontroller at zero cost? Solu ...


