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 (28/69)


More miscellaneous parse_operands conversions.  The most interesting
bit here is .writeback, which we will see a lot more of.

zw

	* tc-arm.c (struct arm_it): Add writeback field to operands struct.
	(parse_ror): New function.
	(OP_I31w, OP_RRw, OP_oROR): New operand parse codes.
	(parse_operands): Handle them.
	(do_rfe, do_srs, do_sxtah, do_sxth): Use parse_operands.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 29)
+++ gas/config/tc-arm.c	(revision 30)
@@ -195,7 +195,8 @@
   {
     int reg;
     int imm;
-    int present    : 1;
+    int present    : 1;  /* operand present */
+    int writeback  : 1;  /* operand has trailing ! */
   } operands[6];
 };
 
@@ -2608,6 +2609,42 @@
   return SUCCESS;
 }
 
+/* Parse a rotation specifier: ROR #0, #8, #16, #24.  *val receives a
+   value suitable for poking into the rotate field of an sxt or sxta
+   instruction.  */
+
+static int
+parse_ror (int *val, char **str)
+{
+  int rot;
+  char *s = *str;
+
+  if (strncasecmp (s, "ROR", 3) == 0)
+    s += 3;
+  else
+    {
+      inst.error = _("missing rotation field after comma");
+      return FAIL;
+    }
+
+  if (immediate_required_here (&s, &rot, 0, 24, FALSE) == FAIL)
+    return FAIL;
+
+  switch (rot)
+    {
+    case  0: *val = 0x0; break;
+    case  8: *val = 0x1; break;
+    case 16: *val = 0x2; break;
+    case 24: *val = 0x3; break;
+
+    default:
+      inst.error = _("rotation can only be 0, 8, 16, or 24");
+      return FAIL;
+    }
+  *str = s;
+  return SUCCESS;
+}
+
 /* Directives: register aliases.  */
 
 static void
@@ -4313,6 +4350,9 @@
 #define OP_bI15    041  /*                             0 .. 15 */
 #define OP_bI31    042  /*                             0 .. 31 */
 
+#define OP_I31w	   050  /* 0 .. 31, optional trailing ! */
+#define OP_RRw	   051  /* ARM register, not the PC, optional trailing ! */
+
 #define OP_CPSF	   060  /* CPS flags */
 #define OP_ENDI	   061	/* Endianness specifier */
 
@@ -4323,7 +4363,9 @@
 
 #define OP_ocI255  210  /* optional, curly-brace enclosed, imm  0 .. 255 */
 
+#define OP_oROR	   220  /* optional rotate right 0/8/16/24 */
 
+
 /* Macro for referring to one of the above constants as a number.
    Should appear solely in parse_operands().  */
 #define OP_(x) OP__(OP_##x)
@@ -4423,6 +4465,17 @@
 	    inst.error = BAD_PC;
 	  break;
 
+	case OP_(RRw):
+	  po_reg_or_fail (REG_TYPE_RN);
+	  if (inst.operands[i].reg == REG_PC)
+	    inst.error = BAD_PC;
+	  if (*str == '!')
+	    {
+	      inst.operands[i].writeback = 1;
+	      str++;
+	    }
+	  break;
+
 	  /* Immediates */
 	case OP_(I0):	 po_imm_or_fail (  0,      0, FALSE);	break;
 	case OP_(I4):	 po_imm_or_fail (  1,      4, FALSE);	break;
@@ -4442,11 +4495,30 @@
 	case OP_(bI31):  po_imm_or_fail (  0,     31, TRUE);    break;
 	case OP_(obIffff): po_imm_or_fail (0, 0xffff, TRUE);    break;
 
+	  /* Immediate variants */
 	case OP_(ocI255):
 	  po_char_or_fail ('{');
 	  po_imm_or_fail (0, 255, TRUE);
 	  po_char_or_fail ('}');
 	  break;
+
+	case OP_(I31w):
+	  /* The expression parser chokes on a trailing !, so we have
+	     to find it first and zap it.  */
+	  {
+	    char *s = str;
+	    while (*s && *s != ',')
+	      s++;
+	    if (s[-1] == '!')
+	      {
+		s[-1] = '\0';
+		inst.operands[i].writeback = 1;
+	      }
+	    po_imm_or_fail (0, 31, TRUE);
+	    if (str == s - 1)
+	      str = s;
+	  }
+	  break;
 	  
 	  /* Expressions */
 	case OP_(iEXP):
@@ -4470,6 +4542,11 @@
 	    return FAIL;
 	  break;
 
+	case OP_(oROR):
+	  if (parse_ror (&inst.operands[i].imm, &str))
+	    return FAIL;
+	  break;
+	  
 	default:
 	  as_fatal ("unhandled operand code %03o", *p);
 	}
@@ -5967,14 +6044,12 @@
 static void
 do_rfe (char * str)
 {
-  reg_nonpc_or_fail (&str, 16);
+  if (parse_operands (str, OPERANDS1(RRw)))
+    return;
 
-  if (*str == '!')
-    {
-      inst.instruction |= WRITE_BACK;
-      str++;
-    }
-  end_of_line (str);
+  inst.instruction |= (inst.operands[0].reg << 16);
+  if (inst.operands[0].writeback)
+    inst.instruction |= WRITE_BACK;
 }
 
 static void
