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


Refactor thumb_mov_compare so it can be used directly as an encoder
function in tinsns[].  Also, minor adjustments to md_apply_fix3.

zw

	* config/tc-arm.c (THUMB_MOVE, THUMB_COMPARE, THUMB_CPY, do_t_compare)
	(do_t_mov): Delete.
	(thumb_mov_compare): Rename do_t_mov_cmp.  Don't handle cpy here.
	Use parse_operands.  Remove 'move' argument; look at inst.instruction
	to distinguish mov from cmp.  Assume inst.instruction is correct for
	HR case.  Defer all immediate value handling to md_apply_fix3.
	(tinsns): Use do_t_mov_cmp for mov and cmp.  Set their opcodes to
	T_OPCODE_MOV_HR and T_OPCODE_CMP_HR respectively.
	(md_apply_fix3 <case BFD_RELOC_ARM_THUMB_IMM>): For consistency with
	other cases, remove extra sanity checks.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 41)
+++ gas/config/tc-arm.c	(revision 42)
@@ -560,10 +560,6 @@
 #define THUMB_H1	0x0080
 #define THUMB_H2	0x0040
 
-#define THUMB_MOVE 0
-#define THUMB_COMPARE 1
-#define THUMB_CPY 2
-
 #define THUMB_LOAD 0
 #define THUMB_STORE 1
 
@@ -6566,86 +6562,49 @@
 }
 
 static void
-thumb_mov_compare (char * str, int move)
+do_t_mov_cmp (char * str)
 {
-  int Rd, Rs = FAIL;
-
-  if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
-      || skip_past_comma (&str) == FAIL)
-    {
-      if (! inst.error)
-	inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (move != THUMB_CPY && is_immediate_prefix (*str))
-    {
-      str++;
-      expression_or_fail (&inst.reloc.exp, &str);
-    }
-  else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+  if (parse_operands (str, OPERANDS2(RR,RR_iEX)))
     return;
 
-  if (Rs != FAIL)
+  if (inst.operands[1].isreg)
     {
-      if (move != THUMB_CPY && Rs < 8 && Rd < 8)
+      if (inst.operands[0].reg < 8 && inst.operands[1].reg < 8)
 	{
-	  if (move == THUMB_MOVE)
-	    /* A move of two lowregs is encoded as ADD Rd, Rs, #0
-	       since a MOV instruction produces unpredictable results.  */
+	  /* A move of two lowregs is encoded as ADD Rd, Rs, #0
+	     since a MOV instruction produces unpredictable results.  */
+	  if (inst.instruction == T_OPCODE_MOV_HR)
 	    inst.instruction = T_OPCODE_ADD_I3;
 	  else
 	    inst.instruction = T_OPCODE_CMP_LR;
-	  inst.instruction |= Rd | (Rs << 3);
+
+	  inst.instruction |= inst.operands[0].reg;
+	  inst.instruction |= inst.operands[1].reg << 3;
 	}
       else
 	{
-	  if (move == THUMB_MOVE)
-	    inst.instruction = T_OPCODE_MOV_HR;
-	  else if (move != THUMB_CPY)
-	    inst.instruction = T_OPCODE_CMP_HR;
-
-	  if (Rd > 7)
-	    inst.instruction |= THUMB_H1;
-
-	  if (Rs > 7)
-	    inst.instruction |= THUMB_H2;
-
-	  inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
+	  /* Opcode in inst.instruction is already correct.  */
+	  inst.instruction |= (inst.operands[0].reg & 0x8) << 4;
+	  inst.instruction |= (inst.operands[0].reg & 0x7);
+	  inst.instruction |= inst.operands[1].reg << 3;
 	}
     }
   else
     {
-      if (Rd > 7)
+      if (inst.operands[0].reg > 7)
 	{
 	  inst.error = _("only lo regs allowed with immediate");
 	  return;
 	}
 
-      if (move == THUMB_MOVE)
+      if (inst.instruction == T_OPCODE_MOV_HR)
 	inst.instruction = T_OPCODE_MOV_I8;
       else
 	inst.instruction = T_OPCODE_CMP_I8;
 
-      inst.instruction |= Rd << 8;
-
-      if (inst.reloc.exp.X_op != O_constant)
-	inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
-      else
-	{
-	  unsigned value = inst.reloc.exp.X_add_number;
-
-	  if (value > 255)
-	    {
-	      inst.error = _("invalid immediate");
-	      return;
-	    }
-
-	  inst.instruction |= value;
-	}
+      inst.instruction |= inst.operands[0].reg << 8;
+      inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
     }
-
-  end_of_line (str);
 }
 
 static void
