PowerPC's floating point registers only support double-precision format, so loading and storing single-precision values requires conversion. The conversion from single to double on load makes sense, but the conversion from double to single for storing does some confusing things. It seems to correctly truncate numbers that are within single-precision range, as well as NaNs, infinity, and zero, but does some weird shifting for everything else instead of rounding to zero or infinity like I would expect.
Examples from PPC750 CPU. The examples which give the result I expected are listed first.
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
Then it goes on to state:
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).
That explains why I got the results I did, but it doesn't explain how that's useful. It seems to me like it would cause horrible errors if the values are ever loaded from memory again.
Why doesn't the stfs instruction perform normal rounding? How is the result expected not to cause problems?
CodePudding user response:
The stfs
documentation says “Note that the value to be stored should be in single-precision format prior to the execution of the stfs instruction.” This means the contents of the register being stored should be the result of some prior instruction that produces a single-precision value, such as fmuls
(single-precision floating-point multiply) or frsp
(round to single-precision).
I would hazard a guess part of the reason is so that it could be fast and easy to implement—stfs
does not have to do rounding and does not have to go to a floating-point unit to do that. It can go directly to a load-store unit which only has logic for handling simpler cases, in which truncating the bits suffices.