This is the mail archive of the binutils@sources.redhat.com 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]

Thumb32 assembler (37/69)


Teach parse_operands about register lists for Thumb and ARM.

zw

	* config/tc-arm.c (OP_RLw): New operand parse code.
	(parse_operands): Implement OP_RLw and OP_REGLST.
	(do_ldmstm, do_t_ldmstm, do_t_push_pop): Use parse_operands.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 39)
+++ gas/config/tc-arm.c	(revision 40)
@@ -4302,7 +4302,8 @@
 
 #define OP_RL      052  /* Thumb low register */
 #define OP_RLlb    053  /* Thumb low register, leading [ */
-#define OP_RLtb    054  /* Thumb low register. trailing ] */
+#define OP_RLtb    054  /* Thumb low register, trailing ] */
+#define OP_RLw	   055	/* Thumb low register, optional trailing ! */
 
 #define OP_CPSF    060  /* CPS flags */
 #define OP_ENDI    061  /* Endianness specifier */
@@ -4472,6 +4473,17 @@
 	    inst.error = BAD_HIREG;
 	  break;
 
+	case OP_(RLw):
+	  po_reg_or_fail (REG_TYPE_RN);
+	  if (inst.operands[i].reg > 7)
+	    inst.error = BAD_HIREG;
+	  if (*str == '!')
+	    {
+	      inst.operands[i].writeback = 1;
+	      str++;
+	    }
+	  break;
+
 	  /* Immediates */
 	I0:
 	case OP_(I0):	 po_imm_or_fail (  0,      0, FALSE);	break;
@@ -4608,6 +4620,17 @@
 	  inst.operands[i].imm = val;
 	  break;
 
+	case OP_(REGLST):
+	  if ((val = reg_list (&str)) == FAIL)
+	    return FAIL;
+	  inst.operands[i].imm = val;
+	  if (*str == '^')
+	    {
+	      inst.operands[1].writeback = 1;
+	      str++;
+	    }
+	  break;
+
 	case OP_(VRSLST):
 	  val = vfp_parse_reg_list (&str, &inst.operands[i].reg, 0);
 	  goto vfp_reglist;
@@ -5055,29 +5078,22 @@
 do_ldmstm (char * str)
 {
   int base_reg;
-  long range;
+  int range;
+  if (parse_operands (str, OPERANDS2(RRw,REGLST)))
+    return;
 
-  note_reg_nonpc_or_fail (base_reg, &str, 16);
+  base_reg = inst.operands[0].reg;
+  range = inst.operands[1].imm;
 
-  if (*str == '!')
-    {
-      inst.instruction |= WRITE_BACK;
-      str++;
-    }
+  inst.instruction |= base_reg << 16;
+  inst.instruction |= range;
 
-  comma_or_fail (&str);
+  if (inst.operands[1].writeback)
+    inst.instruction |= LDM_TYPE_2_OR_3;
 
-  if ((range = reg_list (&str)) == FAIL)
-    return;
-
-  if (*str == '^')
+  if (inst.operands[0].writeback)
     {
-      str++;
-      inst.instruction |= LDM_TYPE_2_OR_3;
-    }
-
-  if (inst.instruction & WRITE_BACK)
-    {
+      inst.instruction |= WRITE_BACK;
       /* Check for unpredictable uses of writeback.  */
       if (inst.instruction & LOAD_BIT)
 	{
@@ -5100,9 +5116,6 @@
 	    as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
 	}
     }
-
-  inst.instruction |= range;
-  end_of_line (str);
 }
 
 /* ARMv5TE load-consecutive (argument parse)
@@ -6891,25 +6904,9 @@
 static void
 do_t_ldmstm (char * str)
 {
-  int Rb;
-  long range;
-
-  if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+  if (parse_operands (str, OPERANDS2(RLw,REGLST)))
     return;
 
-  if (*str != '!')
-    as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
-  else
-    str++;
-
-  if (skip_past_comma (&str) == FAIL
-      || (range = reg_list (&str)) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
   if (inst.reloc.type != BFD_RELOC_UNUSED)
     {
       /* This really doesn't seem worth it.  */
@@ -6917,15 +6914,21 @@
       inst.error = _("expression too complex");
       return;
     }
-
-  if (range & ~0xff)
+  if (inst.operands[1].imm & ~0xff)
     {
       inst.error = _("only lo-regs valid in load/store multiple");
       return;
     }
+  if (inst.operands[1].writeback)
+    {
+      inst.error = _("Thumb load/store multiple does not support {reglist}^");
+      return;
+    }
+  if (!inst.operands[0].writeback)
+    as_warn (_("Thumb load/store multiple always writes back base register"));
 
-  inst.instruction |= (Rb << 8) | range;
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].reg << 8;
+  inst.instruction |= inst.operands[1].imm;
 }
 
 static void
@@ -6966,15 +6969,13 @@
 static void
 do_t_push_pop (char * str)
 {
-  long range;
-
-  if ((range = reg_list (&str)) == FAIL)
+  if (parse_operands (str, OPERANDS1(REGLST)))
+    return;
+  if (inst.operands[0].writeback)
     {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
+      inst.error = _("push/pop do not support {reglist}^");
       return;
     }
-
   if (inst.reloc.type != BFD_RELOC_UNUSED)
     {
       /* This really doesn't seem worth it.  */
@@ -6982,16 +6983,15 @@
       inst.error = _("expression too complex");
       return;
     }
-
-  if (range & ~0xff)
+  if (inst.operands[0].imm & ~0xff)
     {
       if ((inst.instruction == T_OPCODE_PUSH
-	   && (range & ~0xff) == 1 << REG_LR)
+	   && (inst.operands[0].imm & ~0xff) == 1 << REG_LR)
 	  || (inst.instruction == T_OPCODE_POP
-	      && (range & ~0xff) == 1 << REG_PC))
+	      && (inst.operands[0].imm & ~0xff) == 1 << REG_PC))
 	{
 	  inst.instruction |= THUMB_PP_PC_LR;
-	  range &= 0xff;
+	  inst.operands[0].imm &= 0xff;
 	}
       else
 	{
@@ -7000,8 +7000,7 @@
 	}
     }
 
-  inst.instruction |= range;
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].imm;
 }
 
 /* THUMB SETEND instruction (argument parse).  */

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