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


parse_operands conversion of the generic coprocessor instructions.

zw

	* config/tc-arm.c (struct arm_it): Expand operands array to 6 entries.
	(co_proc_number, cp_opc_expr): Delete.
	(OP_bI7, OP_bI15, OP_obI7): New operand parser codes.
	(parse_operands): Handle them.  Add generic support for
	optional operands, and for immediate values lacking a prefix.
	Treat the pattern string as an array of unsigned char.
	Give a more specific diagnostic when an unknown opcode is
	encountered.
	(do_cdp, do_co_reg, do_co_reg2c): Use parse_operands.
	(do_lstc): Use reg_or_fail.  Remove unwanted blank lines.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 25)
+++ gas/config/tc-arm.c	(revision 26)
@@ -195,7 +195,7 @@
   {
     int reg;
     int imm;
-  } operands[4];
+  } operands[6];
 };
 
 static struct arm_it inst;
@@ -2211,33 +2211,6 @@
 }
 
 static int
-co_proc_number (char ** str)
-{
-  int processor;
-
-  if ((processor = arm_reg_parse (str, REG_TYPE_CP)) == FAIL)
-    {
-      inst.error = reg_expected_msgs[REG_TYPE_CP];
-      return FAIL;
-    }
-
-  inst.instruction |= processor << 8;
-  return SUCCESS;
-}
-
-static int
-cp_opc_expr (char ** str, int where, int length)
-{
-  unsigned int val;
-
-  if (immediate_required_here (str, &val, 0, (1 << length) - 1, TRUE) == FAIL)
-    return FAIL;
-
-  inst.instruction |= val << where;
-  return SUCCESS;
-}
-
-static int
 cp_address_offset (char ** str)
 {
   int offset;
@@ -4310,6 +4283,7 @@
    macros below.  */
 
 #define OP_stop	   000	/* end of line */
+
 #define OP_RR	   001	/* ARM register */			   
 #define OP_RRnpc   002	/* ARM register, not r15 */
 #define OP_bRRnpc  003	/* ARM register, not r15, in square brackets */
@@ -4329,8 +4303,10 @@
 #define OP_RIWC	   021	/* iWMMXt wC register */		   
 #define OP_RIWG	   022	/* iWMMXt wCG register */		   
 #define OP_RXA	   023  /* XScale accumulator register */      
+
 #define OP_EXP	   024	/* arbitrary expression */
 #define OP_iEXP	   025	/* same, with optional immediate prefix */
+
 #define OP_I0	   026	/* immediate value 0 */
 #define OP_I4      027  /*                 1 .. 4 */
 #define OP_I7	   030  /*                 0 .. 7 */
@@ -4342,6 +4318,12 @@
 #define OP_I255	   036	/*                 0 .. 255 */
 #define OP_Iffff   037  /*                 0 .. 65535 */
 
+#define OP_bI7	   040  /* immediate, prefix optional, 0 .. 7 */
+#define OP_bI15    041  /*                             0 .. 15 */
+
+/* Optional operands.  All have the high bit set.  */
+#define OP_obI7    200  /* optional bI7 */
+
 /* Macro for referring to one of the above constants as a number.
    Should appear solely in parse_operands().  */
 #define OP_(x) OP__(OP_##x)
@@ -4355,11 +4337,13 @@
 #define OPS___(x) #x
 
 /* Macros for gluing together operand strings.  */
-#define OPERANDS0()	    ""
-#define OPERANDS1(a)        OPS_(a)
-#define OPERANDS2(a,b)      OPS_(a) OPS_(b)
-#define OPERANDS3(a,b,c)    OPS_(a) OPS_(b) OPS_(c)
-#define OPERANDS4(a,b,c,d)  OPS_(a) OPS_(b) OPS_(c) OPS_(d)
+#define OPERANDS0()	       ""
+#define OPERANDS1(a)           OPS_(a)
+#define OPERANDS2(a,b)         OPS_(a) OPS_(b)
+#define OPERANDS3(a,b,c)       OPS_(a) OPS_(b) OPS_(c)
+#define OPERANDS4(a,b,c,d)     OPS_(a) OPS_(b) OPS_(c) OPS_(d)
+#define OPERANDS5(a,b,c,d,e)   OPS_(a) OPS_(b) OPS_(c) OPS_(d) OPS_(e)
+#define OPERANDS6(a,b,c,d,e,f) OPS_(a) OPS_(b) OPS_(c) OPS_(d) OPS_(e) OPS_(f)
 
 /* Generic instruction operand parser.  This does no encoding and no
    semantic validation; it merely squirrels values away in the inst
@@ -4369,6 +4353,7 @@
 parse_operands (char *str, const char *pattern)
 {
   int i;
+  unsigned const char *p = pattern;
 
 #define po_char_or_fail(chr) do {		\
   if (skip_past_char (&str, chr) == FAIL)	\
@@ -4385,16 +4370,16 @@
   inst.operands[i].reg = reg_;				\
 } while (0)
 
-#define po_imm_or_fail(min, max) do {					\
+#define po_imm_or_fail(min, max, popt) do {				\
   int imm_;								\
-  if (immediate_required_here (&str, &imm_, min, max, FALSE) == FAIL)	\
+  if (immediate_required_here (&str, &imm_, min, max, popt) == FAIL)	\
     return FAIL;							\
   inst.operands[i].imm = imm_;						\
 } while (0)
 
   for (i = 0; ; i++)
     {
-      switch (*pattern)
+      switch (*p)
 	{
 	  /* Registers */
 	case OP_(RR):    po_reg_or_fail (REG_TYPE_RN);      break;
@@ -4434,17 +4419,21 @@
 	  break;
 
 	  /* Immediates */
-	case OP_(I0):	 po_imm_or_fail (0, 0);		break;
-	case OP_(I4):	 po_imm_or_fail (1, 4);		break;
-	case OP_(I7):	 po_imm_or_fail (0, 7);		break;
-	case OP_(I15):	 po_imm_or_fail (0, 15);	break;
-	case OP_(I16):	 po_imm_or_fail (1, 16);	break;
-	case OP_(I31):	 po_imm_or_fail (0, 31); 	break;
-	case OP_(I32):	 po_imm_or_fail (1, 32);	break;
-	case OP_(Is63):	 po_imm_or_fail (-64, 63);	break;
-	case OP_(I255):  po_imm_or_fail (0, 255);	break;
-	case OP_(Iffff): po_imm_or_fail (0, 0xffff);	break;
+	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;
+	case OP_(I31):	 po_imm_or_fail (  0,     31, FALSE); 	break;
+	case OP_(I32):	 po_imm_or_fail (  1,     32, FALSE);	break;
+	case OP_(Is63):	 po_imm_or_fail (-64,     63, FALSE);	break;
+	case OP_(I255):  po_imm_or_fail (  0,    255, FALSE);	break;
+	case OP_(Iffff): po_imm_or_fail (  0, 0xffff, FALSE);	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;
+	  
 	  /* Expressions */
 	case OP_(iEXP):
 	  if (is_immediate_prefix (*str))
@@ -4462,12 +4451,17 @@
 	  goto done;
 
 	default:
-	  abort ();
+	  as_fatal ("unhandled operand code %03o", *p);
 	}
 
