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


Refactor coprocessor address parsing for use via parse_operands; this
allows conversion of most of the remaining coprocessor encode
functions, and friendlier diagnostics for some ill-formed VFP
instructions.

zw

	* config/tc-arm.c (struct arm_it): Add postind field to operands;
	reorder operands bitfields to put all address bits together.
	(CP_T_PRE, CP_T_UD, CP_T_WB): Delete.
	(cp_address_required_here): Split into parse_cp_address and
	encode_cp_address_arm.  Restructure for use via parse_operands.
	(OP_I4): Rename OP_bI4.
	(OP_CADDR, OP_RIWR_RIWC): New operand parse codes.
	(parse_operands): Support new codes.  Do not require prefix for bI4.
	(do_lstc, do_vfp_sp_ldst, do_vfp_dp_ldst, dp_fpa_ldst, do_fpa_ldmstm)
	(do_iwmmxt_wldst, do_iwmmxt_wldstw, do_mav_ldst): Use parse_operands.
	(do_mav_ldst_1, do_mav_ldst_2, do_mav_ldst_3, do_mav_ldst_4):
	Update to match.
	(md_apply_fix3): Share most code between BFD_RELOC_ARM_CP_OFF_IMM and
	BFD_RELOC_ARM_CP_OFF_IMM_S2.  For these, clear WRITE_BACK if value is
	zero.
	* testsuite/gas/arm/vfp-bad.l: Adjust expected diagnostics.

===================================================================
Index: gas/testsuite/gas/arm/vfp-bad.l
--- gas/testsuite/gas/arm/vfp-bad.l	(revision 48)
+++ gas/testsuite/gas/arm/vfp-bad.l	(revision 49)
@@ -1,9 +1,9 @@
 [^:]*: Assembler messages:
