This is the mail archive of the binutils@sources.redhat.com 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]

Negative bignums


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"),


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