Subject: FPU Control Word: Initial Value looks wrong

From: Andreas Jaeger <[email-masked]>
Date: 03 Jul 2000 19:30:42 +0200

Porting glibc to MIPS I noticed that the initial contents of the fpu
control word doesn't seem to be right (at least on the machines I've
tried - one with a normal MIPS 2.2.13 and one with 2.2.15 and the
MIPS/Algorithmics patches (including FPU emulator).

The appended small test program should return a 0 (that's the desired
value by glibc for full ISO C99 support) - but it seems to be set to
0x600.

Could the kernel folks fix this, please?  I grepped through the sources
and didn't find a place where the FPU gets initialised.:-(

Thanks,
Andreas

P.S. Here's the test program:
#include <stdlib.h>

#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw) : )
#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw))

int
main (void)
{
  int fpucw;

  _FPU_GETCW (fpucw);

  printf ("%x %d\n", fpucw, fpucw);

  return 0;
}

-- 
 Andreas Jaeger
  SuSE Labs [email-masked]
   private [email-masked]

---

From: Ralf Baechle <[email-masked]>
Date: Tue, 4 Jul 2000 00:32:32 +0200

> and didn't find a place where the FPU gets initialised.:-(

Surprise - the kernel initializes this to zero and the libc should do
the same afair.  Did this change?

I tried your program on a Indy running 2.4.0-test2 + glibc 2.2 and it was
printing ``0 0''.

Could you check the source of your kernel for the value it's writing to
fcr31?  That's the constant FPU_DEFAULT defined in arch/mips/kernel/
r4k_switch.S.  Some quite old kernel were using a different value but I
was actually assuming those versions have already died out.

  Ralf

---

From: Andreas Jaeger <[email-masked]>
Date: 04 Jul 2000 13:39:04 +0200

>>>>> Ralf Baechle writes:

>> and didn't find a place where the FPU gets initialised.:-(

Ralf> Surprise - the kernel initializes this to zero and the libc should do
Ralf> the same afair.  Did this change?

No, that's correct - but I don't get a zero.

Ralf> I tried your program on a Indy running 2.4.0-test2 + glibc 2.2 and it was
Ralf> printing ``0 0''.

Did you try it with a shared program?  Static programs always
initialize the FPU.  Could you run the program on other machines also?

Ralf> Could you check the source of your kernel for the value it's writing to
Ralf> fcr31?  That's the constant FPU_DEFAULT defined in arch/mips/kernel/
Ralf> r4k_switch.S.  Some quite old kernel were using a different value but I
Ralf> was actually assuming those versions have already died out.

The kernels I used have 0 as FPU_DEFAULT - but nevertheless the
returned value is wrong.  When is FPU_DEFAULT written to the FPU?

Andreas

---

From: Ralf Baechle <[email-masked]>
Date: Wed, 5 Jul 2000 00:53:25 +0200

On Tue, Jul 04, 2000 at 01:39:04PM +0200, Andreas Jaeger wrote:

> Did you try it with a shared program?

Yes.

> Static programs always initialize the FPU.  Could you run the program on
> other machines also?

Will do.

> returned value is wrong.  When is FPU_DEFAULT written to the FPU?

We do lazy fp context switching.  So the kernel initializes the FPU for a
process at the moment when it attempts to use it for the first time.  It
does so by enabling the FPU in the status register, clearing all flags in
$fcr31 and setting all fp registers to a SNAN.

  Ralf

---

From: Ralf Baechle <[email-masked]>
Date: Wed, 5 Jul 2000 03:13:18 +0200

Looking at the fcr31 bug I found some other bug which probably isn't causing
what you observe but is a bug anyway - fpu_control_t was a 16-bit type
but should be a 32-bit type.  Patch below.

Is _FPU_IEEE used at all and is it's definition right?

I asked more people to run your test program.  The result is that glibc
2.0.6 (both shared and static tried) and 2.2 print ``0 0'' while glibc
2.0.7 prints a non-zero value.

Can you check if the variable __fpu_control, is it's value non-zero?

  Ralf

2000-07-05  Ralf Baechle  <[email-masked]>

	* sysdeps/mips/fpu_control.h: Make fpu_control_t a 32-bit type.

--- libc/sysdeps/mips/fpu_control.h.orig	Wed Jul  5 02:51:54 2000
+++ libc/sysdeps/mips/fpu_control.h	Wed Jul  5 02:52:58 2000
@@ -1,5 +1,5 @@
 /* FPU control word bits.  Mips version.
-   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Olaf Flebbe and Ralf Baechle.
 
@@ -86,10 +86,10 @@
 #define _FPU_IEEE     0x00000F80
 
 /* Type of the control word.  */
-typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
+typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
 
 /* Macros for accessing the hardware control word.  */
-#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw) : )
+#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw))
 #define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw))
 
 /* Default control word set at startup.  */

---

From: Andreas Jaeger <[email-masked]>
Date: 05 Jul 2000 17:39:55 +0200

>>>>> Ralf Baechle writes:

Ralf> Looking at the fcr31 bug I found some other bug which probably isn't causing
Ralf> what you observe but is a bug anyway - fpu_control_t was a 16-bit type
Ralf> but should be a 32-bit type.  Patch below.
Thanks, I've commited it.

Ralf> Is _FPU_IEEE used at all and is it's definition right?
It's nowhere used - but each architecture has it.  The value looks fine.

Ralf> I asked more people to run your test program.  The result is that glibc
Ralf> 2.0.6 (both shared and static tried) and 2.2 print ``0 0'' while glibc
Ralf> 2.0.7 prints a non-zero value.

OK, I'll investigate the kernels and glibc I'm running a bit more.

Thanks,
Andreas