3

We are writing an emulator and want to know that for a given FPU state, is the state of the the FPU deterministic after running an FPU instruction eg. FDIV?

There are many Intel compatible CPU architectures, that implement x87 instruction set. Should we rely on the resulting CPU state when testing the correctness of our FPU emulation?

Are different implementations round/compute differently?

Calmarius
  • 18,570
  • 18
  • 110
  • 157

3 Answers3

5

Yes, the x87 FPU is deterministic for the basic operations +, -, *, /, sqrt. For instance, in its default state (full-width significand and round-to-nearest-even mode), the result of x + y is exactly the nearest representable 80-bit floating-point value to the result of the mathematical sum of x and y.

Makers of compatible chips have implemented the exact same definition for the operations above.

The x87's instruction set, in pure CISC tradition, also contains high-level instructions to compute mathematical functions, say, an approximation of the sine (FSIN). The results of these instructions have varied over brands and models of processors. In your emulator, you probably need only to provide something as good as one of the worst implementations of these instructions still in use. No-one should complain if you use the result of the sinl() function from the math library of your host language, which is typically better than FSIN (by virtue of being implemented with explicit argument reduction and polynomial approximation, and not a call to FSIN).

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • Why FSQRT deterministic while FSIN not? – Calmarius Sep 19 '13 at 10:53
  • 1
    @Calmarius Because +, -, *, / and square root were standardized in IEEE 754 as operations that had to return a correctly rounded result. They are often called the five “basic operations”. Implementing a correctly rounded sine is extremely difficult, so the standard did not mandate it, so implementers can provide a sine function that isn't correctly rounded, or no sine function at all, and still call their implementation IEEE 754-compliant. – Pascal Cuoq Sep 19 '13 at 11:34
  • @Calmarius: For any particular size of input and output, it is possible (and not difficult) to construct a sqrt(x) function which will know whether its reported result is above, below, or equal to the numerically-perfect value. If one computes a result which is one bit longer than the intended result, that extra bit plus knowledge of whether the correct value is above or below the represented value will suffice to compute a result with any desired rounding mode. For sin(x), such determination is in general not possible. – supercat Apr 07 '14 at 20:40
  • Almost any code that wants accuracy from sin(x) will need to perform argument reduction *before* the last computation yielding the value of x. For example, if one wants to compute the sine of (x/1.0E9) when x is near 3141592654, one would first need to compute the difference between x and (1E9 * pi), and then divide that by 1E9. If one divides x by 1E9 without doing the argument reduction first, the resulting round-off errors will render the accuracy of any future argument reduction irrelevant. – supercat Oct 19 '14 at 23:03
2

It should be, if you stick to the basic FPU instructions, and use the same compiler for your FPU algorithms if you want them to produce consistent results. That's not counting the fact you need to properly initialize your FPU library.

Here is some good reading on the subject if you're interested: https://randomascii.wordpress.com/2013/07/16/floating-point-determinism.

The links to other articles inside this one are exceptionally useful.

antonone
  • 2,045
  • 1
  • 25
  • 35
  • 1
    I think the question is concerned with the emulation of the FPU and that the advice to get consistent results for source code across compilation platforms is largely irrelevant. – Pascal Cuoq Sep 18 '13 at 12:39
1

As others have said, the basic five operations will give identical results on all x87 FPUs. However...

The x87 FPU is peculiar. It's 80-bit registers mean that it may get results that are different than on any other FPU (such as on PowerPC or ARM with have 64-bit floating-point registers). These results may be better or worse. Even setting the x87 rounding mode to 32-bit or 64-bit will not make it the same as PowerPC/ARM because the exponent remains unbounded.

For writing an emulator this shouldn't matter, except that it means that you cannot necessarily use the host FPU to emulate the x87 FPU. I covered many of these issues in these two articles:

http://randomascii.wordpress.com/2013/07/16/floating-point-determinism http://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/