Bug 7001

Summary: setjmp/longjmp do not save/restore correct FPU registers in N32 ABI mode
Product: glibc Reporter: Nicolas S. Dade <n-redhat-glibc>
Component: portsAssignee: Roland McGrath <roland>
Status: RESOLVED INVALID    
Severity: normal CC: glibc-bugs
Priority: P2 Flags: fweimer: security-
Version: 2.8   
Target Milestone: ---   
Host: mips64-unknown-linux-gnu Target:
Build: i686-unknown-linux-gnu Last reconfirmed:

Description Nicolas S. Dade 2008-11-01 10:10:09 UTC
In the files

  glibc/ports/sysdeps/mips/mips64/setjmp_aux.c
  glibc/ports/sysdeps/mips/mips64/__longjmp.c

the innermost #if checks look like this:

  #if _MIPS_SIM == _ABI64
     [ save/restore f24, f25, ... f31 ]
  #else
     [ save/restore f20,, f22, ... f30 ] (Even registers only b/c on 32-bit CPUs
the registers are paired even/odd to hold double precision FP numbers)
  #endif

Thus in _ABIN32 (64-bit CPU using 32-bit pointers) the 32-bit CPU code is
selected, which fails to save or restore any odd numbered registers. The N32 ABI
defines f24-f31 as callee-saved, same as _ABI64 does.

One fix would be to change the tests from

-  #if _MIPS_SIM == _ABI64
+  #if _MIPS_SIM != _ABIO32

This is present in at least glibc-ports-2.7 (where we discovered it), 2.8 and in
CVS HEAD.


-Nicolas Dade
Comment 1 Joseph Myers 2010-03-23 14:47:41 UTC
My copy of the MIPSpro(TM) N32 ABI Handbook says "There are eight callee-saved
floating point registers, $f24..$f31 for the 64-bit interface. There are six for
the n32 ABI, the six even registers in $f20..$f30.".  This agrees with glibc and
GCC.