-[^:]*:4: Error: garbage following instruction -- `fstd d0,\[r0\],#8'
-[^:]*:5: Error: garbage following instruction -- `fstd d0,\[r0,#-8\]!'
-[^:]*:6: Error: garbage following instruction -- `fsts s0,\[r0\],#8'
-[^:]*:7: Error: garbage following instruction -- `fsts s0,\[r0,#-8\]!'
-[^:]*:8: Error: garbage following instruction -- `fldd d0,\[r0\],#8'
-[^:]*:9: Error: garbage following instruction -- `fldd d0,\[r0,#-8\]!'
-[^:]*:10: Error: garbage following instruction -- `flds s0,\[r0\],#8'
-[^:]*:11: Error: garbage following instruction -- `flds s0,\[r0,#-8\]!'
+[^:]*:4: Error: instruction does not support writeback -- `fstd d0,\[r0\],#8'
+[^:]*:5: Error: instruction does not support writeback -- `fstd d0,\[r0,#-8\]!'
+[^:]*:6: Error: instruction does not support writeback -- `fsts s0,\[r0\],#8'
+[^:]*:7: Error: instruction does not support writeback -- `fsts s0,\[r0,#-8\]!'
+[^:]*:8: Error: instruction does not support writeback -- `fldd d0,\[r0\],#8'
+[^:]*:9: Error: instruction does not support writeback -- `fldd d0,\[r0,#-8\]!'
+[^:]*:10: Error: instruction does not support writeback -- `flds s0,\[r0\],#8'
+[^:]*:11: Error: instruction does not support writeback -- `flds s0,\[r0,#-8\]!'
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 48)
+++ gas/config/tc-arm.c	(revision 49)
@@ -198,9 +198,11 @@
     int present    : 1;  /* operand present */
     int isreg	   : 1;  /* operand was a register */
     int immisreg   : 1;  /* .imm field is a second register */
-    int writeback  : 1;  /* operand has trailing ! */
     int hasreloc   : 1;  /* operand has relocation suffix */
-    int postind    : 1;  /* operand is post-indexed */
+    int writeback  : 1;  /* operand has trailing ! */
+    int preind     : 1;  /* preindexed address */
+    int postind    : 1;  /* postindexed address */
+    int negative   : 1;  /* index register was negated */
   } operands[6];
 };
 
@@ -287,9 +289,6 @@
 
 #define CP_T_X   0x00008000
 #define CP_T_Y   0x00400000
-#define CP_T_Pre 0x01000000
-#define CP_T_UD  0x00800000
-#define CP_T_WB  0x00200000
 
 #define CONDS_BIT        0x00100000
 #define LOAD_BIT         0x00100000
@@ -2096,141 +2095,155 @@
   return FAIL;
 }
 
+/* Parse a coprocessor address expression:
+
+      [Rl]{!}	      shorthand for [Rl,#0]{!}
+      [Rl,offset]{!}  +-8 bits, *4 (usually) - preindex, opt. writeback
+      [Rl],offset     +-8 bits, *4 (usually) - postindex
+      [Rl],\{number\} 8 bits - no relocation - "unindexed" (magic)
+      label	      translated to [PC, offset]
+
+   Data is written to inst.operands[i] and/or inst.reloc.exp.
+   Returns SUCCESS or FAIL.  Does not check for no-writeback / no-unindex.  */
+
 static int
-cp_address_required_here (char ** str, int wb_ok, int reloc)
+parse_cp_address (char **str, int i)
 {
-  char * p = * str;
-  int    pre_inc = 0;
-  int    write_back = 0;
+  char  *p = *str;
 
-  if (*p == '[')
-    {
-      int reg;
+  if (skip_past_char (&p, '[') == FAIL)
+    { /* bare address - translate to PC-relative offset */
+      if (my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX))
+	return FAIL;
 
-      p++;
+      inst.reloc.pc_rel = 1;
+      inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
+      inst.operands[i].reg = REG_PC;
+      inst.operands[i].preind = 1;
+      *str = p;
+      return SUCCESS;
+    }
 
-      if ((reg = reg_required_here (&p, 16, REG_TYPE_RN)) == FAIL)
-	return FAIL;
+  if ((inst.operands[i].reg = reg_required_here (&p, -1, REG_TYPE_RN)) == FAIL)
+    return FAIL;
 
-      if (*p == ']')
+  if (skip_past_char (&p, ']') == SUCCESS)
+    {
+      if (*p == '\0' || *p == '!')  /* [Rn]{!} - shorthand for [Rn,#0]{!} */
 	{
-	  p++;
+	  inst.operands[i].preind = 1;
+	  inst.operands[i].writeback = (*p == '!');
+	  inst.reloc.exp.X_op = O_constant;
+	  inst.reloc.exp.X_add_number = 0;
+	  *str = p + (*p == '!');
+	  return SUCCESS;
+	}
 
-	  if (*p == '\0')
-	    {
-	      /* As an extension to the official ARM syntax we allow:
-		   [Rn]
-	         as a short hand for:
-		   [Rn,#0]  */
-	      inst.instruction |= PRE_INDEX | INDEX_UP;
-	      *str = p;
-	      return SUCCESS;
-	    }
+      if (skip_past_comma (&p) == FAIL)
+	{
+	  inst.error = _("comma expected after closing square bracket");
+	  return FAIL;
+	}
 
-	  if (skip_past_comma (& p) == FAIL)
-	    {
-	      inst.error = _("comma expected after closing square bracket");
-	      return FAIL;
-	    }
+      if (skip_past_char (&p, '{') == SUCCESS)
+	{
+	  /* [Rn], {expr} - unindexed, with option */
+	  if (immediate_required_here (&p, &inst.operands[i].imm,
+				       0, 255, TRUE) == FAIL)
+	    return FAIL;
 
-	  if (*p == '#')
+	  if (skip_past_char (&p, '}') == FAIL)
 	    {
-	      if (wb_ok)
-		{
-		  /* [Rn], #expr  */
-		  write_back = WRITE_BACK;
-
-		  if (reg == REG_PC)
-		    {
-		      inst.error = _("pc may not be used in post-increment");
-		      return FAIL;
-		    }
-
-		  if (my_get_expression (& inst.reloc.exp, &p, GE_IMM_PREFIX))
-		    return FAIL;
-		  inst.reloc.type = reloc;
-		}
-	      else
-		pre_inc = PRE_INDEX | INDEX_UP;
-	    }
-	  else if (*p == '{')
-	    {
-	      int option;
-
-	      /* [Rn], {<expr>}  */
-	      p++;
-	      if (immediate_required_here (&p, &option, 0, 255, TRUE) == FAIL)
-		return FAIL;
-
-	      if (*p != '}')
-		{
-		  inst.error = _("'}' expected at end of 'option' field");
-		  return FAIL;
-		}
-	      else
-		{
-		  p++;
-		  inst.instruction |= option;
-		  inst.instruction |= INDEX_UP;
-		}
-	    }
-	  else
-	    {
-	      inst.error = _("# or { expected after comma");
+	      inst.error = _("'}' expected at end of 'option' field");
 	      return FAIL;
 	    }
 	}
       else
 	{
-	  /* '['Rn, #expr']'[!]  */
-
-	  if (skip_past_comma (& p) == FAIL)
-	    {
-	      inst.error = _("pre-indexed expression expected");
-	      return FAIL;
-	    }
-
-	  if (my_get_expression (& inst.reloc.exp, &p, GE_IMM_PREFIX))
+	  if (my_get_expression (&inst.reloc.exp, &p, GE_IMM_PREFIX))
 	    return FAIL;
-	  inst.reloc.type = reloc;
-	  pre_inc = PRE_INDEX;
 
-	  if (*p++ != ']')
-	    {
-	      inst.error = _("missing ]");
-	      return FAIL;
-	    }
-
-	  if (wb_ok && *p == '!')
-	    {
-	      if (reg == REG_PC)
-		{
-		  inst.error = _("pc may not be used with write-back");
-		  return FAIL;
-		}
-
-	      p++;
-	      write_back = WRITE_BACK;
-	    }
+	  inst.operands[i].postind = 1;
+	  inst.operands[i].writeback = 1;
 	}
     }
   else
     {
-      if (my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX))
+      /* '['Rn, #expr']'[!]  */
+      if (skip_past_comma (&p) == FAIL)
+	{
+	  inst.error = _("pre-indexed expression expected");
+	  return FAIL;
+	}
+
+      if (my_get_expression (&inst.reloc.exp, &p, GE_IMM_PREFIX))
 	return FAIL;
 
-      inst.reloc.type = reloc;
-      inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
-      inst.reloc.pc_rel = 1;
-      inst.instruction |= (REG_PC << 16);
-      pre_inc = PRE_INDEX;
-    }
+      if (skip_past_char (&p, ']') == FAIL)
+	{
+	  inst.error = _("missing ]");
+	  return FAIL;
+	}
 
-  inst.instruction |= write_back | pre_inc;
+      if (skip_past_char (&p, '!') == SUCCESS)
+	inst.operands[i].writeback = 1;
+
+      inst.operands[i].preind = 1;
+    }
   *str = p;
   return SUCCESS;
 }
 
+/* inst.operands[i] was set up by parse_cp_address.  Encode it into an
+   ARM-format instruction.  If wb_ok is false, reject use of writeback;
+   if unind_ok is false, reject use of unindexed addressing.  If
+   reloc_override is not 0, use it instead of BFD_ARM_CP_OFF_IMM.  */
+
+static int
+encode_cp_address_arm (int i, int wb_ok, int unind_ok, int reloc_override)
+{
+  inst.instruction |= inst.operands[i].reg << 16;
+
+  assert (!(inst.operands[i].preind && inst.operands[i].postind));
+
+  if (!inst.operands[i].preind && !inst.operands[i].postind) /* unindexed */
+    { 
+      assert (!inst.operands[i].writeback);
+      if (!unind_ok)
+	{
+	  inst.error = _("instruction does not support unindexed addressing");
+	  return FAIL;
+	}
+      inst.instruction |= inst.operands[i].imm;
+      inst.instruction |= INDEX_UP;
+      return SUCCESS;
+    }
+
+  if (inst.operands[i].preind)
+    inst.instruction |= PRE_INDEX;
+
+  if (inst.operands[i].writeback)
+    {
+      if (inst.operands[i].reg == REG_PC)
+	{
+	  inst.error = _("pc may not be used with write-back");
+	  return FAIL;
+	}
+      if (!wb_ok)
+	{
+	  inst.error = _("instruction does not support writeback");
+	  return FAIL;
+	}
+      inst.instruction |= WRITE_BACK;
+    }
+
+  if (reloc_override)
+    inst.reloc.type = reloc_override;
+  else
+    inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
+  return SUCCESS;
+}
+
 /* Parse a Thumb address expression:
 
       [Rl]
@@ -4120,7 +4133,6 @@
 #define OP_EXPr    026  /* same, with optional relocation suffix */
 
 #define OP_I0      027  /* immediate value 0 */
-#define OP_I4      030  /*                 1 .. 4 */
 #define OP_I7      031  /*                 0 .. 7 */
 #define OP_I15     032  /*                 0 .. 15 */
 #define OP_I16     033  /*                 1 .. 16 */
@@ -4133,6 +4145,7 @@
 #define OP_bI7     041  /* immediate, prefix optional, 0 .. 7 */
 #define OP_bI15    042  /*                             0 .. 15 */
 #define OP_bI31    043  /*                             0 .. 31 */
+#define OP_bI4     030  /*                 	       1 .. 4 */
 
 #define OP_I31w    050  /* 0 .. 31, optional trailing ! */
 #define OP_RRw     051  /* ARM register, not the PC, optional trailing ! */
@@ -4148,6 +4161,7 @@
 #define OP_VRDLST  065	/* VFP double-precision register list */
 
 #define OP_TADDR   070	/* Thumb memory address expression */
+#define OP_CADDR   071  /* Co-processor memory address expression */
 
 /* This-or-that operands.  All have bit 7 set.  */
 #define OP_RR_EX   100  /* ARM register or expression */
@@ -4156,6 +4170,7 @@
 #define OP_RR_EXr  103  /* ARM register or expression with opt. reloc suff. */
 #define OP_RR_iEX  104  /* ARM register or expression with imm prefix */
 #define OP_RF_IF   105  /* FPA register or immediate */
+#define OP_RIWR_RIWC 106  /* iWMMXt R or C reg */
 
 /* Optional operands.  All have the high bit set.  */
 #define OP_obI7    200  /* optional, prefix optional, immediate 0 .. 7 */
@@ -4283,7 +4298,6 @@
 	  /* Immediates */
 	I0:
 	case OP_(I0):	 po_imm_or_fail (  0,      0, FALSE);	break;
-	case OP_(I4):	 po_imm_or_fail (  1,      4, FALSE);	break;
 	case OP_(I7):	 po_imm_or_fail (  0,      7, FALSE);	break;
 	case OP_(I15):	 po_imm_or_fail (  0,     15, FALSE);	break;
 	case OP_(I16):	 po_imm_or_fail (  1,     16, FALSE);	break;
@@ -4293,6 +4307,7 @@
 	case OP_(I255):  po_imm_or_fail (  0,    255, FALSE);	break;
 	case OP_(Iffff): po_imm_or_fail (  0, 0xffff, FALSE);	break;
 
+	case OP_(bI4):	 po_imm_or_fail (  1,      4, TRUE);	break;
 	case OP_(obI7):
 	case OP_(bI7):   po_imm_or_fail (  0,      7, TRUE);    break;
 	case OP_(bI15):  po_imm_or_fail (  0,     15, TRUE);    break;
@@ -4386,6 +4401,20 @@
 	    }
 	  break;
 
+	  /* Two kinds of register */
+	case OP_(RIWR_RIWC):
+	  {
+	    struct reg_entry *rege = arm_reg_parse_multi (&str);
+	    if (rege->type != REG_TYPE_MMXWR && rege->type != REG_TYPE_MMXWC)
+	      {
+		inst.error = _("iWMMXt data or control register expected");
+		return FAIL;
+	      }
+	    inst.operands[i].reg = rege->number;
+	    inst.operands[i].isreg = (rege->type == REG_TYPE_MMXWR);
+	  }
+	  break;
+
 	  /* Misc */
 	case OP_(CPSF):	 val = parse_cps_flags (&str);		break;
 	case OP_(ENDI):	 val = parse_endian_specifier (&str);	break;
@@ -4416,6 +4445,11 @@
 	    return FAIL;
 	  break;
 
+	case OP_(CADDR):
+	  if (parse_cp_address (&str, i))
+	    return FAIL;
+	  break;
+
 	default:
 	  as_fatal ("unhandled operand code %03o", *p);
 	}
