* tc.h (struct relax_type, relax_typeS): Move from here..
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
index ff2e4aafcd72f702b2015051902c7efb1ed4a494..7a7c41eac3366fa813652150dfe5a2871d93c241 100644 (file)
@@ -1,5 +1,6 @@
 /* tc-arm.c -- Assemble for the ARM
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+   2004, 2005
    Free Software Foundation, Inc.
    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
        Modified by David Taylor (dtaylor@armltd.co.uk)
@@ -125,6 +126,8 @@ enum arm_float_abi
     /* Legacy a.out format.  */
 #   define FPU_DEFAULT FPU_ARCH_FPA    /* Soft-float, but FPA order.  */
 #  endif
+# elif defined (TE_VXWORKS)
+#  define FPU_DEFAULT FPU_ARCH_VFP     /* Soft-float, VFP order.  */
 # else
    /* For backwards compatibility, default to FPA.  */
 #  define FPU_DEFAULT FPU_ARCH_FPA
@@ -2680,18 +2683,6 @@ do_msr (char * str)
       return;
     }
 
-#if 0  /* The first edition of the ARM architecture manual stated that
-         writing anything other than the flags with an immediate operation
-         had UNPREDICTABLE effects.  This constraint was removed in the
-         second edition of the specification.  */
-  if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
-      && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
-    {
-      inst.error = _("immediate value cannot be used to set this field");
-      return;
-    }
-#endif
-
   inst.instruction |= INST_IMMEDIATE;
 
   if (inst.reloc.exp.X_add_symbol)
@@ -4560,6 +4551,7 @@ do_t_bkpt (char * str)
   end_of_line (str);
 }
 
+#ifdef OBJ_ELF
 static bfd_reloc_code_real_type
 arm_parse_reloc (void)
 {
@@ -4600,6 +4592,7 @@ arm_parse_reloc (void)
 
   return reloc_map[i].reloc;
 }
+#endif
 
 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
    Expects inst.instruction is set for BLX(1).
@@ -9378,10 +9371,10 @@ do_t_ldmstm (char * str)
       return;
     }
 
-  if (inst.reloc.type != BFD_RELOC_NONE)
+  if (inst.reloc.type != BFD_RELOC_UNUSED)
     {
       /* This really doesn't seem worth it.  */
-      inst.reloc.type = BFD_RELOC_NONE;
+      inst.reloc.type = BFD_RELOC_UNUSED;
       inst.error = _("expression too complex");
       return;
     }
@@ -9470,10 +9463,10 @@ do_t_push_pop (char * str)
       return;
     }
 
-  if (inst.reloc.type != BFD_RELOC_NONE)
+  if (inst.reloc.type != BFD_RELOC_UNUSED)
     {
       /* This really doesn't seem worth it.  */
-      inst.reloc.type = BFD_RELOC_NONE;
+      inst.reloc.type = BFD_RELOC_UNUSED;
       inst.error = _("expression too complex");
       return;
     }
@@ -10879,55 +10872,6 @@ build_arm_ops_hsh (void)
     }
 }
 
