]> Git Repo - binutils.git/blobdiff - gas/config/tc-arm.c
bfd/
[binutils.git] / gas / config / tc-arm.c
index 87240977e89eb1779cb8fd3deb683d37761b2a9e..63aa32e75d073b77306d305f15dc740aa7cc743e 100644 (file)
 
 #ifdef OBJ_ELF
 #include "elf/arm.h"
-#include "dwarf2dbg.h"
 #include "dw2gencfi.h"
 #endif
 
-/* XXX Set this to 1 after the next binutils release.  */
-#define WARN_DEPRECATED 0
+#include "dwarf2dbg.h"
+
+#define WARN_DEPRECATED 1
 
 #ifdef OBJ_ELF
 /* Must be at least the size of the largest unwind opcode (currently two).  */
@@ -3448,7 +3448,7 @@ s_arm_unwind_save_mmxwr (void)
 
              op = 0xffff << (reg - 1);
              if (reg > 0
-                 || ((mask & op) == (1u << (reg - 1))))
+                 && ((mask & op) == (1u << (reg - 1))))
                {
                  op = (1 << (reg + i + 1)) - 1;
                  op &= ~((1 << reg) - 1);
@@ -3878,6 +3878,28 @@ static void s_arm_arch (int);
 static void s_arm_cpu (int);
 static void s_arm_fpu (int);
 
+#ifdef TE_PE
+
+static void
+pe_directive_secrel (int dummy ATTRIBUTE_UNUSED) 
+{
+  expressionS exp;
+
+  do
+    {
+      expression (&exp);
+      if (exp.X_op == O_symbol)
+       exp.X_op = O_secrel;
+
+      emit_expr (&exp, 4);
+    }
+  while (*input_line_pointer++ == ',');
+
+  input_line_pointer--;
+  demand_empty_rest_of_line ();
+}
+#endif /* TE_PE */
+
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
      pseudo-op name without dot
@@ -3926,10 +3948,22 @@ const pseudo_typeS md_pseudo_table[] =
   { "eabi_attribute",  s_arm_eabi_attribute,   0 },
 #else
   { "word",       cons, 4},
+
+  /* These are used for dwarf.  */
+  {"2byte", cons, 2},
+  {"4byte", cons, 4},
+  {"8byte", cons, 8},
+  /* These are used for dwarf2.  */
+  { "file", (void (*) (int)) dwarf2_directive_file, 0 },
+  { "loc",  dwarf2_directive_loc,  0 },
+  { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
 #endif
   { "extend",     float_cons, 'x' },
   { "ldouble",    float_cons, 'x' },
   { "packed",     float_cons, 'p' },
+#ifdef TE_PE
+  {"secrel32", pe_directive_secrel, 0},
+#endif
   { 0, 0, 0 }
 };
 \f
@@ -5370,6 +5404,7 @@ enum operand_parse_code
   OP_RR_EXi,   /* ARM register or expression with imm prefix */
   OP_RF_IF,    /* FPA register or immediate */
   OP_RIWR_RIWC, /* iWMMXt R or C reg */
+  OP_RIWC_RIWG, /* iWMMXt wC or wCG reg */
 
   /* Optional operands.         */
   OP_oI7b,      /* immediate, prefix optional, 0 .. 7 */
@@ -5748,9 +5783,10 @@ parse_operands (char *str, const unsigned char *pattern)
        case OP_RIWR_RIWC:
          {
            struct reg_entry *rege = arm_reg_parse_multi (&str);
-           if (rege->type != REG_TYPE_MMXWR
-               && rege->type != REG_TYPE_MMXWC
-               && rege->type != REG_TYPE_MMXWCG)
+           if (!rege
+               || (rege->type != REG_TYPE_MMXWR
+                   && rege->type != REG_TYPE_MMXWC
+                   && rege->type != REG_TYPE_MMXWCG))
              {
                inst.error = _("iWMMXt data or control register expected");
                goto failure;
@@ -5760,6 +5796,21 @@ parse_operands (char *str, const unsigned char *pattern)
          }
          break;
 
+       case OP_RIWC_RIWG:
+         {
+           struct reg_entry *rege = arm_reg_parse_multi (&str);
+           if (!rege
+               || (rege->type != REG_TYPE_MMXWC
+                   && rege->type != REG_TYPE_MMXWCG))
+             {
+               inst.error = _("iWMMXt control register expected");
+               goto failure;
+             }
+           inst.operands[i].reg = rege->number;
+           inst.operands[i].isreg = 1;
+         }
+         break;
+
          /* Misc */
        case OP_CPSF:    val = parse_cps_flags (&str);          break;
        case OP_ENDI:    val = parse_endian_specifier (&str);   break;
@@ -13364,11 +13415,9 @@ output_relax_insn (void)
   symbolS *sym;
   int offset;
 
-#ifdef OBJ_ELF
   /* The size of the instruction is unknown, so tie the debug info to the
      start of the instruction.  */
   dwarf2_emit_insn (0);
-#endif
 
   switch (inst.reloc.exp.X_op)
     {
@@ -13436,9 +13485,7 @@ output_inst (const char * str)
                 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
                 inst.reloc.type);
 
-#ifdef OBJ_ELF
   dwarf2_emit_insn (inst.size);
-#endif
 }
 
 /* Tag values used in struct asm_opcode's tag field.  */
@@ -13535,11 +13582,14 @@ opcode_lookup (char **str)
   const struct asm_opcode *opcode;
   const struct asm_cond *cond;
   char save[2];
+  bfd_boolean neon_supported;
+  
+  neon_supported = ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1);
 
   /* Scan up to the end of the mnemonic, which must end in white space,
-     '.' (in unified mode only), or end of string.  */
+     '.' (in unified mode, or for Neon instructions), or end of string.  */
   for (base = end = *str; *end != '\0'; end++)