@@ -6133,24 +6208,12 @@
 static void
 do_srs (char * str)
 {
-  int val;
-  /* This is necessary because the generic expression parser will
-     choke on "#16!".  */
-  char *exclam = strchr (str, '!');
-  if (exclam)
-    *exclam = '\0';
+  if (parse_operands (str, OPERANDS1(I31w)))
+    return;
 
-  immediate_or_fail (&str, &val, 0, 31, TRUE);
-  inst.instruction |= val;
-
-  if (exclam)
-    *exclam = '!';
-  if (*str == '!')
-    {
-      inst.instruction |= WRITE_BACK;
-      str++;
-    }
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].imm;
+  if (inst.operands[0].writeback)
+    inst.instruction |= WRITE_BACK;
 }
 
 /* ARM V6 strex (argument parse).  */
@@ -6190,67 +6253,13 @@
 static void
 do_sxtah (char * str)
 {
-  int rot;
-  int rotation_clear_mask = 0xfffff3ff;
-  int rotation_eight_mask = 0x00000400;
-  int rotation_sixteen_mask = 0x00000800;
-  int rotation_twenty_four_mask = 0x00000c00;
-
-  reg_nonpc_or_fail (&str, 12);
-  comma_or_fail (&str);
-
-  reg_nonpc_or_fail (&str, 16);
-  comma_or_fail (&str);
-  
-  reg_nonpc_or_fail (&str, 0);
-
-  /* Zero out the rotation field.  */
-  inst.instruction &= rotation_clear_mask;
-
-  /* Check for lack of optional rotation field.  */
-  if (skip_past_comma (&str) == FAIL)
-    {
-      end_of_line (str);
-      return;
-    }
-
-  /* Move past 'ROR'.  */
-  if (strncasecmp (str, "ROR", 3) == 0)
-    str += 3;
-  else
-    {
-      inst.error = _("missing rotation field after comma");
-      return;
-    }
-
-  /* Get the immediate constant.  */
-  if (immediate_required_here (&str, &rot, 0, 24, FALSE) == FAIL)
+  if (parse_operands (str, OPERANDS4(RRnpc,RRnpc,RRnpc,oROR)))
     return;
 
-  switch (rot)
-    {
-    case 0:
-      /* Rotation field has already been zeroed.  */
-      break;
-
-    case 8:
-      inst.instruction |= rotation_eight_mask;
-      break;
-
-    case 16:
-      inst.instruction |= rotation_sixteen_mask;
-      break;
-
-    case 24:
-      inst.instruction |= rotation_twenty_four_mask;
-      break;
-
-    default:
-      inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
-      break;
-    }
-
-  end_of_line (str);
+  inst.instruction |= (inst.operands[0].reg << 12);
+  inst.instruction |= (inst.operands[1].reg << 16);
+  inst.instruction |= (inst.operands[2].reg << 0);
+  inst.instruction |= (inst.operands[3].imm << 10);
 }
 
 /* ARM V6 SXTH.
@@ -6262,63 +6271,12 @@
 static void
 do_sxth (char * str)
 {
-  int rot;
-
-  int rotation_clear_mask = 0xfffff3ff;
-  int rotation_eight_mask = 0x00000400;
-  int rotation_sixteen_mask = 0x00000800;
-  int rotation_twenty_four_mask = 0x00000c00;
-
-  reg_nonpc_or_fail (&str, 12);
-  comma_or_fail (&str);
-
-  reg_nonpc_or_fail (&str, 0);
-
-  /* Zero out the rotation field.  */
-  inst.instruction &= rotation_clear_mask;
-
-  /* Check for lack of optional rotation field.  */
-  if (skip_past_comma (&str) == FAIL)
-    {
-      end_of_line (str);
-      return;
-    }
-
-  /* Move past 'ROR'.  */
-  if (strncasecmp (str, "ROR", 3) == 0)
-    str += 3;
-  else
-    {
-      inst.error = _("missing rotation field after comma");
-      return;
-    }
-
-  /* Get the immediate constant.  */
-  if (immediate_required_here (&str, &rot, 0, 24, FALSE) == FAIL)
+  if (parse_operands (str, OPERANDS3(RRnpc,RRnpc,oROR)))
     return;
-  switch (rot)
-    {
-    case 0:
-      /* Rotation field has already been zeroed.  */
-      break;
-    case 8:
-      inst.instruction |= rotation_eight_mask;
-      break;
 
-    case 16:
-      inst.instruction |= rotation_sixteen_mask;
-      break;
-
-    case 24:
-      inst.instruction |= rotation_twenty_four_mask;
-      break;
-
-    default:
-      inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
-      break;
-    }
-
-  end_of_line (str);
+  inst.instruction |= (inst.operands[0].reg << 12);
+  inst.instruction |= (inst.operands[1].reg << 0);
+  inst.instruction |= (inst.operands[2].imm << 10);
 }
 
 

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