aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2005-01-19 11:53:53 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2005-01-19 11:53:53 +0000
commite5604d797e394c370128dc06e702a14f11f3e8a5 (patch)
tree3f18f33ccb5004f3dbbec974231bfb224be1e79a /gas
parente22430578c7bc54a36eb0a8cc0a083f5b4826998 (diff)
downloadfsf-binutils-gdb-e5604d797e394c370128dc06e702a14f11f3e8a5.zip
fsf-binutils-gdb-e5604d797e394c370128dc06e702a14f11f3e8a5.tar.gz
fsf-binutils-gdb-e5604d797e394c370128dc06e702a14f11f3e8a5.tar.bz2
* 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog11
-rw-r--r--gas/read.c103
-rw-r--r--gas/testsuite/ChangeLog6
-rw-r--r--gas/testsuite/gas/all/gas.exp3
-rw-r--r--gas/testsuite/gas/all/quad.d12
-rw-r--r--gas/testsuite/gas/all/quad.s12
-rw-r--r--gas/testsuite/gas/all/sleb128.d57
-rw-r--r--gas/testsuite/gas/all/sleb128.s22
8 files changed, 191 insertions, 35 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index c0f8ca4..a833acd 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/read.c b/gas/read.c
index e6cee54..e04e00c 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -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++;
- }
-
- byte = val & 0x7f;
- loaded -= 7;
- val >>= 7;
+ /* OR in the next part of the littlenum. */
+ val |= (*bignum << loaded);
+ loaded += LITTLENUM_NUMBER_OF_BITS;
+ size--;
+ bignum++;
- 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. */
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index e1eab3b..e070cf3 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -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.
diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp
index 966c112..6f196fa 100644
--- a/gas/testsuite/gas/all/gas.exp
+++ b/gas/testsuite/gas/all/gas.exp
@@ -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]] "" ""
diff --git a/gas/testsuite/gas/all/quad.d b/gas/testsuite/gas/all/quad.d
new file mode 100644
index 0000000..c3a758d
--- /dev/null
+++ b/gas/testsuite/gas/all/quad.d
@@ -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
diff --git a/gas/testsuite/gas/all/quad.s b/gas/testsuite/gas/all/quad.s
new file mode 100644
index 0000000..af250cd
--- /dev/null
+++ b/gas/testsuite/gas/all/quad.s
@@ -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
diff --git a/gas/testsuite/gas/all/sleb128.d b/gas/testsuite/gas/all/sleb128.d
new file mode 100644
index 0000000..eaff63d
--- /dev/null
+++ b/gas/testsuite/gas/all/sleb128.d
@@ -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
diff --git a/gas/testsuite/gas/all/sleb128.s b/gas/testsuite/gas/all/sleb128.s
new file mode 100644
index 0000000..e8997ca
--- /dev/null
+++ b/gas/testsuite/gas/all/sleb128.s
@@ -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