mesa: Sparc's IROUND() optimization is invalid.
authorDavid Miller <davem@davemloft.net>
Sat, 28 Feb 2009 07:34:41 +0000 (23:34 -0800)
committerBrian Paul <brianp@vmware.com>
Sat, 28 Feb 2009 16:36:56 +0000 (09:36 -0700)
We can't use the "fstoi" instruction like this.

Unlike other floating point instructions, "fstoi" always rounds
towards zero no matter what rounding mode the FPU has been set to.

This was validated using the following test program:

--------------------
static inline int iround(float f)
{
   int r;
   __asm__ ("fstoi %1, %0" : "=f" (r) : "f" (f));
   return r;
}
#define IROUND(x)  iround(x)

#define IROUND_REF(f)  ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))

int main(void)
{
float f = -2.0;

while (f < 3.0f) {
int sparc_val = IROUND(f);
int ref_val = IROUND_REF(f);

if (sparc_val != ref_val)
printf("DIFFERENT[%f]: REF==%d SPARC==%d\n",
       f, ref_val, sparc_val);
f += 0.1f;
}

return 0;
}
--------------------

which prints out things like:

--------------------
DIFFERENT[-1.900000]: REF==-2 SPARC==-1
DIFFERENT[-1.800000]: REF==-2 SPARC==-1
DIFFERENT[-1.700000]: REF==-2 SPARC==-1
DIFFERENT[-1.600000]: REF==-2 SPARC==-1
DIFFERENT[-1.000000]: REF==-1 SPARC==0
DIFFERENT[-0.900000]: REF==-1 SPARC==0
DIFFERENT[-0.800000]: REF==-1 SPARC==0
DIFFERENT[-0.700000]: REF==-1 SPARC==0
DIFFERENT[-0.600000]: REF==-1 SPARC==0
DIFFERENT[0.500000]: REF==1 SPARC==0
DIFFERENT[0.600000]: REF==1 SPARC==0
...
--------------------

So we have to remove Sparc's IROUND() definition, it's wrong.

Signed-off-by: David S. Miller <davem@davemloft.net>
src/mesa/main/imports.h

index 4192f037c00b2fe7c4da9ec7562fa950248fad60..7b61e22e9322b8a18a359be503b685113f0c0ed8 100644 (file)
@@ -256,15 +256,7 @@ static INLINE int GET_FLOAT_BITS( float x )
 /***
  *** IROUND: return (as an integer) float rounded to nearest integer
  ***/
-#if defined(USE_SPARC_ASM) && defined(__GNUC__) && defined(__sparc__)
-static INLINE int iround(float f)
-{
-   int r;
-   __asm__ ("fstoi %1, %0" : "=f" (r) : "f" (f));
-   return r;
-}
-#define IROUND(x)  iround(x)
-#elif defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) && \
+#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) && \
                        (!(defined(__BEOS__) || defined(__HAIKU__))  || \
                        (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)))
 static INLINE int iround(float f)