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


Collapse all of the individual *_reg_required_here functions into
one, and remove the special vfp_dp_encode_reg function; DP registers
can be encoded with the usual "inst.instruction |= reg << N" idiom.
vfp_sp_encode_reg continues to exist, as there are two banks
of SP registers and the encoding is somewhat complicated.

zw

	* config/tc-arm.c (enum vfp_dp_reg_pos): Set values to allow direct use
        in instruction encoding.
	(vfp_sp_encode_reg): Move above reg_required_here.
	(reg_required_here): Change third argument to an enum arm_reg_type;
        pass this to arm_reg_parse.  Remove no_pc handling.  Call
        vfp_sp_encode_reg for REG_TYPE_SN encoding.
	(reg_or_fail, note_reg_or_fail): Change third argument to 'type'.
	(reg_nonpc_or_fail, note_reg_nonpc_or_fail): New macros.
	All existing callers of reg_required_here, reg_or_fail, and
        note_reg_or_fail updated to match above changes.
	(vfp_sp_reg_required_here, vfp_dp_encode_reg, vfp_dp_reg_required_here)
	(fp_reg_required_here, cp_reg_required_here, wreg_required_here)
	(mav_reg_required_here, xsc_reg_required_here): Delete.
	All callers updated to use reg_or_fail, note_reg_or_fail, or
	reg_required_here with appropriate type argument.
	(s_arm_unwind_movsp): Check for PC here again.
	(do_bfi): Check for Rm == PC here.
	(do_t_adr, do_t_blx): Use thumb_reg and expression_or_fail; poke
	register values into instruction here; reorganize for clarity.
	(do_ldstv4, do_smi, do_swi, thumb_add_sub, thumb_load_store)
	(thumb_shift, do_t_branch9, do_t_branch12, do_t_branch23, do_t_swi):
	Use expression_or_fail.
	(do_iwmmxt_byte_addr): Rename do_iwmmxt_wldst.  Do not rearrange
	instruction bits.
	(do_iwmmxt_word_addr): Rename do_iwmmxt_wldstw.  Do not rearrange
	instruction bits.  Use arm_reg_parse_multi.  No need to check for
	non-word size operation.
	(insns): Use do_iwmmxt_wldst for wldrb, wldrh, wldrd, wstrb, wstrh,
	wstrh; do_iwmmxt_wldstw for wldrw and wstrw.
	(do_iwmmxt_wzero): Add clarifying comment.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 11)
+++ gas/config/tc-arm.c	(revision 12)
@@ -502,9 +502,13 @@
   check_wshufh
 };
 
+/* These values are the bit offsets of the register fields, allowing these
+   to be used directly in encoding operations.  */
 enum vfp_dp_reg_pos
 {
-  VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
+  VFP_REG_Dd = 12,
+  VFP_REG_Dn = 16,
+  VFP_REG_Dm = 0
 };
 
 enum vfp_sp_reg_pos
@@ -1346,46 +1350,91 @@
   return FAIL;
 }
 
-/* A standard register must be given at this point.  SHIFT is the
-   place to put it in inst.instruction.  Restores input start point on
-   error.  Returns the reg#, or FAIL.  */
+/* Encode a VFP SP register number into inst.instruction.  */
 
+static void
+vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
+{
+  switch (pos)
+    {
+    case VFP_REG_Sd:
+      inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
+      break;
+
+    case VFP_REG_Sn:
+      inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
+      break;
+
+    case VFP_REG_Sm:
+      inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+/* A register of type TYPE is expected at this point.  SHIFT is the
+   place to put it in inst.instruction.  Returns the register number,
+   or FAIL.  */
+
 static int
-reg_required_here (char ** str, int shift, bfd_boolean no_pc)
+reg_required_here (char **str, int shift, enum arm_reg_type type)
 {
   int reg;
-  char *start = *str;
 
-  if ((reg = arm_reg_parse (str, REG_TYPE_RN)) == FAIL)
+  if ((reg = arm_reg_parse (str, type)) == FAIL)
     {
-      inst.error = gettext (reg_expected_msgs[REG_TYPE_RN]);
+      inst.error = gettext (reg_expected_msgs[type]);
       return FAIL;
     }
 
-  if (reg == REG_PC && no_pc)
+  if (shift >= 0)
     {
-      inst.error = BAD_PC;
-      *str = start;
-      return FAIL;
+      /* VFP SP registers require special handling.  */
+      if (type == REG_TYPE_SN)
+	vfp_sp_encode_reg (reg, shift);
+      else
+	inst.instruction |= reg << shift;
     }
-
-  if (shift >= 0)
-    inst.instruction |= reg << shift;
   return reg;
 }
 
-#define reg_or_fail(str, shift, no_pc)			\
+#define reg_or_fail(str, shift, type)			\
 do {							\
-  if (reg_required_here (str, shift, no_pc) == FAIL)	\
+  if (reg_required_here (str, shift, type) == FAIL)	\
     return;						\
- } while (0)
+} while (0)
 
-#define note_reg_or_fail(var, str, shift, no_pc)		\
+#define note_reg_or_fail(var, str, shift, type)			\
 do {								\
-  if ((var = reg_required_here (str, shift, no_pc)) == FAIL)	\
+  if ((var = reg_required_here (str, shift, type)) == FAIL)	\
     return;							\
- } while (0)
+} while (0)
 
