Patches to add i387 support to Solaris x86 platforms

Peter.Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
Thu Feb 24 00:45:00 GMT 2000


The following patches add i387 support for Solaris x86 platforms and
fix the extraction of long long return values from functions (although I
think that this should be moved to tm-i386.h, see comment in patch).

The i386-tdep.c change follows the line of Mark's recent suggestion to always
assume that floating point results are returned in FP0_REGNUM if
HAVE_I387_REGS is defined.
I tried to keep the i386v4-nat.c changes generic, so that other x86
procfs platforms (Unixware, NCR) should be able to add i387 support without
much trouble.

The testsuite/default.exp patch now handles x86 targets with and without
i387 support, as I doubt that every x86 target has to support i387 as well.

The patches are relative to CVS from last week, they get rid of the following
testsuite fails and cause no regressions:

FAIL: gdb.base/callfuncs.exp: call inferior func with struct - returns float
FAIL: gdb.base/callfuncs.exp: call inferior func with struct - returns double
FAIL: gdb.base/callfwmall.exp: call inferior func with struct - returns float
FAIL: gdb.base/callfwmall.exp: call inferior func with struct - returns double
FAIL: gdb.base/varargs.exp: print find_max_double(5,1.0,17.0,2.0,3.0,4.0)


2000-02-23  Peter Schauer  <pes@regent.e-technik.tu-muenchen.de>

	Add floating point support for Solaris x86.
	* config/i386/tm-i386sol2.h (HAVE_I387_REGS):  Define.
	* i386-tdep.c (i386_extract_return_value):  Extract floating point
	return value from FP0_REGNUM if HAVE_I387_REGS is defined, not only
	for I386_GNULINUX_TARGET. Get rid of obsolete FPDATA_REGNUM
	reference.
	* i386v4-nat.c (supply_fpregset, fill_fpregset):  Add code
	to handle floating point registers for the HAVE_I387_REGS case.

	* config/i386/tm-i386sol2.h (LOW_RETURN_REGNUM, HIGH_RETURN_REGNUM):
	Define for correct extraction of long long return values from
	function calls.

2000-02-23  Peter Schauer  <pes@regent.e-technik.tu-muenchen.de>

	gdb.base/default.exp (info float):  Allow the absence of i387
	support for x86 targets.

*** ./gdb/config/i386/tm-i386sol2.h.orig	Tue Jan 11 04:07:28 2000
--- ./gdb/config/i386/tm-i386sol2.h	Mon Feb 21 09:51:36 2000
***************
*** 21,28 ****
--- 21,34 ----
  #ifndef TM_I386SOL2_H
  #define TM_I386SOL2_H 1
  
+ #define HAVE_I387_REGS
  #include "i386/tm-i386v4.h"
  
+ /* Define eax/edx as return registers for long long return values. */
+ /* FIXME: Maybe this should be moved to tm-i386.h, as it is pretty generic. */
+ #define LOW_RETURN_REGNUM 0	/* Holds low four bytes of result */
+ #define HIGH_RETURN_REGNUM 2	/* Holds high four bytes of result */
+ 
  /* Signal handler frames under Solaris 2 are recognized by a return address
     of 0xFFFFFFFF, the third parameter on the signal handler stack is
     a pointer to an ucontext.  */
