* read.c (convert_to_bignum): New function, split out from...

(emit_expr): ...here.  Handle the case where X_add_number is
	positive and the input value is negative.
	(output_big_sleb128): Fix setting of continuation bit.  Check whether
	the final byte needs to be sign-extended.  Fix size-shrinking loop.
	(emit_leb128_expr): When generating a signed leb128, see whether the
	sign of an O_constant's X_add_number matches the sign of the input
	value.  Use a bignum if not.
This commit is contained in:
Richard Sandiford 2005-01-19 11:53:53 +00:00
parent e22430578c
commit e5604d797e
8 changed files with 192 additions and 36 deletions

View File

@ -1,3 +1,14 @@
2005-01-19 Richard Sandiford <rsandifo@redhat.com>
* read.c (convert_to_bignum): New function, split out from...
(emit_expr): ...here. Handle the case where X_add_number is
positive and the input value is negative.
(output_big_sleb128): Fix setting of continuation bit. Check whether
the final byte needs to be sign-extended. Fix size-shrinking loop.
(emit_leb128_expr): When generating a signed leb128, see whether the
sign of an O_constant's X_add_number matches the sign of the input
value. Use a bignum if not.
2005-01-17 Andrew Stubbs <andrew.stubbs@st.com>
* tc-sh.c (md_begin,md_parse_option): Change arch_sh1_up to

View File

