为什么 PowerPC 的 stfs 指令没有按预期运行?
Why doesn't PowerPC's stfs instruction behave as expected?
PowerPC的浮点寄存器只支持双精度格式,所以加载和存储单精度值需要转换。加载时从单精度到双精度的转换是有意义的,但是从双精度到存储的单精度转换会做一些令人困惑的事情。它似乎正确地截断了单精度范围内的数字,以及 NaN、无穷大和零,但对其他所有内容进行了一些奇怪的移位,而不是像我期望的那样四舍五入到零或无穷大。
来自 PPC750 的示例 CPU。给出我期望的结果的例子列在最前面。
double-precision input decimal approximation single-precision output decimal approximation
0x 400f ffff ffff ffff 3.99999999 0x 407f ffff 3.99999976
0x 7ff8 0000 0000 0000 QNaN 0x 7fc0 0000 QNaN
0x 7ff0 0000 0000 0000 +inf 0x 7f80 0000 +inf
0x 8000 0000 0000 0000 -0.0 0x 8000 0000 -0.0
--------------------------------------------------------------------------------------------------
0x 8000 0000 0000 0001 -4.941e-324 0x 8080 0000 -1.175e-38
0x 00a0 0000 0000 0000 1.139e-305 0x 0500 0000 6.019e-36
0x 7fe0 1234 5678 9abc 9.028e+307 0x 7f00 91a2 1.709e+38
我看了PowerPC Programming Environments Manual
看看它是否可以对此有所启发。 C.7 节描述了 "No Denormalization Required" 和 "Denormalization Required" 情况下的转换步骤。 (请注意,此表示法中的 ||
表示串联。)
然后它继续说明:
Note that if the value to be stored by a single-precision store
floating-point instruction is larger in magnitude than the maximum
number representable in single format, the first case mentioned, “No
Denormalization Required,” applies. The result stored in WORD is then
a well-defined value but is not numerically equal to the value in the
source register (that is, the result of a single-precision load
floating-point from WORD does not compare equal to the contents of
the original source register).
这解释了为什么我得到了我所做的结果,但没有解释它有什么用。在我看来,如果再次从内存中加载这些值会导致可怕的错误。
为什么stfs指令不进行正常舍入?怎么期望结果不会出问题?
stfs
文档说“请注意,在执行 stfs 指令之前,要存储的值应该是单精度格式。”这意味着要存储的寄存器的内容应该是某些先前产生单精度值的指令的结果,例如 fmuls
(单精度浮点乘法)或 frsp
(舍入到单精度)。
我会冒险猜测部分原因是它可以快速且易于实现——stfs
不必进行舍入,也不必转到浮点单元来去做。它可以直接进入加载存储单元,该单元仅具有处理更简单情况的逻辑,其中截断位就足够了。
PowerPC的浮点寄存器只支持双精度格式,所以加载和存储单精度值需要转换。加载时从单精度到双精度的转换是有意义的,但是从双精度到存储的单精度转换会做一些令人困惑的事情。它似乎正确地截断了单精度范围内的数字,以及 NaN、无穷大和零,但对其他所有内容进行了一些奇怪的移位,而不是像我期望的那样四舍五入到零或无穷大。
来自 PPC750 的示例 CPU。给出我期望的结果的例子列在最前面。
double-precision input decimal approximation single-precision output decimal approximation
0x 400f ffff ffff ffff 3.99999999 0x 407f ffff 3.99999976
0x 7ff8 0000 0000 0000 QNaN 0x 7fc0 0000 QNaN
0x 7ff0 0000 0000 0000 +inf 0x 7f80 0000 +inf
0x 8000 0000 0000 0000 -0.0 0x 8000 0000 -0.0
--------------------------------------------------------------------------------------------------
0x 8000 0000 0000 0001 -4.941e-324 0x 8080 0000 -1.175e-38
0x 00a0 0000 0000 0000 1.139e-305 0x 0500 0000 6.019e-36
0x 7fe0 1234 5678 9abc 9.028e+307 0x 7f00 91a2 1.709e+38
我看了PowerPC Programming Environments Manual
看看它是否可以对此有所启发。 C.7 节描述了 "No Denormalization Required" 和 "Denormalization Required" 情况下的转换步骤。 (请注意,此表示法中的 ||
表示串联。)
然后它继续说明:
Note that if the value to be stored by a single-precision store floating-point instruction is larger in magnitude than the maximum number representable in single format, the first case mentioned, “No Denormalization Required,” applies. The result stored in WORD is then a well-defined value but is not numerically equal to the value in the source register (that is, the result of a single-precision load floating-point from WORD does not compare equal to the contents of the original source register).
这解释了为什么我得到了我所做的结果,但没有解释它有什么用。在我看来,如果再次从内存中加载这些值会导致可怕的错误。
为什么stfs指令不进行正常舍入?怎么期望结果不会出问题?
stfs
文档说“请注意,在执行 stfs 指令之前,要存储的值应该是单精度格式。”这意味着要存储的寄存器的内容应该是某些先前产生单精度值的指令的结果,例如 fmuls
(单精度浮点乘法)或 frsp
(舍入到单精度)。
我会冒险猜测部分原因是它可以快速且易于实现——stfs
不必进行舍入,也不必转到浮点单元来去做。它可以直接进入加载存储单元,该单元仅具有处理更简单情况的逻辑,其中截断位就足够了。