-      if (*++pattern == OP_(stop))
+      if (*++p == OP_(stop))
 	break;
 
+      /* If this is an optional argument, and we have no further
+	 operands, stop.  */
+      if ((*p & 0200) && *str == '\0')
+	break;
+
       if (skip_past_comma (&str) == FAIL)
 	goto bad_args;
     }
@@ -4863,27 +4857,15 @@
 static void
 do_cdp (char * str)
 {
-  if (co_proc_number (&str) == FAIL)
+  if (parse_operands (str, OPERANDS6(RCP,bI15,RCN,RCN,RCN,obI7)))
     return;
-  comma_or_fail (&str);
 
-  if (cp_opc_expr (&str, 20, 4) == FAIL)
-    return;
-  comma_or_fail (&str);
-
-  reg_or_fail (&str, 12, REG_TYPE_CN);
-  comma_or_fail (&str);
-
-  reg_or_fail (&str, 16, REG_TYPE_CN);
-  comma_or_fail (&str);
-
-  reg_or_fail (&str, 0, REG_TYPE_CN);
-
-  if (skip_past_comma (&str) == SUCCESS)
-    if (cp_opc_expr (&str, 5, 3) == FAIL)
-      return;
-
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].reg << 8;
+  inst.instruction |= inst.operands[1].imm << 20;
+  inst.instruction |= inst.operands[2].reg << 12;
+  inst.instruction |= inst.operands[3].reg << 16;
+  inst.instruction |= inst.operands[4].reg << 0;
+  inst.instruction |= inst.operands[5].imm << 5;
 }
 
 /* ARM V5 count-leading-zeroes instruction (argument parse)
@@ -4928,31 +4910,15 @@
 static void
 do_co_reg (char * str)
 {
-  if (co_proc_number (&str) == FAIL)
+  if (parse_operands (str, OPERANDS6(RCP,bI7,RR,RCN,RCN,obI7)))
     return;
 
-  comma_or_fail (&str);
-  
-  if (cp_opc_expr (&str, 21, 3) == FAIL)
-    return;
-
-  comma_or_fail (&str);
-
-  reg_or_fail (&str, 12, REG_TYPE_RN);
-
-  comma_or_fail (&str);
-
-  reg_or_fail (&str, 16, REG_TYPE_CN);
-
-  comma_or_fail (&str);
-
-  reg_or_fail (&str, 0, REG_TYPE_CN);
-
-  if (skip_past_comma (&str) == SUCCESS)
-    if (cp_opc_expr (&str, 5, 3) == FAIL)
-      return;
-
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].reg << 8;
+  inst.instruction |= inst.operands[1].imm << 21;
+  inst.instruction |= inst.operands[2].reg << 12;
+  inst.instruction |= inst.operands[3].reg << 16;
+  inst.instruction |= inst.operands[4].reg << 0;
+  inst.instruction |= inst.operands[5].imm << 5;
 }
 
 /* Transfer between coprocessor register and pair of ARM registers.
@@ -4971,25 +4937,14 @@
 static void
 do_co_reg2c (char * str)
 {
-  if (co_proc_number (& str) == FAIL)
+  if (parse_operands (str, OPERANDS5(RCP,bI15,RRnpc,RRnpc,RCN)))
     return;
 
-  comma_or_fail (&str);
-
-  if (cp_opc_expr (&str, 4, 4) == FAIL)
-    return;
-
-  comma_or_fail (&str);
-  reg_nonpc_or_fail (&str, 12);
-
-  comma_or_fail (&str);
-  reg_nonpc_or_fail (&str, 16);
-
-  comma_or_fail (&str);
-
-  reg_or_fail (& str, 0, REG_TYPE_CN);
-
-  end_of_line (str);
+  inst.instruction |= inst.operands[0].reg << 8;
+  inst.instruction |= inst.operands[1].imm << 4;
+  inst.instruction |= inst.operands[2].reg << 12;
+  inst.instruction |= inst.operands[3].reg << 16;
+  inst.instruction |= inst.operands[4].reg << 0;
 }
 
 /* ARM V6 change processor state instruction (argument parse)
@@ -5590,18 +5545,14 @@
   /* Co-processor register load/store.
      Format: <LDC|STC{cond}[L] CP#,CRd,<address>  */
 
-  if (co_proc_number (&str) == FAIL)
-    return;
-
+  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, CP_WB_OK) == FAIL)
     return;
-
   end_of_line (str);
 }
 

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