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


parse_operands conversion for MSR, and some tidying to parse_operands
itself.  Also, this patch begins a trend of removing code from the
operand encoding functions which is redundant with code in
md_apply_fix3.

zw

	* config/tc-arm.c (psr_required_here): Rename parse_psr.  Return the
        PSR mask rather than poking it into inst.instruction.
	(OP_PSR, OP_RR_iEX): New operand parse codes.
	(parse_operands): Handle them.
	(po_reg_or_goto): New parse_operands shorthand macro; use it to
	implement RR_EX, RR_EXr, RR_iEX, RL_iEX, and RRnpc_I0.
	(do_msr): Use parse_operands.  Defer processing of immediate value
	to md_apply_fix3.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 34)
+++ gas/config/tc-arm.c	(revision 35)
@@ -2122,21 +2122,21 @@
 /* Miscellaneous: PSR flags, endian specifiers, coprocessor
    operands. */
 
-/* Parse the input looking for a PSR flag.  */
+/* Parse a PSR flag operand.  The value returned is FAIL on syntax error,
+   or a bitmask suitable to be or-ed into the ARM msr instruction.  */
 static int
-psr_required_here (char **str)
+parse_psr (char **str)
 {
   char *p;
-  bfd_boolean is_spsr;
   unsigned long psr_field;
 
   /* CPSR's and SPSR's can now be lowercase.  This is just a convenience
      feature for ease of use and backwards compatibility.  */
   p = *str;
   if (*p == 's' || *p == 'S')
-    is_spsr = TRUE;
+    psr_field = SPSR_BIT;
   else if (*p == 'c' || *p == 'C')
-    is_spsr = FALSE;
+    psr_field = 0;
   else
     goto error;
 
@@ -2162,24 +2162,17 @@
       if (!psr)
 	goto error;
 
-      psr_field = psr->field;
+      psr_field |= psr->field;
     }
   else
     {
       if (ISALNUM (*p))
 	goto error;    /* Garbage after "[CS]PSR".  */
 
-      psr_field = (PSR_c | PSR_f);
+      psr_field |= (PSR_c | PSR_f);
     }
-
-  /* If this is the SPSR that is being modified, set the R bit.  */
-  if (is_spsr)
-    inst.instruction |= SPSR_BIT;
-
-  /* Set the psr flags in the MSR instruction.  */
-  inst.instruction |= psr_field;
   *str = p;
-  return SUCCESS;
+  return psr_field;
 
  error:
   inst.error = _("flag for {c}psr instruction expected");
@@ -4344,12 +4337,14 @@
 
 #define OP_CPSF	   060  /* CPS flags */
 #define OP_ENDI	   061	/* Endianness specifier */
+#define OP_PSR     062  /* CPSR/SPSR mask for msr */
 
 /* This-or-that operands.  All have bit 7 set.  */
 #define OP_RR_EX   100	/* ARM register or expression */
 #define OP_RL_iEX  101	/* Thumb low register or expression with imm prefix */
 #define OP_RRnpc_I0 102	/* ARM register or literal 0 */
 #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 */
 
 /* Optional operands.  All have the high bit set.  */
 #define OP_obI7    200  /* optional, prefix optional, immediate 0 .. 7 */
@@ -4410,6 +4405,15 @@
   inst.operands[i].isreg = 1;				\
 } while (0)
 
+#define po_reg_or_goto(regtype, label) do {	\
+  int reg_ = arm_reg_parse (&str, regtype);	\
+  if (reg_ == FAIL)				\
+    goto label;					\
+						\
+  inst.operands[i].reg = reg_;			\
+  inst.operands[i].isreg = 1;			\
+} while (0)
+
 #define po_imm_or_fail(min, max, popt) do {				\
   int imm_;								\
   if (immediate_required_here (&str, &imm_, min, max, popt) == FAIL)	\
@@ -4496,6 +4500,7 @@
 	  break;
 	  
 	  /* 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;
@@ -4542,11 +4547,13 @@
 	  
 	  /* Expressions */
 	case OP_(iEXP):
+	iEXP:
 	  if (is_immediate_prefix (*str))
 	    str++;
 	  /* fall through */
 	  
 	case OP_(EXP):
+	EXP:
 	  if (my_get_expression (&inst.reloc.exp, &str))
 	    return FAIL;
 	  break;
@@ -4572,62 +4579,22 @@
 	  break;
 
 	  /* Register or expression */