@@ -5446,21 +5480,17 @@
   end_of_line (str);
 }
 
+/* Co-processor register load/store.
+   Format: <LDC|STC>{cond}[L] CP#,CRd,<address>  */
 static void
 do_lstc (char * str)
 {
-  /* Co-processor register load/store.
-     Format: <LDC|STC{cond}[L] CP#,CRd,<address>  */
-
-  reg_or_fail (&str, 8, REG_TYPE_CP);
-  comma_or_fail (&str);
-
-  reg_or_fail (&str, 12, REG_TYPE_CN);
-  comma_or_fail (&str);
-
-  if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+  if (parse_operands (str, OPERANDS3(RCP,RCN,CADDR)))
     return;
-  end_of_line (str);
+
+  inst.instruction |= inst.operands[0].reg << 8;
+  inst.instruction |= inst.operands[1].reg << 12;
+  encode_cp_address_arm (2, TRUE, TRUE, 0);
 }
 
 static void
@@ -6764,25 +6794,21 @@
 static void
 do_vfp_sp_ldst (char * str)
 {
-  reg_or_fail (&str, VFP_REG_Sd, REG_TYPE_VFS);
-  comma_or_fail (&str);
-
-  if (cp_address_required_here (&str, FALSE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+  if (parse_operands (str, OPERANDS2(RVS,CADDR)))
     return;
 
-  end_of_line (str);
+  vfp_sp_encode_reg (inst.operands[0].reg, VFP_REG_Sd);
+  encode_cp_address_arm (1, FALSE, TRUE, 0);
 }
 
 static void
 do_vfp_dp_ldst (char * str)
 {
-  reg_or_fail (&str, VFP_REG_Dd, REG_TYPE_VFD);
-  comma_or_fail (&str);
-
-  if (cp_address_required_here (&str, FALSE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+  if (parse_operands (str, OPERANDS2(RVD,CADDR)))
     return;
 
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].reg << VFP_REG_Dd;
+  encode_cp_address_arm (1, FALSE, TRUE, 0);
 }
 
 
@@ -6934,108 +6960,54 @@
 static void
 do_fpa_ldst (char * str)
 {
-  reg_or_fail (&str, 12, REG_TYPE_FN);
-  comma_or_fail (&str);
-
-  if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+  if (parse_operands (str, OPERANDS2(RF,CADDR)))
     return;
-
-  end_of_line (str);
+  inst.instruction |= (inst.operands[0].reg << 12);
+  encode_cp_address_arm (1, TRUE, TRUE, 0);
 }
 
 static void
 do_fpa_ldmstm (char * str)
 {
-  int num_regs;
-
-  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)
+  if (parse_operands (str, OPERANDS3(RF,bI4,CADDR)))
     return;
-  comma_or_fail (&str);
 
-  switch (num_regs)
+  inst.instruction |= (inst.operands[0].reg << 12);
+  switch (inst.operands[1].imm)
     {
-    case 1:
-      inst.instruction |= CP_T_X;
-      break;
-    case 2:
-      inst.instruction |= CP_T_Y;
-      break;
-    case 3:
-      inst.instruction |= CP_T_Y | CP_T_X;
-      break;
-    case 4:
-      break;
-    default:
-      abort ();
+    case 1: inst.instruction |= CP_T_X;   	 break;
+    case 2: inst.instruction |= CP_T_Y;   	 break;
+    case 3: inst.instruction |= CP_T_Y | CP_T_X; break;
+    case 4:					 break;
+    default: abort ();
     }
 
-  if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format.  */
+  if (inst.instruction & (PRE_INDEX | INDEX_UP))
     {
-      int reg;
-      int write_back;
-      int offset;
-
       /* The instruction specified "ea" or "fd", so we can only accept
 	 [Rn]{!}.  The instruction does not really support stacking or
 	 unstacking, so we have to emulate these by setting appropriate
 	 bits and offsets.  */
-
-      char_or_fail (&str, '[');
-      note_reg_or_fail (reg, &str, 16, REG_TYPE_RN);
-      char_or_fail (&str, ']');
-
-      if (*str == '!')
+      if (inst.reloc.exp.X_op != O_constant
+	  || inst.reloc.exp.X_add_number != 0)
 	{
-	  write_back = 1;
-	  str++;
-	  if (reg == REG_PC)
-	    {
-	      inst.error =
-		_("r15 not allowed as base register with write-back");
-	      return;
-	    }
+	  inst.error = _("this instruction does not support indexing");
+	  return;
 	}
+      if (inst.operands[2].writeback)
+	inst.instruction |= WRITE_BACK;
+      if (inst.instruction & (PRE_INDEX | WRITE_BACK))
+	inst.reloc.exp.X_add_number = 12 * inst.operands[1].imm;
       else
-	write_back = 0;
+	inst.instruction |= PRE_INDEX;  /* prevent use of unindexed mode */
 
-      if (inst.instruction & CP_T_Pre)
-	{
-	  /* Pre-decrement.  */
-	  offset = 3 * num_regs;
-	  if (write_back)
-	    inst.instruction |= CP_T_WB;
-	}
-      else
-	{
-	  /* Post-increment.  */
-	  if (write_back)
-	    {
-	      inst.instruction |= CP_T_WB;
-	      offset = 3 * num_regs;
-	    }
-	  else
-	    {
-	      /* No write-back, so convert this into a standard pre-increment
-		 instruction -- aesthetically more pleasing.  */
-	      inst.instruction |= CP_T_Pre | CP_T_UD;
-	      offset = 0;
-	    }
-	}
+      if (!(inst.instruction & INDEX_UP))
+	inst.reloc.exp.X_add_number = -inst.reloc.exp.X_add_number;
 
-      inst.instruction |= offset;
+      inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
     }
   else
-    {
-      if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM)
-	  == FAIL)
-	return;
-    }
-
-  end_of_line (str);
+    encode_cp_address_arm (2, TRUE, TRUE, 0);
 }
 
 
