Ensure ARM VPUSH and VPOP instructions do not affect more than 16 registers.
authorNick Clifton <nickc@redhat.com>
Fri, 5 Aug 2016 10:26:13 +0000 (11:26 +0100)
committerNick Clifton <nickc@redhat.com>
Fri, 5 Aug 2016 10:26:13 +0000 (11:26 +0100)
PR gas/20429
* config/tc-arm.c (do_vfp_nsyn_push): Check that no more than 16
registers are pushed.
(do_vfp_nsyn_pop): Check that no more than 16 registers are
popped.
* testsuite/gas/arm/pr20429.s: New test.
* testsuite/gas/arm/pr20429.d: New test driver.
* testsuite/gas/arm/pr20429.1: Expected error output.

gas/ChangeLog
gas/config/tc-arm.c
gas/config/tc-xgate.c
gas/testsuite/gas/arm/pr20429.d [new file with mode: 0644]
gas/testsuite/gas/arm/pr20429.l [new file with mode: 0644]
gas/testsuite/gas/arm/pr20429.s [new file with mode: 0644]

index 9634ea8e5b4b1d9501c914bc2195534bbfe0c07f..792ba877c6a30f6e76b2f47e80c6dbd98a4995fb 100644 (file)
@@ -1,5 +1,14 @@
 2016-08-05  Nick Clifton  <nickc@redhat.com>
 
+       PR gas/20429
+       * config/tc-arm.c (do_vfp_nsyn_push): Check that no more than 16
+       registers are pushed.
+       (do_vfp_nsyn_pop): Check that no more than 16 registers are
+       popped.
+       * testsuite/gas/arm/pr20429.s: New test.
+       * testsuite/gas/arm/pr20429.d: New test driver.
+       * testsuite/gas/arm/pr20429.1: Expected error output.
+
        PR gas/20364
        * config/tc-aarch64.c (s_ltorg): Change the mapping state after
        aligning the frag.
index 73d0531639a9f8b277729122999122a423cc7549..a8d9556c05b4f24f28cc266a3d40c6ab70ddc6ab 100644 (file)
@@ -14390,6 +14390,11 @@ static void
 do_vfp_nsyn_push (void)
 {
   nsyn_insert_sp ();
+
+  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
+             _("register list must contain at least 1 and at most 16 "
+               "registers"));
+
   if (inst.operands[1].issingle)
     do_vfp_nsyn_opcode ("fstmdbs");
   else
@@ -14400,6 +14405,11 @@ static void
 do_vfp_nsyn_pop (void)
 {
   nsyn_insert_sp ();
+
+  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
+             _("register list must contain at least 1 and at most 16 "
+               "registers"));
+
   if (inst.operands[1].issingle)
     do_vfp_nsyn_opcode ("fldmias");
   else
index 769d158ca3313507b9fb86a8d416cec7eaf8ac1c..521fe44ab72fb21e8fbc4ad4208462c78f7c370f 100644 (file)
@@ -108,7 +108,7 @@ static int cmp_opcode (struct xgate_opcode *, struct xgate_opcode *);
 static void xgate_print_table (void);
 static unsigned int xgate_get_operands (char *, s_operand []);
 static register_id reg_name_search (char *);
-static op_modifiers xgate_determine_modifiers(char **);
+static op_modifiers xgate_determine_modifiers (char **);
 static void xgate_scan_operands (struct xgate_opcode *opcode, s_operand []);
 static unsigned int xgate_parse_operand (struct xgate_opcode *, int *, int,
                                         char **, s_operand);
@@ -191,7 +191,7 @@ struct option md_longopts[] =
   { NULL, no_argument, NULL, 0 }
 };
 
-size_t md_longopts_size = sizeof(md_longopts);
+size_t md_longopts_size = sizeof (md_longopts);
 
 const char *
 md_atof (int type, char *litP, int *sizeP)
@@ -301,13 +301,13 @@ md_begin (void)
   xgate_op_table = XNEWVEC (struct xgate_opcode, xgate_num_opcodes);
 
   memset (xgate_op_table, 0,
-         sizeof(struct xgate_opcode) * (xgate_num_opcodes));
+         sizeof (struct xgate_opcode) * (xgate_num_opcodes));
 
   for (xgate_opcode_ptr = (struct xgate_opcode*) xgate_opcodes, i = 0;
        i < xgate_num_opcodes; i++)
     xgate_op_table[i] = xgate_opcode_ptr[i];
 