-    if (*end == ' ' || (unified_syntax && *end == '.'))
+    if (*end == ' ' || ((unified_syntax || neon_supported) && *end == '.'))
       break;
 
   if (end == base)
@@ -13550,9 +13600,11 @@ opcode_lookup (char **str)
     {
       int offset = 2;
       
-      if (end[1] == 'w')
+      /* The .w and .n suffixes are only valid if the unified syntax is in
+         use.  */
+      if (unified_syntax && end[1] == 'w')
        inst.size_req = 4;
-      else if (end[1] == 'n')
+      else if (unified_syntax && end[1] == 'n')
        inst.size_req = 2;
       else
         offset = 0;
@@ -13563,7 +13615,8 @@ opcode_lookup (char **str)
 
       if (end[offset] == '.')      
        {
-         /* See if we have a Neon type suffix.  */
+         /* See if we have a Neon type suffix (possible in either unified or
+             non-unified ARM syntax mode).  */
           if (parse_neon_type (&inst.vectype, str) == FAIL)
            return 0;
         }
@@ -13791,7 +13844,7 @@ md_assemble (char *str)
        ARM_MERGE_FEATURE_SETS (thumb_arch_used, thumb_arch_used,
                                arm_ext_v6t2);
     }
-  else
+  else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1))
     {
       /* Check that this instruction is supported for this CPU.  */
       if (!opcode->avariant ||
@@ -13824,6 +13877,12 @@ md_assemble (char *str)
        ARM_MERGE_FEATURE_SETS (arm_arch_used, arm_arch_used,
                                *opcode->avariant);
     }
+  else
+    {
+      as_bad (_("attempt to use an ARM instruction on a Thumb-only processor "
+               "-- `%s'"), str);
+      return;
+    }
   output_inst (str);
 }
 
@@ -13889,9 +13948,7 @@ arm_frob_label (symbolS * sym)
       label_is_thumb_function_name = FALSE;
     }
 
-#ifdef OBJ_ELF
   dwarf2_emit_label (sym);
-#endif
 }
 
 int