@@ -7188,33 +7160,21 @@
 static void
 do_iwmmxt_wldst (char * str)
 {
-  reg_or_fail (&str, 12, REG_TYPE_MMXWR);
-  comma_or_fail (&str);
-
-  if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM_S2) == FAIL)
+  if (parse_operands (str, OPERANDS2(RIWR,CADDR)))
     return;
 
-  end_of_line (str);
+  inst.instruction |= (inst.operands[0].reg << 12);
+  encode_cp_address_arm (1, TRUE, FALSE, BFD_RELOC_ARM_CP_OFF_IMM_S2);
 }
 
 static void
 do_iwmmxt_wldstw (char * str)
 {
-  struct reg_entry *reg;
-
-  if ((reg = arm_reg_parse_multi (&str)) == NULL
-      || (reg->type != REG_TYPE_MMXWR && reg->type != REG_TYPE_MMXWC))
-    {
-      inst.error = _("iWMMXt data or control register expected");
-      return;
-    }
-  comma_or_fail (&str);
-
-  if (cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM) == FAIL)
+  if (parse_operands (str, OPERANDS2(RIWR_RIWC,CADDR)))
     return;
-  end_of_line (str);
 
-  if (reg->type == REG_TYPE_MMXWC)
+  /* RIWR_RIWC clears .isreg for a control register.  */
+  if (!inst.operands[0].isreg)
     {
       if ((inst.instruction & COND_MASK) != COND_ALWAYS)
 	{
@@ -7225,7 +7185,8 @@
       inst.instruction |= 0xf0000000;
     }
 
-  inst.instruction |= reg->number << 12;
+  inst.instruction |= inst.operands[0].reg << 12;
+  encode_cp_address_arm (1, TRUE, TRUE, 0);
 }
 
 static void
