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: Regression Failure: rbug.c, x86


-- 

===================================================
Donn Terry                  mailto:donn@interix.com
Softway Systems, Inc.        http://www.interix.com
2850 McClelland Dr, Ste. 1800   Ft.Collins CO 80525
Tel: +1-970-204-9900           Fax: +1-970-204-9951
===================================================
Regression Failure: rbug.c, x86

Problem: 
rbug.c fails on some x86 configurations, because conversions get mangled
by various floating precision problems.

Fix:
1) Add more testcases to rbug.c that exercise additional corner cases.
2) Change to use library routines to make the conversions.  (The
   library, being hand-optimized assembler, is likely faster than
   the current version that calls a function anyway.)
3) Run certain values thru memory to assure that the expected rounded
   value is in a register.

There are various aspects to this with varying degrees of optionality.

1)  New library conversions are introduced so the DI conversions are
(optionally, per configuration) done in a library.  x86 verisons of
those library routines are provided that work in both 53 bit mantissa
and 64 bit mantissa mode.  (64 and 80 bit floats.)

A macro is provided so that specific conversions can be redirected
to functions.  If the processor is known to always be in 80 bit mode,
this need not be defined.  (The functions are comparable to the current 
code, so can always be safely used if there's a chance of 53 bit mode
being used.)

2)  A new command line option is provided to take care of a few places
where inline code is currently generated that doesn't work correctly in 
53 bit mode.  The resulting code is enough worse that an option should be 
used.  (If anyone knows of a way to force a *round* to 53 bit mantissa other
than storing to memory, I'd be more than happy to use it; the option
would probably then not be necessary.  However, long hours staring
at the Ref Man have come up empty.)


Note that I've added a number of additional cases to rbug.c.  This
passes regression on Interix in 53-bit mode, and by tweaking rbug.c
to cause that, in 80 bit mode as well.

No new regressions introduced in the full gcc regression 
(including extended rbug.c) on:
  Intel
  Intel with __main tweaked to yield 64 bit mantissa (80 bit float) mode.
  Alpha 32.
This code has also had about 18 months exposure testing on Interix,
with no problems reported.

ChangeLog (gcc):

Tue May 18 10:45:23 1999  Donn Terry (donn@interix.com)

	* config/i386/i386.h (MASK_53BIT_SUPPORT): Define
	(TARGET_53BIT_SUPPORT): Define.  (target_flags): Add corresponding
	flags.
	* config/i386/i386-interix.h (TARGET_DEFAULT): Add MASK_53BIT_SUPPORT.
        (FORCE_LIBRARY_CONVERT_P): Define.
	* config/i386/i386.md:  New insns conditional on TARGET_53BIT_SUPPORT.
        * config/i386/t-interix (LIB2FUNCS_EXTRA): Define.
	* optabs.c (floatunssisf_libfunc,floatunsdisf_libfunc,
	floatunstisf_libfunc,floatunssidf_libfunc,floatunsdidf_libfunc,
	floatunstidf_libfunc,floatunssixf_libfunc,floatunsdixf_libfunc,
	floatunstixf_libfunc):  Declare. (expand_float): Use 
	FORCE_LIBRARY_CONVERT_P, gen calls to new libfuncs.  
	(init_optabs): initialize new libfuncs.
	* config/i386/float.asm: new file with actual functions.

ChangeLog (testsuite):
	* execute/ieee/rbug.c (main): Several more corner cases.


!!!!!!!!!!!!!!!!!!!! NOTE NOTE NOTE NOTE NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
The library additions have only been applied to Interix, and the command
line option defaults to off except for Interix.  Other configurations
may wish to enable this code individually.
!!!!!!!!!!!!!!!!!!!! NOTE NOTE NOTE NOTE NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