-#if 0 /* Suppressed - for now.  */
-#if defined OBJ_ELF || defined OBJ_COFF
-
-#ifdef OBJ_ELF
-#define arm_Note Elf_External_Note
-#else
-typedef struct
-{
-  unsigned char        namesz[4];      /* Size of entry's owner string.  */
-  unsigned char        descsz[4];      /* Size of the note descriptor.  */
-  unsigned char        type[4];        /* Interpretation of the descriptor.  */
-  char         name[1];        /* Start of the name+desc data.  */
-} arm_Note;
-#endif
-
-/* The description is kept to a fix sized in order to make updating
-   it and merging it easier.  */
-#define ARM_NOTE_DESCRIPTION_LENGTH    8
-
-static void
-arm_add_note (const char * name,
-             const char * description,
-             unsigned int type)
-{
-  arm_Note     note ATTRIBUTE_UNUSED;
-  char *       p;
-  unsigned int name_len;
-
-  name_len = (strlen (name) + 1 + 3) & ~3;
-
-  p = frag_more (sizeof (note.namesz));
-  md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
-
-  p = frag_more (sizeof (note.descsz));
-  md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
-
-  p = frag_more (sizeof (note.type));
-  md_number_to_chars (p, (valueT) type, sizeof (note.type));
-
-  p = frag_more (name_len);
-  strcpy (p, name);
-
-  p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
-  strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
-  frag_align (2, 0, 0);
-}
-#endif
-#endif
-
 \f
 static const struct thumb_opcode tinsns[] =
 {
@@ -11059,7 +11003,7 @@ md_begin (void)
     }
   else if (mfpu_opt == -1)
     {
-#if !(defined (TE_LINUX) || defined (TE_NetBSD))
+#if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS)) 
       /* Some environments specify a default FPU.  If they don't, infer it
         from the processor.  */
       if (mcpu_fpu_opt != -1)
@@ -11086,6 +11030,7 @@ md_begin (void)
 
   cpu_variant = mcpu_cpu_opt | mfpu_opt;
 
+#if defined OBJ_COFF || defined OBJ_ELF
   {
     unsigned int flags = 0;
 
@@ -11096,7 +11041,6 @@ md_begin (void)
       {
       case EF_ARM_EABI_UNKNOWN:
 #endif
-#if defined OBJ_COFF || defined OBJ_ELF
        /* Set the flags in the private structure.  */
        if (uses_apcs_26)      flags |= F_APCS26;
        if (support_interwork) flags |= F_INTERWORK;
@@ -11122,7 +11066,7 @@ md_begin (void)
        /* Using VFP conventions (even if soft-float).  */
        if (cpu_variant & FPU_VFP_EXT_NONE)
          flags |= F_VFP_FLOAT;
-#endif
+
 #if defined OBJ_ELF
        if (cpu_variant & FPU_ARCH_MAVERICK)
            flags |= EF_ARM_MAVERICK_FLOAT;
@@ -11136,7 +11080,6 @@ md_begin (void)
        abort ();
       }
 #endif
-#if defined OBJ_COFF || defined OBJ_ELF
     bfd_set_private_flags (stdoutput, flags);
 
     /* We have run out flags in the COFF header to encode the
@@ -11156,8 +11099,8 @@ md_begin (void)
            bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
          }
       }
-#endif
   }
+#endif
 
   /* Record the CPU type as well.  */
   switch (cpu_variant & ARM_CPU_MASK)
@@ -11205,62 +11148,6 @@ md_begin (void)
   else if (cpu_variant & ARM_EXT_V3M)
     mach = bfd_mach_arm_3M;
 
-#if 0 /* Suppressed - for now.  */
-#if defined (OBJ_ELF) || defined (OBJ_COFF)
-
-  /* Create a .note section to fully identify this arm binary.  */
-
-#define NOTE_ARCH_STRING       "arch: "
-
-#if defined OBJ_COFF && ! defined NT_VERSION
-#define NT_VERSION  1
-#define NT_ARCH     2
-#endif
-
-  {
-    segT current_seg = now_seg;
-    subsegT current_subseg = now_subseg;
-    asection * arm_arch;
-    const char * arch_string;
-
-    arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
-
-#ifdef OBJ_COFF
-    bfd_set_section_flags (stdoutput, arm_arch,
-                          SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
-                          | SEC_HAS_CONTENTS);
-#else
-    bfd_set_section_flags (stdoutput, arm_arch,
-                          SEC_READONLY | SEC_HAS_CONTENTS);
-#endif
-    arm_arch->output_section = arm_arch;
-    subseg_set (arm_arch, 0);
-
-    switch (mach)
-      {
-      default:
-      case bfd_mach_arm_unknown: arch_string = "unknown"; break;
-      case bfd_mach_arm_2:       arch_string = "armv2"; break;
-      case bfd_mach_arm_2a:      arch_string = "armv2a"; break;
-      case bfd_mach_arm_3:       arch_string = "armv3"; break;
-      case bfd_mach_arm_3M:      arch_string = "armv3M"; break;
-      case bfd_mach_arm_4:       arch_string = "armv4"; break;
-      case bfd_mach_arm_4T:      arch_string = "armv4t"; break;
-      case bfd_mach_arm_5:       arch_string = "armv5"; break;
-      case bfd_mach_arm_5T:      arch_string = "armv5t"; break;
-      case bfd_mach_arm_5TE:     arch_string = "armv5te"; break;
-      case bfd_mach_arm_XScale:  arch_string = "XScale"; break;
-      case bfd_mach_arm_ep9312:  arch_string = "ep9312"; break;
-      case bfd_mach_arm_iWMMXt:  arch_string = "iWMMXt"; break;
-      }
-
-    arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
-
-    subseg_set (current_seg, current_subseg);
-  }
-#endif
-#endif /* Suppressed code.  */
-
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
 }
 
@@ -11475,17 +11362,10 @@ md_apply_fix3 (fixS *   fixP,
   char *         buf = fixP->fx_where + fixP->fx_frag->fr_literal;
   arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
 
-  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
+  assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
 
   /* Note whether this will delete the relocation.  */
-#if 0
-  /* Patch from REarnshaw to JDavis (disabled for the moment, since it
-     doesn't work fully.)  */
-  if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
-      && !fixP->fx_pcrel)
-#else
   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
-#endif
     fixP->fx_done = 1;
 
   /* If this symbol is in a different section then we need to leave it for
@@ -11504,6 +11384,11 @@ md_apply_fix3 (fixS *   fixP,
 
   switch (fixP->fx_r_type)
     {
+    case BFD_RELOC_NONE:
+      /* This will need to go in the object file.  */
+      fixP->fx_done = 0;
+      break;
+  
     case BFD_RELOC_ARM_IMMEDIATE:
       /* We claim that this fixup has been processed here,
         even if in fact we generate an error because we do
@@ -11764,7 +11649,18 @@ md_apply_fix3 (fixS *   fixP,
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("out of range branch"));
 
-      newval = (value & 0x00ffffff) | (newval & 0xff000000);
+      if (seg->use_rela_p && !fixP->fx_done)
+       {
+         /* Must unshift the value before storing it in the addend.  */
+         value <<= 2;
+#ifdef OBJ_ELF
+         fixP->fx_offset = value;
+#endif
+         fixP->fx_addnumber = value;
+         newval = newval & 0xff000000;
+       }
+      else
+         newval = (value & 0x00ffffff) | (newval & 0xff000000);
       md_number_to_chars (buf, newval, INSN_SIZE);
       break;
 
