1. 浮点寄存器状态
"F"扩展加入了32个32位宽度的浮点寄存器f0~f31和一个浮点控制/状态寄存器fcsr,它用来记录浮点操作模式和异常状态。 浮点寄存器的宽度用FLEN来描述,对于单精度单元来讲FLEN=32。浮点指令一般都是浮点寄存器中的我呢见进行操作,load和store 则在储存器和浮点寄存器之间传输数据。同时也有从整数寄存器中读写数据的指令。
虽然整数、浮点可以采用统一的寄存器文件,甚至这样还可以简化软件上寄存器的分配和调用约定,但是分开以后可以简化浮点单元内部结构,容易于增加寄存器总数,为超标量计算提供强力支持。
2. 浮点控制/状态寄存器
浮点控制/状态寄存器fcsr属于一个RISC-V控制/状态寄存器(CSR)。它是一个32位读/写寄存器,用于浮点算术操作选择动态的舍入模式,并保存产生异常标志,如下。
控制/状态寄存器fcsr可以用FRCSR/FSCSR指令来实施读写操作,但它们均由底层的CSR访问指令实现。
FRCSR通过将fcsr的值复制到整数寄存器rd中来实现读取操作。
FSCSR通过将fcsr原来的值复制到rd,然后将整数寄存器rs1中的值写入fcsr来实现写操作。
fcsr中的字段也可以通过不同的CSR寻址方式来单独访问,并为这些访问在汇编上定义了伪指令。
FRRM指令读取舍入模式字段frm,并将其复制到整数寄存器rs1最低3位中,其他位置0。
FSRM通过将frm的旧值复制到整数寄存器rd中,然后将整数寄存器rs1中的低3位中的值作为新值写入frm中,来实现交换frm。
FRFLAGS、FSFLAGS定义类似,操作对象是异常标志字段fflags。FSRMI和FSFLAGSI则使用立即数而不是rs1来操作。
浮点操作要么使用编码在指令格式中的舍入模式,要么使用frm中的动态舍入模式。舍入模式的编码如下表:
指令编码rm字段中的编码如果位111,则选择保存在frm中的动态舍入模式。如果被设置为一个非法值(101-111),那么后续任何试图使用动态舍入模式的浮点操作指令都会引起非法指令自陷。一些指令尽管用了rm字段,但是不受舍入模式的影响,他们应当把rm字段设置为RNE(000)。
异常标志用来显示字上次标志位被重置以来,已经由浮点指令产生的异常情况,如下。
ISA中部支持在浮点异常上产生自陷,而是需要软件自己对标志位进行检查。
3. NaN 的生成和传递
如果一个浮点操作的结果是NaN,则结果就是规定的NaN。这个NaN符号位为0,并且除了MSB外,其他有效位均为0(IEEE浮点规定凡是|x|>0x7f800000情况均为NaN,而此处规定的NaN仅特指0x7fc00000)。
对于FMIX/FMAX指令,如果其中至少一个操作数为SNAN(signal NaN),或者两个都是QNaN,那么运算的结果就一定是规定的NaN,如果一个操作数是QNaN,另一个操作数不是NaN,则结果是非NaN的那个操作数。(SNAN 的MSB位为0,浮点指令操作它会触发异常,QNaN的MSB位为1,浮点操作不会触发异常)。另外就是,符号注入指令FSGNJ、FSGNJN、FSGNJX不会产生特指NaN,它们都直接操作数据位。
RISC ISA 要求出现异常情况时,强制返回应该标准缺省值,而不是让用户自己干预(ALPHA就是这么干的)。
4. 非规格化数的计算
在非规格化数上的操作处理遵照IEEE 754-2008标准。 用IEEE 标准的说法,极小(tininess)是在舍入之后检测的——也就是说,只有在舍入后结果是非规格化数时,才会产生下溢异常,即使未舍入的结果是一个非规格化数。 这样可以减少虚假的下溢错误信号的生成。
5. 单精度的load和store指令
浮点load和store指令使用与整数ISA相同的“基址+偏移量”的寻址方式,寄存器rs1保存基址,字节偏移量是一个12位有符号数。FLW从存储器中将一个单精度浮点值读入到浮点寄存器rd中。FSW指令将浮点寄存器rs2中的单精度浮点值写入到存储器中。
6. 浮点计算指令
浮点计算指令具有1个或者2个操作数,使用R类指令格式,其主操作码是OP-FP。
浮点计算指令都具有2位的fmt字段,其编码如表 7.3所示。对于F扩展中的所有指令,它被设置为S (00)。所有执行舍入的浮点操作指令,可以通过frm字段选择其舍入模式。
FADD.S、 FSUB.S、FMUL.S、FDIV.S指令在rs1和rs2之间分别执行单精度浮点的加、减、乘、除运算,并将结果写入rd。
FMIN.S、FMAX.S指令分别将rs1、rs2中的较小者或者较大者写入到rd中。
FSQRT.S 指令计算rs1的平方根,并把结果写入rd。
融合加乘指令需要一种新的标准指令格式。R4类指令指明了3个源寄存器(rs1、rs2、rs3)和一个目标寄存器(rd)。这种格式仅仅会被浮点融合加乘指令使用。
FMADD.S ——> rd=rs1rs2+rs3
FMSUB.S ——> rd= rs1rs2-rs3
FNMSUB.S ——> rd= -(rs1rs2-rs3)
FNMADD.S ——> rd = -(rs1rs2+rs3)
7. 单精度浮点转换和传输指令
总体上,整数—浮点之间的转换指令被编码在OP-FP主操作码空间。
浮点转换指令
FCVT.W.S、FCVT.L.S指令将浮点寄存器rs1中的一个浮点数分别转换为一个有符号的32位或者64位整数,并保存到寄存器rd中。
FCVT.S.W、FCVT.S.L指令分别将整数寄存器rs1中的一个有符号的32位或者64位整 数,转换成一个浮点数,保存到浮点寄存器rd中。
FCVT.WU.S、FCVT.LU.S、FCVT.S.WU、FCVT.S.LU指令转换到无符号整数值,或者从无符号整数值转换。
FCVT.L[U].S和FCVT.S.L[U]指令在RV32 中是非法的。如果舍入的结果在目标格式中是不能被表示的,它将被裁剪为最接近的值,并invalid 标志位会被设置。
所有的浮点——整数之间的转换指令都按照frm字段进行舍入。一个浮点寄存器可使用 FCVT.S.W rd,x0 指令初始化 rd为浮点的0,而且这不会产生异常。
符号注入指令(sign-injection instruction)
FSGNJ.S、FSGNJN.S、FSGNJX.S指令从rs1中读取除了符号位以外的所有位。
FSGNJ指令,结果的符号位是rs2的符号位;对于FSGNJN指令,结果的符号位是rs2的符号位取反;
对于FSGNJX指令,结果的符号位是rs1的 符号位和rs2的符号位进行XOR运算。符号注入指令并不设置浮点异常标志。
FSGNJ.S rx,ry,ry 将ry传输到rx(汇编语言伪指令FMV.S rx,ry);
FSGNJN.S rx,ry,ry 将ry取负后传输到rx(汇 编语言伪指令FNEG.S rx,ry);
FSGNJX.S rx,ry,ry 将ry的绝对值传输到rx(汇编语言伪指令FABS.S rx,ry);
浮点传输指令FMV
FMV指令提供了在浮点寄存器和整数寄存器直接进行位传输的指令。FMV.X.S将浮点寄存器rs1中 以IEEE 754-2008编码的单精度浮点值,传输到rd寄存器的低32位。对RV64,目标寄存器rd的高32位,被浮点数的符号位填充。FMV.S.X将整数寄存器rs1的低32位(以IEEE 754-2008编码 的单精度浮点值),传输到浮点寄存器rd中。在传输过程中位数据不会被修改,特别地非规定NaN有效载荷保持不变。
8. 单精度浮点格式比较指令
浮点比较指令用于比较(等于、小于、小于等于)浮点寄存器rs1和rs2之间的值,并将结果的布尔值写入整数寄存器rd中。
FLT.S、FLE.S执行IEEE 754-2008标准称为signaling的比较:也就是说,如果任一输入是NaN, 则产生一个无效操作(Invalid Operation)异常。
FEQ.S执行静默比较(只有输入是SNaN时,才产生一个无效操作异常)。
对于所有3条指令,如果任一操作数是NaN,则结果是0。
9. 单精度浮点分类指令
FCLASS.S 指令检测浮点寄存器rs1中的值,并将一个指示这个浮点数类别的10位掩码,写入整数寄存器rd中。这个掩码的格式如表7.5所示。如果具有该属性则将rd中的对应位置1, 否则清零。最终rd中只有1bit为1,其他位都为0。
待续。。。。。