include/elf/
[deliverable/binutils-gdb.git] / gas / config / tc-alpha.c
index 67f0a823a7f985b5aebe8d76d07132d5a1d9d67b..1ba7aca6b04ed3530525944d050c0911b89cee8c 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
-   Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-   Free Software Foundation, Inc.
+   Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001, 2002 Free Software Foundation, Inc.
    Contributed by Carnegie Mellon University, 1993.
    Written by Alessandro Forin, based on earlier gas-1.38 target CPU files.
    Modified by Ken Raeburn for gas-2.x and ECOFF support.
@@ -106,29 +106,45 @@ struct alpha_macro {
 #define O_pregister    O_md1   /* O_register, in parentheses */
 #define O_cpregister   O_md2   /* + a leading comma */
 
-/* Note, the alpha_reloc_op table below depends on the ordering
-   of O_literal .. O_gpre16.  */
+/* The alpha_reloc_op table below depends on the ordering of these.  */
 #define O_literal      O_md3   /* !literal relocation */
 #define O_lituse_addr  O_md4   /* !lituse_addr relocation */
 #define O_lituse_base  O_md5   /* !lituse_base relocation */
 #define O_lituse_bytoff        O_md6   /* !lituse_bytoff relocation */
 #define O_lituse_jsr   O_md7   /* !lituse_jsr relocation */
-#define O_gpdisp       O_md8   /* !gpdisp relocation */
-#define O_gprelhigh    O_md9   /* !gprelhigh relocation */
-#define O_gprellow     O_md10  /* !gprellow relocation */
-#define O_gprel                O_md11  /* !gprel relocation */
+#define O_lituse_tlsgd O_md8   /* !lituse_tlsgd relocation */
+#define O_lituse_tlsldm        O_md9   /* !lituse_tlsldm relocation */
+#define O_gpdisp       O_md10  /* !gpdisp relocation */
+#define O_gprelhigh    O_md11  /* !gprelhigh relocation */
+#define O_gprellow     O_md12  /* !gprellow relocation */
+#define O_gprel                O_md13  /* !gprel relocation */
+#define O_samegp       O_md14  /* !samegp relocation */
+#define O_tlsgd                O_md15  /* !tlsgd relocation */
+#define O_tlsldm       O_md16  /* !tlsldm relocation */
+#define O_gotdtprel    O_md17  /* !gotdtprel relocation */
+#define O_dtprelhi     O_md18  /* !dtprelhi relocation */
+#define O_dtprello     O_md19  /* !dtprello relocation */
+#define O_dtprel       O_md20  /* !dtprel relocation */
+#define O_gottprel     O_md21  /* !gottprel relocation */
+#define O_tprelhi      O_md22  /* !tprelhi relocation */
+#define O_tprello      O_md23  /* !tprello relocation */
+#define O_tprel                O_md24  /* !tprel relocation */
 
 #define DUMMY_RELOC_LITUSE_ADDR                (BFD_RELOC_UNUSED + 1)
 #define DUMMY_RELOC_LITUSE_BASE                (BFD_RELOC_UNUSED + 2)
 #define DUMMY_RELOC_LITUSE_BYTOFF      (BFD_RELOC_UNUSED + 3)
 #define DUMMY_RELOC_LITUSE_JSR         (BFD_RELOC_UNUSED + 4)
+#define DUMMY_RELOC_LITUSE_TLSGD       (BFD_RELOC_UNUSED + 5)
+#define DUMMY_RELOC_LITUSE_TLSLDM      (BFD_RELOC_UNUSED + 6)
 
 #define LITUSE_ADDR    0
 #define LITUSE_BASE    1
 #define LITUSE_BYTOFF  2
 #define LITUSE_JSR     3
+#define LITUSE_TLSGD   4
+#define LITUSE_TLSLDM  5
 
-#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_gprel)
+#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_tprel)
 
 /* Macros for extracting the type and number of encoded register tokens */
 
@@ -495,10 +511,23 @@ static const struct alpha_reloc_op_tag {
   DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1),
   DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1),
   DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1),
+  DEF(lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1),
+  DEF(lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1),
   DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1),
   DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0),
   DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0),