@@ -7606,37 +7567,37 @@
   <insn><cond> CRd,[Rn],<offset>.  */
 
 static void
-do_mav_ldst (char * str, enum arm_reg_type reg0)
+do_mav_ldst (char *str, const char *operands)
 {
-  reg_or_fail (&str, 12, reg0);
-  comma_or_fail (&str);
+  if (parse_operands (str, operands))
+    return;
 
-  cp_address_required_here (&str, TRUE, BFD_RELOC_ARM_CP_OFF_IMM);
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].reg << 12;
+  encode_cp_address_arm (1, TRUE, TRUE, 0);
 }
 
 static void
 do_mav_ldst_1 (char * str)
 {
-  do_mav_ldst (str, REG_TYPE_MVF);
+  do_mav_ldst (str, OPERANDS2(RMF,CADDR));
 }
 
 static void
 do_mav_ldst_2 (char * str)
 {
-  do_mav_ldst (str, REG_TYPE_MVD);
+  do_mav_ldst (str, OPERANDS2(RMD,CADDR));
 }
 
 static void
 do_mav_ldst_3 (char * str)
 {
-  do_mav_ldst (str, REG_TYPE_MVFX);
+  do_mav_ldst (str, OPERANDS2(RMFX,CADDR));
 }
 
 static void
 do_mav_ldst_4 (char * str)
 {
-  do_mav_ldst (str, REG_TYPE_MVDX);
+  do_mav_ldst (str, OPERANDS2(RMDX,CADDR));
 }
 
 /* XScale instructions.  Also sorted arithmetic before move.  */