@@ -15712,7 +15769,7 @@ static const struct asm_opcode insns[] =
  cCE(tinsrb,   e600010, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
  cCE(tinsrh,   e600050, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
  cCE(tinsrw,   e600090, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
- cCE(tmcr,     e000110, 2, (RIWC, RR),             rn_rd),
+ cCE(tmcr,     e000110, 2, (RIWC_RIWG, RR),        rn_rd),
  cCE(tmcrr,    c400000, 3, (RIWR, RR, RR),         rm_rd_rn),
  cCE(tmia,     e200010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
  cCE(tmiaph,   e280010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
@@ -15723,7 +15780,7 @@ static const struct asm_opcode insns[] =
  cCE(tmovmskb, e100030, 2, (RR, RIWR),             rd_rn),
  cCE(tmovmskh, e500030, 2, (RR, RIWR),             rd_rn),
  cCE(tmovmskw, e900030, 2, (RR, RIWR),             rd_rn),
- cCE(tmrc,     e100110, 2, (RR, RIWC),             rd_rn),
+ cCE(tmrc,     e100110, 2, (RR, RIWC_RIWG),        rd_rn),
  cCE(tmrrc,    c500000, 3, (RR, RR, RIWR),         rd_rn_rm),
  cCE(torcb,    e13f150, 1, (RR),                   iwmmxt_tandorc),
  cCE(torch,    e53f150, 1, (RR),                   iwmmxt_tandorc),
@@ -16362,12 +16419,22 @@ valueT
 md_section_align (segT  segment ATTRIBUTE_UNUSED,
                  valueT size)
 {
-#ifdef OBJ_ELF
-  return size;
-#else
-  /* Round all sects to multiple of 4. */
-  return (size + 3) & ~3;
+#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
+  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
+    {
+      /* For a.out, force the section size to be aligned.  If we don't do
+        this, BFD will align it for us, but it will not write out the
+        final bytes of the section.  This may be a bug in BFD, but it is
+        easier to fix it here since that is how the other a.out targets
+        work.  */
+      int align;
+
+      align = bfd_get_section_alignment (stdoutput, segment);
+      size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
+    }
 #endif
+
+  return size;
 }
 
 /* This is called from HANDLE_ALIGN in write.c.         Fill in the contents
@@ -16867,6 +16934,16 @@ create_unwind_entry (int have_data)
   return 0;
 }
 
+
+/* Initialize the DWARF-2 unwind information for this procedure.  */
+
+void
+tc_arm_frame_initial_instructions (void)
+{
+  cfi_add_CFA_def_cfa (REG_SP, 0);
+}
+#endif /* OBJ_ELF */
+
 /* Convert REGNAME to a DWARF-2 register number.  */
 
 int
@@ -16880,15 +16957,18 @@ tc_arm_regname_to_dw2regnum (char *regname)
   return reg;
 }
 
-/* Initialize the DWARF-2 unwind information for this procedure.  */
-
+#ifdef TE_PE
 void
-tc_arm_frame_initial_instructions (void)
+tc_pe_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
 {
-  cfi_add_CFA_def_cfa (REG_SP, 0);
-}
-#endif /* OBJ_ELF */
+  expressionS expr;
 
+  expr.X_op = O_secrel;
+  expr.X_add_symbol = symbol;
+  expr.X_add_number = 0;
+  emit_expr (&expr, size);
+}
+#endif
 
 /* MD interface: Symbol and relocation handling.  */
 
@@ -17880,6 +17960,9 @@ md_apply_fix (fixS *    fixP,
     case BFD_RELOC_ARM_ROSEGREL32:
     case BFD_RELOC_ARM_SBREL32:
     case BFD_RELOC_32_PCREL:
+#ifdef TE_PE
+    case BFD_RELOC_32_SECREL:
+#endif
       if (fixP->fx_done || !seg->use_rela_p)
 #ifdef TE_WINCE
        /* For WinCE we only do this for pcrel fixups.  */
@@ -18418,6 +18501,9 @@ tc_gen_reloc (asection *section, fixS *fixp)
     case BFD_RELOC_THUMB_PCREL_BLX:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
+#ifdef TE_PE
+    case BFD_RELOC_32_SECREL:
+#endif
       code = fixp->fx_r_type;
       break;
 
@@ -18600,6 +18686,14 @@ cons_fix_new_arm (fragS *      frag,
       break;
     }
 
+#ifdef TE_PE
+  if (exp->X_op == O_secrel)
+  {
+    exp->X_op = O_symbol;
+    type = BFD_RELOC_32_SECREL;
+  }
+#endif
+
   fix_new_exp (frag, where, (int) size, exp, pcrel, type);
 }
 
@@ -18869,6 +18963,16 @@ set_constant_flonums (void)
       abort ();
 }
 
+/* Auto-select Thumb mode if it's the only available instruction set for the
+   given architecture.  */
+
+static void
+autoselect_thumb_from_cpu_variant (void)
+{
+  if (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1))
+    opcode_select (16);
+}
+
 void
 md_begin (void)
 {
@@ -18969,6 +19073,8 @@ md_begin (void)
 
   ARM_MERGE_FEATURE_SETS (cpu_variant, *mcpu_cpu_opt, *mfpu_opt);
 
+  autoselect_thumb_from_cpu_variant ();
+
   arm_arch_used = thumb_arch_used = arm_arch_none;
 
 #if defined OBJ_COFF || defined OBJ_ELF
This page took 0.108541 seconds and 4 git commands to generate.