-  DEF(gprel, BFD_RELOC_GPREL16, 0, 0)
+  DEF(gprel, BFD_RELOC_GPREL16, 0, 0),
+  DEF(samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0),
+  DEF(tlsgd, BFD_RELOC_ALPHA_TLSGD, 0, 1),
+  DEF(tlsldm, BFD_RELOC_ALPHA_TLSLDM, 0, 1),
+  DEF(gotdtprel, BFD_RELOC_ALPHA_GOTDTPREL16, 0, 0),
+  DEF(dtprelhi, BFD_RELOC_ALPHA_DTPREL_HI16, 0, 0),
+  DEF(dtprello, BFD_RELOC_ALPHA_DTPREL_LO16, 0, 0),
+  DEF(dtprel, BFD_RELOC_ALPHA_DTPREL16, 0, 0),
+  DEF(gottprel, BFD_RELOC_ALPHA_GOTTPREL16, 0, 0),
+  DEF(tprelhi, BFD_RELOC_ALPHA_TPREL_HI16, 0, 0),
+  DEF(tprello, BFD_RELOC_ALPHA_TPREL_LO16, 0, 0),
+  DEF(tprel, BFD_RELOC_ALPHA_TPREL16, 0, 0),
 };
 
 #undef DEF
@@ -513,12 +542,17 @@ static const int alpha_num_reloc_op
 /* Structure to hold explict sequence information.  */
 struct alpha_reloc_tag
 {
-  fixS *slaves;                        /* head of linked list of !literals */
+  fixS *master;                        /* the literal reloc */
+  fixS *slaves;                        /* head of linked list of lituses */
   segT segment;                        /* segment relocs are in or undefined_section*/
   long sequence;               /* sequence # */
   unsigned n_master;           /* # of literals */
   unsigned n_slaves;           /* # of lituses */
-  char multi_section_p;                /* True if more than one section was used */
+  unsigned saw_tlsgd : 1;      /* true if ... */
+  unsigned saw_tlsldm : 1;
+  unsigned saw_lu_tlsgd : 1;
+  unsigned saw_lu_tlsldm : 1;
+  unsigned multi_section_p : 1;        /* true if more than one section was used */
   char string[1];              /* printable form of sequence to hash with */
 };
 
@@ -1118,14 +1152,14 @@ md_pcrel_from (fixP)
    the distance to the "lda" instruction for setting the addend to
    GPDISP.  */
 
-int
-md_apply_fix3 (fixP, valueP, seg)
+void
+md_apply_fix3 (fixP, valP, seg)
      fixS *fixP;
-     valueT *valueP;
+     valueT * valP;
      segT seg;
 {
   char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
-  valueT value = *valueP;
+  valueT value = * valP;
   unsigned image, size;
 
   switch (fixP->fx_r_type)
@@ -1184,7 +1218,7 @@ md_apply_fix3 (fixP, valueP, seg)
          md_number_to_chars (fixpos, value, size);
          goto done;
        }
-      return 1;
+      return;
 
 #ifdef OBJ_ECOFF
     case BFD_RELOC_GPREL32:
@@ -1199,7 +1233,7 @@ md_apply_fix3 (fixP, valueP, seg)
     case BFD_RELOC_GPREL16:
     case BFD_RELOC_ALPHA_GPREL_HI16:
     case BFD_RELOC_ALPHA_GPREL_LO16:
-      return 1;
+      return;
 
     case BFD_RELOC_23_PCREL_S2:
       if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
@@ -1208,7 +1242,7 @@ md_apply_fix3 (fixP, valueP, seg)
          image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF);
          goto write_done;
        }
-      return 1;
+      return;
 
     case BFD_RELOC_ALPHA_HINT:
       if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
@@ -1217,22 +1251,37 @@ md_apply_fix3 (fixP, valueP, seg)
          image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF);
          goto write_done;
        }