-  qsort (xgate_op_table, xgate_num_opcodes, sizeof(struct xgate_opcode),
+  qsort (xgate_op_table, xgate_num_opcodes, sizeof (struct xgate_opcode),
         (int (*)(const void *, const void *)) cmp_opcode);
 
   /* Calculate number of handles since this will be
@@ -457,7 +457,7 @@ xgate_listing_header (void)
 symbolS *
 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
 {
-  return 0;
+  return NULL;
 }
 
 /* GAS will call this function for each section at the end of the assembly,
@@ -486,7 +486,7 @@ md_assemble (char *input_line)
 
   fixup_required = 0;
   oper_check = 0; /* set error flags */
-  input_line = extract_word (input_line, op_name, sizeof(op_name));
+  input_line = extract_word (input_line, op_name, sizeof (op_name));
 
   /* Check to make sure we are not reading a bogus line.  */
   if (!op_name[0])
@@ -552,10 +552,10 @@ md_assemble (char *input_line)
                }
              else
                {
-                 operandCount = xgate_get_operands(input_line, new_operands);
+                 operandCount = xgate_get_operands (input_line, new_operands);
                  macro_opcode = xgate_find_match (opcode_handle,
                                                   opcode_handle->number_of_modes, new_operands,
-                                              operandCount);
+                                                  operandCount);
                  xgate_scan_operands (macro_opcode, new_operands);
                }
            }
@@ -889,7 +889,8 @@ static char *
 xgate_parse_exp (char *s, expressionS * op)
 {
   input_line_pointer = s;
-  expression(op);
+
+  expression (op);
   if (op->X_op == O_absent)
     as_bad (_("missing operand"));
   return input_line_pointer;
@@ -915,51 +916,55 @@ xgate_find_match (struct xgate_opcode_handle *opcode_handle,
       switch (operandCount)
         {
       case 0:
-        if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_INH))
+        if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_INH))
           return opcode_handle->opc0[i];
         break;
       case 1:
         if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
-          if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_MON))
-            return opcode_handle->opc0[i];
-          if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_DYA_MON))
-            return opcode_handle->opc0[i];
+         {
+           if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_MON))
+             return opcode_handle->opc0[i];
+           if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_DYA_MON))
+             return opcode_handle->opc0[i];
+         }
         if (oprs[0].reg == REG_NONE)
-          if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM3))
+          if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM3))
             return opcode_handle->opc0[i];
         break;
       case 2:
         if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
           {
             if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
-              if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_DYA))
-                return opcode_handle->opc0[i];
+             {
+               if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_DYA))
+                 return opcode_handle->opc0[i];
+             }
             if (oprs[1].reg == REG_CCR)
-              if (!strcmp(opcode_handle->opc0[i]->constraints,
+              if (!strcmp (opcode_handle->opc0[i]->constraints,
                   XGATE_OP_MON_R_C))
                 return opcode_handle->opc0[i];
             if (oprs[1].reg == REG_PC)
-              if (!strcmp(opcode_handle->opc0[i]->constraints,
+              if (!strcmp (opcode_handle->opc0[i]->constraints,
                   XGATE_OP_MON_R_P))
                 return opcode_handle->opc0[i];
             if (oprs[1].reg == REG_NONE)
-              if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM16)
-                  || !strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM8)
-                  || !strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM4)
-                  || !strcmp(opcode_handle->opc0[i]->constraints,
+              if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM16)
+                  || !strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM8)
+                  || !strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM4)
+                  || !strcmp (opcode_handle->opc0[i]->constraints,
                       XGATE_OP_IMM16mADD)
-                  || !strcmp(opcode_handle->opc0[i]->constraints,
+                  || !strcmp (opcode_handle->opc0[i]->constraints,
                       XGATE_OP_IMM16mAND)
-                  || !strcmp(opcode_handle->opc0[i]->constraints,
+                  || !strcmp (opcode_handle->opc0[i]->constraints,
                       XGATE_OP_IMM16mCPC)
-                  || !strcmp(opcode_handle->opc0[i]->constraints,
+                  || !strcmp (opcode_handle->opc0[i]->constraints,
                       XGATE_OP_IMM16mSUB)
-                  || !strcmp(opcode_handle->opc0[i]->constraints,
+                  || !strcmp (opcode_handle->opc0[i]->constraints,
                       XGATE_OP_IMM16mLDW))
                 return opcode_handle->opc0[i];
           }
         if (oprs[0].reg == REG_CCR)
-          if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_MON_C_R))
+          if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_MON_C_R))
             return opcode_handle->opc0[i];
         break;
       case 3:
