This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] pa-RISC correct conversion (long double -> unsigned int)


The PA port of GCC does not handle the conversion of TFmode (16-byte
double) to unsigned SImode. This presents a problem with some code in
GDB because the code in GDB attempt to ensure that the FP number is
between 2^31 and 2^32 in value.  This is too large to fit in a signed
32-bit quantity, but will fit in an unsigned 32-bit quantity. The
attached program x3.c demonstrates the problem.  When executed the x3.c
program will get an error in the library. The HP library doesn't have a
16-byte double to unsigned 32-bit quantity conversion, and a function
had to be written to handle this correctly in gcc.

The patch is attached to this mail and below is the change log.  The
patch was tested with the current version of fsf and corrected the
problem.  Is it okay to apply this patch?

2001-02-11  Will Cohen  <wcohen@redhat.com>

	* config/pa/quadlib.c (_U_Qfcnvfxt_quad_to_usgl): New function.
	* config/pa/long_double.h (FIXUNS_TRUNCTFSI2_LIBCALL): Added.
	(INIT_TARGET_OPTABS): Use FIXUNS_TRUNCTFSI2_LIBCALL for
	fixunstfsi_libfunc.


-Will


/*
 * This test program boils down a sequence of operations that happen
 * in floatformat_from_doublest when converting the value "1.1" in
 * long double (16-byte) format to some target.
 *
 * I am seeing a bug where the mant_long assignment throws SIGFPE.
 */

#include <stdio.h>

long double dfrom = 1.1;
long double m1;
long double m2;
unsigned long mant_long;

int main( )
{
  /* Simulate frexp */
  m1 = dfrom / 2.0;

  m2 = m1 * 4294967296.0;
  mant_long = ((unsigned long) m2) & 0xffffffff;

  /* The correct value here is 0x8ccccccc.  */
  printf( "%x\n", mant_long );
  return 0;
}
Index: long_double.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/pa/long_double.h,v
retrieving revision 1.3
diff -c -2 -p -r1.3 long_double.h
*** long_double.h	2000/05/01 17:30:35	1.3
--- long_double.h	2001/02/12 20:48:46
*************** do { long value[4];                     
*** 53,56 ****
--- 53,57 ----
  #define FIX_TRUNCTFSI2_LIBCALL \
    (TARGET_64BIT ? "__U_Qfcnvfxt_quad_to_sgl" : "_U_Qfcnvfxt_quad_to_sgl")
+ #define FIXUNS_TRUNCTFSI2_LIBCALL "_U_Qfcnvfxt_quad_to_usgl"
  #define FIX_TRUNCTFDI2_LIBCALL "_U_Qfcnvfxt_quad_to_dbl"
  #define EQTF2_LIBCALL "_U_Qfeq"
*************** do { long value[4];                     
*** 90,94 ****
      fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL);\
      fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);\
!     fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL);  \
      fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);  \
      eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EQTF2_LIBCALL);		\
--- 91,95 ----
      fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL);\
      fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);\
!     fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFSI2_LIBCALL);\
      fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);  \
      eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EQTF2_LIBCALL);		\
Index: quadlib.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/pa/quadlib.c,v
retrieving revision 1.2
diff -c -2 -p -r1.2 quadlib.c
*** quadlib.c	2000/05/15 23:14:16	1.2
--- quadlib.c	2001/02/12 20:48:46
*************** __U_Qfcnvfxt_quad_to_sgl (long double a)
*** 93,94 ****
--- 93,102 ----
  }
  #endif
+ 
+ /* HP only has signed conversion in library, so need to synthesize an
+    unsigned version */
+ unsigned int
+ _U_Qfcnvfxt_quad_to_usgl(long double a)
+ {
+   return (unsigned int) _U_Qfcnvfxt_quad_to_dbl (a);
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]