This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR11867, bignum operations


gas only supports the unary '-', '~', and '!' operators for bignums,
and all three were broken.  '!' gave the logical inverse of the proper
result, and the other two ignored any leading zeros.

	PR gas/11867
	* expr.c (operand <'-' and '~'>): Widen bignums.
	(operand <'!'>): Correct bignum result and convert to O_constant.
	* read.c (emit_expr): Don't assert on .byte bignum.  Don't display
	bignum truncated warning for sign extended bignums.

Index: gas/expr.c
===================================================================
RCS file: /cvs/src/src/gas/expr.c,v
retrieving revision 1.83
diff -u -p -r1.83 expr.c
--- gas/expr.c	22 Jun 2010 07:43:40 -0000	1.83
+++ gas/expr.c	2 Aug 2010 12:45:19 -0000
@@ -1056,6 +1056,15 @@ operand (expressionS *expressionP, enum 
 	      {
 		for (i = 0; i < expressionP->X_add_number; ++i)
 		  generic_bignum[i] = ~generic_bignum[i];
+
+		/* Extend the bignum to at least the size of .octa.  */
+		if (expressionP->X_add_number < SIZE_OF_LARGE_NUMBER)
+		  {
+		    expressionP->X_add_number = SIZE_OF_LARGE_NUMBER;
+		    for (; i < expressionP->X_add_number; ++i)
+		      generic_bignum[i] = ~(LITTLENUM_TYPE) 0;
+		  }
+
 		if (c == '-')
 		  for (i = 0; i < expressionP->X_add_number; ++i)
 		    {
@@ -1066,14 +1075,12 @@ operand (expressionS *expressionP, enum 
 	      }
 	    else if (c == '!')
 	      {
-		int nonzero = 0;
 		for (i = 0; i < expressionP->X_add_number; ++i)
-		  {
-		    if (generic_bignum[i])
-		      nonzero = 1;
-		    generic_bignum[i] = 0;
-		  }
-		generic_bignum[0] = nonzero;
+		  if (generic_bignum[i] != 0)
+		    break;
+		expressionP->X_add_number = i >= expressionP->X_add_number;
+		expressionP->X_op = O_constant;
+		expressionP->X_unsigned = 1;
 	      }
 	  }
 	else if (expressionP->X_op != O_illegal
Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.166
diff -u -p -r1.166 read.c
--- gas/read.c	28 Jun 2010 14:06:56 -0000	1.166
+++ gas/read.c	2 Aug 2010 07:37:27 -0000
@@ -4263,15 +4263,32 @@ emit_expr (expressionS *exp, unsigned in
       unsigned int size;
       LITTLENUM_TYPE *nums;
 
-      know (nbytes % CHARS_PER_LITTLENUM == 0);
-
       size = exp->X_add_number * CHARS_PER_LITTLENUM;
       if (nbytes < size)
 	{
-	  as_warn (_("bignum truncated to %d bytes"), nbytes);
+	  int i = nbytes / CHARS_PER_LITTLENUM;
+	  if (i != 0)
+	    {
+	      LITTLENUM_TYPE sign = 0;
+	      if ((generic_bignum[--i]
+		   & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) != 0)
+		sign = ~(LITTLENUM_TYPE) 0;
+	      while (++i < exp->X_add_number)
+		if (generic_bignum[i] != sign)
+		  break;
+	    }
+	  if (i < exp->X_add_number)
+	    as_warn (_("bignum truncated to %d bytes"), nbytes);
 	  size = nbytes;
 	}
 
+      if (nbytes == 1)
+	{
+	  md_number_to_chars (p, (valueT) generic_bignum[0], 1);
+	  return;
+	}
+      know (nbytes % CHARS_PER_LITTLENUM == 0);
+
       if (target_big_endian)
 	{
 	  while (nbytes > size)

-- 
Alan Modra
Australia Development Lab, IBM


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