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


Introduce more compact notation for the very common construction

  if (expr)
    {
      inst.error = diagnostic;
      return;
    }

zw

	* config/tc-arm.c (BAD_COND): Clarify message.
	(reject_overlap): Delete.
	(constraint): New macro.
	(do_bfc, do_bfi, do_bfx, encode_branch, do_blx, do_ldrd, do_ldstt)
	(do_ldsttv4, do_mrs, do_pld, do_strex, do_t_add_sub, do_t_arit3)
	(do_t_ldmstm, do_t_lds, do_t_ldst, do_t_mov_cmp, do_t_shift)
	(do_t_push_pop, do_vfp_reg2_from_sp2, do_vfp_sp2_from_reg2)
	(vfp_sp_ldstm, vfp_dp_ldstm, do_fpa_ldmstm, do_iwmmxt_tandorc)
	(do_iwmmxt_wldstw, do_xsc_mra): Use constraint.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 58)
+++ gas/config/tc-arm.c	(revision 59)
@@ -452,7 +452,7 @@
 
 #define BAD_ARGS	_("bad arguments to instruction")
 #define BAD_PC		_("r15 not allowed here")
-#define BAD_COND	_("instruction is not conditional")
+#define BAD_COND	_("instruction cannot be conditional")
 #define BAD_OVERLAP	_("registers may not be the same")
 #define BAD_HIREG	_("lo register required")
 
@@ -4147,31 +4147,16 @@
 #undef po_reg_or_goto
 #undef po_imm_or_fail
 
-/* Operand validation functions.  */
-
-/* Set inst.error to BAD_OVERLAP and return FAIL if any of the
-   specified pairs of register operands are the same.  N is the number
-   of pairs.  */
-static int
-reject_overlap (int n, ...)
-{
-  va_list ap;
-  va_start (ap, n);
-  while (n--)
-    {
-      int op1 = va_arg (ap, int);
-      int op2 = va_arg (ap, int);
-      if (inst.operands[op1].reg == inst.operands[op2].reg)
-	{
-	  inst.error = BAD_OVERLAP;
-	  return FAIL;
-	}
-    }
-  va_end (ap);
-  return SUCCESS;
-}
-
 
+/* Shorthand macro for instruction encoding functions issuing errors.  */
+#define constraint(expr, err) do {		\
+  if (expr)					\
+    {						\
+      inst.error = err;				\
+      return;					\
+    }						\
+} while (0)
+
 /* Functions for instruction encoding, sorted by subarchitecture.
    First some generics; their names are taken from the conventional
    bit positions for register arguments in ARM format instructions.  */
