This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Ensure ARM VPUSH and VPOP instructions do not affect more than 16 registers.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b126985ec3f922f86a9fa164cc0f443b1aa9e0bb

commit b126985ec3f922f86a9fa164cc0f443b1aa9e0bb
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Aug 5 11:26:13 2016 +0100

    Ensure ARM VPUSH and VPOP instructions do not affect more than 16 registers.
    
    	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.

Diff:
---
 gas/ChangeLog                   |  9 +++++
 gas/config/tc-arm.c             | 10 ++++++
 gas/config/tc-xgate.c           | 80 ++++++++++++++++++++++-------------------
 gas/testsuite/gas/arm/pr20429.d |  3 ++
 gas/testsuite/gas/arm/pr20429.l | 11 ++++++
 gas/testsuite/gas/arm/pr20429.s | 13 +++++++
 6 files changed, 89 insertions(+), 37 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 9634ea8..792ba87 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 73d0531..a8d9556 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -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
diff --git a/gas/config/tc-xgate.c b/gas/config/tc-xgate.c
index 769d158..521fe44 100644
--- a/gas/config/tc-xgate.c
+++ b/gas/config/tc-xgate.c
@@ -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
index 0000000..8837537
--- /dev/null
+++ b/gas/testsuite/gas/arm/pr20429.d
@@ -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
index 0000000..73886dd
--- /dev/null
+++ b/gas/testsuite/gas/arm/pr20429.l
@@ -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
index 0000000..02195c9
--- /dev/null
+++ b/gas/testsuite/gas/arm/pr20429.s
@@ -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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]