This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Negative bignums
- From: Earl Chew <earl_chew at agilent dot com>
- To: binutils at sources dot redhat dot com
- Date: Sat, 23 Oct 2004 17:06:46 -0700
- Subject: 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"),