-	case OP_(RR_EX):
-	  {
-	    int reg_ = arm_reg_parse (&str, REG_TYPE_RN);
-	    if (reg_ != FAIL)
-	      {
-		inst.operands[i].reg = reg_;
-		inst.operands[i].isreg = 1;
-	      }
-	    else if (my_get_expression (&inst.reloc.exp, &str))
-		return FAIL;
-	  }
-	  break;
+	case OP_(RR_EX):  po_reg_or_goto (REG_TYPE_RN, EXP);  break;
+	case OP_(RR_EXr): po_reg_or_goto (REG_TYPE_RN, EXPr); break;
+	case OP_(RR_iEX): po_reg_or_goto (REG_TYPE_RN, iEXP); break;
 
-	case OP_(RR_EXr):
-	  {
-	    int reg_ = arm_reg_parse (&str, REG_TYPE_RN);
-	    if (reg_ != FAIL)
-	      {
-		inst.operands[i].reg = reg_;
-		inst.operands[i].isreg = 1;
-	      }
-	    else
-	      goto EXPr;
-	  }
-	  break;
-
 	case OP_(oRL_iEX):
 	case OP_(RL_iEX):
-	  if (is_immediate_prefix (*str))
-	    {
-	      str++;
-	      if (my_get_expression (&inst.reloc.exp, &str))
-		return FAIL;
-	    }
-	  else
-	    {
-	      po_reg_or_fail (REG_TYPE_RN);
-	      if (inst.operands[i].reg > 7)
-		inst.error = BAD_HIREG;
-	    }
+	  po_reg_or_goto (REG_TYPE_RN, iEXP);
+	  if (inst.operands[i].reg > 7)
+	    inst.error = BAD_HIREG;
 	  break;
 
 	  /* Register or immediate */
 	case OP_(RRnpc_I0):
-	  {
-	    int reg_ = arm_reg_parse (&str, REG_TYPE_RN);
-	    if (reg_ != FAIL)
-	      {
-		inst.operands[i].reg = reg_;
-		inst.operands[i].isreg = 1;
-		if (reg_ == REG_PC)
-		  inst.error = BAD_PC;
-	      }
-	    else
-	      po_imm_or_fail (0, 0, FALSE);
-	  }
+	  po_reg_or_goto (REG_TYPE_RN, I0);
+	  if (inst.operands[i].reg == REG_PC)
+	    inst.error = BAD_PC;
 	  break;
 
 	  /* Misc */
@@ -4645,6 +4612,15 @@
 	  if (parse_ror (&inst.operands[i].imm, &str))
 	    return FAIL;
 	  break;
+
+	case OP_(PSR):
+	  {
+	    int psrmask = parse_psr (&str);
+	    if (psrmask == FAIL)
+	      return FAIL;
+	    inst.operands[i].imm = psrmask;
+	  }
+	  break;
 	  
 	default:
 	  as_fatal ("unhandled operand code %03o", *p);
@@ -5764,56 +5740,18 @@
 static void
 do_msr (char * str)
 {
-  if (psr_required_here (&str) == FAIL)
+  if (parse_operands (str, OPERANDS2(PSR,RR_iEX)))
     return;
 
-  comma_or_fail (&str);
-
-  if (reg_required_here (&str, 0, REG_TYPE_RN) != FAIL)
+  inst.instruction |= inst.operands[0].imm;
+  if (inst.operands[1].isreg)
+    inst.instruction |= inst.operands[1].reg;
+  else
     {
-      end_of_line (str);
-      return;
-    }
-
-  if (! is_immediate_prefix (* str))
-    {
-      inst.error =
-	_("only a register or immediate value can follow a psr flag");
-      return;
-    }
-
-  str ++;
-  inst.error = NULL;
-
-  if (my_get_expression (& inst.reloc.exp, & str))
-    {
-      inst.error =
-	_("only a register or immediate value can follow a psr flag");
-      return;
-    }
-
-  inst.instruction |= INST_IMMEDIATE;
-
-  if (inst.reloc.exp.X_add_symbol)
-    {
+      inst.instruction |= INST_IMMEDIATE;
       inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
       inst.reloc.pc_rel = 0;
     }
-  else
-    {
-      unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
-
-      if (value == (unsigned) FAIL)
-	{
-	  inst.error = _("invalid constant");
-	  return;
-	}
-
-      inst.instruction |= value;
-    }
-
-  inst.error = NULL;
-  end_of_line (str);
 }
 
 static void

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