@@ -11779,7 +11675,21 @@ md_apply_fix3 (fixS *   fixP,
        hbit   = (value >> 1) & 1;
        value  = (value >> 2) & 0x00ffffff;
        value  = (value + (newval & 0x00ffffff)) & 0x00ffffff;
-       newval = value | (newval & 0xfe000000) | (hbit << 24);
+
+       if (seg->use_rela_p && !fixP->fx_done)
+         {
+           /* Must sign-extend and unshift the value before storing
+              it in the addend.  */
+           value = SEXT24 (value);
+           value = (value << 2) | hbit;
+#ifdef OBJ_ELF
+           fixP->fx_offset = value;
+#endif
+           fixP->fx_addnumber = value;
+           newval = newval & 0xfe000000;
+         }
+       else
+         newval = value | (newval & 0xfe000000) | (hbit << 24);
        md_number_to_chars (buf, newval, INSN_SIZE);
       }
       break;
@@ -11795,7 +11705,16 @@ md_apply_fix3 (fixS *   fixP,
        if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("branch out of range"));
-       newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
+       if (seg->use_rela_p && !fixP->fx_done)
+         {
+#ifdef OBJ_ELF
+           fixP->fx_offset = value;
+#endif
+           fixP->fx_addnumber = value;
+           newval = newval & 0xff00;
+         }
+       else
+         newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
       }
       md_number_to_chars (buf, newval, THUMB_SIZE);
       break;
@@ -11811,7 +11730,16 @@ md_apply_fix3 (fixS *   fixP,
        if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("branch out of range"));