diff -drupP egcs.orig/gcc/config/i386/float.asm egcs/gcc/config/i386/float.asm
--- egcs.orig/gcc/config/i386/float.asm	Wed Dec 31 17:00:00 1969
+++ egcs/gcc/config/i386/float.asm	Sat May 15 21:34:42 1999
@@ -0,0 +1,137 @@
+/* Convert unsigned DI to float.  This routine exists because NT sets the 
+   floating point precision to 2 (53 bit mantissa) rather than to 3 (64 bit
+   mantissa).  (This is for some reason associated with backwards
+   compatability).  However, to get proper rounding of certain
+   double integers, the computation needs to be carried out in 64
+   bit mantissa mode.  We change and restore the precision to
+   perform the conversion.  (It's the add of 2^64 that's the problem;
+   all other operations are done in the size specified by the
+   instruction, but the add is done in the precision set in the
+   control word, and low order bits that would participate in
+   rounding the value correctly are discarded before they get their
+   chance.)
+
+   We need to force a round to the required precision before returning,
+   because if the value is taken directly from the register in subsequent
+   code (with a smaller precision), it will have the low order bits we so
+   carefully preserved truncated (discarded) rather than rounded according
+   to the current rounding mode.
+
+   Given the code previously generated in line (which entails a function
+   call anyway) this is actually fewer instructions executed than inline.
+   (In principle, this code could be inlined, but there are limits!) 
+   (Regression ieee/rbug.c (and others) test this; it must pass all.) */
+   
+.section	.rdata,"x"
+	.align 2
+LC1:
+	.long 0x0,0x80000000,0x403f  /* 2^64 as a float. */
+.text
+
+	.global	___floatunsdidf
+___floatunsdidf:
+	pushl %ebp
+	movl %esp,%ebp
+	subl $8,%esp			/* temp for ctl words, then DF */
+	fstcw 2(%esp) 			/* make 2 copies of current ctl wrd */
+	fstcw 0(%esp) 
+	orw $0x300,0(%esp)		/* set one to pmode of 3 (64 bit) */
+	fldcw 0(%esp)			/* and load it */
+	fildq 8(%ebp)			/* load the value to be converted */
+	ftst				/*   as signed, and check the sign */
+	fnstsw %ax
+	andb $69,%ah
+	cmpb $1,%ah
+	jne L12
+	fldt LC1			/* add 2^64 if it was negative */
+	faddp %st(1)
+L12:
+	fldcw 2(%esp)
+	fstpl 0(%esp)			/* force a round to DF (via mem) */
+	fldl 0(%esp)
+
+	movl %ebp,%esp
+	popl %ebp
+	ret
+
+/* see comments above */
+
+	.global	___floatunsdisf
+___floatunsdisf:
+	pushl %ebp
+	movl %esp,%ebp
+	subl $4,%esp			/* temp for ctl wrd, then SF */
+	fstcw 2(%esp) 
+	fstcw 0(%esp) 
+	orw $0x300,0(%esp)
+	fldcw 0(%esp)
+	fildq 8(%ebp)
+	ftst
+	fnstsw %ax
+	andb $69,%ah
+	cmpb $1,%ah
+	jne L10
+	fldt LC1
+	faddp %st(1)
+L10:
+	fldcw 2(%esp)
+	fstps 0(%esp)			/* force a round to SF */
+	flds 0(%esp)
+
+	movl %ebp,%esp
+	popl %ebp
+	ret
+
+	.global	___floatunsdixf
+___floatunsdixf:
+	pushl %ebp
+	movl %esp,%ebp
+	subl $8,%esp
+	fstcw 2(%esp) 
+	fstcw 0(%esp) 
+	orw $0x300,0(%esp)
+	fldcw 0(%esp)
+	fildq 8(%ebp)
+	ftst
+	fnstsw %ax
+	andb $69,%ah
+	cmpb $1,%ah
+	jne L11
+	fldt LC1
+	faddp %st(1)
+L11:
+	fldcw 2(%esp)
+	/* no need to round these */
+
+	movl %ebp,%esp
+	popl %ebp
+	ret
+
+#if defined(L_floatunsditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
+/* This can't happen(?), but for completeness sake... */
+
+	.global	___floatunsditf
+___floatunsditf:
+	pushl %ebp
+	movl %esp,%ebp
+	subl $8,%esp
+	fstcw 2(%esp) 
+	fstcw 0(%esp) 
+	orw $0x300,0(%esp)
+	fldcw 0(%esp)
+	fildq 8(%ebp)
+	ftst
+	fnstsw %ax
+	andb $69,%ah
+	cmpb $1,%ah
+	jne L9
+	fldt LC1
+	faddp %st(1)
+L9:
+	fldcw 2(%esp)
+	/* no need to round these */
+
+	movl %ebp,%esp
+	popl %ebp
+	ret
+#endif
diff -drupP egcs.orig/gcc/config/i386/i386-interix.h egcs/gcc/config/i386/i386-interix.h
--- egcs.orig/gcc/config/i386/i386-interix.h	Fri May 14 16:22:38 1999
+++ egcs/gcc/config/i386/i386-interix.h	Mon May 17 13:19:59 1999
@@ -43,7 +43,7 @@ Boston, MA 02111-1307, USA.  */
 #undef TARGET_DEFAULT
 #define TARGET_DEFAULT \
    (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE | \
-    MASK_ALIGN_DOUBLE)
+    MASK_ALIGN_DOUBLE | MASK_53BIT_SUPPORT)
 
 #undef TARGET_CPU_DEFAULT
 #define TARGET_CPU_DEFAULT 2 /* 486 */
