This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PR11867, bignum operations
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Mon, 2 Aug 2010 22:48:04 +0930
- Subject: 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