@@ -969,22 +974,22 @@ xgate_find_match (struct xgate_opcode_handle *opcode_handle,
               {
                 if (oprs[2].reg >= REG_R0 && oprs[2].reg <= REG_R7)
                   {
-                    if (!strcmp(opcode_handle->opc0[i]->constraints,
+                    if (!strcmp (opcode_handle->opc0[i]->constraints,
                         XGATE_OP_IDR)
-                        || !strcmp(opcode_handle->opc0[i]->constraints,
+                        || !strcmp (opcode_handle->opc0[i]->constraints,
                             XGATE_OP_TRI))
                       return opcode_handle->opc0[i];
                   }
 
                 if (oprs[2].reg == REG_NONE)
-                  if (!strcmp(opcode_handle->opc0[i]->constraints,
+                  if (!strcmp (opcode_handle->opc0[i]->constraints,
                       XGATE_OP_IDO5))
                     return opcode_handle->opc0[i];
               }
           }
         break;
       default:
-        as_bad(_("unknown operand count"));
+        as_bad (_("unknown operand count"));
         break;
         }
     }
@@ -1004,7 +1009,7 @@ xgate_frob_symbol (symbolS *sym)
   bfdsym = symbol_get_bfdsym (sym);
   elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
 
-  gas_assert(elfsym);
+  gas_assert (elfsym);
 
   /* Mark the symbol as being *from XGATE  */
   elfsym->internal_elf_sym.st_target_internal = 1;
@@ -1051,6 +1056,7 @@ xgate_get_operands (char *line, s_operand oprs[])
 
 /* reg_name_search() finds the register number given its name.
    Returns the register number or REG_NONE on failure.  */
+
 static register_id
 reg_name_search (char *name)
 {
@@ -1080,7 +1086,7 @@ reg_name_search (char *name)
 /* Parse operand modifiers such as inc/dec/hi/low.  */
 
 static op_modifiers
-xgate_determine_modifiers(char **line)
+xgate_determine_modifiers (char **line)
 {
   char *local_line = line[0];
 
@@ -1149,7 +1155,7 @@ xgate_scan_operands (struct xgate_opcode *opcode, s_operand oprs[])
       ++op;
       bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
 
-      if(first_operand_equals_second)
+      if (first_operand_equals_second)
        bin = xgate_apply_operand (operand, &oper_mask, bin,
                                   operand_bit_length);
       /* Parse second operand.  */
@@ -1229,9 +1235,9 @@ xgate_parse_operand (struct xgate_opcode *opcode,
       if (operand.reg == REG_NONE)
        as_bad (_(": expected register name r0-r7 ") );
       op_mask = operand.reg;
-      if(operand.mod == MOD_POSTINC)
+      if (operand.mod == MOD_POSTINC)
        pp_fix = INCREMENT;
-      if(operand.mod == MOD_PREDEC)
+      if (operand.mod == MOD_PREDEC)
        pp_fix = DECREMENT;
       op_mask <<= 2;
       op_mask |= pp_fix;
diff --git a/gas/testsuite/gas/arm/pr20429.d b/gas/testsuite/gas/arm/pr20429.d
new file mode 100644 (file)
index 0000000..8837537
--- /dev/null
@@ -0,0 +1,3 @@
+# name: PR 20429: Too many registers in VPUSH/VPOP
+# as: -mfpu=neon
+# error-output: pr20429.l
diff --git a/gas/testsuite/gas/arm/pr20429.l b/gas/testsuite/gas/arm/pr20429.l
new file mode 100644 (file)
index 0000000..73886dd
--- /dev/null
@@ -0,0 +1,11 @@
+[^:]*: Assembler messages:
+[^:]*:5: Error: register list must contain at least 1 and at most 16 registers -- `vpush {d0-d31}'
+[^:]*:6: Error: register list must contain at least 1 and at most 16 registers -- `vpush {d1-d17}'
+[^:]*:7: Error: register list must contain at least 1 and at most 16 registers -- `vpop {d1-d17}'
+[^:]*:8: Error: register list must contain at least 1 and at most 16 registers -- `vpop {d0-d31}'
+[^:]*:10: Error: register list must contain at least 1 and at most 16 registers -- `vpush {q0-q15}'
+[^:]*:11: Error: register list must contain at least 1 and at most 16 registers -- `vpush {q1-q9}'
+[^:]*:12: Error: register list must contain at least 1 and at most 16 registers -- `vpop {q1-q9}'
+[^:]*:13: Error: register list must contain at least 1 and at most 16 registers -- `vpop {q0-q15}'
+#pass
+
diff --git a/gas/testsuite/gas/arm/pr20429.s b/gas/testsuite/gas/arm/pr20429.s
new file mode 100644 (file)
index 0000000..02195c9
--- /dev/null
@@ -0,0 +1,13 @@
+.syntax unified
+.arm
+
+.text
+       vpush {d0-d31}          // 32 > 16, not catched.
+       vpush {d1-d17}          // 17 > 16, not catched.
+       vpop {d1-d17}           // 17 > 16, not catched.
+       vpop {d0-d31}           // 32 > 16, not catched.
+
+       vpush {q0-q15}          // 32 > 16, not catched.
+       vpush {q1-q9}           // 18 > 16, not catched.
+       vpop {q1-q9}            // 18 > 16, not catched.
+       vpop {q0-q15}           // 32 > 16, not catched.
This page took 0.04735 seconds and 4 git commands to generate.