-      return 1;
+      return;
+
+#ifdef OBJ_ELF
+    case BFD_RELOC_ALPHA_BRSGP:
+    case BFD_RELOC_ALPHA_TLSGD:
+    case BFD_RELOC_ALPHA_TLSLDM:
+    case BFD_RELOC_ALPHA_GOTDTPREL16:
+    case BFD_RELOC_ALPHA_DTPREL_HI16:
+    case BFD_RELOC_ALPHA_DTPREL_LO16:
+    case BFD_RELOC_ALPHA_DTPREL16:
+    case BFD_RELOC_ALPHA_GOTTPREL16:
+    case BFD_RELOC_ALPHA_TPREL_HI16:
+    case BFD_RELOC_ALPHA_TPREL_LO16:
+    case BFD_RELOC_ALPHA_TPREL16:
+      return;
+#endif
 
 #ifdef OBJ_ECOFF
     case BFD_RELOC_ALPHA_LITERAL:
       md_number_to_chars (fixpos, value, 2);
-      return 1;
+      return;
 #endif
     case BFD_RELOC_ALPHA_ELF_LITERAL:
     case BFD_RELOC_ALPHA_LITUSE:
     case BFD_RELOC_ALPHA_LINKAGE:
     case BFD_RELOC_ALPHA_CODEADDR:
-      return 1;
+      return;
 
     case BFD_RELOC_VTABLE_INHERIT:
     case BFD_RELOC_VTABLE_ENTRY:
-      return 1;
+      return;
 
     default:
       {
@@ -1262,7 +1311,7 @@ md_apply_fix3 (fixP, valueP, seg)
     }
 
   if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0)
-    return 1;
+    return;
   else
     {
       as_warn_where (fixP->fx_file, fixP->fx_line,
@@ -1275,12 +1324,9 @@ write_done:
 
 done:
   fixP->fx_done = 1;
-  return 0;
 }
 
-/*
- * Look for a register name in the given symbol.
- */
+/* Look for a register name in the given symbol.  */
 
 symbolS *
 md_undefined_symbol (name)
@@ -1367,6 +1413,49 @@ alpha_define_label (sym)
   alpha_insn_label = sym;
 }
 
+/* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and
+   let it get resolved at assembly time.  */
+
+void
+alpha_validate_fix (f)
+     fixS *f;
+{
+#ifdef OBJ_ELF
+  int offset = 0;
+  const char *name;
+
+  if (f->fx_r_type != BFD_RELOC_ALPHA_BRSGP)
+    return;
+
+  if (! S_IS_DEFINED (f->fx_addsy))
+    return;
+
+  switch (S_GET_OTHER (f->fx_addsy) & STO_ALPHA_STD_GPLOAD)
+    {
+    case STO_ALPHA_NOPV:
+      break;
+    case STO_ALPHA_STD_GPLOAD:
+      offset = 8;
+      break;
+    default:
+      if (S_IS_LOCAL (f->fx_addsy))
+       name = "<local>";
+      else
+       name = S_GET_NAME (f->fx_addsy);
+      as_bad_where (f->fx_file, f->fx_line,
+                   _("!samegp reloc against symbol without .prologue: %s"),
+                   name);
+      break;
+    }
+
+  if (! (S_IS_EXTERN (f->fx_addsy) || S_IS_WEAK (f->fx_addsy)))
+    {
+      f->fx_r_type = BFD_RELOC_23_PCREL_S2;
+      f->fx_offset += offset;
+    }
+#endif
+}
+
 /* Return true if we must always emit a reloc for a type and false if
    there is some hope of resolving it at assembly time.  */
 
@@ -1391,8 +1480,19 @@ alpha_force_relocation (f)
     case BFD_RELOC_ALPHA_GPREL_LO16:
     case BFD_RELOC_ALPHA_LINKAGE:
     case BFD_RELOC_ALPHA_CODEADDR:
+    case BFD_RELOC_ALPHA_BRSGP:
     case BFD_RELOC_VTABLE_INHERIT:
     case BFD_RELOC_VTABLE_ENTRY:
+    case BFD_RELOC_ALPHA_TLSGD:
+    case BFD_RELOC_ALPHA_TLSLDM:
+    case BFD_RELOC_ALPHA_GOTDTPREL16:
+    case BFD_RELOC_ALPHA_DTPREL_HI16:
+    case BFD_RELOC_ALPHA_DTPREL_LO16:
+    case BFD_RELOC_ALPHA_DTPREL16:
+    case BFD_RELOC_ALPHA_GOTTPREL16:
+    case BFD_RELOC_ALPHA_TPREL_HI16:
+    case BFD_RELOC_ALPHA_TPREL_LO16:
+    case BFD_RELOC_ALPHA_TPREL16:
       return 1;
 
     case BFD_RELOC_23_PCREL_S2:
@@ -1402,8 +1502,6 @@ alpha_force_relocation (f)
       return 0;
 
     default:
-      assert ((int) f->fx_r_type < 0
-             && -(int) f->fx_r_type < (int) alpha_num_operands);
       return 0;
     }
 }
@@ -1427,6 +1525,7 @@ alpha_fix_adjustable (f)
     case BFD_RELOC_ALPHA_GPDISP_HI16:
     case BFD_RELOC_ALPHA_GPDISP_LO16:
     case BFD_RELOC_ALPHA_GPDISP:
+    case BFD_RELOC_ALPHA_BRSGP:
       return 0;
 
     case BFD_RELOC_ALPHA_LITERAL:
@@ -1450,9 +1549,21 @@ alpha_fix_adjustable (f)
     case BFD_RELOC_ALPHA_HINT:
       return 1;
 
+    case BFD_RELOC_ALPHA_TLSGD:
+    case BFD_RELOC_ALPHA_TLSLDM:
+    case BFD_RELOC_ALPHA_GOTDTPREL16:
+    case BFD_RELOC_ALPHA_DTPREL_HI16:
+    case BFD_RELOC_ALPHA_DTPREL_LO16:
+    case BFD_RELOC_ALPHA_DTPREL16:
+    case BFD_RELOC_ALPHA_GOTTPREL16:
+    case BFD_RELOC_ALPHA_TPREL_HI16:
+    case BFD_RELOC_ALPHA_TPREL_LO16:
+    case BFD_RELOC_ALPHA_TPREL16:
+      /* ??? No idea why we can't return a reference to .tbss+10, but
+        we're preventing this in the other assemblers.  Follow for now.  */
+      return 0;
+
     default:
-      assert ((int) f->fx_r_type < 0
-             && - (int) f->fx_r_type < (int) alpha_num_operands);
       return 1;
     }
   /*NOTREACHED*/
@@ -1511,7 +1622,8 @@ tc_gen_reloc (sec, fixp)
        * of thing, and as a result we need to fake it out here.
        */
       if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)
-          || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
+          || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE)
+          || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL))
          && !S_IS_COMMON (fixp->fx_addsy))
        reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
 #endif
@@ -1620,7 +1732,6 @@ alpha_adjust_symtab_relocs (abfd, sec, ptr)
   fixS *fixp;
   fixS *next;
   fixS *slave;
-  unsigned long n_slaves = 0;
 
   /* If seginfo is NULL, we did not create this section; don't do
      anything with it.  By using a pointer to a pointer, we can update
@@ -1643,21 +1754,39 @@ alpha_adjust_symtab_relocs (abfd, sec, ptr)
       switch (fixp->fx_r_type)
        {
        case BFD_RELOC_ALPHA_LITUSE:
-         n_slaves++;
          if (fixp->tc_fix_data.info->n_master == 0)
            as_bad_where (fixp->fx_file, fixp->fx_line,
                          _("No !literal!%ld was found"),
                          fixp->tc_fix_data.info->sequence);
+         if (fixp->fx_offset == LITUSE_TLSGD)
+           {
+             if (! fixp->tc_fix_data.info->saw_tlsgd)
+               as_bad_where (fixp->fx_file, fixp->fx_line,
+                             _("No !tlsgd!%ld was found"),
+                             fixp->tc_fix_data.info->sequence);
+           }
+         else if (fixp->fx_offset == LITUSE_TLSLDM)
+           {
+             if (! fixp->tc_fix_data.info->saw_tlsldm)
+               as_bad_where (fixp->fx_file, fixp->fx_line,
+                             _("No !tlsldm!%ld was found"),
+                             fixp->tc_fix_data.info->sequence);
+           }
          break;
 
        case BFD_RELOC_ALPHA_GPDISP_LO16:
-         n_slaves++;
          if (fixp->tc_fix_data.info->n_master == 0)
            as_bad_where (fixp->fx_file, fixp->fx_line,
                          _("No ldah !gpdisp!%ld was found"),
                          fixp->tc_fix_data.info->sequence);
          break;
 
+       case BFD_RELOC_ALPHA_ELF_LITERAL:
+         if (fixp->tc_fix_data.info->saw_tlsgd
+             || fixp->tc_fix_data.info->saw_tlsldm)
+           break;
+         /* FALLTHRU */
+
        default:
          *prevP = fixp;
          prevP = &fixp->fx_next;