*** ./gdb/i386-tdep.c.orig	Tue Oct 19 04:46:36 1999
--- ./gdb/i386-tdep.c	Sat Feb 19 20:10:27 2000
***************
*** 702,726 ****
       char regbuf[REGISTER_BYTES];
       char *valbuf;
  {
!   /* On AIX and i386 GNU/Linux, floating point values are returned in
       floating point registers.  */
! #if defined(I386_AIX_TARGET) || defined(I386_GNULINUX_TARGET)
    if (TYPE_CODE_FLT == TYPE_CODE (type))
      {
        double d;
        /* 387 %st(0), gcc uses this */
        floatformat_to_double (&floatformat_i387_ext,
- #if defined(FPDATA_REGNUM)
- 			     &regbuf[REGISTER_BYTE (FPDATA_REGNUM)],
- #else /* !FPDATA_REGNUM */
  			     &regbuf[REGISTER_BYTE (FP0_REGNUM)],
- #endif /* FPDATA_REGNUM */
- 
  			     &d);
        store_floating (valbuf, TYPE_LENGTH (type), d);
      }
    else
! #endif /* I386_AIX_TARGET || I386_GNULINUX_TARGET*/
      {
  #if defined(LOW_RETURN_REGNUM)
        int len = TYPE_LENGTH (type);
--- 702,721 ----
       char regbuf[REGISTER_BYTES];
       char *valbuf;
  {
!   /* If we have i387 registers, floating point values are returned in
       floating point registers.  */
! #if defined(I386_AIX_TARGET) || defined(HAVE_I387_REGS)
    if (TYPE_CODE_FLT == TYPE_CODE (type))
      {
        double d;
        /* 387 %st(0), gcc uses this */
        floatformat_to_double (&floatformat_i387_ext,
  			     &regbuf[REGISTER_BYTE (FP0_REGNUM)],
  			     &d);
        store_floating (valbuf, TYPE_LENGTH (type), d);
      }
    else
! #endif /* I386_AIX_TARGET || HAVE_I387_REGS */
      {
  #if defined(LOW_RETURN_REGNUM)
        int len = TYPE_LENGTH (type);
*** ./gdb/i386v4-nat.c.orig	Wed Jul  7 22:07:05 1999
--- ./gdb/i386v4-nat.c	Sun Feb 20 18:52:36 2000
***************
*** 148,158 ****
     (fpregset_t *), unpack the register contents and supply them as gdb's
     idea of the current floating point register values. */
  
  void
  supply_fpregset (fpregsetp)
       fpregset_t *fpregsetp;
  {
!   /* FIXME: see m68k-tdep.c for an example, for the m68k. */
  }
  
  /*  Given a pointer to a floating point register set in /proc format
--- 148,206 ----
     (fpregset_t *), unpack the register contents and supply them as gdb's
     idea of the current floating point register values. */
  
+ /* FIXME: Assumes that fpregsetp contains an i387 FSAVE area. */
+ static const int freg_offset_map[] =
+ {
+ #if !defined(FPREGSET_FSAVE_OFFSET)
+ #define FPREGSET_FSAVE_OFFSET	0
+ #endif
+   FPREGSET_FSAVE_OFFSET + 28 + 0 * 10,
+   FPREGSET_FSAVE_OFFSET + 28 + 1 * 10,
+   FPREGSET_FSAVE_OFFSET + 28 + 2 * 10,
+   FPREGSET_FSAVE_OFFSET + 28 + 3 * 10,
+   FPREGSET_FSAVE_OFFSET + 28 + 4 * 10,
+   FPREGSET_FSAVE_OFFSET + 28 + 5 * 10,
+   FPREGSET_FSAVE_OFFSET + 28 + 6 * 10,
+   FPREGSET_FSAVE_OFFSET + 28 + 7 * 10,
+   FPREGSET_FSAVE_OFFSET + 0,
+   FPREGSET_FSAVE_OFFSET + 4,
+   FPREGSET_FSAVE_OFFSET + 8,
+   FPREGSET_FSAVE_OFFSET + 16,
+   FPREGSET_FSAVE_OFFSET + 12,
+   FPREGSET_FSAVE_OFFSET + 24,
+   FPREGSET_FSAVE_OFFSET + 20,
+   FPREGSET_FSAVE_OFFSET + 16
+ };
+ 
  void
  supply_fpregset (fpregsetp)
       fpregset_t *fpregsetp;
  {
! #if defined(HAVE_I387_REGS)
!   int regi;
!   
!   for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++)
!     {
!       char tbuf[4];
!       ULONGEST tval;
!       char *from = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM];
! 
!       if (regi == FCS_REGNUM)
! 	{
! 	  tval = extract_unsigned_integer (from, 4) & 0xffff;
! 	  store_unsigned_integer (tbuf, 4, tval);
! 	  supply_register (regi, tbuf);
! 	}
!       else if (regi == FOP_REGNUM)
! 	{
! 	  tval = (extract_unsigned_integer (from, 4) >> 16) & ((1 << 11) - 1);
! 	  store_unsigned_integer (tbuf, 4, tval);
! 	  supply_register (regi, tbuf);
! 	}
!       else
! 	supply_register (regi, from);
!     }
! #endif
  }
  
  /*  Given a pointer to a floating point register set in /proc format
***************
*** 165,171 ****
       fpregset_t *fpregsetp;
       int regno;
  {
!   /* FIXME: see m68k-tdep.c for an example, for the m68k. */
  }
  
  #endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */
--- 213,251 ----
       fpregset_t *fpregsetp;
       int regno;
  {
! #if defined(HAVE_I387_REGS)
!   int regi;
! 
!   for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++)
!     {
!       if ((regno == -1) || (regno == regi))
! 	{
! 	  char *to = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM];
! 	  char *from = (char *) &registers[REGISTER_BYTE (regi)];
! 	  ULONGEST valto;
! 	  ULONGEST valfrom;
! 
! 	  if (regi == FCS_REGNUM)
! 	    {
! 	      valto = extract_unsigned_integer (to, 4);
! 	      valfrom = extract_unsigned_integer (from, 4);
! 	      valto = (valto & ~0xffff) | (valfrom & 0xffff);
! 	      store_unsigned_integer (to, 4, valto);
! 	    }
! 	  else if (regi == FOP_REGNUM)
! 	    {
! 	      valto = extract_unsigned_integer (to, 4);
! 	      valfrom = extract_unsigned_integer (from, 4);
! 	      valto = (valto & 0xffff) | ((valfrom & ((1 << 11) - 1)) << 16);
! 	      store_unsigned_integer (to, 4, valto);
! 	    }
! 	  else
! 	    {
! 	      memcpy (to, from, REGISTER_RAW_SIZE (regi));
! 	    }
! 	}
!     }
! #endif
  }
  
  #endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */

*** ./gdb/testsuite/gdb.base/default.exp.orig	Tue Jan 18 01:54:37 2000
--- ./gdb/testsuite/gdb.base/default.exp	Mon Feb 21 08:10:00 2000
***************
*** 304,311 ****
      gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
  } elseif [istarget "strongarm*-*-*"] then {
      gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
! } elseif [istarget "i\[3456\]86-*-*"] then {
!     gdb_test "info float" "R7:.*Status Word:.*Opcode:.*" "info float"
  } else {
      gdb_test "info float" "No floating point info available for this processor." "info float"
  }
--- 304,311 ----
      gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
  } elseif [istarget "strongarm*-*-*"] then {
      gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
! } elseif [istarget "i*86-*-*"] then {
!     gdb_test "info float" "R7:.*Status Word:.*Opcode:.*|No floating point info available for this processor." "info float"
  } else {
      gdb_test "info float" "No floating point info available for this processor." "info float"
  }

-- 
Peter Schauer			pes@regent.e-technik.tu-muenchen.de


More information about the Gdb-patches mailing list