+/* Convenience macros for the common case of needing an ARM register
+   that isn't the PC.  */
+#define reg_nonpc_or_fail(str, shift)			\
+do {							\
+  int reg_;						\
+  note_reg_or_fail (reg_, str, shift, REG_TYPE_RN);	\
+  if (reg_ == REG_PC)					\
+    {							\
+      inst.error = BAD_PC;				\
+      return;						\
+    }							\
+} while (0)
+
+#define note_reg_nonpc_or_fail(var, str, shift)		\
+do {							\
+  note_reg_or_fail (var, str, shift, REG_TYPE_RN);	\
+  if (var == REG_PC)					\
+    {							\
+      inst.error = BAD_PC;				\
+      return;						\
+    }							\
+} while (0)
+
 /* Parse and validate that a register is of the right form, this saves
    repeated checking of this information in many similar cases.
    Unlike the 32-bit case we do not insert the register into the opcode
@@ -1397,7 +1446,7 @@
 {
   int reg;
 
-  if ((reg = reg_required_here (strp, -1, FALSE)) == FAIL)
+  if ((reg = reg_required_here (strp, -1, REG_TYPE_RN)) == FAIL)
     return FAIL;
 
   switch (hi_lo)
@@ -1425,190 +1474,6 @@
   return reg;
 }
 
-/* Encode a VFP SP register number.  */
-
-static void
-vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
-{
-  switch (pos)
-    {
-    case VFP_REG_Sd:
-      inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
-      break;
-
-    case VFP_REG_Sn:
-      inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
-      break;
-
-    case VFP_REG_Sm:
-      inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
-      break;
-
-    default:
-      abort ();
-    }
-}
-
-static int
-vfp_sp_reg_required_here (char **str, enum vfp_sp_reg_pos pos)
-{
-  int reg;
-
-  if ((reg = arm_reg_parse (str, REG_TYPE_SN)) == FAIL)
-    {
-      inst.error = gettext (reg_expected_msgs[REG_TYPE_SN]);
-      return FAIL;
-    }
-  else
-    {
-      vfp_sp_encode_reg (reg, pos);
-      return reg;
-    }
-}
-
-static void
-vfp_dp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
-{
-  switch (pos)
-    {
-    case VFP_REG_Dd:
-      inst.instruction |= reg << 12;
-      break;
-
-    case VFP_REG_Dn:
-      inst.instruction |= reg << 16;
-      break;
-
-    case VFP_REG_Dm:
-      inst.instruction |= reg << 0;
-      break;
-
-    default:
-      abort ();
-    }
-}
-
-static int
-vfp_dp_reg_required_here (char **str, enum vfp_dp_reg_pos pos)
-{
-  int reg;
-
-  if ((reg = arm_reg_parse (str, REG_TYPE_DN)) == FAIL)
-    {
-      inst.error = gettext (reg_expected_msgs[REG_TYPE_DN]);
-      return FAIL;
-    }
-  else
-    {
-      vfp_dp_encode_reg (reg, pos);
-      return reg;
-    }
-}
-
-static int
-fp_reg_required_here (char **str, int where)
-{
-  int reg;
-
-  if ((reg = arm_reg_parse (str, REG_TYPE_FN)) == FAIL)
-    {
-      inst.error = gettext (reg_expected_msgs[REG_TYPE_FN]);
-      return FAIL;
-    }
-  else
-    {
-      inst.instruction |= reg << where;
-      return reg;
-    }
-}
-
-static int
-cp_reg_required_here (char **str, int where)
-{
-  int reg;
-
-  if ((reg = arm_reg_parse (str, REG_TYPE_CN)) == FAIL)
-    {
-      inst.error = gettext (reg_expected_msgs[REG_TYPE_CN]);
-      return FAIL;
-    }
-  else
-    {
-      inst.instruction |= reg << where;
-      return reg;
-    }
-}
-
-/* A Intel Wireless MMX technology register
-   must be given at this point.
-   Shift is the place to put it in inst.instruction.
-   Restores input start point on err.
-   Returns the reg#, or FAIL.  */
-
-static int
-wreg_required_here (char **str, int shift, enum arm_reg_type regtype)
-{
-  int reg;
-
-  if ((reg = arm_reg_parse (str, regtype)) == FAIL)
-    {
-      inst.error = gettext (reg_expected_msgs[regtype]);
-      return FAIL;
-    }
-  else
-    {
-      if (shift >= 0)
-	inst.instruction |= reg << shift;
-      return reg;
-    }
-}
-
-/* A register must be given at this point.
-
-   Shift is the place to put it in inst.instruction.
-
-   Restores input start point on err.
-   Returns the reg#, or FAIL.  */
-
-static int
-mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
-{
-  int reg;
-
-  if ((reg = arm_reg_parse (str, regtype)) == FAIL)
-    {
-      inst.error = gettext (reg_expected_msgs[regtype]);
-      return FAIL;
-    }
-  else
-    {
-      if (shift >= 0)
-	inst.instruction |= reg << shift;
-      return reg;
-    }
-}
-
-/* Expects *str -> the characters "acc0", possibly with leading blanks.
-   Advances *str to the next non-alphanumeric.
-   Returns 0, or else FAIL (in which case sets inst.error).
-
-  (In a future XScale, there may be accumulators other than zero.
-  At that time this routine and its callers can be upgraded to suit.)  */
-
-static int
-xsc_reg_required_here (char ** str)
-{
-  skip_whitespace (*str);
-
-  if (arm_reg_parse (str, REG_TYPE_XSCALE) == FAIL)
-    {
-      inst.error = gettext (reg_expected_msgs[REG_TYPE_XSCALE]);
-      return FAIL;
-    }
-  else
-    return 0;
-}
-
 /* Register lists.  */
 
 static long
@@ -1635,7 +1500,7 @@
 
 	      skip_whitespace (str);
 
-	      if ((reg = reg_required_here (& str, -1, FALSE)) == FAIL)
+	      if ((reg = reg_required_here (& str, -1, REG_TYPE_RN)) == FAIL)
 		return FAIL;
 
 	      if (in_range)
@@ -1921,7 +1786,8 @@
 
   skip_whitespace (p);
 
