cross-compiled floating point constants broken

Jim Wilson wilson@cygnus.com
Wed Feb 10 17:35:00 GMT 1999


I noticed two more problems with my earlier real.c sign-extension change,
besides the fact that it broke alpha-x-m68k and many other 64b-x-32b crosses.
I confused WIDE_INT and long, and I was doing out-of-bounds array accesses.
The real.c change clearly has to be backed out.

In order to get alpha-x-m32r working again, I added sign-extension code
to split_double in final.c and operand_subword in emit-rtl.c, and modified
m32r.md to call operand_subword instead of calling REAL_VALUE_TO_TARGET_SINGLE.

	If you are saying, for example, that this code from m68k.c fails
	because of the GEN_INT, then I believe that is not so.
	...
	The results of this program fragment are used only for printing in
	hex, so they must _not_ be sign extended.

You are right, the code doesn't fail.  However, it isn't because the values
are printed in hex.  The rtx created here are eventually passed to
print_operand, which prints CONST_INTs in decimal by default.  But it does
work because the assembler will read the non-sign-extended decimal values
correctly.

This is an important point that I got wrong.  And it means my list of
files that fail without sign-extension is wrong.  There are still a number
of problems, just not as many as I thought there were.

Two problems I pointed out in machine independent files need to be fixed
in order to get the alpha-x-m32r working, but I'll leave the rest of the
stuff alone unless someone first proves that they are wrong to reduce the
risk of accidentally breaking something else again.

I've checked this in.  I've tested this with alpha-x-m32r-elf, alpha-x-m68k-elf
and native irix6 builds.

Wed Feb 10 17:12:21 1999  Jim Wilson  <wilson@cygnus.com>

	* emit-rtl.c (operand_subword): Sign extend REAL_VALUE_TO_TARGET_SINGLE
	result.
	* final.c (split_double): Sign extend REAL_VALUE_TO_TARGET_DOUBLE
	result.
	* real.c (endian): Delete sign extension code.
	* config/m32r/m32r.md (movsf_insn+1): REAL_VALUE_TO_TARGET_SINGLE call
	replaced with operand_subword call.

Index: emit-rtl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/emit-rtl.c,v
retrieving revision 1.51
diff -p -r1.51 emit-rtl.c
*** emit-rtl.c	1999/01/29 15:25:17	1.51
--- emit-rtl.c	1999/02/11 01:13:44
*************** operand_subword (op, i, validate_address
*** 1303,1308 ****
--- 1303,1320 ----
        REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
        REAL_VALUE_TO_TARGET_SINGLE (rv, l);
  
+       /* If 32 bits is an entire word for the target, but not for the host,
+ 	 then sign-extend on the host so that the number will look the same
+ 	 way on the host that it would on the target.  See for instance
+ 	 simplify_unary_operation.  The #if is needed to avoid compiler
+ 	 warnings.  */
+ 
+ #if HOST_BITS_PER_LONG > 32
+       if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32
+ 	  && (l & ((long) 1 << 31)))
+ 	l |= ((long) (-1) << 32);
+ #endif
+ 
        if (BITS_PER_WORD == 16)
  	{
  	  if ((i & 0x1) == !WORDS_BIG_ENDIAN)
Index: final.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/final.c,v
retrieving revision 1.72
diff -p -r1.72 final.c
*** final.c	1999/01/27 01:42:14	1.72
--- final.c	1999/02/11 01:13:44
*************** split_double (value, first, second)
*** 3929,3934 ****
--- 3929,3950 ----
  	 not necessarily BITS_PER_WORD bits.  */
        REAL_VALUE_TO_TARGET_DOUBLE (r, l);
  
+       /* If 32 bits is an entire word for the target, but not for the host,
+ 	 then sign-extend on the host so that the number will look the same
+ 	 way on the host that it would on the target.  See for instance
+ 	 simplify_unary_operation.  The #if is needed to avoid compiler
+ 	 warnings.  */
+ 
+ #if HOST_BITS_PER_LONG > 32
+       if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32)
+ 	{
+ 	  if (l[0] & ((long) 1 << 31))
+ 	    l[0] |= ((long) (-1) << 32);
+ 	  if (l[1] & ((long) 1 << 31))
+ 	    l[1] |= ((long) (-1) << 32);
+ 	}
+ #endif
+ 
        *first = GEN_INT ((HOST_WIDE_INT) l[0]);
        *second = GEN_INT ((HOST_WIDE_INT) l[1]);
  #else
Index: real.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/real.c,v
retrieving revision 1.23
diff -p -r1.23 real.c
*** real.c	1999/02/08 11:40:32	1.23
--- real.c	1999/02/11 01:13:46
*************** endian (e, x, mode)
*** 558,580 ****
  	  abort ();
  	}
      }
- 
-   /* If 32 bits is an entire word for the target, but not for the host,
-      then sign-extend on the host so that the number will look the same
-      way on the host that it would on the target.  See for instance
-      simplify_unary_operation.  The #if is needed to avoid compiler
-      warnings.  */
- 
- #if HOST_BITS_PER_WIDE_INT > 32
-   if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == 32)
-     {
-       if (x[0] & ((HOST_WIDE_INT) 1 << 31))
- 	x[0] |= ((HOST_WIDE_INT) (-1) << 32);
- 
-       if (x[1] & ((HOST_WIDE_INT) 1 << 31))
- 	x[1] |= ((HOST_WIDE_INT) (-1) << 32);
-     }
- #endif
  }
  
  
--- 558,563 ----
Index: config/m32r/m32r.md
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/m32r/m32r.md,v
retrieving revision 1.13
diff -p -r1.13 m32r.md
*** m32r.md	1998/12/16 21:06:04	1.13
--- m32r.md	1999/02/11 01:13:47
***************
*** 589,602 ****
    [(set (match_dup 2) (match_dup 3))]
    "
  {
-   long l;
-   REAL_VALUE_TYPE rv;
- 
-   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-   REAL_VALUE_TO_TARGET_SINGLE (rv, l);
- 
    operands[2] = operand_subword (operands[0], 0, 0, SFmode);
!   operands[3] = GEN_INT (l);
  }")
  
  (define_expand "movdf"
--- 589,596 ----
    [(set (match_dup 2) (match_dup 3))]
    "
  {
    operands[2] = operand_subword (operands[0], 0, 0, SFmode);
!   operands[3] = operand_subword (operands[1], 0, 0, SFmode);
  }")
  
  (define_expand "movdf"


More information about the Gcc-patches mailing list