@@ -1665,10 +1794,10 @@ alpha_adjust_symtab_relocs (abfd, sec, ptr)
        }
     }
 
-  /* If there were any dependent relocations, go and add them back to
-     the chain.  They are linked through the next_reloc field in
-     reverse order, so as we go through the next_reloc chain, we
-     effectively reverse the chain once again.
+  /* Go back and re-chain dependent relocations.  They are currently
+     linked through the next_reloc field in reverse order, so as we
+     go through the next_reloc chain, we effectively reverse the chain
+     once again.
 
      Except if there is more than one !literal for a given sequence
      number.  In that case, the programmer and/or compiler is not sure
@@ -1688,6 +1817,27 @@ alpha_adjust_symtab_relocs (abfd, sec, ptr)
       next = fixp->fx_next;
       switch (fixp->fx_r_type)
        {
+       case BFD_RELOC_ALPHA_TLSGD:
+       case BFD_RELOC_ALPHA_TLSLDM:
+         if (!fixp->tc_fix_data.info)
+           break;
+         if (fixp->tc_fix_data.info->n_master == 0)
+           break;
+         else if (fixp->tc_fix_data.info->n_master > 1)
+           {
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("too many !literal!%ld for %s"),
+                           fixp->tc_fix_data.info->sequence,
+                           (fixp->fx_r_type == BFD_RELOC_ALPHA_TLSGD
+                            ? "!tlsgd" : "!tlsldm"));
+             break;
+           }
+
+         fixp->tc_fix_data.info->master->fx_next = fixp->fx_next;
+         fixp->fx_next = fixp->tc_fix_data.info->master;
+         fixp = fixp->fx_next;
+         /* FALLTHRU */
+
        case BFD_RELOC_ALPHA_ELF_LITERAL:
          if (fixp->tc_fix_data.info->n_master == 1
              && ! fixp->tc_fix_data.info->multi_section_p)
@@ -1770,19 +1920,27 @@ debug_exp (tok, ntok)
        case O_pregister:               name = "O_pregister";           break;
        case O_cpregister:              name = "O_cpregister";          break;
        case O_literal:                 name = "O_literal";             break;
+       case O_lituse_addr:             name = "O_lituse_addr";         break;
        case O_lituse_base:             name = "O_lituse_base";         break;
        case O_lituse_bytoff:           name = "O_lituse_bytoff";       break;
        case O_lituse_jsr:              name = "O_lituse_jsr";          break;
+       case O_lituse_tlsgd:            name = "O_lituse_tlsgd";        break;
+       case O_lituse_tlsldm:           name = "O_lituse_tlsldm";       break;
        case O_gpdisp:                  name = "O_gpdisp";              break;
        case O_gprelhigh:               name = "O_gprelhigh";           break;
        case O_gprellow:                name = "O_gprellow";            break;
        case O_gprel:                   name = "O_gprel";               break;
-       case O_md11:                    name = "O_md11";                break;
-       case O_md12:                    name = "O_md12";                break;
-       case O_md13:                    name = "O_md13";                break;
-       case O_md14:                    name = "O_md14";                break;
-       case O_md15:                    name = "O_md15";                break;
-       case O_md16:                    name = "O_md16";                break;
+       case O_samegp:                  name = "O_samegp";              break;
+       case O_tlsgd:                   name = "O_tlsgd";               break;
+       case O_tlsldm:                  name = "O_tlsldm";              break;
+       case O_gotdtprel:               name = "O_gotdtprel";           break;
+       case O_dtprelhi:                name = "O_dtprelhi";            break;
+       case O_dtprello:                name = "O_dtprello";            break;
+       case O_dtprel:                  name = "O_dtprel";              break;
+       case O_gottprel:                name = "O_gottprel";            break;
+       case O_tprelhi:                 name = "O_tprelhi";             break;
+       case O_tprello:                 name = "O_tprello";             break;
+       case O_tprel:                   name = "O_tprel";               break;
        }
 
       fprintf (stderr, ", %s(%s, %s, %d)", name,
@@ -1849,7 +2007,7 @@ tokenize_arguments (str, tok, ntok)
            goto err;
 
          ++input_line_pointer;
-          SKIP_WHITESPACE ();
+         SKIP_WHITESPACE ();
          p = input_line_pointer;
          c = get_symbol_end ();
 
@@ -1872,7 +2030,7 @@ tokenize_arguments (str, tok, ntok)
            }
 
          *input_line_pointer = c;