@@ -496,6 +496,13 @@ do {									\
     (VAR) = _name;							\
 } while (0)
       
+/* Define this if some unsigned fixed->float conversions that would normally
+   be done by converting signed and a fixup need a library call instead;
+   Signed cases don't ever get here, so don't test for that. */
+  
+#define FORCE_LIBRARY_CONVERT_P(FROM, TO)                              \
+     (GET_MODE(FROM)==DImode || GET_MODE(FROM)==TImode)
+  
 #if 0	
 /* Turn this back on when the linker is updated to handle grouped
    .data$ sections correctly. See corresponding note in i386/interix.c. 
diff -drupP egcs.orig/gcc/config/i386/i386.h egcs/gcc/config/i386/i386.h
--- egcs/egcs.orig/gcc/config/i386/i386.h	Fri May 14 16:22:39 1999
+++ egcs/gcc/config/i386/i386.h	Mon May 17 12:50:10 1999
@@ -79,7 +79,7 @@ extern int target_flags;
 
 /* Masks for the -m switches */
 #define MASK_80387		000000000001	/* Hardware floating point */
-#define MASK_NOTUSED1		000000000002	/* bit not currently used */
+#define MASK_53BIT_SUPPORT	000000000002	/* Support 53 bit mantissa */
 #define MASK_NOTUSED2		000000000004	/* bit not currently used */
 #define MASK_RTD		000000000010	/* Use ret that pops args */
 #define MASK_ALIGN_DOUBLE	000000000020	/* align doubles to 2 word boundary */
@@ -100,6 +100,11 @@ extern int target_flags;
 /* Use the floating point instructions */
 #define TARGET_80387 (target_flags & MASK_80387)
 
+/* When converting 64 bit integers to float, be sure all bits participate
+   (at least via rounding).  Only a problem when FPU is in 53-bit 
+   (or less) mantissa mode. */
+#define TARGET_53BIT_SUPPORT (target_flags & MASK_53BIT_SUPPORT)
+
 /* Compile using ret insn that pops args.
    This will not work unless you use prototypes at least
    for all functions that can take varying numbers of args.  */  
@@ -212,6 +217,8 @@ extern const int x86_double_with_add;
   { "no-debug-arg",		-MASK_DEBUG_ARG, 0 /* intentionally undoc */ },			\
   { "stack-arg-probe",		 MASK_STACK_PROBE, "Enable stack probing" },			\
   { "no-stack-arg-probe",	-MASK_STACK_PROBE, "" },			\
+  { "53bit-mantissa",		 MASK_53BIT_SUPPORT, "Precise float convert of long long" },			\
+  { "no-53bit-mantissa",	-MASK_53BIT_SUPPORT, "" },			\
   { "windows",			0, 0 /* intentionally undoc */ },					\
   { "dll",			0, 0 /* intentionally undoc */ },					\
   SUBTARGET_SWITCHES							\
diff -drupP egcs.orig/gcc/config/i386/i386.md egcs/gcc/config/i386/i386.md
--- egcs.orig/gcc/config/i386/i386.md	Fri May 14 16:22:39 1999
+++ egcs/gcc/config/i386/i386.md	Mon May 17 11:37:14 1999
@@ -2983,10 +2983,39 @@
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=f")
 	(float:SF (match_operand:DI 1 "memory_operand" "m")))]
