2005-04-20 Paul Brook <paul@codesourcery.com>
[external/binutils.git] / gas / config / tc-arm.c
index 7b4887d..8dd268c 100644 (file)
@@ -560,6 +560,7 @@ struct asm_opcode
 #define THUMB_SIZE     2       /* Size of thumb instruction.  */
 #define THUMB_PP_PC_LR 0x0100
 #define THUMB_LOAD_BIT 0x0800
+#define THUMB2_LOAD_BIT 0x00100000
 
 #define BAD_ARGS       _("bad arguments to instruction")
 #define BAD_PC         _("r15 not allowed here")
@@ -2955,11 +2956,11 @@ bad:
   as_bad (_("expected <tag> , <value>"));
   ignore_rest_of_line ();
 }
+#endif /* OBJ_ELF */
 
 static void s_arm_arch (int);
 static void s_arm_cpu (int);
 static void s_arm_fpu (int);
-#endif /* OBJ_ELF */
 
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
@@ -2984,6 +2985,9 @@ const pseudo_typeS md_pseudo_table[] =
   { "ltorg",      s_ltorg,       0 },
   { "pool",       s_ltorg,       0 },
   { "syntax",     s_syntax,      0 },
+  { "cpu",        s_arm_cpu,     0 },
+  { "arch",       s_arm_arch,    0 },
+  { "fpu",        s_arm_fpu,     0 },
 #ifdef OBJ_ELF
   { "word",       s_arm_elf_cons, 4 },
   { "long",       s_arm_elf_cons, 4 },
@@ -2999,9 +3003,6 @@ const pseudo_typeS md_pseudo_table[] =
   { "pad",             s_arm_unwind_pad,       0 },
   { "setfp",           s_arm_unwind_setfp,     0 },
   { "unwind_raw",      s_arm_unwind_raw,       0 },
-  { "cpu",             s_arm_cpu,              0 },
-  { "arch",            s_arm_arch,             0 },
-  { "fpu",             s_arm_fpu,              0 },
   { "eabi_attribute",  s_arm_eabi_attribute,   0 },
 #else
   { "word",       cons, 4},
@@ -3705,7 +3706,10 @@ parse_tb (char **str)
   int reg;
 
   if (skip_past_char (&p, '[') == FAIL)
-    return FAIL;
+    {
+      inst.error = _("'[' expected");
+      return FAIL;
+    }
 
   if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
     {
@@ -3715,7 +3719,10 @@ parse_tb (char **str)
   inst.operands[0].reg = reg;
 
   if (skip_past_comma (&p) == FAIL)
-    return FAIL;
+    {
+      inst.error = _("',' expected");
+      return FAIL;
+    }
   
   if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
     {
@@ -4132,7 +4139,13 @@ parse_operands (char *str, const unsigned char *pattern)
 
     failure:
       if (!backtrack_pos)
-       return FAIL;
+       {
+         /* The parse routine should already have set inst.error, but set a
+            defaut here just in case.  */
+         if (!inst.error)
+           inst.error = _("syntax error");
+         return FAIL;
+       }
 
       /* Do not backtrack over a trailing optional argument that
         absorbed some text.  We will only fail again, with the
@@ -4140,7 +4153,11 @@ parse_operands (char *str, const unsigned char *pattern)
         probably less helpful than the current one.  */
       if (backtrack_index == i && backtrack_pos != str
          && upat[i+1] == OP_stop)
-       return FAIL;
+       {
+         if (!inst.error)
+           inst.error = _("syntax error");
+         return FAIL;
+       }
 
       /* Try again, skipping the optional argument at backtrack_pos.  */
       str = backtrack_pos;
@@ -4443,7 +4460,14 @@ encode_arm_cp_address (int i, int wb_ok, int unind_ok, int reloc_override)
 static int
 move_or_literal_pool (int i, bfd_boolean thumb_p, bfd_boolean mode_3)
 {
-  if ((inst.instruction & (thumb_p ? THUMB_LOAD_BIT : LOAD_BIT)) == 0)
+  unsigned long tbit;
+
+  if (thumb_p)
+    tbit = (inst.instruction > 0xffff) ? THUMB2_LOAD_BIT : THUMB_LOAD_BIT;
+  else
+    tbit = LOAD_BIT;
+
+  if ((inst.instruction & tbit) == 0)
     {
       inst.error = _("invalid pseudo operation");
       return 1;
@@ -4457,7 +4481,7 @@ move_or_literal_pool (int i, bfd_boolean thumb_p, bfd_boolean mode_3)
     {
       if (thumb_p)
        {
-         if ((inst.reloc.exp.X_add_number & ~0xFF) == 0)
+         if (!unified_syntax && (inst.reloc.exp.X_add_number & ~0xFF) == 0)
            {
              /* This can be done with a mov(1) instruction.  */
              inst.instruction  = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8);
@@ -5965,7 +5989,7 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   bfd_boolean is_pc = (inst.operands[i].reg == REG_PC);
 
   constraint (!inst.operands[i].isreg,
-             _("Thumb does not support the ldr =N pseudo-operation"));
+             _("Instruction does not support =N addresses"));
 
   inst.instruction |= inst.operands[i].reg << 16;
   if (inst.operands[i].immisreg)
@@ -6979,6 +7003,13 @@ do_t_ldst (void)
   opcode = inst.instruction;
   if (unified_syntax)
     {
+      if (!inst.operands[1].isreg)
+       {
+         if (opcode <= 0xffff)
+           inst.instruction = THUMB_OP32 (opcode);
+         if (move_or_literal_pool (0, /*thumb_p=*/TRUE, /*mode_3=*/FALSE))
+           return;
+       }
       if (inst.operands[1].isreg
          && !inst.operands[1].writeback
          && !inst.operands[1].shifted && !inst.operands[1].postind
@@ -11912,6 +11943,14 @@ md_apply_fix (fixS *   fixP,
        {
          newval = md_chars_to_number (buf, INSN_SIZE);
          newval |= (value >> 2) & 0x00ffffff;
+         /* Set the H bit on BLX instructions.  */
+         if (temp == 1)
+           {
+             if (value & 2)
+               newval |= 0x01000000;
+             else
+               newval &= ~0x01000000;
+           }
          md_number_to_chars (buf, newval, INSN_SIZE);
        }
       break;
@@ -13870,6 +13909,7 @@ arm_md_end (void)
   p = frag_more (size);
   elf32_arm_set_eabi_attr_contents (stdoutput, (bfd_byte *)p, size);
 }
+#endif /* OBJ_ELF */
 
 
 /* Parse a .cpu directive.  */
@@ -13976,5 +14016,4 @@ s_arm_fpu (int ignored ATTRIBUTE_UNUSED)
   *input_line_pointer = saved_char;
   ignore_rest_of_line ();
 }
-#endif /* OBJ_ELF */