@@ -4298,12 +4283,7 @@
 do_bfc (void)
 {
   unsigned int msb = inst.operands[1].imm + inst.operands[2].imm;
-  if (msb > 32)
-    {
-      inst.error = _("bit-field extends past end of register");
-      return;
-    }
-
+  constraint (msb > 32, _("bit-field extends past end of register"));
   /* The instruction encoding stores the LSB and MSB,
      not the LSB and width.  */
   inst.instruction |= inst.operands[0].reg << 12;
@@ -4322,12 +4302,7 @@
     inst.operands[1].reg = REG_PC;
 
   msb = inst.operands[2].imm + inst.operands[3].imm;
-  if (msb > 32)
-    {
-      inst.error = _("bit-field extends past end of register");
-      return;
-    }
-
+  constraint (msb > 32, _("bit-field extends past end of register"));
   /* The instruction encoding stores the LSB and MSB,
      not the LSB and width.  */
   inst.instruction |= inst.operands[0].reg << 12;
@@ -4339,12 +4314,8 @@
 static void
 do_bfx (void)
 {
-  if (inst.operands[2].imm + inst.operands[3].imm > 32)
-    {
-      inst.error = _("bit-field extends past end of register");
-      return;
-    }
-
+  constraint (inst.operands[2].imm + inst.operands[3].imm > 32,
+	      _("bit-field extends past end of register"));
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= inst.operands[1].reg;
   inst.instruction |= inst.operands[2].imm << 7;
@@ -4372,11 +4343,8 @@
 {
   if (inst.operands[0].hasreloc)
     {
-      if (inst.operands[0].imm != BFD_RELOC_ARM_PLT32)
-	{
-	  inst.error = _("the only suffix valid here is '(plt)'");
-	  return;
-	}
+      constraint (inst.operands[0].imm != BFD_RELOC_ARM_PLT32,
+		  _("the only suffix valid here is '(plt)'"));
       inst.reloc.type	= BFD_RELOC_ARM_PLT32;
       inst.reloc.pc_rel = 0;
     }
@@ -4417,11 +4385,7 @@
     {
       /* Arg is an address; this instruction cannot be executed
 	 conditionally, and the opcode must be adjusted.  */
-      if ((inst.instruction & COND_MASK) != COND_ALWAYS)
-	{
-	  inst.error = BAD_COND;
-	  return;
-	}
+      constraint ((inst.instruction & COND_MASK) != COND_ALWAYS, BAD_COND);
       inst.instruction = 0xfafffffe;
       encode_branch (BFD_RELOC_ARM_PCREL_BLX);
     }
@@ -4566,23 +4530,10 @@
 static void
 do_ldrd (void)
 {
-  if (!inst.operands[1].isreg)
-    {
-      inst.error = _("'[' expected");
-      return;
-    }
-
-  if (inst.operands[0].reg % 2 != 0)
-    {
-      inst.error = _("destination register must be even");
-      return;
-    }
-  if (inst.operands[0].reg == REG_LR)
-    {
-      inst.error = _("r14 not allowed here");
-      return;
-    }
-
+  constraint (!inst.operands[1].isreg, _("'[' expected"));
+  constraint (inst.operands[0].reg % 2 != 0,
+	      _("destination register must be even"));
+  constraint (inst.operands[0].reg == REG_LR, _("r14 not allowed here"));
   if (inst.instruction & LOAD_BIT)
     {
       /* encode_addr_mode_3_arm will diagnose overlap between the base
@@ -4623,17 +4574,13 @@
      reject [Rn,...].  */
   if (inst.operands[1].preind)
     {
-      if (inst.reloc.exp.X_op == O_constant && inst.reloc.exp.X_add_number == 0)
-	{
-	  inst.operands[1].preind = 0;
-	  inst.operands[1].postind = 1;
-	  inst.operands[1].writeback = 1;
-	}
-      else
-	{
-	  inst.error = _("this instruction requires a post-indexed address");
-	  return;
-	}
+      constraint (inst.reloc.exp.X_op != O_constant ||
+		  inst.reloc.exp.X_add_number != 0,
+		  _("this instruction requires a post-indexed address"));
+
+      inst.operands[1].preind = 0;
+      inst.operands[1].postind = 1;
+      inst.operands[1].writeback = 1;
     }
   inst.instruction |= inst.operands[0].reg << 12;
   encode_addr_mode_2_arm (1, /*is_t=*/TRUE);
@@ -4658,17 +4605,13 @@
      reject [Rn,...].  */
   if (inst.operands[1].preind)
     {
-      if (inst.reloc.exp.X_op == O_constant && inst.reloc.exp.X_add_number == 0)
-	{
-	  inst.operands[1].preind = 0;
-	  inst.operands[1].postind = 1;
-	  inst.operands[1].writeback = 1;
-	}
-      else
-	{
-	  inst.error = _("this instruction requires a post-indexed address");
-	  return;
-	}
+      constraint (inst.reloc.exp.X_op != O_constant ||
+		  inst.reloc.exp.X_add_number != 0,
+		  _("this instruction requires a post-indexed address"));
+
+      inst.operands[1].preind = 0;
+      inst.operands[1].postind = 1;
+      inst.operands[1].writeback = 1;
     }
   inst.instruction |= inst.operands[0].reg << 12;
   encode_addr_mode_3_arm (1, /*is_t=*/TRUE);
@@ -4721,12 +4664,9 @@
 do_mrs (void)
 {
   /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all.  */
-  if ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f)) != (PSR_c|PSR_f))
-    {
-      inst.error = _("'CPSR' or 'SPSR' expected");
-      return;
-    }
-
+  constraint ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f))
+	      != (PSR_c|PSR_f),
+	      _("'CPSR' or 'SPSR' expected"));
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= (inst.operands[1].imm & SPSR_BIT);
 }
