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指令集的更多相关文章

  1. Risc-V指令集

    https://riscv.org/specifications/ Risc-V文档包括:用户层指令集文档和特权架构文档,下面这两个文件的官网链接. User-Level ISA Specificat ...

  2. SSE指令集学习:Compiler Intrinsic

    大多数的函数是在库中,Intrinsic Function却内嵌在编译器中(built in to the compiler). 1. Intrinsic Function Intrinsic Fun ...

  3. ARM-汇编指令集(总结)

    ARM汇编指令集 指令.伪指令 (汇编)指令:   是机器码的助记符,经过汇编器编译后,由CPU执行. (汇编)伪指令:用来指导指令执行,是汇编器的产物,最终不会生成机器码. 有两种不同风格的ARM指 ...

  4. iOS------苹果设备处理器指令集(iPhone初代到iPhone5s)

    (via 雅香小筑) Arm处理器,因为其低功耗和小尺寸而闻名,几乎所有的手机处理器都基于arm,其在嵌入式系统中的应用非常广泛,它的性能在同等功耗产品中也很出色. Armv6.armv7.armv7 ...

  5. SSE指令集优化学习:双线性插值

    对SSE的学习总算迈出了第一步,用2天时间对双线性插值的代码进行了优化,现将实现的过程梳理以下,算是对这段学习的一个总结. 1. 什么是SSE 说到SSE,首先要弄清楚的一个概念是SIMD(单指令多数 ...

  6. RISC指令集的五个周期

    RISC指令集的五个周期 RISC(reduced instruction set computer,精简指令集计算机)简称为精简指令集.RISC把执行指令的精力主要放在了经常使用的指令上面.本文主要 ...

  7. x86指令集同频性能提升

    x86近5000条指令,迄今为止最复杂的指令集.这里不研究CISC & RISC,也不考虑process制程变化,主要是看最近几代IA架构对于同频率下性能的提升. x86指令集nasm文档 h ...

  8. CPU指令集

    cpu作为一台电脑中的核心,它的作用是无法替代的.而cpu本身只是在块硅晶片上所集成的超大规模的集成电路,集成的晶体管数量可达到上亿个,是由非常先进复杂的制造工艺制造出来的,拥有相当高的科技含量. C ...

  9. 在UWP应用中加入Cortana语音指令集

    本文介绍小娜语音指令集的使用场景,如何将UWP应用接入小娜的语音指令集,使用户直接通过小娜启动应用并使用应用中 一些轻量级的功能.文中以必应词典作为实例讲解必应词典UWP版本是如何接入小娜语音功能的. ...

随机推荐

  1. Java中public、protected、default和private的区别

    public: 具有最大的访问权限,可以访问任何一个在classpath下的类.接口.异常等.它往往用于对外的情况,也就是对象或类对外的一种接口的形式. protected: 主要的作用就是用来保护子 ...

  2. 026.Zabbix简单调优

    一 调优相关对应项 Zabbix busy trapper processes, in % StartTrappers=5 Zabbix busy poller processes, in % Sta ...

  3. POP3_关于 multipart/related;boundary=

    http协议对mime类型有详细描述,multipart/....是单个消息头包含多个消息体的解决方案.multipart媒体类型对发送非文本的各媒体类型是有用的.目前常用的有这些subtype: M ...

  4. 用 consul + consul-template + registrator + nginx 打造真正可动态扩展的服务架构

        https://mp.weixin.qq.com/s?src=3&timestamp=1503654544&ver=1&signature=UcJdgd4vgt*3AR ...

  5. java execute、executeQuery和executeUpdate之间的区别

    在用纯JSP做一个页面报警功能的时候习惯性的用executeQuery来执行SQL语句,结果执行update时就遇到问题,语句能执行,但返回结果出现问题,另外还忽略了executeUpdate的返回值 ...

  6. delphi Ribbon 111

    Ribbon上包含以下一些元素,如图所示: 元素对应API: Element Ribbon API Quick Access Toolbar RibbonControl.ToolbarRibbonQu ...

  7. In-Place upgrade to Team Foundation Server (TFS) 2015 from TFS 2013Team Foundation Server TFS TFS 2015 TFS upgrade TFS with Sharepoint

    This upgrade document gives detailed step by step procedure for the In-Place upgrade from TFS 2013 t ...

  8. 面试笔试-脚本-1:使用shell脚本输出登录次数最多的用户

    原题目: 一个文本类型的文件,里面每行存放一个登陆者的IP(某些行是反复的),写一个shell脚本输出登陆次数最多的用户. 之前刚看到这个题目时,立即没有想到一行直接解决的办法,尽管知道能够先进行排序 ...

  9. QQ去除未读状态的动画

    QQ去除未读状态的动画 by 伍雪颖 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmFpbmxlc3Zpbw==/font/5a6L5L2T/fonts ...

  10. 为什么使用this构造器

    当一个类有多个构造函数的时候,常使用this构造器: public class SomeClass { public SomeClass() { //TODO:初始化一些字段 } public Som ...