-  "TARGET_80387"
+  "TARGET_80387 && !TARGET_53BIT_SUPPORT"
   "* return AS1 (fild%z1,%1);"
   [(set_attr "type" "fpop")])
 
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=f")
+	(float:SF (match_operand:DI 1 "memory_operand" "m")))]
+  "TARGET_80387 && TARGET_53BIT_SUPPORT"
+  "*
+{
+  /* For the DI to SF conversion, we must route the result thru
+     memory before doing anything else to it, to assure it gets
+     rounded properly.  (If FP processor is in 53-bit mode (mode==2),
+     it will truncate if any subsequent arithmentic is done before
+     the round.  NT is in that state.) */
+   rtx xops[4];
+ 
+   xops[0] = AT_SP (Pmode);
+   xops[1] = stack_pointer_rtx;
+   xops[2] = GEN_INT (GET_MODE_SIZE(GET_MODE(operands[0])));
+   xops[3] = operands[1];
+
+   output_asm_insn (AS2 (sub%L1,%2,%1), xops);
+
+   output_asm_insn (AS1 (fild%z3,%3), xops);
+   output_asm_insn (AS1 (fstp%S0,%y0), xops);
+   output_asm_insn (AS1 (fld%S0,%y0), xops);
+
+   output_asm_insn (AS2 (add%L1,%2,%1), xops);
+   RET;
+}"
+  [(set_attr "type" "fpop")])
+
 (define_expand "floatsidf2"
   [(parallel [(set (match_operand:DF 0 "register_operand" "")
 		   (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
@@ -3106,10 +3135,39 @@
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
 	(float:DF (match_operand:DI 1 "memory_operand" "m")))]
-  "TARGET_80387"
+  "TARGET_80387 && !TARGET_53BIT_SUPPORT"
   "* return AS1 (fild%z1,%1);"
   [(set_attr "type" "fpop")])
 
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=f")
+	(float:DF (match_operand:DI 1 "memory_operand" "m")))]
+  "TARGET_80387 && TARGET_53BIT_SUPPORT"
+  "*
+{
+  /* For the DI to DF conversion, we must route the result thru
+     memory before doing anything else to it, to assure it gets
+     rounded properly.  (If FP processor is in 53-bit mode (mode==2),
+     it will truncate if any subsequent arithmentic is done before
+     the round.  NT is in that state.) */
+  rtx xops[4];
+
+  xops[0] = AT_SP (Pmode);
+  xops[1] = stack_pointer_rtx;
+  xops[2] = GEN_INT (GET_MODE_SIZE(GET_MODE(operands[1])));
+  xops[3] = operands[1];
+
+  output_asm_insn (AS2 (sub%L1,%2,%1), xops);
+
+  output_asm_insn (AS1 (fild%z3,%3), xops);
+  output_asm_insn (AS1 (fstp%Q0,%y0), xops);
+  output_asm_insn (AS1 (fld%Q0,%y0), xops);
+
+  output_asm_insn (AS2 (add%L1,%2,%1), xops);
+  RET;
+}"
+  [(set_attr "type" "fpop")])
+
 (define_expand "floatsixf2"
   [(parallel [(set (match_operand:XF 0 "register_operand" "")
 		   (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))
@@ -3226,6 +3284,9 @@
 	(float:XF (match_dup 2)))]
   "")
 
+;; Conversion from DI to XF: if we're not in 64 bit mantissa mode, lots of
+;; other things are not going to work as expected anyway, so we don't 
+;; bother with the fixup.
 (define_insn ""
   [(set (match_operand:XF 0 "register_operand" "=f")
 	(float:XF (match_operand:DI 1 "memory_operand" "m")))]
diff -drupP egcs.orig/gcc/config/i386/t-interix egcs/gcc/config/i386/t-interix
--- egcs.orig/gcc/config/i386/t-interix	Fri May 14 16:22:42 1999
+++ egcs/gcc/config/i386/t-interix	Sat May 15 20:43:54 1999
@@ -5,6 +5,8 @@ CROSS_LIBGCC1 = libgcc1-asm.a
 LIB1ASMSRC = i386/cygwin.asm
 LIB1ASMFUNCS = _chkstk
 
+LIB2FUNCS_EXTRA = $(srcdir)/config/i386/float.asm
+
 interix.o: $(srcdir)/config/i386/interix.c
 	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/interix.c
 
diff -drupP egcs.orig/gcc/optabs.c egcs/gcc/optabs.c
--- egcs.orig/gcc/optabs.c	Fri May 14 16:23:45 1999
+++ egcs/gcc/optabs.c	Fri May 14 16:31:56 1999
@@ -182,6 +182,22 @@ rtx floatsitf_libfunc;
 rtx floatditf_libfunc;
 rtx floattitf_libfunc;
 
+rtx floatunssisf_libfunc;
+rtx floatunsdisf_libfunc;
+rtx floatunstisf_libfunc;
+
+rtx floatunssidf_libfunc;
+rtx floatunsdidf_libfunc;
+rtx floatunstidf_libfunc;
+
+rtx floatunssixf_libfunc;
+rtx floatunsdixf_libfunc;
+rtx floatunstixf_libfunc;
+
+rtx floatunssitf_libfunc;
+rtx floatunsditf_libfunc;
+rtx floatunstitf_libfunc;
+
 rtx fixsfsi_libfunc;
 rtx fixsfdi_libfunc;
 rtx fixsfti_libfunc;
@@ -3608,7 +3624,11 @@ expand_float (to, from, unsignedp)
 
   /* Unsigned integer, and no way to convert directly.
      Convert as signed, then conditionally adjust the result.  */
-  if (unsignedp)
+  if (unsignedp
+#ifdef FORCE_LIBRARY_CONVERT_P
+      && !FORCE_LIBRARY_CONVERT_P(from, to)
+#endif
+    )
     {
       rtx label = gen_label_rtx ();
       rtx temp;
@@ -3723,7 +3743,13 @@ expand_float (to, from, unsignedp)
 #endif
 
   /* No hardware instruction available; call a library routine to convert from
-     SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
+     SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.
+
+     It is possible to get here with an unsigned conversion if for some
+     reason the processor needs a library function for unsigned.  i386
+     does if the processor is not running in precision mode 3 (which
+     is the case on NT, at least).  The lib is probably faster than the
+     above, anyway, and the lib function works for all precisions). */
     {
       rtx libfcn;
       rtx insns;
@@ -3738,52 +3764,104 @@ expand_float (to, from, unsignedp)
       if (flag_force_mem)
 	from = force_not_mem (from);
 
-      if (GET_MODE (to) == SFmode)
-	{
-	  if (GET_MODE (from) == SImode)
-	    libfcn = floatsisf_libfunc;
-	  else if (GET_MODE (from) == DImode)
-	    libfcn = floatdisf_libfunc;
-	  else if (GET_MODE (from) == TImode)
-	    libfcn = floattisf_libfunc;
-	  else
-	    abort ();
-	}
-      else if (GET_MODE (to) == DFmode)
-	{
-	  if (GET_MODE (from) == SImode)
-	    libfcn = floatsidf_libfunc;
-	  else if (GET_MODE (from) == DImode)
-	    libfcn = floatdidf_libfunc;
-	  else if (GET_MODE (from) == TImode)
-	    libfcn = floattidf_libfunc;
-	  else
-	    abort ();
-	}
-      else if (GET_MODE (to) == XFmode)
+      if (unsignedp) 
 	{
-	  if (GET_MODE (from) == SImode)
-	    libfcn = floatsixf_libfunc;
-	  else if (GET_MODE (from) == DImode)
-	    libfcn = floatdixf_libfunc;
-	  else if (GET_MODE (from) == TImode)
-	    libfcn = floattixf_libfunc;
+	  if (GET_MODE (to) == SFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatunssisf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatunsdisf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floatunstisf_libfunc;
+	      else
+		abort ();
+	    }
+	  else if (GET_MODE (to) == DFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatunssidf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatunsdidf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floatunstidf_libfunc;
+	      else
+		abort ();
+	    }
+	  else if (GET_MODE (to) == XFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatunssixf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatunsdixf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floatunstixf_libfunc;
+	      else
+		abort ();
+	    }
+	  else if (GET_MODE (to) == TFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatunssitf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatunsditf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floatunstitf_libfunc;
+	      else
+		abort ();
+	    }
 	  else
 	    abort ();
 	}
-      else if (GET_MODE (to) == TFmode)
+      else
 	{
-	  if (GET_MODE (from) == SImode)
-	    libfcn = floatsitf_libfunc;
-	  else if (GET_MODE (from) == DImode)
-	    libfcn = floatditf_libfunc;
-	  else if (GET_MODE (from) == TImode)
-	    libfcn = floattitf_libfunc;
+	  if (GET_MODE (to) == SFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatsisf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatdisf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floattisf_libfunc;
+	      else
+		abort ();
+	    }
+	  else if (GET_MODE (to) == DFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatsidf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatdidf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floattidf_libfunc;
+	      else
+		abort ();
+	    }
+	  else if (GET_MODE (to) == XFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatsixf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatdixf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floattixf_libfunc;
+	      else
+		abort ();
+	    }
+	  else if (GET_MODE (to) == TFmode)
+	    {
+	      if (GET_MODE (from) == SImode)
+		libfcn = floatsitf_libfunc;
+	      else if (GET_MODE (from) == DImode)
+		libfcn = floatditf_libfunc;
+	      else if (GET_MODE (from) == TImode)
+		libfcn = floattitf_libfunc;
+	      else
+		abort ();
+	    }
 	  else
 	    abort ();
 	}
-      else
-	abort ();
 
       start_sequence ();
 
@@ -3794,7 +3872,9 @@ expand_float (to, from, unsignedp)
       end_sequence ();
 
       emit_libcall_block (insns, target, value,
-			  gen_rtx_FLOAT (GET_MODE (to), from));
+			  unsignedp ? 
+			      gen_rtx_UNSIGNED_FLOAT(GET_MODE (to), from):
+			      gen_rtx_FLOAT (GET_MODE (to), from));
     }
 
  done:
@@ -4426,6 +4506,22 @@ init_optabs ()
   floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf");
   floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf");
   floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf");
+
+  floatunssisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunssisf");
+  floatunsdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunsdisf");
+  floatunstisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunstisf");
+
+  floatunssidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunssidf");
+  floatunsdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunsdidf");
+  floatunstidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunstidf");
+
+  floatunssixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunssixf");
+  floatunsdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunsdixf");
+  floatunstixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunstixf");
+
+  floatunssitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunssitf");
+  floatunsditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunsditf");
+  floatunstitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatunstitf");
 
   fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi");
   fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi");
diff -drupP egcs.orig/gcc/testsuite/gcc.c-torture/execute/ieee/rbug.c egcs/gcc/testsuite/gcc.c-torture/execute/ieee/rbug.c
--- egcs.orig/gcc/testsuite/gcc.c-torture/execute/ieee/rbug.c	Fri May 14 16:21:24 1999
+++ egcs/gcc/testsuite/gcc.c-torture/execute/ieee/rbug.c	Mon May 17 14:35:45 1999
@@ -14,11 +14,35 @@ float s (unsigned long long k)
   return x;
 }
 
+float t (long long k)
+{
+  float x;
+
+  x = (float) k;
+  return x;
+}
+
 main ()
 {
   unsigned long long int k;
+  long long int l;
   double x;
+  float y;
 
+/* The following is for hand-testing only, and on i386 boxes only; set
+   the processor's FP width to either 2 or 3 (64 bit or 80 bit floats). 
+   (Use 200 or 300 in the orw below) */
+#if 0
+   asm(  " subl $4,%%esp\n"
+	 " fstcw 0(%%esp)\n"
+	 " andw $0xfcff,0(%%esp)\n"
+	 " orw $0x300,0(%%esp)\n"
+	 " fldcw 0(%%esp)\n"
+	 " addl $4,%%esp\n"
+	 : 
+	 : 
+	 );
+#endif
   /* CYGNUS LOCAL -- meissner/32bit doubles */
   if (sizeof (double) >= 8)
     {
@@ -30,12 +54,54 @@ main ()
     }
   /* END CYGNUS LOCAL -- meissner/32bit doubles */
 
+  /* unsigned "negatives" */
   k = 0x8234508000000001ULL;
   x = s (k);
   k = (unsigned long long) x;
   if (k != 0x8234510000000000ULL)
     abort ();
 
+  /* signed */
+  l = 0x7134504000000001LL;
+  x = t (l);
+  l = (long long) x;
+  if (l != 0x7134508000000000LL)
+    abort ();
+
+  /* signed, no function involved (optimizer issue) */
+  l = 0x7234504000000001LL;
+  y = (float)l;
+  l = (long long) y;
+  if (l != 0x7234508000000000LL)
+    abort ();
+
+  /* signed, no function involved, subsequent arithmetic.  Will fail
+     at least at -O0 (on i386) if there's a bug. */
+  l = 0x7334504000000001LL;
+  y = (float)l + 0.0;
+  l = (long long) y;
+  if (l != 0x7334508000000000LL)
+    abort ();
+
+  /* Same thing, negative */
+  l = -0x7134504000000001LL;
+  x = t (l);
+  l = (long long) x;
+  if (l != -0x7134508000000000LL)
+    abort ();
+
+  /* negative, signed, no function involved (optimizer issue) */
+  l = -0x7234504000000001LL;
+  y = (float)l;
+  l = (long long) y;
+  if (l != -0x7234508000000000LL)
+    abort ();
+
+  /* negative, signed, no function involved, subsequent arithmetic.  */
+  l = -0x7334504000000001LL;
+  y = (float)l + 0.0;
+  l = (long long) y;
+  if (l != -0x7334508000000000LL)
+    abort ();
   exit (0);
 }
-

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