assembly 为什么FLD m80fp不为SNaN输入引发异常,而双精度或浮点型FLD可以?

vsikbqxv  于 2023-02-19  发布在  其他
关注(0)|答案(1)|浏览(132)

以下是使用FLD时可能出现的例外情况:

  • #IS发生堆栈下溢或上溢。
  • #IA源操作数是SNaN。如果源操作数是扩展双精度浮点格式(FLD m80fp或FLD ST(i)),则不出现此错误。
  • #D源操作数是非规格化值。如果源操作数为扩展精度双精度浮点格式,则不会出现此情况。

为什么#IA异常“在源操作数为扩展双精度浮点格式时不发生”?
我认为双精度浮点和双扩展精度浮点格式基本上是相同的,都可以对SNaN进行编码。
这种差异有什么逻辑上的原因吗?或者它就是这样?

g52tjvyc

g52tjvyc1#

fld m64fpm32fp必须转换为x87寄存器中使用的内部80位格式。您可以将其视为会引发#SNaN异常的转换过程。
fld m80fp只是一个纯数据负载,它已经是本机内部格式,如frstor
(Wikipedia声称AMD CPU do 在SNaN 80位加载时发出FP异常信号,这是AMD和Intel实现x86-64的细微差别之一。但该Wiki列表之前已被证明是不准确的,例如bsf/bsr声明似乎是基于对文档的误解,@Electro评论说,AMD的手册说,当源格式为80位时,fld不会引发FP异常,但当存储SNaN时,fst/fstp总是引发FP异常。)
从浮点型或双精度型到扩展80位的转换必须检查源浮点型的位,扩展尾数并根据指数字段是否为非零(正规或次正规)添加一个明确的前导1或0。
x87双扩展与IEEE binary64(也称为double或qword)之间的主要区别是尾数位的显式与隐式。两者都可以对SNaN进行编码,但它们肯定不像binary 32和binary 64那样“基本相同”(只是字段更宽)。
这种“不一致性”大概可以追溯到8087,当时晶体管预算非常有限;即使fld m80fp不使用通常的转换硬件,也要检查SNaN,这会消耗额外的晶体管。
请注意,fld m80fp是 * 唯一 * 可以让x87 FPU读取tbyte FP值的方法(frstor或更现代的fxrstorxrstor除外)。没有fadd m80fp或其他任何东西。因此,任何涉及从内存阅读m80 fp的操作都不必引发SNaN异常。
大多数FP数学指令(如fadd st0, m64fp and fadd st0, m32fp)都有内存源操作数形式,这些指令可能也需要转换为内部格式作为其操作的一部分,因此您希望检测内存源SNaN作为转换的一部分是有意义的。
因此,如果您正在设计8087,则在转换32位和64位输入时,让处理内存加载的逻辑检查SNaN是有意义的,而不仅仅是在加载80位本机格式时。这可能是英特尔最初继承该行为的地方,因此,使后来的CPU不同以保留该行为是没有意义的。
IDK是否认为这是一个缺点,或者它实际上是一个“好”的想法,你可以加载80位的原生FP值,而不可能引发异常。AMD显然决定不,并没有信号的SNaN的fld m80fp的FP异常。
或者,您可以将其视为一件坏事,即fld dword / qword在重新格式化浮点数时可能引发异常,而不可能丢失数据,并且不执行任何实际计算。

背景:

通常情况下,你一开始就不会遇到SNaN。无效操作(如除以0)的输出是QNaN,IIRC。因此,只有当你自己用整数指令或静态常量数据创建一个SNaN时,你才会得到SNaN。(我认为)
当然,通常会屏蔽FP异常,这样它就不会 * 出错 *,只是在FP状态字中设置一个粘滞位。

相关问题