-       newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
+       if (seg->use_rela_p && !fixP->fx_done)
+         {
+#ifdef OBJ_ELF
+           fixP->fx_offset = value;
+#endif
+           fixP->fx_addnumber = value;
+           newval = newval & 0xf800;
+         }
+       else
+         newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
       }
       md_number_to_chars (buf, newval, THUMB_SIZE);
       break;
@@ -11836,20 +11764,35 @@ md_apply_fix3 (fixS *   fixP,
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("branch with link out of range"));
 
-       newval  = (newval  & 0xf800) | ((value & 0x7fffff) >> 12);
-       newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
        if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
          /* For a BLX instruction, make sure that the relocation is rounded up
             to a word boundary.  This follows the semantics of the instruction
             which specifies that bit 1 of the target address will come from bit
             1 of the base address.  */
-         newval2 = (newval2 + 1) & ~ 1;
+         value = (value + 1) & ~ 1;
+
+       if (seg->use_rela_p && !fixP->fx_done)
+         {
+#ifdef OBJ_ELF
+           fixP->fx_offset = value;
+#endif
+           fixP->fx_addnumber = value;
+           newval = newval & 0xf800;
+           newval2 = newval2 & 0xf800;
+         }
+       else
+         {
+           newval  = (newval  & 0xf800) | ((value & 0x7fffff) >> 12);
+           newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
+         }
        md_number_to_chars (buf, newval, THUMB_SIZE);
        md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
       }
       break;
 
     case BFD_RELOC_8:
+      if (seg->use_rela_p && !fixP->fx_done)
+       break;
       if (fixP->fx_done || fixP->fx_pcrel)
        md_number_to_chars (buf, value, 1);
 #ifdef OBJ_ELF
