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


With all the function renames, the Thumb instruction section has
gotten out of alphabetical order.  Re-sort it.

zw

	* tc-arm.c: Sort Thumb instruction section alphabetically again.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 45)
+++ gas/config/tc-arm.c	(revision 46)
@@ -6230,9 +6230,7 @@
 }
 
 
-/* Thumb instructions.  The generic argument parsing routines
-   (thumb_*) come first, in alphabetical order, then the
-   per-instruction routines (do_t_*), also in alphabetical order. */
+/* Thumb instructions, in alphabetical order. */
 
 /* Parse an add or subtract instruction.  The high bit of inst.instruction
    is set if the opcode was SUB.  */
@@ -6306,191 +6304,6 @@
 }
 
 static void
-do_t_ldst (char *str)
-{
-  if (parse_operands (str, OPERANDS2(RL,TADDR)))
-    return;
-
-  if (!inst.operands[1].isreg) /* =expr pseudo */
-    {
-      if (inst.instruction & THUMB_LOAD_BIT)
-	{
-	  inst.error = _("invalid pseudo operation");
-	  return;
-	}
-
-      if (inst.reloc.exp.X_op == O_constant
-	  && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
-	{
-	  /* This can be done with a mov instruction.  */
-	  inst.instruction  = T_OPCODE_MOV_I8 | (inst.operands[0].reg << 8);
-	  inst.instruction |= inst.reloc.exp.X_add_number;
-	  return;
-	}
-
-      /* Insert into literal pool.  */
-      if (add_to_lit_pool () == FAIL)
-	{
-	  inst.error = _("literal pool insertion failed");
-	  return;
-	}
-
-      inst.reloc.type   = BFD_RELOC_ARM_THUMB_OFFSET;
-      inst.reloc.exp.X_add_number += 4;  /* pipeline offset */
-      inst.operands[1].reg = REG_PC;
-    }
-
-  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;
-	}
-
-      if (inst.operands[1].reg == REG_PC)
-	inst.instruction = T_OPCODE_LDR_PC;
-      else if (inst.instruction & THUMB_LOAD_BIT)
-	inst.instruction = T_OPCODE_LDR_SP;
-      else
-	inst.instruction = T_OPCODE_STR_SP;
-
-      inst.instruction |= inst.operands[0].reg << 8;
-    }
-  else if (!inst.operands[1].immisreg)
-    {
-      /* Immediate offset.  */
-      switch (inst.instruction)
-	{
-	case T_OPCODE_STR_RW: inst.instruction = T_OPCODE_STR_IW; break;
-	case T_OPCODE_STR_RH: inst.instruction = T_OPCODE_STR_IH; break;
-	case T_OPCODE_STR_RB: inst.instruction = T_OPCODE_STR_IB; break;
-	case T_OPCODE_LDR_RW: inst.instruction = T_OPCODE_LDR_IW; break;
-	case T_OPCODE_LDR_RH: inst.instruction = T_OPCODE_LDR_IH; break;
-	case T_OPCODE_LDR_RB: inst.instruction = T_OPCODE_LDR_IB; break;
-	default: abort ();
-	}
-
-      inst.instruction |= inst.operands[0].reg;
-      inst.instruction |= inst.operands[1].reg << 3;
-    }
-  else
-    {
-      /* Register offset.  Opcode is already correct.  */
-      inst.instruction |= inst.operands[0].reg;
-      inst.instruction |= inst.operands[1].reg << 3;
-      inst.instruction |= inst.operands[1].imm << 6;
-    }
-}
-
-static void
-do_t_mov_cmp (char * str)
-{
-  if (parse_operands (str, OPERANDS2(RR,RR_iEX)))
-    return;
-
-  if (inst.operands[1].isreg)
-    {
-      if (inst.operands[0].reg < 8 && inst.operands[1].reg < 8)
-	{
-	  /* 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 |= inst.operands[0].reg;
-	  inst.instruction |= inst.operands[1].reg << 3;
-	}
-      else
-	{
-	  /* 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 (inst.operands[0].reg > 7)
-	{
-	  inst.error = _("only lo regs allowed with immediate");
-	  return;
-	}
-
-      if (inst.instruction == T_OPCODE_MOV_HR)
-	inst.instruction = T_OPCODE_MOV_I8;
-      else
-	inst.instruction = T_OPCODE_CMP_I8;
-
-      inst.instruction |= inst.operands[0].reg << 8;
-      inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
-    }
-}
-
-static void
-do_t_shift (char * str)
-{
-  int Rs;
-  if (parse_operands (str, OPERANDS3(RL,RL_iEX,oRL_iEX)))
-    return;
-
-  if (inst.operands[2].present)
-    {
-      /* If there were three operands, operand 1 must be a register.  */
-      if (!inst.operands[1].isreg)
-        {
-	  inst.error = BAD_ARGS;
-	  return;
-	}
-      else if (inst.operands[2].isreg)  /* Rd, Rs, Rn */
-	{
-	  if (inst.operands[0].reg != inst.operands[1].reg)
-	    {
-	      inst.error = _("source1 and dest must be same register");
-	      return;
-	    }
-	  inst.instruction |= inst.operands[0].reg;
-	  inst.instruction |= inst.operands[2].reg << 3;
-	  return;
-	}
-      else /* Rd, Rs, imm */
-	Rs = inst.operands[1].reg;
-    }
-  else if (inst.operands[1].isreg)  /* Rd, Rs -> Rd, Rd, Rs */
-    {
-      inst.instruction |= inst.operands[0].reg;
-      inst.instruction |= inst.operands[2].reg << 3;
-      return;
-    }
-  else /* Rd, imm -> Rd, Rd, imm */
-    Rs = inst.operands[0].reg;
-
-  /* If we get here, we are doing a shift by an immediate. inst.operands[0].reg
-     and Rs are the registers, and inst.reloc is the immediate.  */
-  switch (inst.instruction)
-    {
-    case T_OPCODE_ASR_R: inst.instruction = T_OPCODE_ASR_I; break;
-    case T_OPCODE_LSL_R: inst.instruction = T_OPCODE_LSL_I; break;
-    case T_OPCODE_LSR_R: inst.instruction = T_OPCODE_LSR_I; break;
-    }
-  inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
-  inst.instruction |= inst.operands[0].reg | (Rs << 3);
-}
-
-static void
 do_t_adr (char * str)
 {
   if (parse_operands (str, OPERANDS2(RL,EXP)))
@@ -6703,43 +6516,140 @@
 }
 
 static void
-do_t_push_pop (char * str)
+do_t_ldst (char *str)
 {
-  if (parse_operands (str, OPERANDS1(REGLST)))
+  if (parse_operands (str, OPERANDS2(RL,TADDR)))
     return;
-  if (inst.operands[0].writeback)
+
+  if (!inst.operands[1].isreg) /* =expr pseudo */
     {
-      inst.error = _("push/pop do not support {reglist}^");
-      return;
+      if (inst.instruction & THUMB_LOAD_BIT)
+	{
+	  inst.error = _("invalid pseudo operation");
+	  return;
+	}
+
+      if (inst.reloc.exp.X_op == O_constant
+	  && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
+	{
+	  /* This can be done with a mov instruction.  */
+	  inst.instruction  = T_OPCODE_MOV_I8 | (inst.operands[0].reg << 8);
+	  inst.instruction |= inst.reloc.exp.X_add_number;
+	  return;
+	}
+
+      /* Insert into literal pool.  */
+      if (add_to_lit_pool () == FAIL)
+	{
+	  inst.error = _("literal pool insertion failed");
+	  return;
+	}
+
+      inst.reloc.type   = BFD_RELOC_ARM_THUMB_OFFSET;
+      inst.reloc.exp.X_add_number += 4;  /* pipeline offset */
+      inst.operands[1].reg = REG_PC;
     }
-  if (inst.reloc.type != BFD_RELOC_UNUSED)
+
+  if (inst.operands[1].reg == REG_PC || inst.operands[1].reg == REG_SP)
     {
-      /* This really doesn't seem worth it.  */
-      inst.reloc.type = BFD_RELOC_UNUSED;
-      inst.error = _("expression too complex");
-      return;
+      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;
+	}
+
+      if (inst.operands[1].reg == REG_PC)
+	inst.instruction = T_OPCODE_LDR_PC;
+      else if (inst.instruction & THUMB_LOAD_BIT)
+	inst.instruction = T_OPCODE_LDR_SP;
+      else
+	inst.instruction = T_OPCODE_STR_SP;
+
+      inst.instruction |= inst.operands[0].reg << 8;
     }
-  if (inst.operands[0].imm & ~0xff)
+  else if (!inst.operands[1].immisreg)
     {
-      if ((inst.instruction == T_OPCODE_PUSH
-	   && (inst.operands[0].imm & ~0xff) == 1 << REG_LR)
-	  || (inst.instruction == T_OPCODE_POP
-	      && (inst.operands[0].imm & ~0xff) == 1 << REG_PC))
+      /* Immediate offset.  */
+      switch (inst.instruction)
 	{
-	  inst.instruction |= THUMB_PP_PC_LR;
-	  inst.operands[0].imm &= 0xff;
+	case T_OPCODE_STR_RW: inst.instruction = T_OPCODE_STR_IW; break;
+	case T_OPCODE_STR_RH: inst.instruction = T_OPCODE_STR_IH; break;
+	case T_OPCODE_STR_RB: inst.instruction = T_OPCODE_STR_IB; break;
+	case T_OPCODE_LDR_RW: inst.instruction = T_OPCODE_LDR_IW; break;
+	case T_OPCODE_LDR_RH: inst.instruction = T_OPCODE_LDR_IH; break;
+	case T_OPCODE_LDR_RB: inst.instruction = T_OPCODE_LDR_IB; break;
+	default: abort ();
 	}
+
+      inst.instruction |= inst.operands[0].reg;
+      inst.instruction |= inst.operands[1].reg << 3;
+    }
+  else
+    {
+      /* Register offset.  Opcode is already correct.  */
+      inst.instruction |= inst.operands[0].reg;
+      inst.instruction |= inst.operands[1].reg << 3;
+      inst.instruction |= inst.operands[1].imm << 6;
+    }
+}
+
+static void
+do_t_mov_cmp (char * str)
+{
+  if (parse_operands (str, OPERANDS2(RR,RR_iEX)))
+    return;
+
+  if (inst.operands[1].isreg)
+    {
+      if (inst.operands[0].reg < 8 && inst.operands[1].reg < 8)
+	{
+	  /* 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 |= inst.operands[0].reg;
+	  inst.instruction |= inst.operands[1].reg << 3;
+	}
       else
 	{
-	  inst.error = _("invalid register list to push/pop instruction");
-	  return;
+	  /* 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 (inst.operands[0].reg > 7)
+	{
+	  inst.error = _("only lo regs allowed with immediate");
+	  return;
+	}
 
-  inst.instruction |= inst.operands[0].imm;
+      if (inst.instruction == T_OPCODE_MOV_HR)
+	inst.instruction = T_OPCODE_MOV_I8;
+      else
+	inst.instruction = T_OPCODE_CMP_I8;
+
+      inst.instruction |= inst.operands[0].reg << 8;
+      inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
+    }
 }
 
-/* THUMB SETEND instruction (argument parse).  */
 
 static void
 do_t_setend (char * str)
@@ -6752,6 +6662,56 @@
 }
 
 static void
+do_t_shift (char * str)
+{
+  int Rs;
+  if (parse_operands (str, OPERANDS3(RL,RL_iEX,oRL_iEX)))
+    return;
+
+  if (inst.operands[2].present)
+    {
+      /* If there were three operands, operand 1 must be a register.  */
+      if (!inst.operands[1].isreg)
+        {
+	  inst.error = BAD_ARGS;
+	  return;
+	}
+      else if (inst.operands[2].isreg)  /* Rd, Rs, Rn */
+	{
+	  if (inst.operands[0].reg != inst.operands[1].reg)
+	    {
+	      inst.error = _("source1 and dest must be same register");
+	      return;
+	    }
+	  inst.instruction |= inst.operands[0].reg;
+	  inst.instruction |= inst.operands[2].reg << 3;
+	  return;
+	}
+      else /* Rd, Rs, imm */
+	Rs = inst.operands[1].reg;
+    }
+  else if (inst.operands[1].isreg)  /* Rd, Rs -> Rd, Rd, Rs */
+    {
+      inst.instruction |= inst.operands[0].reg;
+      inst.instruction |= inst.operands[2].reg << 3;
+      return;
+    }
+  else /* Rd, imm -> Rd, Rd, imm */
+    Rs = inst.operands[0].reg;
+
+  /* If we get here, we are doing a shift by an immediate. inst.operands[0].reg
+     and Rs are the registers, and inst.reloc is the immediate.  */
+  switch (inst.instruction)
+    {
+    case T_OPCODE_ASR_R: inst.instruction = T_OPCODE_ASR_I; break;
+    case T_OPCODE_LSL_R: inst.instruction = T_OPCODE_LSL_I; break;
+    case T_OPCODE_LSR_R: inst.instruction = T_OPCODE_LSR_I; break;
+    }
+  inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
+  inst.instruction |= inst.operands[0].reg | (Rs << 3);
+}
+
+static void
 do_t_swi (char * str)
 {
   if (parse_operands (str, OPERANDS1(EXP)))
@@ -6759,6 +6719,43 @@
 
   inst.reloc.type = BFD_RELOC_ARM_SWI;
 }
+
+static void
+do_t_push_pop (char * str)
+{
+  if (parse_operands (str, OPERANDS1(REGLST)))
+    return;
+  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;
+    }
+  if (inst.operands[0].imm & ~0xff)
+    {
+      if ((inst.instruction == T_OPCODE_PUSH
+	   && (inst.operands[0].imm & ~0xff) == 1 << REG_LR)
+	  || (inst.instruction == T_OPCODE_POP
+	      && (inst.operands[0].imm & ~0xff) == 1 << REG_PC))
+	{
+	  inst.instruction |= THUMB_PP_PC_LR;
+	  inst.operands[0].imm &= 0xff;
+	}
+      else
+	{
+	  inst.error = _("invalid register list to push/pop instruction");
+	  return;
+	}
+    }
+
+  inst.instruction |= inst.operands[0].imm;
+}
 
 /* VFP instructions.  In a logical order: SP variant first, monad
    before dyad, arithmetic then move then load/store.  */

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