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]

Re: mn10300 64-bit clean-up


On May 20, 2000, Richard Henderson <rth@cygnus.com> wrote:

> On Sat, May 20, 2000 at 06:42:05PM -0300, Alexandre Oliva wrote:
>> * final.c (split_double): Right shift of negative values is not
>> portable.

> Ok.

>> -	  /* On machines where HOST_BITS_PER_WIDE_INT == BITS_PER_WORD
>> -	     the shift below will cause a compiler warning, even though
>> -	     this code won't be executed.  So put the shift amounts in
>> -	     variables to avoid the warning.  */
> [...]
>> +	  high >>= BITS_PER_WORD - 1;
>> +	  high >>= 1;

> That comment is largely applicable here.

Ok, here's what I've checked in:

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@cygnus.com>

	* final.c (split_double): Right shift of negative values is not
	portable.

Index: gcc/final.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/final.c,v
retrieving revision 1.188
diff -u -r1.188 final.c
--- gcc/final.c	2000/05/15 17:46:34	1.188
+++ gcc/final.c	2000/05/20 22:57:49
@@ -3952,25 +3952,50 @@
 	  /* In this case the CONST_INT holds both target words.
 	     Extract the bits from it into two word-sized pieces.
 	     Sign extend each half to HOST_WIDE_INT.  */
-	  rtx low, high;
-	  /* On machines where HOST_BITS_PER_WIDE_INT == BITS_PER_WORD
-	     the shift below will cause a compiler warning, even though
-	     this code won't be executed.  So put the shift amounts in
-	     variables to avoid the warning.  */
-	  int rshift = HOST_BITS_PER_WIDE_INT - BITS_PER_WORD;
-	  int lshift = HOST_BITS_PER_WIDE_INT - 2 * BITS_PER_WORD;
+	  unsigned HOST_WIDE_INT low, high;
+	  unsigned HOST_WIDE_INT mask, sign_bit, sign_extend;
 
-	  low = GEN_INT ((INTVAL (value) << rshift) >> rshift);
-	  high = GEN_INT ((INTVAL (value) << lshift) >> rshift);
+	  /* Set sign_bit to the most significant bit of a word.  */
+	  sign_bit = 1;
+	  sign_bit <<= BITS_PER_WORD - 1;
+
+	  /* Set mask so that all bits of the word are set.  We could
+	     have used 1 << BITS_PER_WORD instead of basing the
+	     calculation on sign_bit.  However, on machines where
+	     HOST_BITS_PER_WIDE_INT == BITS_PER_WORD, it could cause a
+	     compiler warning, even though the code would never be
+	     executed.  */
+	  mask = sign_bit << 1;
+	  mask--;
+
+	  /* Set sign_extend as any remaining bits.  */
+	  sign_extend = ~mask;
+	  
+	  /* Pick the lower word and sign-extend it.  */
+	  low = INTVAL (value);
+	  low &= mask;
+	  if (low & sign_bit)
+	    low |= sign_extend;
+
+	  /* Pick the higher word, shifted to the least significant
+	     bits, and sign-extend it.  */
+	  high = INTVAL (value);
+	  high >>= BITS_PER_WORD - 1;
+	  high >>= 1;
+	  high &= mask;
+	  if (high & sign_bit)
+	    high |= sign_extend;
+
+	  /* Store the words in the target machine order.  */
 	  if (WORDS_BIG_ENDIAN)
 	    {
-	      *first = high;
-	      *second = low;
+	      *first = GEN_INT (high);
+	      *second = GEN_INT (low);
 	    }
 	  else
 	    {
-	      *first = low;
-	      *second = high;
+	      *first = GEN_INT (low);
+	      *second = GEN_INT (high);
 	    }
 	}
       else
@@ -4055,7 +4080,7 @@
       if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
 	   || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
 	  && ! flag_pretend_float)
-      abort ();
+	abort ();
 
       if (
 #ifdef HOST_WORDS_BIG_ENDIAN

-- 
Alexandre Oliva    Enjoy Guaranį, see http://www.ic.unicamp.br/~oliva/
Cygnus Solutions, a Red Hat company        aoliva@{redhat, cygnus}.com
Free Software Developer and Evangelist    CS PhD student at IC-Unicamp
oliva@{lsd.ic.unicamp.br, gnu.org}   Write to mailing lists, not to me

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