-  if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8, FALSE) != FAIL)
+  if (kind == NO_SHIFT_RESTRICT
+      && reg_required_here (& p, 8, REG_TYPE_RN) != FAIL)
     {
       inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
       * str = p;
@@ -2086,7 +1952,7 @@
 
   skip_whitespace (* str);
 
-  if (reg_required_here (str, 0, FALSE) != FAIL)
+  if (reg_required_here (str, 0, REG_TYPE_RN) != FAIL)
     {
       if (skip_past_comma (str) == SUCCESS)
 	/* Shift operation on register.  */
@@ -2173,7 +2039,7 @@
 {
   skip_whitespace (* str);
 
-  if (fp_reg_required_here (str, 0) != FAIL)
+  if (reg_required_here (str, 0, REG_TYPE_FN) != FAIL)
     return SUCCESS;
   else
     {
@@ -2314,7 +2180,7 @@
       /* Fall through.  */
 
     default:
-      if (reg_required_here (str, 0, FALSE) == FAIL)
+      if (reg_required_here (str, 0, REG_TYPE_RN) == FAIL)
 	return FAIL;
 
       inst.instruction |= add | OFFSET_REG;
@@ -2376,7 +2242,7 @@
       /* Fall through.  */
 
     default:
-      if (reg_required_here (str, 0, FALSE) == FAIL)
+      if (reg_required_here (str, 0, REG_TYPE_RN) == FAIL)
 	return FAIL;
 
       inst.instruction |= add;
@@ -2406,7 +2272,7 @@
 
       skip_whitespace (str);
 
-      if ((rn = reg_required_here (& str, 16, FALSE)) == FAIL)
+      if ((rn = reg_required_here (&str, 16, REG_TYPE_RN)) == FAIL)
 	return FAIL;
 
       skip_whitespace (str);
@@ -2710,7 +2576,7 @@
       p++;
       skip_whitespace (p);
 
-      if ((reg = reg_required_here (& p, 16, FALSE)) == FAIL)
+      if ((reg = reg_required_here (&p, 16, REG_TYPE_RN)) == FAIL)
 	return FAIL;
 
       skip_whitespace (p);
@@ -2898,7 +2764,7 @@
       p++;
       skip_whitespace (p);
 
-      if ((reg = reg_required_here (& p, 16, FALSE)) == FAIL)
+      if ((reg = reg_required_here (&p, 16, REG_TYPE_RN)) == FAIL)
         return FAIL;
 
       skip_whitespace (p);
@@ -4554,23 +4420,22 @@
   valueT op;
 
   SKIP_WHITESPACE ();
-  reg = reg_required_here (&input_line_pointer, -1, TRUE);
+  reg = arm_reg_parse (&input_line_pointer, REG_TYPE_RN);
   if (reg == FAIL)
     {
-      as_bad (inst.error);
+      as_bad (_(reg_expected_msgs[REG_TYPE_RN]));
       ignore_rest_of_line ();
       return;
     }
+  demand_empty_rest_of_line ();
 
-  /* pc handled in reg_required_here */
-  if (reg == 13)
+  if (reg == REG_SP || reg == REG_PC)
     {
-      as_bad (_("r13 not permitted in .unwind_movsp directive"));
-      ignore_rest_of_line ();
+      as_bad (_("SP and PC not permitted in .unwind_movsp directive"));
       return;
     }
 
-  if (unwind.fp_reg != 13)
+  if (unwind.fp_reg != REG_SP)
     as_bad (_("unexpected .unwind_movsp directive"));
 
   /* Generate opcode to restore the value.  */
@@ -4581,7 +4446,6 @@
   unwind.fp_reg = reg;
   unwind.fp_offset = unwind.frame_size;
   unwind.sp_restored = 1;
-  demand_empty_rest_of_line ();
 }
 
 /* Parse an unwind_pad directive.  */
@@ -4617,11 +4481,11 @@
   int fp_reg;
   int offset;
 
-  fp_reg = reg_required_here (&input_line_pointer, -1, FALSE);
+  fp_reg = arm_reg_parse (&input_line_pointer, REG_TYPE_RN);
   if (skip_past_comma (&input_line_pointer) == FAIL)
     sp_reg = FAIL;
   else
-    sp_reg = reg_required_here (&input_line_pointer, -1, FALSE);
+    sp_reg = arm_reg_parse (&input_line_pointer, REG_TYPE_RN);
 
   if (fp_reg == FAIL || sp_reg == FAIL)
     {
@@ -4785,7 +4649,7 @@
      into a relative address of the form "add rd, pc, #label-.-8".  */
 
   skip_whitespace (str);
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
   expression_or_fail (&inst.reloc.exp, &str);
   end_of_line (str);
@@ -4808,7 +4672,7 @@
      add rd, rd, #high(label-.-8)"  */
 
   skip_whitespace (str);
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
   expression_or_fail (&inst.reloc.exp, &str);
   end_of_line (str);
@@ -4827,9 +4691,9 @@
 do_arit (char * str)
 {
   skip_whitespace (str);
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
-  reg_or_fail (&str, 16, FALSE);
+  reg_or_fail (&str, 16, REG_TYPE_RN);
   comma_or_fail (&str);
 
   if (data_op2 (&str) == FAIL)
@@ -4868,20 +4732,22 @@
 do_bfc (char *str)
 {
   skip_whitespace (str);
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   bfci_lsb_and_width (str);
 }
 
 static void
 do_bfi (char *str)
 {
+  int rm;
+
   /* Rd.  */
   skip_whitespace (str);
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
   /* Rm.  Accept #0 in this position as an alternative syntax for bfc.  */
-  if (reg_required_here (&str, 0, TRUE) == FAIL)
+  if ((rm = reg_required_here (&str, 0, REG_TYPE_RN)) == FAIL)
     {
       int dummy;
 
@@ -4891,6 +4757,12 @@
       inst.instruction |= 0x0000000f;  /* Rm = PC -> bfc, not bfi.  */
     }
 
+  if (rm == REG_PC)
+    {
+      inst.error = BAD_PC;
+      return;
+    }
+
   bfci_lsb_and_width (str);
 }
 
@@ -4901,11 +4773,11 @@
 
   /* Rd.  */
   skip_whitespace (str);
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
   /* Rm.  */
-  reg_or_fail (&str, 0, FALSE);
+  reg_or_fail (&str, 0, REG_TYPE_RN);
   comma_or_fail (&str);
 
   /* lsb, width. */
@@ -5048,7 +4920,7 @@
   int reg;
 
   skip_whitespace (str);
-  note_reg_or_fail (reg, &str, 0, FALSE);
+  note_reg_or_fail (reg, &str, 0, REG_TYPE_RN);
   end_of_line (str);
 
   /* Note - it is not illegal to do a "bx pc".  Useless, but not illegal.  */
@@ -5070,7 +4942,7 @@
   int rm;
 
   skip_whitespace (str);
-  rm = reg_required_here (&str, 0, FALSE);
+  rm = reg_required_here (&str, 0, REG_TYPE_RN);
 
   if (rm != FAIL)
     {
@@ -5108,7 +4980,7 @@
   int reg;
 
   skip_whitespace (str);
-  note_reg_or_fail (reg, &str, 0, FALSE);
+  note_reg_or_fail (reg, &str, 0, REG_TYPE_RN);
   end_of_line (str);
 
   /* Note - it is not illegal to do a "bxj pc".  Useless, but not illegal.  */
@@ -5126,27 +4998,20 @@
 
   if (co_proc_number (&str) == FAIL)
     return;
-
   comma_or_fail (&str);
 
   if (cp_opc_expr (&str, 20, 4) == FAIL)
     return;
-
   comma_or_fail (&str);
 
-  if (cp_reg_required_here (&str, 12) == FAIL)
-    return;
-
+  reg_or_fail (&str, 12, REG_TYPE_CN);
   comma_or_fail (&str);
 
-  if (cp_reg_required_here (&str, 16) == FAIL)
-    return;
-
+  reg_or_fail (&str, 16, REG_TYPE_CN);
   comma_or_fail (&str);
-  
-  if (cp_reg_required_here (&str, 0) == FAIL)
-    return;
 
+  reg_or_fail (&str, 0, REG_TYPE_CN);
+
   if (skip_past_comma (&str) == SUCCESS)
     if (cp_opc_expr (&str, 5, 3) == FAIL)
       return;
@@ -5164,9 +5029,9 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   end_of_line (str);
 }
 
@@ -5175,7 +5040,7 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 16, FALSE);
+  reg_or_fail (&str, 16, REG_TYPE_RN);
   comma_or_fail (&str);
 
   if (data_op2 (&str) == FAIL)
@@ -5211,17 +5076,15 @@
 
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
 
   comma_or_fail (&str);
 
-  if (cp_reg_required_here (&str, 16) == FAIL)
-    return;
+  reg_or_fail (&str, 16, REG_TYPE_CN);
 
   comma_or_fail (&str);
 
-  if (cp_reg_required_here (&str, 0) == FAIL)
-    return;
+  reg_or_fail (&str, 0, REG_TYPE_CN);
 
   if (skip_past_comma (&str) == SUCCESS)
     if (cp_opc_expr (&str, 5, 3) == FAIL)
@@ -5257,15 +5120,14 @@
     return;
 
   comma_or_fail (&str);
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
 
   comma_or_fail (&str);
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
 
   comma_or_fail (&str);
 
-  if (cp_reg_required_here (& str, 0) == FAIL)
-    return;
+  reg_or_fail (& str, 0, REG_TYPE_CN);
 
   end_of_line (str);
 }
@@ -5301,7 +5163,7 @@
 
   skip_whitespace (str);
 
-  note_reg_or_fail (base_reg, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (base_reg, &str, 16);
 
   skip_whitespace (str);
 
@@ -5365,7 +5227,7 @@
 
   skip_whitespace (str);
 
-  note_reg_or_fail (rd, &str, 12, FALSE);
+  note_reg_or_fail (rd, &str, 12, REG_TYPE_RN);
 
   comma_or_fail (&str);
 
@@ -5420,7 +5282,7 @@
   skip_whitespace (str);
 
   /* Parse Rd.  */
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
   /* Skip past '['.  */
@@ -5432,7 +5294,7 @@
     }
   str++;
 
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
 
   /* Skip past ']'.  */
   skip_whitespace (str);
@@ -5454,7 +5316,7 @@
 
   skip_whitespace (str);
 
-  note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+  note_reg_or_fail (conflict_reg, &str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
   if (*str == '[')
@@ -5465,7 +5327,7 @@
 
       skip_whitespace (str);
 
-      note_reg_or_fail (reg, &str, 16, FALSE);
+      note_reg_or_fail (reg, &str, 16, REG_TYPE_RN);
 
       /* Conflicts can occur on stores as well as loads.  */
       conflict_reg = (conflict_reg == reg);
@@ -5623,7 +5485,7 @@
   int conflict_reg;
 
   skip_whitespace (str);
-  note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+  note_reg_or_fail (conflict_reg, &str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
   if (*str == '[')
@@ -5633,7 +5495,7 @@
       str++;
 
       skip_whitespace (str);
-      note_reg_or_fail (reg, &str, 16, FALSE);
+      note_reg_or_fail (reg, &str, 16, REG_TYPE_RN);
 
       /* ldrt/strt always use post-indexed addressing, so if the base is
 	 the same as Rd, we warn.  */
@@ -5691,7 +5553,7 @@
   int value;
 
   skip_whitespace (str);
-  note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+  note_reg_or_fail (conflict_reg, &str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
   if (*str == '[')
@@ -5702,7 +5564,7 @@
 
       skip_whitespace (str);
 
-      note_reg_or_fail (reg, &str, 16, FALSE);
+      note_reg_or_fail (reg, &str, 16, REG_TYPE_RN);
 
       /* Conflicts can occur on stores as well as loads.  */
       conflict_reg = (conflict_reg == reg);
@@ -5792,8 +5654,7 @@
 
       skip_whitespace (str);
 
-      if (my_get_expression (&inst.reloc.exp, &str))
-	return;
+      expression_or_fail (&inst.reloc.exp, &str);
 
       if (inst.reloc.exp.X_op != O_constant
 	  && inst.reloc.exp.X_op != O_symbol)
@@ -5846,8 +5707,7 @@
     }
   else
     {
-      if (my_get_expression (&inst.reloc.exp, &str))
-	return;
+      expression_or_fail (&inst.reloc.exp, &str);
 
       inst.instruction |= HWOFFSET_IMM;
       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
@@ -5871,7 +5731,7 @@
 
   skip_whitespace (str);
 
-  note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+  note_reg_or_fail (conflict_reg, &str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
   if (*str == '[')
@@ -5881,7 +5741,7 @@
       str++;
 
       skip_whitespace (str);
-      note_reg_or_fail (reg, &str, 16, FALSE);
+      note_reg_or_fail (reg, &str, 16, REG_TYPE_RN);
 
       /* ldrt/strt always use post-indexed addressing, so if the base is
 	 the same as Rd, we warn.  */
@@ -5941,8 +5801,7 @@
 
   comma_or_fail (&str);
 
-  if (cp_reg_required_here (&str, 12) == FAIL)
-    return;
+  reg_or_fail (&str, 12, REG_TYPE_CN);
 
   comma_or_fail (&str);
 
@@ -5960,16 +5819,16 @@
   /* Only one format "rd, rm, rs, rn".  */
   skip_whitespace (str);
 
-  note_reg_or_fail (rd, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (rd, &str, 16);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rm, &str, 0, TRUE);
+  note_reg_nonpc_or_fail (rm, &str, 0);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 8, TRUE);
+  reg_nonpc_or_fail (&str, 8);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   end_of_line (str);
   
   /* This restriction does not apply to mls (nor to mla in v6, but
@@ -5995,7 +5854,7 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
   if (data_op2 (&str) == FAIL)
@@ -6016,7 +5875,7 @@
   int val;
 
   skip_whitespace (str);
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
   immediate_or_fail (&str, &val, 0, 65535, FALSE);
   end_of_line (str);
@@ -6032,7 +5891,7 @@
   /* Only one syntax.  */
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
   skip_whitespace (str);
@@ -6080,9 +5939,8 @@
 
   skip_whitespace (str);
 
-  if (reg_required_here (&str, 0, FALSE) != FAIL)
+  if (reg_required_here (&str, 0, REG_TYPE_RN) != FAIL)
     {
-      inst.error = NULL;
       end_of_line (str);
       return;
     }
@@ -6136,13 +5994,13 @@
   /* Only one format "rd, rm, rs".  */
   skip_whitespace (str);
 
-  note_reg_or_fail (rd, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (rd, &str, 16);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rm, &str, 0, TRUE);
+  note_reg_nonpc_or_fail (rm, &str, 0);
   comma_or_fail (&str);
 
-  reg_required_here (&str, 8, TRUE);
+  reg_or_fail (&str, 8, REG_TYPE_RN);
   end_of_line (str);
 
   if (rm == rd)
@@ -6163,16 +6021,16 @@
   /* Only one format "rdlo, rdhi, rm, rs".  */
   skip_whitespace (str);
 
-  note_reg_or_fail (rdlo, &str, 12, TRUE);
+  note_reg_nonpc_or_fail (rdlo, &str, 12);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rdhi, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (rdhi, &str, 16);
   comma_or_fail (&str);
     
-  note_reg_or_fail (rm, &str, 0, TRUE);
+  note_reg_nonpc_or_fail (rm, &str, 0);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 8, TRUE);
+  reg_nonpc_or_fail (&str, 8);
   end_of_line (str);
 
   /* rdhi, rdlo and rm must all be different.  */
@@ -6214,13 +6072,13 @@
 
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rn, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (rn, &str, 16);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rm, &str, 0, TRUE);
+  note_reg_nonpc_or_fail (rm, &str, 0);
 
 
   /* Check for optional shift immediate constant.  */
@@ -6282,7 +6140,7 @@
   ++str;
   skip_whitespace (str);
 
-  note_reg_or_fail (rd, &str, 16, FALSE);
+  note_reg_or_fail (rd, &str, 16, REG_TYPE_RN);
 
   skip_whitespace (str);
 
@@ -6350,13 +6208,13 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
   end_of_line (str);
 }
 
@@ -6370,13 +6228,13 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   end_of_line (str);
 }
 
@@ -6384,10 +6242,10 @@
 do_rbit (char *str)
 {
   skip_whitespace (str);
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, FALSE);
+  reg_or_fail (&str, 0, REG_TYPE_RN);
   end_of_line (str);
 }
 
@@ -6402,10 +6260,10 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   end_of_line (str);
 }
 
