mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-29 04:53:56 +08:00
gas/
* read.c (convert_to_bignum): Add sign parameter. Use it instead of X_unsigned to determine sign of resulting bignum. (emit_expr): Pass extra argument to convert_to_bignum. (emit_leb128_expr): Use X_extrabit instead of X_unsigned. Pass X_extrabit to convert_to_bignum. (parse_bitfield_cons): Set X_extrabit. * expr.c (make_expr_symbol, expr_build_uconstant, operand): Initialise X_extrabit field as appropriate. (add_to_result): New. (subtract_from_result): New. (expr): Use above. * expr.h (expressionS): Add X_extrabit field. gas/testsuite/ * gas/all/sleb128-2.s: New test. * gas/all/sleb128-3.s: Likewise. * gas/all/sleb128-4.s: Likewise. * gas/all/sleb128-5.s: Likewise. * gas/all/sleb128-7.s: Likewise. * gas/all/sleb128-2.d: New. * gas/all/sleb128-3.d: New. * gas/all/sleb123-4.d: New. * gas/all/sleb123-5.d: New. * gas/all/sleb123-7.d: New. * gas/all/gas.exp (sleb128-2, sleb128-3, sleb128-4, sleb128-5) (sleb128-7): Run new tests.
This commit is contained in:
parent
cf2cb5ec99
commit
956a6ba3fe
@ -1,3 +1,18 @@
|
||||
2013-04-10 Julian Brown <julian@codesourcery.com>
|
||||
|
||||
* read.c (convert_to_bignum): Add sign parameter. Use it
|
||||
instead of X_unsigned to determine sign of resulting bignum.
|
||||
(emit_expr): Pass extra argument to convert_to_bignum.
|
||||
(emit_leb128_expr): Use X_extrabit instead of X_unsigned. Pass
|
||||
X_extrabit to convert_to_bignum.
|
||||
(parse_bitfield_cons): Set X_extrabit.
|
||||
* expr.c (make_expr_symbol, expr_build_uconstant, operand):
|
||||
Initialise X_extrabit field as appropriate.
|
||||
(add_to_result): New.
|
||||
(subtract_from_result): New.
|
||||
(expr): Use above.
|
||||
* expr.h (expressionS): Add X_extrabit field.
|
||||
|
||||
2013-04-10 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
* gas/config/tc-arm.c (encode_arm_addr_mode_3): Only reject base
|
||||
|
67
gas/expr.c
67
gas/expr.c
@ -90,6 +90,7 @@ make_expr_symbol (expressionS *expressionP)
|
||||
zero.X_op = O_constant;
|
||||
zero.X_add_number = 0;
|
||||
zero.X_unsigned = 0;
|
||||
zero.X_extrabit = 0;
|
||||
clean_up_expression (&zero);
|
||||
expressionP = &zero;
|
||||
}
|
||||
@ -161,6 +162,7 @@ expr_build_uconstant (offsetT value)
|
||||
e.X_op = O_constant;
|
||||
e.X_add_number = value;
|
||||
e.X_unsigned = 1;
|
||||
e.X_extrabit = 0;
|
||||
return make_expr_symbol (&e);
|
||||
}
|
||||
|
||||
@ -732,6 +734,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
|
||||
something like ``.quad 0x80000000'' is not sign extended even
|
||||
though it appears negative if valueT is 32 bits. */
|
||||
expressionP->X_unsigned = 1;
|
||||
expressionP->X_extrabit = 0;
|
||||
|
||||
/* Digits, assume it is a bignum. */
|
||||
|
||||
@ -1026,6 +1029,8 @@ operand (expressionS *expressionP, enum expr_mode mode)
|
||||
This is compatible with other people's
|
||||
assemblers. Sigh. */
|
||||
expressionP->X_unsigned = 0;
|
||||
if (expressionP->X_add_number)
|
||||
expressionP->X_extrabit ^= 1;
|
||||
}
|
||||
else if (c == '~' || c == '"')
|
||||
expressionP->X_add_number = ~ expressionP->X_add_number;
|
||||
@ -1078,6 +1083,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
|
||||
expressionP->X_add_number = i >= expressionP->X_add_number;
|
||||
expressionP->X_op = O_constant;
|
||||
expressionP->X_unsigned = 1;
|
||||
expressionP->X_extrabit = 0;
|
||||
}
|
||||
}
|
||||
else if (expressionP->X_op != O_illegal
|
||||
@ -1717,6 +1723,42 @@ operatorf (int *num_chars)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* Implement "word-size + 1 bit" addition for
|
||||
{resultP->X_extrabit:resultP->X_add_number} + {rhs_highbit:amount}. This
|
||||
is used so that the full range of unsigned word values and the full range of
|
||||
signed word values can be represented in an O_constant expression, which is
|
||||
useful e.g. for .sleb128 directives. */
|
||||
|
||||
static void
|
||||
add_to_result (expressionS *resultP, offsetT amount, int rhs_highbit)
|
||||
{
|
||||
valueT ures = resultP->X_add_number;
|
||||
valueT uamount = amount;
|
||||
|
||||
resultP->X_add_number += amount;
|
||||
|
||||
resultP->X_extrabit ^= rhs_highbit;
|
||||
|
||||
if (ures + uamount < ures)
|
||||
resultP->X_extrabit ^= 1;
|
||||
}
|
||||
|
||||
/* Similarly, for subtraction. */
|
||||
|
||||
static void
|
||||
subtract_from_result (expressionS *resultP, offsetT amount, int rhs_highbit)
|
||||
{
|
||||
valueT ures = resultP->X_add_number;
|
||||
valueT uamount = amount;
|
||||
|
||||
resultP->X_add_number -= amount;
|
||||
|
||||
resultP->X_extrabit ^= rhs_highbit;
|
||||
|
||||
if (ures < uamount)
|
||||
resultP->X_extrabit ^= 1;
|
||||
}
|
||||
|
||||
/* Parse an expression. */
|
||||
|
||||
segT
|
||||
@ -1832,7 +1874,7 @@ expr (int rankarg, /* Larger # is higher rank. */
|
||||
&& (md_register_arithmetic || resultP->X_op != O_register))
|
||||
{
|
||||
/* X + constant. */
|
||||
resultP->X_add_number += right.X_add_number;
|
||||
add_to_result (resultP, right.X_add_number, right.X_extrabit);
|
||||
}
|
||||
/* This case comes up in PIC code. */
|
||||
else if (op_left == O_subtract
|
||||
@ -1850,10 +1892,11 @@ expr (int rankarg, /* Larger # is higher rank. */
|
||||
symbol_get_frag (right.X_add_symbol),
|
||||
&frag_off))
|
||||
{
|
||||
resultP->X_add_number -= right.X_add_number;
|
||||
resultP->X_add_number -= frag_off / OCTETS_PER_BYTE;
|
||||
resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
|
||||
- S_GET_VALUE (right.X_add_symbol));
|
||||
offsetT symval_diff = S_GET_VALUE (resultP->X_add_symbol)
|
||||
- S_GET_VALUE (right.X_add_symbol);
|
||||
subtract_from_result (resultP, right.X_add_number, right.X_extrabit);
|
||||
subtract_from_result (resultP, frag_off / OCTETS_PER_BYTE, 0);
|
||||
add_to_result (resultP, symval_diff, symval_diff < 0);
|
||||
resultP->X_op = O_constant;
|
||||
resultP->X_add_symbol = 0;
|
||||
}
|
||||
@ -1861,7 +1904,7 @@ expr (int rankarg, /* Larger # is higher rank. */
|
||||
&& (md_register_arithmetic || resultP->X_op != O_register))
|
||||
{
|
||||
/* X - constant. */
|
||||
resultP->X_add_number -= right.X_add_number;
|
||||
subtract_from_result (resultP, right.X_add_number, right.X_extrabit);
|
||||
}
|
||||
else if (op_left == O_add && resultP->X_op == O_constant
|
||||
&& (md_register_arithmetic || right.X_op != O_register))
|
||||
@ -1870,7 +1913,7 @@ expr (int rankarg, /* Larger # is higher rank. */
|
||||
resultP->X_op = right.X_op;
|
||||
resultP->X_add_symbol = right.X_add_symbol;
|
||||
resultP->X_op_symbol = right.X_op_symbol;
|
||||
resultP->X_add_number += right.X_add_number;
|
||||
add_to_result (resultP, right.X_add_number, right.X_extrabit);
|
||||
retval = rightseg;
|
||||
}
|
||||
else if (resultP->X_op == O_constant && right.X_op == O_constant)
|
||||
@ -1910,7 +1953,9 @@ expr (int rankarg, /* Larger # is higher rank. */
|
||||
/* Constant + constant (O_add) is handled by the
|
||||
previous if statement for constant + X, so is omitted
|
||||
here. */
|
||||
case O_subtract: resultP->X_add_number -= v; break;
|
||||
case O_subtract:
|
||||
subtract_from_result (resultP, v, 0);
|
||||
break;
|
||||
case O_eq:
|
||||
resultP->X_add_number =
|
||||
resultP->X_add_number == v ? ~ (offsetT) 0 : 0;
|
||||
@ -1954,10 +1999,11 @@ expr (int rankarg, /* Larger # is higher rank. */
|
||||
resultP->X_op = op_left;
|
||||
resultP->X_op_symbol = right.X_add_symbol;
|
||||
if (op_left == O_add)
|
||||
resultP->X_add_number += right.X_add_number;
|
||||
add_to_result (resultP, right.X_add_number, right.X_extrabit);
|
||||
else if (op_left == O_subtract)
|
||||
{
|
||||
resultP->X_add_number -= right.X_add_number;
|
||||
subtract_from_result (resultP, right.X_add_number,
|
||||
right.X_extrabit);
|
||||
if (retval == rightseg
|
||||
&& SEG_NORMAL (retval)
|
||||
&& !S_FORCE_RELOC (resultP->X_add_symbol, 0)
|
||||
@ -1977,6 +2023,7 @@ expr (int rankarg, /* Larger # is higher rank. */
|
||||
resultP->X_op = op_left;
|
||||
resultP->X_add_number = 0;
|
||||
resultP->X_unsigned = 1;
|
||||
resultP->X_extrabit = 0;
|
||||
}
|
||||
|
||||
if (retval != rightseg)
|
||||
|
@ -136,6 +136,11 @@ typedef struct expressionS {
|
||||
when performing arithmetic on these values).
|
||||
FIXME: This field is not set very reliably. */
|
||||
unsigned int X_unsigned : 1;
|
||||
/* This is used to implement "word size + 1 bit" arithmetic, so that e.g.
|
||||
expressions used with .sleb128 directives can use the full range available
|
||||
for an unsigned word, but can also properly represent all values of a
|
||||
signed word. */
|
||||
unsigned int X_extrabit : 1;
|
||||
|
||||
/* 7 additional bits can be defined if needed. */
|
||||
|
||||
|
15
gas/read.c
15
gas/read.c
@ -1306,10 +1306,10 @@ read_a_source_file (char *name)
|
||||
}
|
||||
|
||||
/* Convert O_constant expression EXP into the equivalent O_big representation.
|
||||
Take the sign of the number from X_unsigned rather than X_add_number. */
|
||||
Take the sign of the number from SIGN rather than X_add_number. */
|
||||
|
||||
static void
|
||||
convert_to_bignum (expressionS *exp)
|
||||
convert_to_bignum (expressionS *exp, int sign)
|
||||
{
|
||||
valueT value;
|
||||
unsigned int i;
|
||||
@ -1322,8 +1322,8 @@ convert_to_bignum (expressionS *exp)
|
||||
}
|
||||
/* Add a sequence of sign bits if the top bit of X_add_number is not
|
||||
the sign of the original value. */
|
||||
if ((exp->X_add_number < 0) != !exp->X_unsigned)
|
||||
generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK;
|
||||
if ((exp->X_add_number < 0) == !sign)
|
||||
generic_bignum[i++] = sign ? LITTLENUM_MASK : 0;
|
||||
exp->X_op = O_big;
|
||||
exp->X_add_number = i;
|
||||
}
|
||||
@ -4250,7 +4250,7 @@ emit_expr (expressionS *exp, unsigned int nbytes)
|
||||
if (op == O_constant && nbytes > sizeof (valueT))
|
||||
{
|
||||
extra_digit = exp->X_unsigned ? 0 : -1;
|
||||
convert_to_bignum (exp);
|
||||
convert_to_bignum (exp, !exp->X_unsigned);
|
||||
op = O_big;
|
||||
}
|
||||
|
||||
@ -4544,6 +4544,7 @@ parse_bitfield_cons (exp, nbytes)
|
||||
exp->X_add_number = value;
|
||||
exp->X_op = O_constant;
|
||||
exp->X_unsigned = 1;
|
||||
exp->X_extrabit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5103,12 +5104,12 @@ emit_leb128_expr (expressionS *exp, int sign)
|
||||
}
|
||||
else if (op == O_constant
|
||||
&& sign
|
||||
&& (exp->X_add_number < 0) != !exp->X_unsigned)
|
||||
&& (exp->X_add_number < 0) == !exp->X_extrabit)
|
||||
{
|
||||
/* We're outputting a signed leb128 and the sign of X_add_number
|
||||
doesn't reflect the sign of the original value. Convert EXP
|
||||
to a correctly-extended bignum instead. */
|
||||
convert_to_bignum (exp);
|
||||
convert_to_bignum (exp, exp->X_extrabit);
|
||||
op = O_big;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,18 @@
|
||||
2013-04-10 Julian Brown <julian@codesourcery.com>
|
||||
|
||||
* gas/all/sleb128-2.s: New test.
|
||||
* gas/all/sleb128-3.s: Likewise.
|
||||
* gas/all/sleb128-4.s: Likewise.
|
||||
* gas/all/sleb128-5.s: Likewise.
|
||||
* gas/all/sleb128-7.s: Likewise.
|
||||
* gas/all/sleb128-2.d: New.
|
||||
* gas/all/sleb128-3.d: New.
|
||||
* gas/all/sleb123-4.d: New.
|
||||
* gas/all/sleb123-5.d: New.
|
||||
* gas/all/sleb123-7.d: New.
|
||||
* gas/all/gas.exp (sleb128-2, sleb128-3, sleb128-4, sleb128-5)
|
||||
(sleb128-7): Run new tests.
|
||||
|
||||
2013-04-10 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
* gas/testsuite/gas/arm/ldst-pc.s: Add index, non-writeback
|
||||
|
@ -369,6 +369,11 @@ if { ![istarget "bfin-*-*"] } then {
|
||||
run_dump_test assign
|
||||
}
|
||||
run_dump_test sleb128
|
||||
run_dump_test sleb128-2
|
||||
run_dump_test sleb128-3
|
||||
run_dump_test sleb128-4
|
||||
run_dump_test sleb128-5
|
||||
run_dump_test sleb128-7
|
||||
|
||||
# .byte is 32 bits on tic4x, and .p2align isn't supported on tic54x
|
||||
# .space is different on hppa*-hpux.
|
||||
|
7
gas/testsuite/gas/all/sleb128-2.d
Normal file
7
gas/testsuite/gas/all/sleb128-2.d
Normal file
@ -0,0 +1,7 @@
|
||||
#objdump : -s -j .data
|
||||
#name : .sleb128 tests (2)
|
||||
|
||||
.*: .*
|
||||
|
||||
Contents of section \.data:
|
||||
.* 7d2a.*
|
13
gas/testsuite/gas/all/sleb128-2.s
Normal file
13
gas/testsuite/gas/all/sleb128-2.s
Normal file
@ -0,0 +1,13 @@
|
||||
.text
|
||||
.globl foo
|
||||
foo:
|
||||
.L1:
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.L2:
|
||||
|
||||
.data
|
||||
bar:
|
||||
.sleb128 .L1 - .L2
|
||||
.byte 42
|
7
gas/testsuite/gas/all/sleb128-3.d
Normal file
7
gas/testsuite/gas/all/sleb128-3.d
Normal file
@ -0,0 +1,7 @@
|
||||
#objdump : -s -j .data
|
||||
#name : .sleb128 tests (3)
|
||||
|
||||
.*: .*
|
||||
|
||||
Contents of section \.data:
|
||||
.* 9c7f2a.*
|
4
gas/testsuite/gas/all/sleb128-3.s
Normal file
4
gas/testsuite/gas/all/sleb128-3.s
Normal file
@ -0,0 +1,4 @@
|
||||
.data
|
||||
bar:
|
||||
.sleb128 100 - 200
|
||||
.byte 42
|
7
gas/testsuite/gas/all/sleb128-4.d
Normal file
7
gas/testsuite/gas/all/sleb128-4.d
Normal file
@ -0,0 +1,7 @@
|
||||
#objdump : -s -j .data
|
||||
#name : .sleb128 tests (4)
|
||||
|
||||
.*: .*
|
||||
|
||||
Contents of section \.data:
|
||||
.* 83808080 082a.*
|
13
gas/testsuite/gas/all/sleb128-4.s
Normal file
13
gas/testsuite/gas/all/sleb128-4.s
Normal file
@ -0,0 +1,13 @@
|
||||
.text
|
||||
.globl foo
|
||||
foo:
|
||||
.L1:
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.L2:
|
||||
|
||||
.data
|
||||
bar:
|
||||
.sleb128 .L2 - .L1 + (1 << 31)
|
||||
.byte 42
|
7
gas/testsuite/gas/all/sleb128-5.d
Normal file
7
gas/testsuite/gas/all/sleb128-5.d
Normal file
@ -0,0 +1,7 @@
|
||||
#objdump : -s -j .data
|
||||
#name : .sleb128 tests (5)
|
||||
|
||||
.*: .*
|
||||
|
||||
Contents of section \.data:
|
||||
.* 012a.*
|
13
gas/testsuite/gas/all/sleb128-5.s
Normal file
13
gas/testsuite/gas/all/sleb128-5.s
Normal file
@ -0,0 +1,13 @@
|
||||
.text
|
||||
.globl foo
|
||||
foo:
|
||||
.L1:
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.L2:
|
||||
|
||||
.data
|
||||
bar:
|
||||
.sleb128 .L1 - .L2 + 4
|
||||
.byte 42
|
7
gas/testsuite/gas/all/sleb128-7.d
Normal file
7
gas/testsuite/gas/all/sleb128-7.d
Normal file
@ -0,0 +1,7 @@
|
||||
#objdump : -s -j .data
|
||||
#name : .sleb128 tests (7)
|
||||
|
||||
.*: .*
|
||||
|
||||
Contents of section \.data:
|
||||
.* cb012ac5 012acb01 2ac5012a.*
|
19
gas/testsuite/gas/all/sleb128-7.s
Normal file
19
gas/testsuite/gas/all/sleb128-7.s
Normal file
@ -0,0 +1,19 @@
|
||||
.text
|
||||
.globl foo
|
||||
foo:
|
||||
.L1:
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.L2:
|
||||
|
||||
.data
|
||||
bar:
|
||||
.sleb128 200+(.L2 - .L1)
|
||||
.byte 42
|
||||
.sleb128 200+(.L1 - .L2)
|
||||
.byte 42
|
||||
.sleb128 (.L2 - .L1)+200
|
||||
.byte 42
|
||||
.sleb128 (.L1 - .L2)+200
|
||||
.byte 42
|
Loading…
Reference in New Issue
Block a user