Fix checking bignum values that are being inserted into byte sized containers.
authorNick Clifton <nickc@redhat.com>
Wed, 16 Mar 2016 11:33:55 +0000 (11:33 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 16 Mar 2016 11:33:55 +0000 (11:33 +0000)
* read.c (emit_expr_with_reloc): Add code check a bignum with
nbytes == 1.
* config/rx/rx-parse.y (rx_intop): Accept bignum values for sizes
other than 32-bits.
* testsuite/gas/elf/bignum.s: New test source file.
* testsuite/gas/elf/bignum.d: New test driver file.
* testsuite/gas/elf/elf.exp: Run the new test.

gas/ChangeLog
gas/config/rx-parse.y
gas/read.c
gas/testsuite/gas/elf/bignums.d [new file with mode: 0644]
gas/testsuite/gas/elf/bignums.s [new file with mode: 0644]
gas/testsuite/gas/elf/elf.exp

index d67d7521c94c1195ab5117fb74c5aedc7924c4e2..0f1c13b2610a1e3223e6a9b847239eb2c7ccddcf 100644 (file)
@@ -1,3 +1,13 @@
+2016-03-16  Nick Clifton  <nickc@redhat.com>
+
+       * read.c (emit_expr_with_reloc): Add code check a bignum with
+       nbytes == 1.
+       * config/rx/rx-parse.y (rx_intop): Accept bignum values for sizes
+       other than 32-bits.
+       * testsuite/gas/elf/bignum.s: New test source file.
+       * testsuite/gas/elf/bignum.d: New test driver file.
+       * testsuite/gas/elf/elf.exp: Run the new test.
+
 2016-03-15  Ulrich Drepper  <drepper@gmail.com>
 
        * doc/c-i386.texi (Register Naming): Update to details of the
index 3bd37d0cae72fcfca7e56ba7c4c0e56c5f7c48ad..c0e321708e922b8743c7dfa466e81acc5f718cfc 100644 (file)
@@ -1494,9 +1494,14 @@ rx_intop (expressionS exp, int nbits, int opbits)
   long v;
   long mask, msb;
 
-  if (exp.X_op == O_big && nbits == 32)
-      return 1;
-  if (exp.X_op != O_constant)
+  if (exp.X_op == O_big)
+    {
+      if (nbits == 32)
+       return 1;
+      if (exp.X_add_number == -1)
+       return 0;
+    }
+  else if (exp.X_op != O_constant)
     return 0;
   v = exp.X_add_number;
 
index 8f5dfff6c7f5ca3aa5795c9114aafb7e419d56a2..ea6d9f61df1aab3dd2925d4b2c236ccffcbadb52 100644 (file)
@@ -4411,7 +4411,8 @@ emit_expr_with_reloc (expressionS *exp,
       if ((get & mask) != 0
          && ((get & mask) != mask
              || (get & hibit) == 0))
-       {               /* Leading bits contain both 0s & 1s.  */
+       {
+         /* Leading bits contain both 0s & 1s.  */
 #if defined (BFD64) && BFD_HOST_64BIT_LONG_LONG
 #ifndef __MSVCRT__
          as_warn (_("value 0x%llx truncated to 0x%llx"),
@@ -4437,16 +4438,34 @@ emit_expr_with_reloc (expressionS *exp,
       if (nbytes < size)
        {
          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;
            }
+         else if (nbytes == 1)
+           {
+             /* We have nbytes == 1 and CHARS_PER_LITTLENUM == 2 (probably).
+                Check that bits 8.. of generic_bignum[0] match bit 7
+                and that they match all of generic_bignum[1..exp->X_add_number].  */
+             LITTLENUM_TYPE sign = (generic_bignum[0] & (1 << 7)) ? -1 : 0;
+             LITTLENUM_TYPE himask = LITTLENUM_MASK & ~ 0xFF;
+
+             if ((generic_bignum[0] & himask) == (sign & himask))
+               {
+                 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;
diff --git a/gas/testsuite/gas/elf/bignums.d b/gas/testsuite/gas/elf/bignums.d
new file mode 100644 (file)
index 0000000..799ef3c
--- /dev/null
@@ -0,0 +1,14 @@
+#readelf: -x .data
+#name: bignum byte values
+#not-target: rx-*
+# The RX target sometimes calls its data section D_1.
+# 
+# Test that 8-bit and 16-bit constants can be specified via bignums.
+# 
+# Note - we should really apply this test to all targets, not just
+# ELF based ones, but we need a tool that can dump the data section
+# in a fixed format and readelf fits the bill.
+
+Hex dump of section .*:
+  0x00000000 9800(7698|9876) 9800(7698|9876) 9800.*
+#pass
diff --git a/gas/testsuite/gas/elf/bignums.s b/gas/testsuite/gas/elf/bignums.s
new file mode 100644 (file)
index 0000000..91de585
--- /dev/null
@@ -0,0 +1,23 @@
+       .data
+
+       # On a 64-bit host the two values below will be read into a simple
+       # 64-bit field in the expressionS structure and the type will be set
+       # to O_constant.  On a 32-bit host however they will read into the
+       # generic_bignum array and the type set to O_bignum.  Either way they
+       # should both evaluate without errors.
+       #
+       # Note - some targets place .hword values on a 16-bit boundary, so we
+       # declare a second, zero, .byte value in order to make the data
+       # consistent across all targets.
+
+       .byte  0xffffffffffffff98, 0
+       .hword 0xffffffffffff9876
+
+       # Check that on 64-bit hosts real bignum values also work.
+
+       .byte  0xffffffffffffffffffffffffffffff98, 0
+       .hword 0xffffffffffffffffffffffffffff9876
+
+       # Also check a ridiculously long bignum value.
+
+       .byte  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff98, 0
index fb5619d5621c9f799d35564f49eec6cea7583f0d..bde875bdf4e3dd897be829f47b65ce4d731b807d 100644 (file)
@@ -226,9 +226,10 @@ if { [is_elf_format] } then {
 
     run_dump_test "strtab"
 
-load_lib gas-dg.exp
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" ""
-dg-finish
+    run_dump_test "bignums"
     
+    load_lib gas-dg.exp
+    dg-init
+    dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" ""
+    dg-finish
 }