@@ -6420,7 +6278,7 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
 
   skip_whitespace (str);
 
@@ -6440,7 +6298,7 @@
   skip_whitespace (str);
 
   /* Parse <Rd>, field.  */
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
   /* Parse #<immed>,  field.  */
@@ -6449,7 +6307,7 @@
   inst.instruction |= (val + bias) << 16;
 
   /* Parse <Rm> field.  */
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
 
   if (skip_past_comma (&str) == SUCCESS)
     decode_shift (&str, SHIFT_LSL_OR_ASR_IMMEDIATE);
@@ -6481,7 +6339,7 @@
   skip_whitespace (str);
 
   /* Parse the <Rd> field.  */
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
   /* Parse #<immed>, field.  */
@@ -6490,7 +6348,7 @@
   inst.instruction |= (val + bias) << 16;
 
   /* Parse <Rm> field.  */
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   end_of_line (str);
 }
 
@@ -6530,8 +6388,7 @@
   if (is_immediate_prefix (*str))
     str++;
 
-  if (my_get_expression (& inst.reloc.exp, & str))
-    return;
+  expression_or_fail (& inst.reloc.exp, & str);
 
   inst.reloc.type = BFD_RELOC_ARM_SMI;
   inst.reloc.pc_rel = 0;
@@ -6547,8 +6404,7 @@
   if (is_immediate_prefix (*str))
     str++;
 
-  if (my_get_expression (& inst.reloc.exp, & str))
-    return;
+  expression_or_fail (& inst.reloc.exp, & str);
 
   inst.reloc.type = BFD_RELOC_ARM_SWI;
   inst.reloc.pc_rel = 0;
@@ -6565,16 +6421,16 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   comma_or_fail (&str);
   
-  reg_or_fail (&str, 8, TRUE);
+  reg_nonpc_or_fail (&str, 8);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
 
   end_of_line (str);
 }
@@ -6591,16 +6447,16 @@
 
   skip_whitespace (str);
 
-  note_reg_or_fail (rdlo, &str, 12, TRUE);
+  note_reg_nonpc_or_fail (rdlo, &str, 12);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rdhi, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (rdhi, &str, 16);
   comma_or_fail (&str);
   
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 8, TRUE);
+  reg_nonpc_or_fail (&str, 8);
 
   if (rdlo == rdhi)
     as_tsktsk (_("rdhi and rdlo must be different"));
@@ -6616,13 +6472,13 @@
 do_smul (char * str)
 {
   skip_whitespace (str);
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   comma_or_fail (&str);
   
-  reg_or_fail (&str, 8, TRUE);
+  reg_nonpc_or_fail (&str, 8);
 
   end_of_line (str);
 }
@@ -6657,10 +6513,10 @@
 
   /* Parse Rd, Rm,.  */
   skip_whitespace (str);
-  note_reg_or_fail (rd, &str, 12, TRUE);
+  note_reg_nonpc_or_fail (rd, &str, 12);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rm, &str, 0, TRUE);
+  note_reg_nonpc_or_fail (rm, &str, 0);
   comma_or_fail (&str);
     
   if (rd == rm)
@@ -6679,7 +6535,7 @@
   skip_whitespace (str);
 
   /* Parse Rn.  */
