Negative bignums

Earl Chew earl_chew@agilent.com
Sun Oct 24 00:06:00 GMT 2004


Whilst cross-compiling for powerpc using gcc 3.4.1, I came across:

   Error: bignum invalid

After some searching I found a description and a patch at:

http://lists.freebsd.org/pipermail/freebsd-amd64/2004-March/000886.html

Adapting the patch to the current version is straightforward. I've
attached a version of the patch I adapted for binutils 2.15.90.0.3
(via ucLibc).

Would you consider incorporating the patch to save having to
use --enable-64-bit-bfd on 32 bit targets?

Earl

--- binutils-2.15.90.0.3/gas/expr.c.orig	2004-04-12 12:56:34.000000000 -0700
+++ binutils-2.15.90.0.3/gas/expr.c	2004-10-20 20:34:24.061886400 -0700
@@ -37,6 +37,7 @@
  #ifdef BFD64
  static valueT generic_bignum_to_int64 (void);
  #endif
+static void bignum_negate (expressionS *);
  static void integer_constant (int radix, expressionS * expressionP);
  static void mri_char_constant (expressionS *);
  static void current_location (expressionS *);
@@ -733,6 +734,39 @@
      }
  }

+/* In:	An expressionP for a bignum to negate.
+
+   Out:	A negated expressionP.
+      && exp->X_add_number == 0
+      && symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big
+*/
+
+static void
+bignum_negate (expressionS *exp)
+{
+    int i;
+    unsigned long carry;
+
+    /* Negate the bignum: one's complement each digit and add 1.  */
+    carry = 1;
+    for (i = 0; i < exp->X_add_number; i++)
+    {
+	unsigned long next;
+
+	next = (((~(generic_bignum[i] & LITTLENUM_MASK))
+		 & LITTLENUM_MASK)
+		  + carry);
+	generic_bignum[i] = next & LITTLENUM_MASK;
+	carry = next >> LITTLENUM_NUMBER_OF_BITS;
+    }
+
+    if (carry > 0)
+    {
+	generic_bignum[exp->X_add_number] = carry;
+	exp->X_add_number ++;
+    }
+}
+
  /* In:	Input_line_pointer points to 1st char of operand, which may
  	be a space.

@@ -1077,14 +1111,24 @@
  	else if (expressionP->X_op != O_illegal
  		 && expressionP->X_op != O_absent)
  	  {
-	    expressionP->X_add_symbol = make_expr_symbol (expressionP);
  	    if (c == '-')
-	      expressionP->X_op = O_uminus;
+	    {
+		if (expressionP->X_op == O_big
+		    && expressionP->X_add_number > 0)
+		  bignum_negate(expressionP);
+		else
+		  expressionP->X_op = O_uminus;
+	    }
  	    else if (c == '~' || c == '"')
  	      expressionP->X_op = O_bit_not;
  	    else
  	      expressionP->X_op = O_logical_not;
-	    expressionP->X_add_number = 0;
+
+	    if (expressionP->X_op != O_big)
+	    {
+	      expressionP->X_add_number = 0;
+	      expressionP->X_add_symbol = make_expr_symbol (expressionP);
+	    }
  	  }
  	else
  	  as_warn (_("Unary operator %c ignored because bad operand follows"),



More information about the Binutils mailing list