-          SKIP_WHITESPACE ();
+         SKIP_WHITESPACE ();
          if (*input_line_pointer != '!')
            {
              if (r->require_seq)
@@ -2173,6 +2331,7 @@ find_macro_match (first_macro, tok, pntok)
                case O_gprelhigh:
                case O_gprellow:
                case O_gprel:
+               case O_samegp:
                  goto match_failed;
 
                default:
@@ -2331,7 +2490,7 @@ assemble_insn (opcode, tok, ntok, insn, reloc)
            abort ();
 
          /* There is one special case for which an insn receives two
-            relocations, and thus the user-supplied reloc does not 
+            relocations, and thus the user-supplied reloc does not
             override the operand reloc.  */
          if (operand->default_reloc == BFD_RELOC_ALPHA_HINT)
            {
@@ -2432,7 +2591,7 @@ emit_insn (insn)
     {
       const struct alpha_operand *operand = (const struct alpha_operand *) 0;
       struct alpha_fixup *fixup = &insn->fixups[i];
-      struct alpha_reloc_tag *info;
+      struct alpha_reloc_tag *info = NULL;
       int size, pcrel;
       fixS *fixP;
 
@@ -2474,6 +2633,14 @@ emit_insn (insn)
        case BFD_RELOC_GPREL16:
        case BFD_RELOC_ALPHA_GPREL_HI16:
        case BFD_RELOC_ALPHA_GPREL_LO16:
+       case BFD_RELOC_ALPHA_GOTDTPREL16:
+       case BFD_RELOC_ALPHA_DTPREL_HI16:
+       case BFD_RELOC_ALPHA_DTPREL_LO16:
+       case BFD_RELOC_ALPHA_DTPREL16:
+       case BFD_RELOC_ALPHA_GOTTPREL16:
+       case BFD_RELOC_ALPHA_TPREL_HI16:
+       case BFD_RELOC_ALPHA_TPREL_LO16:
+       case BFD_RELOC_ALPHA_TPREL16:
          fixP->fx_no_overflow = 1;
          break;
 
@@ -2508,7 +2675,10 @@ emit_insn (insn)
        case BFD_RELOC_ALPHA_ELF_LITERAL:
          fixP->fx_no_overflow = 1;
 
+         if (insn->sequence == 0)
+           break;
          info = get_alpha_reloc_tag (insn->sequence);
+         info->master = fixP;
          info->n_master++;
          if (info->segment != now_seg)
            info->multi_section_p = 1;
@@ -2526,12 +2696,31 @@ emit_insn (insn)
          goto do_lituse;
        case DUMMY_RELOC_LITUSE_JSR:
          fixP->fx_offset = LITUSE_JSR;
+         goto do_lituse;
+       case DUMMY_RELOC_LITUSE_TLSGD:
+         fixP->fx_offset = LITUSE_TLSGD;
+         goto do_lituse;
+       case DUMMY_RELOC_LITUSE_TLSLDM:
+         fixP->fx_offset = LITUSE_TLSLDM;
+         goto do_lituse;
        do_lituse:
          fixP->fx_addsy = section_symbol (now_seg);
          fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
 
          info = get_alpha_reloc_tag (insn->sequence);
-         info->n_slaves++;
+         if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD)
+           info->saw_lu_tlsgd = 1;
+         else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM)
+           info->saw_lu_tlsldm = 1;
+         if (++info->n_slaves > 1)
+           {
+             if (info->saw_lu_tlsgd)
+               as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"),
+                       insn->sequence);
+             else if (info->saw_lu_tlsldm)
+               as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"),
+                       insn->sequence);
+           }
          fixP->tc_fix_data.info = info;
          fixP->tc_fix_data.next_reloc = info->slaves;
          info->slaves = fixP;
