Home > Software engineering >  Why doesn't PowerPC's stfs instruction behave as expected?
Why doesn't PowerPC's stfs instruction behave as expected?

Time:01-18

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

I looked at the conversion steps

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.

  • Related