@@ -10522,28 +10483,25 @@
 #endif
 
     case BFD_RELOC_ARM_CP_OFF_IMM:
-      sign = value >= 0;
       if (value < -1023 || value > 1023 || (value & 3))
 	as_bad_where (fixP->fx_file, fixP->fx_line,
 		      _("co-processor offset out of range"));
+    cp_off_common:
+      sign = value >= 0;
       if (value < 0)
 	value = -value;
       newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
       newval |= (value >> 2) | (sign ? INDEX_UP : 0);
+      if (value == 0)
+	newval &= ~WRITE_BACK;
       md_number_to_chars (buf, newval, INSN_SIZE);
       break;
 
     case BFD_RELOC_ARM_CP_OFF_IMM_S2:
-      sign = value >= 0;
       if (value < -255 || value > 255)
         as_bad_where (fixP->fx_file, fixP->fx_line,
                       _("co-processor offset out of range"));
-      if (value < 0)
-        value = -value;
-      newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
-      newval |= value | (sign ?  INDEX_UP : 0);
-      md_number_to_chars (buf, newval , INSN_SIZE);
-      break;
+      goto cp_off_common;
 
     case BFD_RELOC_ARM_THUMB_OFFSET:
       newval = md_chars_to_number (buf, THUMB_SIZE);

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