-  note_reg_or_fail (rn, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (rn, &str, 16);
   if (rd == rn)
     {
       inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
@@ -6705,10 +6561,10 @@
 
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
 
   if (skip_past_comma (&str) == FAIL
       || *str++ != '[')
@@ -6719,7 +6575,7 @@
 
   skip_whitespace (str);
 
-  note_reg_or_fail (reg, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (reg, &str, 16);
 
   skip_whitespace (str);
 
@@ -6750,13 +6606,13 @@
   int rotation_twenty_four_mask = 0x00000c00;
 
   skip_whitespace (str);
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
   comma_or_fail (&str);
   
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
 
   /* Zero out the rotation field.  */
   inst.instruction &= rotation_clear_mask;
@@ -6825,10 +6681,10 @@
   int rotation_twenty_four_mask = 0x00000c00;
 
   skip_whitespace (str);
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
 
   /* Zero out the rotation field.  */
   inst.instruction &= rotation_clear_mask;
@@ -6905,8 +6761,7 @@
     {
       Rs = Rd;
       str++;
-      if (my_get_expression (&inst.reloc.exp, &str))
-	return;
+      expression_or_fail (&inst.reloc.exp, &str);
     }
   else
     {
@@ -6923,8 +6778,7 @@
       else if (is_immediate_prefix (*str))
 	{
 	  str++;
-	  if (my_get_expression (&inst.reloc.exp, &str))
-	    return;
+	  expression_or_fail (&inst.reloc.exp, &str);
 	}
       else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
 	return;
@@ -7080,8 +6934,7 @@
 	  if (is_immediate_prefix (*str))
 	    {
 	      str++;
-	      if (my_get_expression (&inst.reloc.exp, &str))
-		return;
+	      expression_or_fail (&inst.reloc.exp, &str);
 	    }
 	  else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
 	    return;
@@ -7112,8 +6965,7 @@
 
       skip_whitespace (str);
 
-      if (my_get_expression (& inst.reloc.exp, & str))
-	return;
+      expression_or_fail (& inst.reloc.exp, & str);
 
       end_of_line (str);
 
@@ -7152,8 +7004,7 @@
     }
   else
     {
-      if (my_get_expression (&inst.reloc.exp, &str))
-	return;
+      expression_or_fail (&inst.reloc.exp, &str);
 
       inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
       inst.reloc.pc_rel = 1;
@@ -7275,8 +7126,7 @@
   if (move != THUMB_CPY && is_immediate_prefix (*str))
     {
       str++;
-      if (my_get_expression (&inst.reloc.exp, &str))
-	return;
+      expression_or_fail (&inst.reloc.exp, &str);
     }
   else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
     return;
@@ -7363,8 +7213,7 @@
       /* Two operand immediate format, set Rs to Rd.  */
       Rs = Rd;
       str ++;
-      if (my_get_expression (&inst.reloc.exp, &str))
-	return;
+      expression_or_fail (&inst.reloc.exp, &str);
     }
   else
     {
@@ -7381,8 +7230,7 @@
       else if (is_immediate_prefix (*str))
 	{
 	  str++;
-	  if (my_get_expression (&inst.reloc.exp, &str))
-	    return;
+	  expression_or_fail (&inst.reloc.exp, &str);
 	}
       else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
 	return;
@@ -7466,21 +7314,19 @@
   skip_whitespace (str);
 
   /* Store Rd in temporary location inside instruction.  */
-  if ((reg = reg_required_here (&str, 4, FALSE)) == FAIL
-      || (reg > 7)  /* For Thumb reg must be r0..r7.  */
-      || skip_past_comma (&str) == FAIL
-      || my_get_expression (&inst.reloc.exp, &str))
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if ((reg = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+    return;
 
+  comma_or_fail (&str);
+  expression_or_fail (&inst.reloc.exp, &str);
+  
   inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
   inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
   inst.reloc.pc_rel = 1;
-  inst.instruction |= REG_PC; /* Rd is already placed into the instruction.  */
 
+  inst.instruction |= reg << 4;
+  inst.instruction |= REG_PC;
+
   end_of_line (str);
 }
 
@@ -7572,44 +7418,38 @@
 static void
 do_t_blx (char * str)
 {
-  char * mystr = str;
   int rm;
 
-  skip_whitespace (mystr);
-  inst.instruction = 0x4780;
+  skip_whitespace (str);
 
-  /* Note that this call is to the ARM register recognizer.  BLX(2)
-     uses the ARM register space, not the Thumb one, so a call to
-     thumb_reg() would be wrong.  */
-  rm = reg_required_here (& mystr, 3, FALSE);
-  inst.error = 0;
+  /* BLX(2) can be applied to any integer register.  */
+  rm = thumb_reg (&str, THUMB_REG_ANY);
 
   if (rm != FAIL)
     {
-      /* It's BLX(2).  The .instruction was zapped with rm & is final.  */
+      /* We have a register, so this is BLX(2).  */
+      inst.instruction = 0x4780;
       inst.size = 2;
+      inst.instruction |= (rm << 3);
     }
   else
     {
-      /* No ARM register.  This must be BLX(1).  Change the .instruction.  */
+      /* No register.  This must be BLX(1).  */
+      expression_or_fail (&inst.reloc.exp, &str);
+
       inst.instruction = 0xf7ffeffe;
       inst.size = 4;
-
-      if (my_get_expression (& inst.reloc.exp, & mystr))
-	return;
-
       inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BLX;
       inst.reloc.pc_rel = 1;
     }
 
-  end_of_line (mystr);
+  end_of_line (str);
 }
 
 static void
 do_t_branch9 (char * str)
 {
-  if (my_get_expression (&inst.reloc.exp, &str))
-    return;
+  expression_or_fail (&inst.reloc.exp, &str);
   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
   inst.reloc.pc_rel = 1;
   end_of_line (str);
@@ -7618,8 +7458,7 @@
 static void
 do_t_branch12 (char * str)
 {
-  if (my_get_expression (&inst.reloc.exp, &str))
-    return;
+  expression_or_fail (&inst.reloc.exp, &str);
   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
   inst.reloc.pc_rel = 1;
   end_of_line (str);
@@ -7628,8 +7467,7 @@
 static void
 do_t_branch23 (char * str)
 {
-  if (my_get_expression (& inst.reloc.exp, & str))
-    return;
+  expression_or_fail (& inst.reloc.exp, & str);
 
   inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BRANCH23;
   inst.reloc.pc_rel = 1;
@@ -7880,8 +7718,7 @@
 {
   skip_whitespace (str);
 
-  if (my_get_expression (&inst.reloc.exp, &str))
-    return;
+  expression_or_fail (&inst.reloc.exp, &str);
 
   inst.reloc.type = BFD_RELOC_ARM_SWI;
   end_of_line (str);
@@ -7895,17 +7732,10 @@
 {
   skip_whitespace (str);
 
-  if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Sd, REG_TYPE_SN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Sm, REG_TYPE_SN);
   end_of_line (str);
 }
 
@@ -7914,17 +7744,10 @@
 {
   skip_whitespace (str);
 
-  if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Dd, REG_TYPE_DN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Dm, REG_TYPE_DN);
   end_of_line (str);
 }
 
@@ -7933,19 +7756,13 @@
 {
   skip_whitespace (str);
 
-  if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Sd, REG_TYPE_SN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, VFP_REG_Sn, REG_TYPE_SN);
+  comma_or_fail (&str);
 
+  reg_or_fail (&str, VFP_REG_Sm, REG_TYPE_SN);
   end_of_line (str);
 }
 
@@ -7954,19 +7771,13 @@
 {
   skip_whitespace (str);
 
-  if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Dd, REG_TYPE_DN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, VFP_REG_Dn, REG_TYPE_DN);
+  comma_or_fail (&str);
 
+  reg_or_fail (&str, VFP_REG_Dm, REG_TYPE_DN);
   end_of_line (str);
 }
 
@@ -7974,14 +7785,7 @@
 do_vfp_sp_compare_z (char * str)
 {
   skip_whitespace (str);
-
-  if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Sd, REG_TYPE_SN);
   end_of_line (str);
 }
 
@@ -7989,14 +7793,7 @@
 do_vfp_dp_compare_z (char * str)
 {
   skip_whitespace (str);
-
-  if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Dd, REG_TYPE_DN);
   end_of_line (str);
 }
 
@@ -8005,17 +7802,10 @@
 {
   skip_whitespace (str);
 
-  if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Dd, REG_TYPE_DN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Sm, REG_TYPE_SN);
   end_of_line (str);
 }
 
@@ -8024,17 +7814,10 @@
 {
   skip_whitespace (str);
 
-  if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Sd, REG_TYPE_SN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Dm, REG_TYPE_DN);
   end_of_line (str);
 }
 
@@ -8043,16 +7826,10 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Sn, REG_TYPE_SN);
   end_of_line (str);
 }
 