@@ -11862,6 +11805,8 @@ md_apply_fix3 (fixS *   fixP,
       break;
 
     case BFD_RELOC_16:
+      if (seg->use_rela_p && !fixP->fx_done)
+       break;
       if (fixP->fx_done || fixP->fx_pcrel)
        md_number_to_chars (buf, value, 2);
 #ifdef OBJ_ELF
@@ -11877,6 +11822,8 @@ md_apply_fix3 (fixS *   fixP,
     case BFD_RELOC_ARM_GOT32:
     case BFD_RELOC_ARM_GOTOFF:
     case BFD_RELOC_ARM_TARGET2:
+      if (seg->use_rela_p && !fixP->fx_done)
+       break;
       md_number_to_chars (buf, 0, 4);
       break;
 #endif
@@ -11887,6 +11834,8 @@ md_apply_fix3 (fixS *   fixP,
     case BFD_RELOC_ARM_ROSEGREL32:
     case BFD_RELOC_ARM_SBREL32:
     case BFD_RELOC_32_PCREL:
+      if (seg->use_rela_p && !fixP->fx_done)
+       break;
       if (fixP->fx_done || fixP->fx_pcrel)
        md_number_to_chars (buf, value, 4);
 #ifdef OBJ_ELF
@@ -12107,7 +12056,7 @@ md_apply_fix3 (fixS *   fixP,
       fixP->fx_done = 0;
       return;
 
-    case BFD_RELOC_NONE:
+    case BFD_RELOC_UNUSED:
     default:
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("bad relocation fixup type (%d)"), fixP->fx_r_type);
@@ -12163,6 +12112,7 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
          break;
        }
 
+    case BFD_RELOC_NONE:
     case BFD_RELOC_ARM_PCREL_BRANCH:
     case BFD_RELOC_ARM_PCREL_BLX:
     case BFD_RELOC_RVA:
@@ -12227,6 +12177,7 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
 
        switch (fixp->fx_r_type)
          {
+         case BFD_RELOC_NONE:             type = "NONE";         break;
          case BFD_RELOC_ARM_OFFSET_IMM8:  type = "OFFSET_IMM8";  break;
          case BFD_RELOC_ARM_SHIFT_IMM:    type = "SHIFT_IMM";    break;
          case BFD_RELOC_ARM_SMI:          type = "SMI";          break;
@@ -12350,7 +12301,7 @@ output_inst (const char * str)
   else
     md_number_to_chars (to, inst.instruction, inst.size);
 
-  if (inst.reloc.type != BFD_RELOC_NONE)
+  if (inst.reloc.type != BFD_RELOC_UNUSED)
     fix_new_arm (frag_now, to - frag_now->fr_literal,
                 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
                 inst.reloc.type);
@@ -12367,12 +12318,6 @@ md_assemble (char * str)
   char *p;
   char *start;
 
-  /* Align the instruction.
-     This may not be the right thing to do but ...  */
-#if 0
-  arm_align (2, 0);
-#endif
-
   /* Align the previous label if needed.  */
   if (last_label_seen != NULL)
     {
@@ -12382,7 +12327,7 @@ md_assemble (char * str)
     }
 
   memset (&inst, '\0', sizeof (inst));
-  inst.reloc.type = BFD_RELOC_NONE;
+  inst.reloc.type = BFD_RELOC_UNUSED;
 
   skip_whitespace (str);
 
@@ -12759,8 +12704,8 @@ static struct arm_cpu_option_table arm_cpus[] =
   {"arm1020",          ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
   {"arm1020t",         ARM_ARCH_V5T,    FPU_ARCH_VFP_V1},
   {"arm1020e",         ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
-  {"arm1026ejs",       ARM_ARCH_V5TE  FPU_ARCH_VFP_V2},
-  {"arm1026ej-s",      ARM_ARCH_V5TE  FPU_ARCH_VFP_V2},
+  {"arm1026ejs",       ARM_ARCH_V5TEJ,  FPU_ARCH_VFP_V2},
+  {"arm1026ej-s",      ARM_ARCH_V5TEJ,  FPU_ARCH_VFP_V2},
   {"arm1136js",                ARM_ARCH_V6,     FPU_NONE},
   {"arm1136j-s",       ARM_ARCH_V6,     FPU_NONE},
   {"arm1136jfs",       ARM_ARCH_V6,     FPU_ARCH_VFP_V2},
@@ -13502,6 +13447,10 @@ elf32_arm_target_format (void)
   return (target_big_endian
          ? "elf32-bigarm-symbian"
          : "elf32-littlearm-symbian");
+#elif defined (TE_VXWORKS)
+  return (target_big_endian
+         ? "elf32-bigarm-vxworks"
+         : "elf32-littlearm-vxworks");
 #else
   if (target_big_endian)
     return "elf32-bigarm";
@@ -13952,6 +13901,14 @@ create_unwind_entry (int have_data)
       /* Custom personality routine.  */
       fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
               BFD_RELOC_ARM_PREL31);
+
+      /* Indicate dependency to linker.  */
+        {
+          char *name = "__aeabi_unwind_cpp_pr0";
+         symbolS *pr = symbol_find_or_make (name);
+         fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
+       }
+
       where += 4;
       ptr += 4;
 
@@ -13961,18 +13918,28 @@ create_unwind_entry (int have_data)
       break;
 
     /* ABI defined personality routines.  */
-    /* TODO: Emit R_ARM_NONE to the personality routine.  */
     case 0:
       /* Three opcodes bytes are packed into the first word.  */
       data = 0x80;
       n = 3;
-      break;
+      goto emit_reloc;
 
     case 1:
     case 2:
       /* The size and first two opcode bytes go in the first word.  */
       data = ((0x80 + unwind.personality_index) << 8) | size;
       n = 2;
+      goto emit_reloc;
+
+    emit_reloc:
+      {
+       /* Indicate dependency to linker.  */
+       char *name[] = { "__aeabi_unwind_cpp_pr0",
+                        "__aeabi_unwind_cpp_pr1",
+                        "__aeabi_unwind_cpp_pr2" };
+       symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
+       fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
+      }
       break;
 
     default:
@@ -14079,7 +14046,7 @@ s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
 
   /* Self relative offset of the function start.  */
   fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
-          BFD_RELOC_32);
+          BFD_RELOC_ARM_PREL31);
 
   if (val)
     /* Inline exception table entry.  */
This page took 0.031036 seconds and 4 git commands to generate.