@@ -2539,6 +2728,38 @@ emit_insn (insn)
            info->multi_section_p = 1;
          break;
 
+       case BFD_RELOC_ALPHA_TLSGD:
+         fixP->fx_no_overflow = 1;
+
+         if (insn->sequence == 0)
+           break;
+         info = get_alpha_reloc_tag (insn->sequence);
+         if (info->saw_tlsgd)
+           as_bad (_("duplicate !tlsgd!%ld"), insn->sequence);
+         else if (info->saw_tlsldm)
+           as_bad (_("sequence number in use for !tlsldm!%ld"),
+                   insn->sequence);
+         else
+           info->saw_tlsgd = 1;
+         fixP->tc_fix_data.info = info;
+         break;
+
+       case BFD_RELOC_ALPHA_TLSLDM:
+         fixP->fx_no_overflow = 1;
+
+         if (insn->sequence == 0)
+           break;
+         info = get_alpha_reloc_tag (insn->sequence);
+         if (info->saw_tlsldm)
+           as_bad (_("duplicate !tlsldm!%ld"), insn->sequence);
+         else if (info->saw_tlsgd)
+           as_bad (_("sequence number in use for !tlsgd!%ld"),
+                   insn->sequence);
+         else
+           info->saw_tlsldm = 1;
+         fixP->tc_fix_data.info = info;
+         break;
+
        default:
          if ((int) fixup->reloc < 0)
            {
@@ -2602,13 +2823,16 @@ assemble_tokens (opname, tok, ntok, local_macros_on)
   int cpumatch = 1;
   bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
 
+#ifdef RELOC_OP_P
   /* If a user-specified relocation is present, this is not a macro.  */
   if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
     {
       reloc = ALPHA_RELOC_TABLE (tok[ntok - 1].X_op)->reloc;
       ntok--;
     }
-  else if (local_macros_on)
+  else
+#endif
+  if (local_macros_on)
     {
       macro = ((const struct alpha_macro *)
               hash_find (alpha_macro_hash, opname));
@@ -2665,7 +2889,6 @@ static const char * const extXh_op[] = { NULL,    "extwh", "extlh", "extqh" };
 static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
 static const char * const mskXh_op[] = { NULL,    "mskwh", "msklh", "mskqh" };
 static const char * const stX_op[] = { "stb", "stw", "stl", "stq" };
-static const char * const ldX_op[] = { "ldb", "ldw", "ldll", "ldq" };
 static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL };
 
 /* Implement the ldgp macro.  */
@@ -3985,7 +4208,11 @@ s_alpha_text (i)
      int i;
 
 {
+#ifdef OBJ_ELF
+  obj_elf_text (i);
+#else
   s_text (i);
+#endif
   alpha_insn_label = NULL;
   alpha_auto_align_on = 1;
   alpha_current_align = 0;
@@ -3998,7 +4225,11 @@ static void
 s_alpha_data (i)
      int i;
 {
+#ifdef OBJ_ELF
+  obj_elf_data (i);
+#else
   s_data (i);
+#endif
   alpha_insn_label = NULL;
   alpha_auto_align_on = 1;
   alpha_current_align = 0;
@@ -5410,7 +5641,7 @@ alpha_elf_section_letter (letter, ptr_msg)
   if (letter == 's')
     return SHF_ALPHA_GPREL;
 
-  *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string");
+  *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string");
   return 0;
 }
 
@@ -5473,10 +5704,10 @@ void
 alpha_handle_align (fragp)
      fragS *fragp;
 {
-  static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f };
+  static char const unop[4] = { 0x00, 0x00, 0xfe, 0x2f };
   static char const nopunop[8] = {
     0x1f, 0x04, 0xff, 0x47,
-    0x00, 0x00, 0xe0, 0x2f
+    0x00, 0x00, 0xfe, 0x2f
   };
 
   int bytes, fix;
This page took 0.032604 seconds and 4 git commands to generate.