@@ -8063,16 +7840,12 @@
 
   skip_whitespace (str);
 
-  if (reg_required_here (&str, 12, FALSE) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 16, FALSE) == FAIL
-      || skip_past_comma (&str) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
+  reg_or_fail (&str, 16, REG_TYPE_RN);
+  comma_or_fail (&str);
+
   /* We require exactly two consecutive SP registers.  */
   if (vfp_parse_reg_list (&str, &reg, 0) != 2)
     {
@@ -8089,16 +7862,11 @@
 {
   skip_whitespace (str);
 
-  if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Sn, REG_TYPE_SN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12, FALSE) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  end_of_line (str);
 
   end_of_line (str);
 }
@@ -8117,17 +7885,12 @@
 	inst.error = _("only two consecutive VFP SP registers allowed here");
     }
   vfp_sp_encode_reg (reg, VFP_REG_Sm);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12, FALSE) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 16, FALSE) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
+  reg_or_fail (&str, 16, REG_TYPE_RN);
   end_of_line (str);
 }
 
@@ -8136,16 +7899,10 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, VFP_REG_Dn, REG_TYPE_DN);
   end_of_line (str);
 }
 
@@ -8154,18 +7911,13 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 16, FALSE) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 16, REG_TYPE_RN);
+  comma_or_fail (&str);
 
+  reg_or_fail (&str, VFP_REG_Dm, REG_TYPE_DN);
   end_of_line (str);
 }
 
@@ -8174,17 +7926,10 @@
 {
   skip_whitespace (str);
 
-  if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Dn, REG_TYPE_DN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12, FALSE) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   end_of_line (str);
 }
 
@@ -8193,19 +7938,13 @@
 {
   skip_whitespace (str);
 
-  if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
-    return;
+  reg_or_fail (&str, VFP_REG_Dm, REG_TYPE_DN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12, FALSE) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 16, FALSE) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
+  reg_or_fail (&str, 16, REG_TYPE_RN);
   end_of_line (str);
 }
 
@@ -8214,15 +7953,11 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || vfp_psr_required_here (&str) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if (vfp_psr_required_here (&str) == FAIL)
+    return;
 
   end_of_line (str);
 }
@@ -8234,15 +7969,9 @@
 
   if (vfp_psr_required_here (&str) == FAIL)
     return;
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12, FALSE) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   end_of_line (str);
 }
 
@@ -8251,20 +7980,11 @@
 {
   skip_whitespace (str);
 
-  if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, VFP_REG_Sd, REG_TYPE_SN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || cp_address_required_here (&str, CP_NO_WB) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if (cp_address_required_here (&str, CP_NO_WB) == FAIL)
+    return;
 
   end_of_line (str);
 }
@@ -8274,20 +7994,11 @@
 {
   skip_whitespace (str);
 
-  if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, VFP_REG_Dd, REG_TYPE_DN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || cp_address_required_here (&str, CP_NO_WB) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if (cp_address_required_here (&str, CP_NO_WB) == FAIL)
+    return;
 
   end_of_line (str);
 }
@@ -8301,7 +8012,7 @@
 
   skip_whitespace (str);
 
-  reg_or_fail (&str, 16, FALSE);
+  reg_or_fail (&str, 16, REG_TYPE_RN);
 
   skip_whitespace (str);
 
@@ -8316,17 +8027,14 @@
       return;
     }
 
-  if (skip_past_comma (&str) == FAIL
-      || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-  vfp_sp_encode_reg (reg, VFP_REG_Sd);
+  comma_or_fail (&str);
 
-  inst.instruction |= count;
+  if ((count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
+    return;
   end_of_line (str);
+
+  vfp_sp_encode_reg (reg, VFP_REG_Sd);
+  inst.instruction |= count;
 }
 
 static void
@@ -8337,7 +8045,7 @@
 
   skip_whitespace (str);
 
-  reg_or_fail (&str, 16, FALSE);
+  reg_or_fail (&str, 16, REG_TYPE_RN);
 
   skip_whitespace (str);
 
@@ -8352,14 +8060,11 @@
       return;
     }
 
-  if (skip_past_comma (&str) == FAIL
-      || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  comma_or_fail (&str);
 
+  if ((count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
+    return;
+
   count <<= 1;
   if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
     count += 1;
@@ -8415,8 +8120,7 @@
 
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
-
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   end_of_line (str);
 }
 
@@ -8425,20 +8129,11 @@
 {
   skip_whitespace (str);
 
-  if (fp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 16, REG_TYPE_FN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || fp_op2 (&str) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if (fp_op2 (&str) == FAIL)
+    return;
 
   end_of_line (str);
 }
@@ -8448,20 +8143,11 @@
 {
   skip_whitespace (str);
 
-  if (fp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_FN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || fp_op2 (&str) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if (fp_op2 (&str) == FAIL)
+    return;
 
   end_of_line (str);
 }
@@ -8471,28 +8157,14 @@
 {
   skip_whitespace (str);
 
-  if (fp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_FN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || fp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 16, REG_TYPE_FN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || fp_op2 (&str) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if (fp_op2 (&str) == FAIL)
+    return;
 
   end_of_line (str);
 }
@@ -8502,21 +8174,10 @@
 {
   skip_whitespace (str);
 
-  if (fp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 16, REG_TYPE_FN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12, FALSE) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, 12, REG_TYPE_RN);
   end_of_line (str);
 }
 
@@ -8525,16 +8186,10 @@
 {
   skip_whitespace (str);
 
-  reg_or_fail (&str, 12, FALSE);
+  reg_or_fail (&str, 12, REG_TYPE_RN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || fp_reg_required_here (&str, 0) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
+  reg_or_fail (&str, 0, REG_TYPE_FN);
   end_of_line (str);
 }
 
@@ -8543,20 +8198,11 @@
 {
   skip_whitespace (str);
 
-  if (fp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_FN);
+  comma_or_fail (&str);
 
-  if (skip_past_comma (&str) == FAIL
-      || cp_address_required_here (&str, CP_WB_OK) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  if (cp_address_required_here (&str, CP_WB_OK) == FAIL)
+    return;
 
   end_of_line (str);
 }
@@ -8568,16 +8214,13 @@
 
   skip_whitespace (str);
 
-  if (fp_reg_required_here (&str, 12) == FAIL
-      || skip_past_comma (&str) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 12, REG_TYPE_FN);
+  comma_or_fail (&str);
 
   /* Get Number of registers to transfer.  */
   if (immediate_required_here (&str, &num_regs, 1, 4, TRUE) == FAIL)
     return;
+  comma_or_fail (&str);
 
   switch (num_regs)
     {
@@ -8606,20 +8249,16 @@
 	 [Rn]{!}.  The instruction does not really support stacking or
 	 unstacking, so we have to emulate these by setting appropriate
 	 bits and offsets.  */
-      if (skip_past_comma (&str) == FAIL
-	  || *str != '[')
+      if (*str != '[')
 	{
-	  if (! inst.error)
-	    inst.error = BAD_ARGS;
+	  inst.error = BAD_ARGS;
 	  return;
 	}
 
       str++;
       skip_whitespace (str);
 
-      if ((reg = reg_required_here (&str, 16, FALSE)) == FAIL)
-	return;
-
+      note_reg_or_fail (reg, &str, 16, REG_TYPE_RN);
       skip_whitespace (str);
 
       if (*str != ']')
@@ -8669,12 +8308,10 @@
 
       inst.instruction |= offset;
     }
-  else if (skip_past_comma (&str) == FAIL
-	   || cp_address_required_here (&str, CP_WB_OK) == FAIL)
+  else
     {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
+      if (cp_address_required_here (&str, CP_WB_OK) == FAIL)
+	return;
     }
 
   end_of_line (str);
@@ -8703,131 +8340,131 @@
   switch (insn_type)
     {
     case check_rd:
-      if ((reg = reg_required_here (&str, 12, FALSE)) == FAIL)
+      if ((reg = reg_required_here (&str, 12, REG_TYPE_RN)) == FAIL)
 	return FAIL;
       break;
 
     case check_wr:
-       if ((wreg_required_here (&str, 0, REG_TYPE_MMXWR)) == FAIL)
+       if ((reg_required_here (&str, 0, REG_TYPE_MMXWR)) == FAIL)
 	 return FAIL;
        break;
 
     case check_wrwr:
-      if ((wreg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL))
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL))
 	return FAIL;
       break;
 
     case check_wrwrwr:
-      if ((wreg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL))
+	   || reg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL))
 	return FAIL;
       break;
 
     case check_wrwrwcg:
-      if ((wreg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 0, REG_TYPE_MMXWCG) == FAIL))
+	   || reg_required_here (&str, 0, REG_TYPE_MMXWCG) == FAIL))
 	return FAIL;
       break;
 
     case check_tbcst:
-      if ((wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 12, FALSE) == FAIL))
+	   || reg_required_here (&str, 12, REG_TYPE_RN) == FAIL))
 	return FAIL;
       break;
 
     case check_tmovmsk:
-      if ((reg_required_here (&str, 12, FALSE) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL))
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL))
 	return FAIL;
       break;
 
     case check_tmia:
-      if ((wreg_required_here (&str, 5, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 5, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 0, FALSE) == FAIL
+	   || reg_required_here (&str, 0, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 12, FALSE) == FAIL))
+	   || reg_required_here (&str, 12, REG_TYPE_RN) == FAIL))
 	return FAIL;
       break;
 
     case check_tmcrr:
-      if ((wreg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 12, FALSE) == FAIL
+	   || reg_required_here (&str, 12, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 16, FALSE) == FAIL))
+	   || reg_required_here (&str, 16, REG_TYPE_RN) == FAIL))
 	return FAIL;
       break;
 
     case check_tmrrc:
-      if ((reg_required_here (&str, 12, FALSE) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 16, FALSE) == FAIL
+	   || reg_required_here (&str, 16, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL))
+	   || reg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL))
 	return FAIL;
       break;
 
     case check_tmcr:
-      if ((wreg_required_here (&str, 16, REG_TYPE_MMXWC) == FAIL
+      if ((reg_required_here (&str, 16, REG_TYPE_MMXWC) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 12, FALSE) == FAIL))
+	   || reg_required_here (&str, 12, REG_TYPE_RN) == FAIL))
 	return FAIL;
       break;
 
     case check_tmrc:
-      if ((reg_required_here (&str, 12, FALSE) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWC) == FAIL))
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWC) == FAIL))
 	return FAIL;
       break;
 
     case check_tinsr:
-      if ((wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || reg_required_here (&str, 12, FALSE) == FAIL
+	   || reg_required_here (&str, 12, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL))
 	return FAIL;
       break;
 
     case check_textrc:
-      if ((reg_required_here (&str, 12, FALSE) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL))
 	return FAIL;
       break;
 
     case check_waligni:
-      if ((wreg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL
+	   || reg_required_here (&str, 0, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL))
 	return FAIL;
       break;
 
     case check_textrm:
-      if ((reg_required_here (&str, 12, FALSE) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_RN) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL))
 	return FAIL;
       break;
 
     case check_wshufh:
-      if ((wreg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
+      if ((reg_required_here (&str, 12, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL
-	   || wreg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
+	   || reg_required_here (&str, 16, REG_TYPE_MMXWR) == FAIL
 	   || skip_past_comma (&str) == FAIL))
 	return FAIL;
       break;
@@ -8851,28 +8488,6 @@
 }
 
 static void
-do_iwmmxt_byte_addr (char * str)
-{
-  int op = (inst.instruction & 0x300) >> 8;
-  int reg;
-
-  inst.instruction &= ~0x300;
-  inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
-
-  skip_whitespace (str);
-
-  if ((reg = wreg_required_here (&str, 12, REG_TYPE_MMXWR)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || cp_byte_address_required_here (&str) == FAIL)
-    {
-      if (! inst.error)
-        inst.error = BAD_ARGS;
-    }
-  else
-    end_of_line (str);
-}
-
-static void
 do_iwmmxt_tandc (char * str)
 {
   int reg;
@@ -8894,7 +8509,8 @@
 {
   unsigned long number;
 
-  if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
+  if ((number = check_iwmmxt_insn (str, check_textrc, 7))
+      == (unsigned long) FAIL)
     return;
 
   inst.instruction |= number & 0x7;
@@ -8905,7 +8521,8 @@
 {
   unsigned long number;
 
-  if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
+  if ((number = check_iwmmxt_insn (str, check_textrm, 7))
+      == (unsigned long) FAIL)
     return;
 
   inst.instruction |= number & 0x7;
@@ -8916,7 +8533,8 @@
 {
   unsigned long number;
 
-  if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
+  if ((number = check_iwmmxt_insn (str, check_tinsr, 7))
+      == (unsigned long) FAIL)
     return;
 
   inst.instruction |= number & 0x7;
@@ -8969,7 +8587,8 @@
 {
   unsigned long number;
 
-  if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
+  if ((number = check_iwmmxt_insn (str, check_waligni, 7))
+      == (unsigned long) FAIL)
     return;
 
   inst.instruction |= ((number & 0x7) << 20);
@@ -8985,40 +8604,50 @@
 }
 
 static void
-do_iwmmxt_word_addr (char * str)
+do_iwmmxt_wldst (char * str)
 {
-  int op = (inst.instruction & 0x300) >> 8;
-  int reg;
+  skip_whitespace (str);
 
-  inst.instruction &= ~0x300;
-  inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
+  reg_or_fail (&str, 12, REG_TYPE_MMXWR);
+  comma_or_fail (&str);
 
+  if (cp_byte_address_required_here (&str) == FAIL)
+    return;
+
+  end_of_line (str);
+}
+
+static void
+do_iwmmxt_wldstw (char * str)
+{
+  struct reg_entry *reg;
+
   skip_whitespace (str);
 
-  if ((reg = wreg_required_here (&str, 12, REG_TYPE_MMXWR)) == FAIL)
+  if ((reg = arm_reg_parse_multi (&str)) == NULL
+      || (reg->type != REG_TYPE_MMXWR && reg->type != REG_TYPE_MMXWC))
     {
-      inst.error = 0;
-      if ((reg = wreg_required_here (&str, 12, REG_TYPE_MMXWC)) == FAIL)
-	return;
-      
-      if ((inst.instruction & COND_MASK) != COND_ALWAYS)
-	inst.error = _("conditional execution not supported "
-		       "with control register");
-      if (op != 2)
-	inst.error = _("non-word size not supported with control register");
-      inst.instruction |=  0xf0000100;
-      inst.instruction &= ~0x00400000;
+      inst.error = _("iWMMXt data or control register expected");
+      return;
     }
+  comma_or_fail (&str);
 
-  if (skip_past_comma (& str) == FAIL
-      || cp_address_required_here (& str, CP_WB_OK) == FAIL)
+  if (cp_address_required_here (&str, CP_WB_OK) == FAIL)
+    return;
+  end_of_line (str);
+
+  if (reg->type == REG_TYPE_MMXWC)
     {
-      if (! inst.error)
-        inst.error = BAD_ARGS;
-      return;
+      if ((inst.instruction & COND_MASK) != COND_ALWAYS)
+	{
+	  inst.error = _("conditional execution not supported "
+			 "with control register");
+	  return;
+	}
+      inst.instruction |= 0xf0000000;
     }
 
-  end_of_line (str);
+  inst.instruction |= reg->number << 12;
 }
 
 static void
@@ -9044,7 +8673,8 @@
 {
   unsigned long number;
 
-  if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
+  if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff))
+      == (unsigned long) FAIL)
     return;
 
   inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
@@ -9056,7 +8686,10 @@
   if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
     return;
 
-  inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
+  /* WZERO reg is an alias for WANDN reg, reg, reg.
+     Copy Rm field to Rd and Rn.  */
+  inst.instruction |= ((inst.instruction & 0xf) << 12);
+  inst.instruction |= ((inst.instruction & 0xf) << 16);
 }
 
 /* Cirrus Maverick instructions.  Simple 2-, 3-, and 4-register
@@ -9076,16 +8709,12 @@
   shift1 = (mode >> 8) & 0xff;
 
   skip_whitespace (str);
+  reg_or_fail (&str, shift0, reg0);
 
-  if (mav_reg_required_here (&str, shift0, reg0) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, shift1, reg1) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-    }
-  else
-    end_of_line (str);
+  comma_or_fail (&str);
+  reg_or_fail (&str, shift1, reg1);
+
+  end_of_line (str);
 }
 
 /* Isnsn like "foo X,Y,Z".  */
@@ -9104,18 +8733,15 @@
   shift2 = (mode >> 16) & 0xff;
 
   skip_whitespace (str);
+  reg_or_fail (&str, shift0, reg0);
 
-  if (mav_reg_required_here (&str, shift0, reg0) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, shift1, reg1) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, shift2, reg2) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-    }
-  else
-    end_of_line (str);
+  comma_or_fail (&str);
+  reg_or_fail (&str, shift1, reg1);
+
+  comma_or_fail (&str);
+  reg_or_fail (&str, shift2, reg2);
+
+  end_of_line (str);
 }
 
 /* Insn like "foo W,X,Y,Z".
@@ -9137,20 +8763,18 @@
   shift3 = (mode >> 24) & 0xff;
 
   skip_whitespace (str);
+  reg_or_fail (&str, shift0, reg0);
 
-  if (mav_reg_required_here (&str, shift0, reg0) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, shift1, reg1) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, shift2, reg2) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, shift3, reg3) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-    }
-  else
-    end_of_line (str);
+  comma_or_fail (&str);
+  reg_or_fail (&str, shift1, reg1);
+
+  comma_or_fail (&str);
+  reg_or_fail (&str, shift2, reg2);
+
+  comma_or_fail (&str);
+  reg_or_fail (&str, shift3, reg3);
+
+  end_of_line (str);
 }
 
 /* Wrapper functions.  */
@@ -9368,17 +8992,10 @@
 {
   skip_whitespace (str);
 
-  /* cfmvsc32.  */
-  if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
+  reg_or_fail (&str, -1, REG_TYPE_DSPSC);
+  comma_or_fail (&str);
 
-      return;
-    }
-
+  reg_or_fail (&str, 12, REG_TYPE_MVDX);
   end_of_line (str);
 }
 
@@ -9388,17 +9005,10 @@
 {
   skip_whitespace (str);
 
-  /* cfmv32sc.  */
-  if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
+  reg_or_fail (&str, 12, REG_TYPE_MVDX);
+  comma_or_fail (&str);
 
-      return;
-    }
-
+  reg_or_fail (&str, -1, REG_TYPE_DSPSC);
   end_of_line (str);
 }
 