@ -1,6 +1,7 @@
/* read.c - read a source file -
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -1082,6 +1083,29 @@ read_a_source_file (char *name)
#endif
}
/* 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. */
static void
convert_to_bignum (expressionS *exp)
{
valueT value;
unsigned int i;
value = exp->X_add_number;
for (i = 0; i < sizeof (exp->X_add_number) / CHARS_PER_LITTLENUM; i++)
{
generic_bignum[i] = value & LITTLENUM_MASK;
value >>= LITTLENUM_NUMBER_OF_BITS;
}
/* 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;
exp->X_op = O_big;
exp->X_add_number = i;
}
/* For most MRI pseudo-ops, the line actually ends at the first
nonquoted space. This function looks for that point, stuffs a null
in, and sets *STOPCP to the character that used to be there, and
@ -3541,22 +3565,9 @@ emit_expr (expressionS *exp, unsigned int nbytes)
pass to md_number_to_chars, handle it as a bignum. */
if (op == O_constant && nbytes > sizeof (valueT))
{
valueT val;
int gencnt;
if (!exp->X_unsigned && exp->X_add_number < 0)
extra_digit = (valueT) -1;
val = (valueT) exp->X_add_number;
gencnt = 0;
do
{
generic_bignum[gencnt] = val & LITTLENUM_MASK;
val >>= LITTLENUM_NUMBER_OF_BITS;
++gencnt;
}
while (val != 0);
op = exp->X_op = O_big;
exp->X_add_number = gencnt;
extra_digit = exp->X_unsigned ? 0 : -1;
convert_to_bignum (exp);
op = O_big;
}
if (op == O_constant)
@ -4276,36 +4287,48 @@ output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
unsigned byte;
/* Strip leading sign extensions off the bignum. */
while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
while (size > 1
&& bignum[size - 1] == LITTLENUM_MASK
&& bignum[size - 2] > LITTLENUM_MASK / 2)
size--;
do
{
if (loaded < 7 && size > 0)
{
val |= (*bignum << loaded);
loaded += 8 * CHARS_PER_LITTLENUM;
size--;
bignum++;
}
/* OR in the next part of the littlenum. */
val |= (*bignum << loaded);
loaded += LITTLENUM_NUMBER_OF_BITS;
size--;
bignum++;
byte = val & 0x7f;
loaded -= 7;
val >>= 7;
if (size == 0)
/* Add bytes until there are less than 7 bits left in VAL
or until every non-sign bit has been written. */
do
{
if ((val == 0 && (byte & 0x40) == 0)
|| (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
&& (byte & 0x40) != 0))
byte = val & 0x7f;
loaded -= 7;
val >>= 7;
if (size > 0
|| val != ((byte & 0x40) == 0 ? 0 : ((valueT) 1 << loaded) - 1))
byte |= 0x80;
}
if (orig)
*p = byte;
p++;
}
while ((byte & 0x80) != 0 && loaded >= 7);
}
while (size > 0);
/* Mop up any left-over bits (of which there will be less than 7). */
if ((byte & 0x80) != 0)
{
/* Sign-extend VAL. */
if (val & (1 << (loaded - 1)))
val |= ~0 << loaded;
if (orig)
*p = byte;
*p = val & 0x7f;
p++;
}
while (byte & 0x80);
return p - orig;
}
@ -4384,6 +4407,16 @@ emit_leb128_expr (expressionS *exp, int sign)
as_warn (_("register value used as expression"));
op = O_constant;
}
else if (op == O_constant
&& sign
&& (exp->X_add_number < 0) != !exp->X_unsigned)
{
/* 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);
op = O_big;
}
/* Let check_eh_frame know that data is being emitted. nbytes == -1 is
a signal that this is leb128 data. It shouldn't optimize this away. */

View File

@ -1,3 +1,9 @@
2005-01-19 Richard Sandiford <rsandifo@redhat.com>
* gas/all/sleb128.[sd]: New test.
* gas/all/quad.[sd]: New test.
* gas/all/gas.exp: Run them.
2005-01-17 Andrew Stubbs <andrew.stubbs@st.com>
* gas/sh/arch/arch.exp: Correct the email address.

View File

@ -195,6 +195,9 @@ if { [istarget "i*86-*-*pe*"] \
gas_test "fastcall.s" "" "" "fastcall labels"
}
run_dump_test sleb128
run_dump_test quad
load_lib gas-dg.exp
dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" ""

View File

@ -0,0 +1,12 @@
#objdump : -s -j .data
#name : .quad tests
.*: .*
Contents of section .data:
0000 (00000000 76543210 00000000 80000000|10325476 00000000 00000080 00000000) .*
0010 (00000000 87654321 00000000 ffffffff|21436587 00000000 ffffffff 00000000) .*
0020 (ffffffff 89abcdf0 ffffffff 80000000|f0cdab89 ffffffff 00000080 ffffffff) .*
0030 (ffffffff 789abcdf ffffffff 00000001|dfbc9a78 ffffffff 01000000 ffffffff) .*
0040 (01234567 89abcdef fedcba98 76543211|efcdab89 67452301 11325476 98badcfe) .*
#pass

View File

@ -0,0 +1,12 @@
.data
.quad 0x76543210
.quad 0x80000000
.quad 0x87654321
.quad 0xffffffff
.quad -0x76543210
.quad -0x80000000
.quad -0x87654321
.quad -0xffffffff
.quad 0x123456789abcdef
.quad -0x123456789abcdef

View File

@ -0,0 +1,57 @@
#objdump : -s -j .data
#name : .sleb128 tests
.*: .*
Contents of section .data:
#
# 0x76543210 : 000_0111 0110_010 1_0100_00 11_0010_0 001_0000
# 0x80000000 : 000_1000 0000_000 0_0000_00 00_0000_0 000_0000
# 0x87654321 : 000_1000 0111_011 0_0101_01 00_0011_0 010_0001
# 0xffffffff : ..................................... 111_1111
#
0000 90e4d0b2 07808080 8008a186 95bb08ff .*
#
# 0xffffffff : 000_1111 1111_111 1_1111_11 11_1111_1 ........
# -0x76543210 : 111_1000 1001_101 0_1011_11 00_1101_1 111_0000
# -0x80000000 : 111_1000 0000_000 0_0000_00 00_0000_0 000_0000
# -0x87654321 : ........................... 11_1100_1 101_1111
#
0010 ffffff0f f09bafcd 78808080 8078dff9 .*
#
# -0x87654321 : 111_0111 1000_100 1_1010_10 ..................
# -0xffffffff : 111_0000 0000_000 0_0000_00 00_0000_0 000_0001
# 789abcdef : 111_1000 1001_101 0_1011_11 00_1101_1 110_1111
# 0x123456 : ........ 0010_001 1_0100_01 01_0110_0
#
0020 eac47781 80808070 ef9bafcd f8acd191 .*
#
# 0x123456 : 000_0001 ............................
# 789abcdef : 000_0111 0110_010 1_0100_00 11_0010_0 001_0001
# -0x123456 : 111_1110 1101_110 0_1011_10 01_1001_1
# fffffffff : 000_0000 0000_000 0_0000_00 00_0000_0 000_0001
# -0x7ff : ......... 00_0000_0
#
0030 0191e4d0 b287d3ae ee7e8180 80808080 .*
#
# -0x7ff : 1_1000_00 .........
# 000000000 : 000_0000 0000_000 0_0000_00 00_0000_0 000_0000
# -0x800 : 1_1000_00 00_0000_0
# fffffffff : 000_0000 0000_000 0_0000_00 00_0000_0 000_0001
# -0x7ffffff : .................. 0000_000 0_0000_00 00_0000_0
#
0040 60808080 80808060 81808080 80808080 .*
#
# -0x7ffffff : 11_1111_1 000_0000 ............................
# 000000000 : 000_0000 0000_000 0_0000_00 00_0000_0 000_0000
# -0x8000000 : 11_1111_1 000_0000 0000_000 0_0000_00 00_0000_0
# -0x100000000 : ........ 0000_000 0_0000_00 00_0000_0 000_0000
#
0050 807f8080 80808080 8080807f 80808080 .*
#
# -0x100000000 : 111_0000 .....................................
# 000000000 : 000_0000 0000_000 0_0000_00 00_0000_0 000_0000
# -0x1000 : 1_0000_00 00_0000_0
#
0060 70808080 80808040 00000000 00000000 .*
#pass

View File

@ -0,0 +1,22 @@
.data
.sleb128 0x76543210
.sleb128 0x80000000
.sleb128 0x87654321
.sleb128 0xffffffff
.sleb128 -0x76543210
.sleb128 -0x80000000
.sleb128 -0x87654321
.sleb128 -0xffffffff
.sleb128 0x123456789abcdef
.sleb128 -0x123456789abcdef
.sleb128 -0x7fffffffffff
.sleb128 -0x800000000000
.sleb128 -0x7fffffffffffffff
.sleb128 -0x8000000000000000
.sleb128 -0x100000000
.sleb128 -0x1000000000000
.fill 32