@@ -6848,12 +6807,6 @@
      because BX PC only works if the instruction is word aligned.  */
 }
 
-static void
-do_t_compare (char * str)
-{
-  thumb_mov_compare (str, THUMB_COMPARE);
-}
-
 /* THUMB CPS instruction (argument parse).  */
 
 static void
@@ -6870,7 +6823,12 @@
 static void
 do_t_cpy (char * str)
 {
-  thumb_mov_compare (str, THUMB_CPY);
+  if (parse_operands (str, OPERANDS2(RR,RR)))
+    return;
+
+  inst.instruction |= (inst.operands[0].reg & 0x8) << 4;
+  inst.instruction |= (inst.operands[0].reg & 0x7) << 0;
+  inst.instruction |= inst.operands[1].reg << 3;
 }
 
 static void
@@ -6933,12 +6891,6 @@
 }
 
 static void
-do_t_mov (char * str)
-{
-  thumb_mov_compare (str, THUMB_MOVE);
-}
-
-static void
 do_t_push_pop (char * str)
 {
   if (parse_operands (str, OPERANDS1(REGLST)))
@@ -9781,7 +9733,7 @@
   {"bl",	0xf7fffffe,	4,	ARM_EXT_V4T, do_t_branch23},
   {"bx",	0x4700,		2,	ARM_EXT_V4T, do_t_bx},
   {"cmn",	T_OPCODE_CMN,	2,	ARM_EXT_V4T, do_t_arit},
-  {"cmp",	0x0000,		2,	ARM_EXT_V4T, do_t_compare},
+  {"cmp",	T_OPCODE_CMP_HR,2,	ARM_EXT_V4T, do_t_mov_cmp},
   {"eor",	0x4040,		2,	ARM_EXT_V4T, do_t_arit},
   {"ldmia",	0xc800,		2,	ARM_EXT_V4T, do_t_ldmstm},
   {"ldr",	0x0000,		2,	ARM_EXT_V4T, do_t_ldr},
@@ -9793,7 +9745,7 @@
   {"ldsh",	0x5e00,		2,	ARM_EXT_V4T, do_t_lds},
   {"lsl",	0x4080,		2,	ARM_EXT_V4T, do_t_shift},
   {"lsr",	0x40c0,		2,	ARM_EXT_V4T, do_t_shift},
-  {"mov",	0x0000,		2,	ARM_EXT_V4T, do_t_mov},
+  {"mov",	T_OPCODE_MOV_HR,2,	ARM_EXT_V4T, do_t_mov_cmp},
   {"mul",	T_OPCODE_MUL,	2,	ARM_EXT_V4T, do_t_arit},
   {"mvn",	T_OPCODE_MVN,	2,	ARM_EXT_V4T, do_t_arit},
   {"neg",	T_OPCODE_NEG,	2,	ARM_EXT_V4T, do_t_arit},
@@ -11174,20 +11126,11 @@
 
     case BFD_RELOC_ARM_THUMB_IMM:
       newval = md_chars_to_number (buf, THUMB_SIZE);
-      switch (newval >> 11)
-	{
-	case 0x04: /* 8bit immediate MOV.  */
-	case 0x05: /* 8bit immediate CMP.  */
-	  if (value < 0 || value > 255)
-	    as_bad_where (fixP->fx_file, fixP->fx_line,
-			  _("invalid immediate: %ld is too large"),
-			  (long) value);
-	  newval |= value;
-	  break;
-
-	default:
-	  abort ();
-	}
+      if (value < 0 || value > 255)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("invalid immediate: %ld is too large"),
+		      (long) value);
+      newval |= value;
       md_number_to_chars (buf, newval, THUMB_SIZE);
       break;
 

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