@@ -9411,22 +9021,15 @@
 	      enum arm_reg_type reg0,
 	      enum arm_reg_type reg1)
 {
-  int error;
   int imm, neg = 0;
 
   skip_whitespace (str);
 
-  error = 0;
+  reg_or_fail (&str, 12, reg0);
+  comma_or_fail (&str);
 
-  if (mav_reg_required_here (&str, 12, reg0) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || mav_reg_required_here (&str, 16, reg1) == FAIL
-      || skip_past_comma  (&str) == FAIL)
-    {
-      if (!inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
+  reg_or_fail (&str, 16, reg1);
+  comma_or_fail (&str);
 
   /* Calculate the immediate operand.
      The operand is a 7bit signed number.  */
@@ -9495,11 +9098,14 @@
 
   skip_whitespace (str);
 
-  if (mav_reg_required_here (&str, 12, reg0) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || *str++ != '['
-      || reg_required_here (&str, 16, FALSE) == FAIL)
-    goto fail_ldst;
+  reg_or_fail (&str, 12, reg0);
+  comma_or_fail (&str);
+  if (*str++ != '[')
+    {
+      inst.error = BAD_ARGS;
+      return;
+    }
+  reg_or_fail (&str, 16, REG_TYPE_RN);
 
   if (skip_past_comma (&str) == SUCCESS)
     {
@@ -9532,12 +9138,15 @@
 	  return;
 	}
 
-      if (skip_past_comma (&str) == FAIL
-	  || (offset = mav_parse_offset (&str, &negative), inst.error))
-	goto fail_ldst;
+      comma_or_fail (&str);
 
+      offset = mav_parse_offset (&str, &negative);
+      if (inst.error)
+	return;
+
       inst.instruction |= CP_T_WB; /* Post indexed, set bit W.  */
     }
+  end_of_line (str);
 
   if (negative)
     offset = -offset;
@@ -9545,12 +9154,6 @@
     inst.instruction |= CP_T_UD; /* Positive, so set bit U.  */
 
   inst.instruction |= offset >> 2;
-  end_of_line (str);
-  return;
-
-fail_ldst:
-  if (!inst.error)
-     inst.error = BAD_ARGS;
 }
 
 static void
@@ -9587,14 +9190,15 @@
 static void
 do_xsc_mia (char * str)
 {
-  if (xsc_reg_required_here (&str) == FAIL)
-    return;
+  skip_whitespace (str);
+
+  reg_or_fail (&str, -1, REG_TYPE_XSCALE);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 0, TRUE);
+  reg_nonpc_or_fail (&str, 0);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   end_of_line (str);
 }
 
@@ -9605,14 +9209,15 @@
 static void
 do_xsc_mar (char * str)
 {
-  if (xsc_reg_required_here (& str) == FAIL)
-    return;
+  skip_whitespace (str);
+
+  reg_or_fail (&str, -1, REG_TYPE_XSCALE);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 12, TRUE);
+  reg_nonpc_or_fail (&str, 12);
   comma_or_fail (&str);
 
-  reg_or_fail (&str, 16, TRUE);
+  reg_nonpc_or_fail (&str, 16);
   end_of_line (str);
 }
 
@@ -9628,14 +9233,13 @@
 
   skip_whitespace (str);
 
-  note_reg_or_fail (rdlo, &str, 12, TRUE);
+  note_reg_nonpc_or_fail (rdlo, &str, 12);
   comma_or_fail (&str);
 
-  note_reg_or_fail (rdhi, &str, 16, TRUE);
+  note_reg_nonpc_or_fail (rdhi, &str, 16);
   comma_or_fail (&str);
 
-  if (xsc_reg_required_here (& str) == FAIL)
-    return;
+  reg_or_fail (&str, -1, REG_TYPE_XSCALE);
   end_of_line (str);
 
   /* inst.instruction has now been zapped with both rdlo and rdhi.  */
@@ -10946,10 +10550,10 @@
   {"wcmpgtsb",   0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
   {"wcmpgtsh",   0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
   {"wcmpgtsw",   0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
-  {"wldrb",      0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
-  {"wldrh",      0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
-  {"wldrw",      0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
-  {"wldrd",      0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
+  {"wldrb",      0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldst},
+  {"wldrh",      0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldst},
+  {"wldrw",      0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldstw},
+  {"wldrd",      0xec500100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldst},
   {"wmacs",      0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
   {"wmacsz",     0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
   {"wmacu",      0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
@@ -11009,10 +10613,10 @@
   {"wsrlwg",     0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
   {"wsrld",      0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
   {"wsrldg",     0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
-  {"wstrb",      0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
-  {"wstrh",      0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
-  {"wstrw",      0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
-  {"wstrd",      0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
+  {"wstrb",      0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldst},
+  {"wstrh",      0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldst},
+  {"wstrw",      0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldstw},
+  {"wstrd",      0xec400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wldst},
   {"wsubbss",    0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
   {"wsubb",      0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
   {"wsubbus",    0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},

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