@@ -4839,27 +4779,14 @@
 static void
 do_pld (void)
 {
-  if (!inst.operands[0].isreg)
-    {
-      inst.error = _("'[' expected after PLD mnemonic");
-      return;
-    }
-  if (inst.operands[0].postind)
-    {
-      inst.error = _("post-indexed expression used in preload instruction");
-      return;
-    }
-  if (inst.operands[0].writeback)
-    {
-      inst.error = _("writeback used in preload instruction");
-      return;
-    }
-  if (!inst.operands[0].preind)
-    {
-      inst.error = _("unindexed addressing used in preload instruction");
-      return;
-    }
-
+  constraint (!inst.operands[0].isreg,
+	      _("'[' expected after PLD mnemonic"));
+  constraint (inst.operands[0].postind,
+	      _("post-indexed expression used in preload instruction"));
+  constraint (inst.operands[0].writeback,
+	      _("writeback used in preload instruction"));
+  constraint (!inst.operands[0].preind,
+	      _("unindexed addressing used in preload instruction"));
   inst.instruction |= inst.operands[0].reg;
   encode_addr_mode_2_arm (0, /*is_t=*/FALSE);
 }
@@ -5007,8 +4934,8 @@
 static void
 do_strex (void)
 {
-  if (reject_overlap (2, 0,1, 0,2))
-    return;
+  constraint (inst.operands[0].reg == inst.operands[1].reg
+	      || inst.operands[0].reg == inst.operands[2].reg, BAD_OVERLAP);
 
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= inst.operands[1].reg;
@@ -5075,19 +5002,9 @@
   /* We now have Rd, Rs, and Rn set to registers.  */
   if (Rd > 7 || Rs > 7 || Rn > 7)
     {
-      if (Rs != Rd)
-	{
-	  inst.error = _("dest and source1 must be the same register");
-	  return;
-	}
-
+      constraint (Rs != Rd, _("dest and source1 must be the same register"));
       /* Can't do this for SUB.	 */
-      if (subtract)
-	{
-	  inst.error = _("subtract valid only on lo regs");
-	  return;
-	}
-
+      constraint (subtract, _("subtract valid only on lo regs"));
       inst.instruction = T_OPCODE_ADD_HI;
       inst.instruction |= (Rd & 8) << 4;
       inst.instruction |= (Rd & 7);
@@ -5130,12 +5047,10 @@
 static void
 do_t_arit3 (void)
 {
-  if (inst.operands[1].present
-      && inst.operands[0].reg != inst.operands[1].reg)
-    {
-      inst.error = _("dest and source1 must be the same register");
-      return;
-    }
+  constraint (inst.operands[1].present
+	      && inst.operands[0].reg != inst.operands[1].reg,
+	      _("dest and source1 must be the same register"));
+
   inst.instruction |= inst.operands[0].reg;
   inst.instruction |= inst.operands[2].reg << 3;
 }
@@ -5217,23 +5132,13 @@
 static void
 do_t_ldmstm (void)
 {
-  if (inst.reloc.type != BFD_RELOC_UNUSED)
-    {
-      /* This really doesn't seem worth it.  */
-      inst.reloc.type = BFD_RELOC_UNUSED;
-      inst.error = _("expression too complex");
-      return;
-    }
-  if (inst.operands[1].imm & ~0xff)
-    {
-      inst.error = _("only lo-regs valid in load/store multiple");
-      return;
-    }
-  if (inst.operands[1].writeback)
-    {
-      inst.error = _("Thumb load/store multiple does not support {reglist}^");
-      return;
-    }
+  /* This really doesn't seem worth it.  */
+  constraint (inst.reloc.type != BFD_RELOC_UNUSED,
+	      _("expression too complex"));
+  constraint (inst.operands[1].imm & ~0xff,
+	      _("only lo-regs valid in load/store multiple"));
+  constraint (inst.operands[1].writeback,
+	      _("Thumb load/store multiple does not support {reglist}^"));
   if (!inst.operands[0].writeback)
     as_warn (_("Thumb load/store multiple always writes back base register"));
 
@@ -5245,18 +5150,11 @@
 do_t_lds (void)
 {
   /* Only [Rn,Rm] is acceptable.  */
-  if (!inst.operands[1].isreg || !inst.operands[1].immisreg
-      || inst.operands[1].postind || inst.operands[1].shifted
-      || inst.operands[1].negative)
-    {
-      inst.error = _("invalid addressing mode");
-      return;
-    }
-  if (inst.operands[1].reg > 7 || inst.operands[1].imm > 7)
-    {
-      inst.error = BAD_HIREG;
-      return;
-    }
+  constraint (!inst.operands[1].isreg || !inst.operands[1].immisreg
+	      || inst.operands[1].postind || inst.operands[1].shifted
+	      || inst.operands[1].negative,
+	      _("invalid addressing mode"));
+  constraint (inst.operands[1].reg > 7 || inst.operands[1].imm > 7, BAD_HIREG);
 
   inst.instruction |= inst.operands[0].reg;
   inst.instruction |= inst.operands[1].reg << 3;
@@ -5270,30 +5168,17 @@
     if (move_or_literal_pool (0, /*thumb_p=*/TRUE, /*mode_3=*/FALSE))
       return;
 
-  if (!inst.operands[1].preind || inst.operands[1].shifted)
-    {
-      inst.error = _("Thumb does not support this addressing mode");
-      return;
-    }
-
+  constraint (!inst.operands[1].preind || inst.operands[1].shifted,
+	      _("Thumb does not support this addressing mode"));
   if (inst.operands[1].reg == REG_PC || inst.operands[1].reg == REG_SP)
     {
-      if (inst.instruction & 0x0600)
-	{
-	  inst.error = _("byte or halfword not valid for base register");
-	  return;
-	}
-      else if (inst.operands[1].reg == REG_PC
-	       && !(inst.instruction & THUMB_LOAD_BIT))
-	{
-	  inst.error = _("r15 based store not allowed");
-	  return;
-	}
-      else if (inst.operands[1].immisreg)
-	{
-	  inst.error = _("invalid base register for register offset");
-	  return;
-	}
+      constraint (inst.instruction & 0x0600,
+		  _("byte or halfword not valid for base register"));
+      constraint (inst.operands[1].reg == REG_PC
+		  && !(inst.instruction & THUMB_LOAD_BIT),
+		  _("r15 based store not allowed"));
+      constraint (inst.operands[1].immisreg,
+		  _("invalid base register for register offset"));
 
       if (inst.operands[1].reg == REG_PC)
 	inst.instruction = T_OPCODE_LDR_PC;
@@ -5309,11 +5194,7 @@
       return;
     }
 
-  if (inst.operands[0].reg > 7)
-    {
-      inst.error = BAD_HIREG;
-      return;
-    }
+  constraint (inst.operands[0].reg > 7, BAD_HIREG);
 
   if (!inst.operands[1].immisreg)
     {
@@ -5336,16 +5217,9 @@
   else
     {
       /* Register offset.  Opcode is already correct.  */
-      if (inst.operands[1].reg > 7)
-	{
-	  inst.error = BAD_HIREG;
-	  return;
-	}
-      else if (inst.operands[1].negative)
-	{
-	  inst.error = _("Thumb does not support [Rn,-Rm] addressing");
-	  return;
-	}
+      constraint (inst.operands[1].reg > 7, BAD_HIREG);
+      constraint (inst.operands[1].negative,
+		  _("Thumb does not support [Rn,-Rm] addressing"));
       inst.instruction |= inst.operands[0].reg;
       inst.instruction |= inst.operands[1].reg << 3;
       inst.instruction |= inst.operands[1].imm << 6;
@@ -5374,12 +5248,8 @@
     }
   else
     {
-      if (inst.operands[0].reg > 7)
-	{
-	  inst.error = _("only lo regs allowed with immediate");
-	  return;
-	}
-
+      constraint (inst.operands[0].reg > 7,
+		  _("only lo regs allowed with immediate"));
       if (inst.instruction == T_OPCODE_MOV_HR)
 	inst.instruction = T_OPCODE_MOV_I8;
       else
@@ -5407,11 +5277,8 @@
 
   if (inst.operands[2].isreg)  /* Rd, {Rs,} Rn */
     {
-      if (inst.operands[0].reg != Rs)
-	{
-	  inst.error = _("source1 and dest must be same register");
-	  return;
-	}
+      constraint (inst.operands[0].reg != Rs,
+		  _("source1 and dest must be same register"));
       inst.instruction |= inst.operands[0].reg;
       inst.instruction |= inst.operands[2].reg << 3;
       return;
@@ -5438,18 +5305,11 @@
 static void
 do_t_push_pop (void)
 {
-  if (inst.operands[0].writeback)
-    {
-      inst.error = _("push/pop do not support {reglist}^");
-      return;
-    }
-  if (inst.reloc.type != BFD_RELOC_UNUSED)
-    {
-      /* This really doesn't seem worth it.  */
-      inst.reloc.type = BFD_RELOC_UNUSED;
-      inst.error = _("expression too complex");
-      return;
-    }
+  constraint (inst.operands[0].writeback,
+	      _("push/pop do not support {reglist}^"));
+  constraint (inst.reloc.type != BFD_RELOC_UNUSED,
+	      _("expression too complex"));
+
   if (inst.operands[0].imm & ~0xff)
     {
       if ((inst.instruction == T_OPCODE_PUSH
@@ -5518,12 +5378,8 @@
 static void
 do_vfp_reg2_from_sp2 (void)
 {
-  if (inst.operands[2].imm != 2)
-    {
-      inst.error = _("only two consecutive VFP SP registers allowed here");
-      return;
-    }
-
+  constraint (inst.operands[2].imm != 2,
+	      _("only two consecutive VFP SP registers allowed here"));
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= inst.operands[1].reg << 16;
   vfp_sp_encode_reg (inst.operands[2].reg, VFP_REG_Sm);
@@ -5539,12 +5395,8 @@
 static void
 do_vfp_sp2_from_reg2 (void)
 {
-  if (inst.operands[0].imm != 2)
-    {
-      inst.error = _("only two consecutive VFP SP registers allowed here");
-      return;
-    }
-
+  constraint (inst.operands[0].imm != 2,
+	      _("only two consecutive VFP SP registers allowed here"));
   vfp_sp_encode_reg (inst.operands[0].reg, VFP_REG_Sm);
   inst.instruction |= inst.operands[1].reg << 12;
   inst.instruction |= inst.operands[2].reg << 16;
@@ -5570,12 +5422,9 @@
 {
   if (inst.operands[0].writeback)
     inst.instruction |= WRITE_BACK;
-  else if (ldstm_type != VFP_LDSTMIA)
-    {
-      inst.error = _("this addressing mode requires base-register writeback");
-      return;
-    }
-
+  else
+    constraint (ldstm_type != VFP_LDSTMIA,
+		_("this addressing mode requires base-register writeback"));
   inst.instruction |= inst.operands[0].reg << 16;
   vfp_sp_encode_reg (inst.operands[1].reg, VFP_REG_Sd);
   inst.instruction |= inst.operands[1].imm;
@@ -5588,11 +5437,9 @@
 
   if (inst.operands[0].writeback)
     inst.instruction |= WRITE_BACK;
-  else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
-    {
-      inst.error = _("this addressing mode requires base-register writeback");
-      return;
-    }
+  else
+    constraint (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX,
+		_("this addressing mode requires base-register writeback"));
 
   inst.instruction |= inst.operands[0].reg << 16;
   inst.instruction |= inst.operands[1].reg << 12;
@@ -5669,12 +5516,9 @@
 	 [Rn]{!}.  The instruction does not really support stacking or
 	 unstacking, so we have to emulate these by setting appropriate
 	 bits and offsets.  */
-      if (inst.reloc.exp.X_op != O_constant
-	  || inst.reloc.exp.X_add_number != 0)
-	{
-	  inst.error = _("this instruction does not support indexing");
-	  return;
-	}
+      constraint (inst.reloc.exp.X_op != O_constant
+		  || inst.reloc.exp.X_add_number != 0,
+		  _("this instruction does not support indexing"));
       if (inst.operands[2].writeback)
 	inst.instruction |= WRITE_BACK;
       if (inst.instruction & (PRE_INDEX | WRITE_BACK))
@@ -5697,8 +5541,7 @@
 static void
 do_iwmmxt_tandorc (void)
 {
-  if (inst.operands[0].reg != REG_PC)
-    inst.error = _("only r15 allowed here");
+  constraint (inst.operands[0].reg != REG_PC, _("only r15 allowed here"));
 }
 
 static void
@@ -5763,12 +5606,7 @@
   /* RIWR_RIWC clears .isreg for a control register.  */
   if (!inst.operands[0].isreg)
     {
-      if ((inst.instruction & COND_MASK) != COND_ALWAYS)
-	{
-	  inst.error = _("conditional execution not supported "
-			 "with control register");
-	  return;
-	}
+      constraint ((inst.instruction & COND_MASK) != COND_ALWAYS, BAD_COND);
       inst.instruction |= 0xf0000000;
     }
 
@@ -5878,9 +5716,7 @@
 static void
 do_xsc_mra (void)
 {
-  if (reject_overlap (1, 0,1))
-    return;
-
+  constraint (inst.operands[0].reg == inst.operands[1].reg, BAD_OVERLAP);
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= inst.operands[1].reg << 16;
 }

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