[AArch64] Make register indices be full 64-bit values
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 28 Jun 2016 08:21:04 +0000 (09:21 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 28 Jun 2016 08:21:04 +0000 (09:21 +0100)
aarch64_opnd_info used bitfields to hold vector element indices,
but values were stored into those bitfields before their ranges had
been checked.  This meant large invalid indices could be silently
truncated to smaller valid indices.

The two obvious fixes were to do the range checking earlier or use
a full 64-bit field for the index.  I went for the latter for two
reasons:

      - Doing the range checking in operand_general_constraint_met_p
        seems structurally cleaner than doing it while parsing.

      - The bitfields didn't really buy us anything.  The imm field
        of the union is already 128 bits, so we can use a full int64_t
        index without growing the structure.

The patch also adds missing range checks for the elements in a register
list index.

include/
* opcode/aarch64.h (aarch64_opnd_info): Change index fields to int64_t.

opcodes/
* aarch64-opc.c (operand_general_constraint_met_p): Check the
range of ldst_elemlist operands.
(print_register_list): Use PRIi64 to print the index.
(aarch64_print_operand): Likewise.

gas/
* testsuite/gas/aarch64/diagnostic.s,
testsuite/gas/aarch64/diagnostic.l: Add tests for out-of-range indices.

gas/ChangeLog
gas/testsuite/gas/aarch64/diagnostic.l
gas/testsuite/gas/aarch64/diagnostic.s
include/ChangeLog
include/opcode/aarch64.h
opcodes/ChangeLog
opcodes/aarch64-opc.c

index ba19df2eae6e86858e3fd77ad57e299b8cad1c22..8958d6fa44264716b6d8697a66735bde762de804 100644 (file)
@@ -1,3 +1,8 @@
+2016-06-28  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * testsuite/gas/aarch64/diagnostic.s,
+       testsuite/gas/aarch64/diagnostic.l: Add tests for out-of-range indices.
+
 2016-06-28  Maciej W. Rozycki  <macro@imgtec.com>
 
        * config/tc-mips.c (mips16_reloc_p): Handle
index 2d7bd48a037dbcc94444ed8a29a1f88916cabaea..c278887ecb1ff7a6ef84442dbceed698c580593d 100644 (file)
 [^:]*:131: Error: integer 64-bit register expected at operand 3 -- `ldp x6,x29,\[w7,#8\]!'
 [^:]*:132: Error: integer 64-bit register expected at operand 2 -- `str x30,\[w11,#8\]!'
 [^:]*:133: Error: integer 64-bit register expected at operand 3 -- `stp x8,x27,\[wsp,#8\]!'
+[^:]*:213: Error: register element index out of range 0 to 1 at operand 2 -- `dup v0\.2d,v1\.2d\[-1\]'
+[^:]*:216: Error: register element index out of range 0 to 1 at operand 2 -- `dup v0\.2d,v1\.2d\[2\]'
+[^:]*:217: Error: register element index out of range 0 to 1 at operand 2 -- `dup v0\.2d,v1\.2d\[64\]'
+[^:]*:219: Error: register element index out of range 0 to 3 at operand 2 -- `dup v0\.4s,v1\.4s\[-1\]'
+[^:]*:222: Error: register element index out of range 0 to 3 at operand 2 -- `dup v0\.4s,v1\.4s\[4\]'
+[^:]*:223: Error: register element index out of range 0 to 3 at operand 2 -- `dup v0\.4s,v1\.4s\[65\]'
+[^:]*:225: Error: register element index out of range 0 to 7 at operand 2 -- `dup v0\.8h,v1\.8h\[-1\]'
+[^:]*:228: Error: register element index out of range 0 to 7 at operand 2 -- `dup v0\.8h,v1\.8h\[8\]'
+[^:]*:229: Error: register element index out of range 0 to 7 at operand 2 -- `dup v0\.8h,v1\.8h\[66\]'
+[^:]*:231: Error: register element index out of range 0 to 15 at operand 2 -- `dup v0\.16b,v1\.16b\[-1\]'
+[^:]*:234: Error: register element index out of range 0 to 15 at operand 2 -- `dup v0\.16b,v1\.16b\[16\]'
+[^:]*:235: Error: register element index out of range 0 to 15 at operand 2 -- `dup v0\.16b,v1\.16b\[67\]'
+[^:]*:237: Error: register element index out of range 0 to 1 at operand 1 -- `ld2 {v0\.d,v1\.d}\[-1\],\[x0\]'
+[^:]*:240: Error: register element index out of range 0 to 1 at operand 1 -- `ld2 {v0\.d,v1\.d}\[2\],\[x0\]'
+[^:]*:241: Error: register element index out of range 0 to 1 at operand 1 -- `ld2 {v0\.d,v1\.d}\[64\],\[x0\]'
+[^:]*:243: Error: register element index out of range 0 to 3 at operand 1 -- `ld2 {v0\.s,v1\.s}\[-1\],\[x0\]'
+[^:]*:246: Error: register element index out of range 0 to 3 at operand 1 -- `ld2 {v0\.s,v1\.s}\[4\],\[x0\]'
+[^:]*:247: Error: register element index out of range 0 to 3 at operand 1 -- `ld2 {v0\.s,v1\.s}\[65\],\[x0\]'
+[^:]*:249: Error: register element index out of range 0 to 7 at operand 1 -- `ld2 {v0\.h,v1\.h}\[-1\],\[x0\]'
+[^:]*:252: Error: register element index out of range 0 to 7 at operand 1 -- `ld2 {v0\.h,v1\.h}\[8\],\[x0\]'
+[^:]*:253: Error: register element index out of range 0 to 7 at operand 1 -- `ld2 {v0\.h,v1\.h}\[66\],\[x0\]'
+[^:]*:255: Error: register element index out of range 0 to 15 at operand 1 -- `ld2 {v0\.b,v1\.b}\[-1\],\[x0\]'
+[^:]*:258: Error: register element index out of range 0 to 15 at operand 1 -- `ld2 {v0\.b,v1\.b}\[16\],\[x0\]'
+[^:]*:259: Error: register element index out of range 0 to 15 at operand 1 -- `ld2 {v0\.b,v1\.b}\[67\],\[x0\]'
index fbde0e0e56049882ee8e6f7625c1930c3b63a430..ac2eb5cb902a980757c478f1991142d9884c3c41 100644 (file)
        ldst_single_wb_64 ldrsh
 
        ldst_single_wb_64 ldrsw
+
+       dup     v0.2d, v1.2d[-1]
+       dup     v0.2d, v1.2d[0]
+       dup     v0.2d, v1.2d[1]
+       dup     v0.2d, v1.2d[2]
+       dup     v0.2d, v1.2d[64]
+
+       dup     v0.4s, v1.4s[-1]
+       dup     v0.4s, v1.4s[0]
+       dup     v0.4s, v1.4s[3]
+       dup     v0.4s, v1.4s[4]
+       dup     v0.4s, v1.4s[65]
+
+       dup     v0.8h, v1.8h[-1]
+       dup     v0.8h, v1.8h[0]
+       dup     v0.8h, v1.8h[7]
+       dup     v0.8h, v1.8h[8]
+       dup     v0.8h, v1.8h[66]
+
+       dup     v0.16b, v1.16b[-1]
+       dup     v0.16b, v1.16b[0]
+       dup     v0.16b, v1.16b[15]
+       dup     v0.16b, v1.16b[16]
+       dup     v0.16b, v1.16b[67]
+
+       ld2     {v0.d, v1.d}[-1], [x0]
+       ld2     {v0.d, v1.d}[0], [x0]
+       ld2     {v0.d, v1.d}[1], [x0]
+       ld2     {v0.d, v1.d}[2], [x0]
+       ld2     {v0.d, v1.d}[64], [x0]
+
+       ld2     {v0.s, v1.s}[-1], [x0]
+       ld2     {v0.s, v1.s}[0], [x0]
+       ld2     {v0.s, v1.s}[3], [x0]
+       ld2     {v0.s, v1.s}[4], [x0]
+       ld2     {v0.s, v1.s}[65], [x0]
+
+       ld2     {v0.h, v1.h}[-1], [x0]
+       ld2     {v0.h, v1.h}[0], [x0]
+       ld2     {v0.h, v1.h}[7], [x0]
+       ld2     {v0.h, v1.h}[8], [x0]
+       ld2     {v0.h, v1.h}[66], [x0]
+
+       ld2     {v0.b, v1.b}[-1], [x0]
+       ld2     {v0.b, v1.b}[0], [x0]
+       ld2     {v0.b, v1.b}[15], [x0]
+       ld2     {v0.b, v1.b}[16], [x0]
+       ld2     {v0.b, v1.b}[67], [x0]
index ad63599b0b6e678031794d4d6a4ebe17dc5868f0..e5a80b96b799767b60ac02f5e4acbaae2c382893 100644 (file)
@@ -1,3 +1,7 @@
+2016-06-28  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * opcode/aarch64.h (aarch64_opnd_info): Change index fields to int64_t.
+
 2016-06-28  Maciej W. Rozycki  <macro@imgtec.com>
 
        * elf/mips.h (R_MIPS16_PC16_S1): New relocation.
index e6f080ca6f8ae7e7280e80aae2f735ef4e0e8f0c..b35a818a6576145676df0f95cfe18d461f311f33 100644 (file)
@@ -748,8 +748,8 @@ struct aarch64_opnd_info
        } reg;
       struct
        {
-         unsigned regno : 5;
-         unsigned index : 4;
+         unsigned int regno;
+         int64_t index;
        } reglane;
       /* e.g. LVn.  */
       struct
@@ -759,7 +759,7 @@ struct aarch64_opnd_info
          /* 1 if it is a list of reg element.  */
          unsigned has_index : 1;
          /* Lane index; valid only when has_index is 1.  */
-         unsigned index : 4;
+         int64_t index;
        } reglist;
       /* e.g. immediate or pc relative address offset.  */
       struct
index fd597866da27e2c383e355748eeabda75b5f1b8d..69d329845c1f065936d70c2369df8554958b9346 100644 (file)
@@ -1,3 +1,10 @@
+2016-06-28  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * aarch64-opc.c (operand_general_constraint_met_p): Check the
+       range of ldst_elemlist operands.
+       (print_register_list): Use PRIi64 to print the index.
+       (aarch64_print_operand): Likewise.
+
 2016-06-25  Trevor Saunders  <tbsaunde+binutils@tbsaunde.org>
 
        * mcore-opc.h: Remove sentinal.
index d9a31e83a5e1659a8614d4815ed1c4c00b6d69f8..322b991a4bc3e3ade711ba025747ea2664d7a714 100644 (file)
@@ -1521,6 +1521,16 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
       break;
 
     case AARCH64_OPND_CLASS_SIMD_REGLIST:
+      if (type == AARCH64_OPND_LEt)
+       {
+         /* Get the upper bound for the element index.  */
+         num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
+         if (!value_in_range_p (opnd->reglist.index, 0, num))
+           {
+             set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, num);
+             return 0;
+           }
+       }
       /* The opcode dependent area stores the number of elements in
         each structure to be loaded/stored.  */
       num = get_opcode_dependent_value (opcode);
@@ -2256,7 +2266,7 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd)
 
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
-    snprintf (tb, 8, "[%d]", opnd->reglist.index);
+    snprintf (tb, 8, "[%" PRIi64 "]", opnd->reglist.index);
   else
     tb[0] = '\0';
 
@@ -2479,7 +2489,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Ed:
     case AARCH64_OPND_En:
     case AARCH64_OPND_Em:
-      snprintf (buf, size, "v%d.%s[%d]", opnd->reglane.regno,
+      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
                aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reglane.index);
       break;