Add expected failures for CR16 tests
[deliverable/binutils-gdb.git] / gas / config / tc-sparc.c
index 5c610a9670e67a41ea2d51919c2f16e422882d9b..3b07fecfd81baf3f61e8e77ed11d6abad4b25051 100644 (file)
@@ -1,12 +1,12 @@
 /* tc-sparc.c -- Assemble for the SPARC
    Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public
    License along with GAS; see the file COPYING.  If not, write
-   to the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-#include <stdio.h>
+   to the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
 
 #include "opcode/sparc.h"
+#include "dw2gencfi.h"
 
 #ifdef OBJ_ELF
 #include "elf/sparc.h"
@@ -116,6 +115,9 @@ static int target_little_endian_data;
 /* Symbols for global registers on v9.  */
 static symbolS *globals[8];
 
+/* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
+int sparc_cie_data_alignment;
+
 /* V9 and 86x have big and little endian data, but instructions are always big
    endian.  The sparclet has bi-endian support but both data and insns have
    the same endianness.  Global `target_big_endian' is used for data.
@@ -129,7 +131,7 @@ static symbolS *globals[8];
 /* Handle of the OPCODE hash table.  */
 static struct hash_control *op_hash;
 
-static int log2 PARAMS ((int));
+static int mylog2 PARAMS ((int));
 static void s_data1 PARAMS ((void));
 static void s_seg PARAMS ((int));
 static void s_proc PARAMS ((int));
@@ -138,7 +140,9 @@ static void s_common PARAMS ((int));
 static void s_empty PARAMS ((int));
 static void s_uacons PARAMS ((int));
 static void s_ncons PARAMS ((int));
+#ifdef OBJ_ELF
 static void s_register PARAMS ((int));
+#endif
 
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -159,8 +163,6 @@ const pseudo_typeS md_pseudo_table[] =
   {"uaword", s_uacons, 4},
   {"uaxword", s_uacons, 8},
 #ifdef OBJ_ELF
-  {"file", dwarf2_directive_file, 0},
-  {"loc", dwarf2_directive_loc, 0},
   /* These are specific to sparc/svr4.  */
   {"2byte", s_uacons, 2},
   {"4byte", s_uacons, 4},
@@ -170,9 +172,6 @@ const pseudo_typeS md_pseudo_table[] =
   {NULL, 0, 0},
 };
 
-/* Size of relocation record.  */
-const int md_reloc_size = 12;
-
 /* This array holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  */
 const char comment_chars[] = "!";      /* JF removed '|' from
@@ -203,7 +202,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
    changed in read.c.  Ideally it shouldn't have to know about it at all,
    but nothing is ideal around here.  */
 
-#define isoctal(c)  ((unsigned) ((c) - '0') < '8')
+#define isoctal(c)  ((unsigned) ((c) - '0') < 8)
 
 struct sparc_it
   {
@@ -333,8 +332,12 @@ sparc_target_format ()
 #endif
 #endif
 
+#ifdef TE_VXWORKS
+  return "elf32-sparc-vxworks";
+#endif
+
 #ifdef OBJ_ELF
-  return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc";
+  return sparc_arch_size == 64 ? ELF64_TARGET_FORMAT : ELF_TARGET_FORMAT;
 #endif
 
   abort ();
@@ -542,12 +545,12 @@ md_parse_option (c, arg)
          {
            if (sparc_arch_size == 32)
              {
-               if (strcmp (*l, "elf32-sparc") == 0)
+               if (CONST_STRNEQ (*l, "elf32-sparc"))
                  break;
              }
            else
              {
-               if (strcmp (*l, "elf64-sparc") == 0)
+               if (CONST_STRNEQ (*l, "elf64-sparc"))
                  break;
              }
          }
@@ -723,7 +726,7 @@ struct
   {NULL, NULL, NULL},
 };
 \f
-/* sparc64 priviledged registers.  */
+/* sparc64 privileged and hyperprivileged registers.  */
 
 struct priv_reg_entry
 {
@@ -749,10 +752,22 @@ struct priv_reg_entry priv_reg_table[] =
   {"otherwin", 13},
   {"wstate", 14},
   {"fq", 15},
+  {"gl", 16},
   {"ver", 31},
   {"", -1},                    /* End marker.  */
 };
 
+struct priv_reg_entry hpriv_reg_table[] =
+{
+  {"hpstate", 0},
+  {"htstate", 1},
+  {"hintp", 3},
+  {"htba", 5},
+  {"hver", 6},
+  {"hstick_cmpr", 31},
+  {"", -1},                    /* End marker.  */
+};
+
 /* v9a specific asrs.  */
 
 struct priv_reg_entry v9a_asr_table[] =
@@ -798,6 +813,7 @@ md_begin ()
   if (! default_init_p)
     init_default_arch ();
 
+  sparc_cie_data_alignment = sparc_arch_size == 64 ? -8 : -4;
   op_hash = hash_new ();
 
   while (i < (unsigned int) sparc_num_opcodes)
@@ -1299,11 +1315,12 @@ md_assemble (str)
 
   know (str);
   special_case = sparc_ip (str, &insn);
+  if (insn == NULL)
+    return;
 
   /* We warn about attempts to put a floating point branch in a delay slot,
      unless the delay slot has been annulled.  */
-  if (insn != NULL
-      && last_insn != NULL
+  if (last_insn != NULL
       && (insn->flags & F_FBR) != 0
       && (last_insn->flags & F_DELAYED) != 0
       /* ??? This test isn't completely accurate.  We assume anything with
@@ -1316,7 +1333,6 @@ md_assemble (str)
      point instruction and a floating point branch.  We insert one
      automatically, with a warning.  */
   if (max_architecture < SPARC_OPCODE_ARCH_V9
-      && insn != NULL
       && last_insn != NULL
       && (insn->flags & F_FBR) != 0
       && (last_insn->flags & F_FLOAT) != 0)
@@ -1412,7 +1428,9 @@ sparc_ip (str, pinsn)
       break;
 
     default:
-      as_fatal (_("Unknown opcode: `%s'"), str);
+      as_bad (_("Unknown opcode: `%s'"), str);
+      *pinsn = NULL;
+      return special_case;
     }
   insn = (struct sparc_opcode *) hash_find (op_hash, str);
   *pinsn = insn;
@@ -1568,6 +1586,42 @@ sparc_ip (str, pinsn)
                  goto error;
                }
 
+           case '$':
+           case '%':
+             /* Parse a sparc64 hyperprivileged register.  */
+             if (*s == '%')
+               {
+                 struct priv_reg_entry *p = hpriv_reg_table;
+                 unsigned int len = 9999999; /* Init to make gcc happy.  */
+
+                 s += 1;
+                 while (p->name[0] > s[0])
+                   p++;
+                 while (p->name[0] == s[0])
+                   {
+                     len = strlen (p->name);
+                     if (strncmp (p->name, s, len) == 0)
+                       break;
+                     p++;
+                   }
+                 if (p->name[0] != s[0])
+                   {
+                     error_message = _(": unrecognizable hyperprivileged register");
+                     goto error;
+                   }
+                 if (*args == '$')
+                   opcode |= (p->regnum << 14);
+                 else
+                   opcode |= (p->regnum << 25);
+                 s += len;
+                 continue;
+               }
+             else
+               {
+                 error_message = _(": unrecognizable hyperprivileged register");
+                 goto error;
+               }
+
            case '_':
            case '/':
              /* Parse a v9a/v9b ancillary state register.  */
@@ -1804,10 +1858,92 @@ sparc_ip (str, pinsn)
              break;
 
            case '\0':          /* End of args.  */
-             if (*s == '\0')
+             if (s[0] == ',' && s[1] == '%')
                {
-                 match = 1;
+                 static const struct tls_ops
+                 {
+                   /* The name as it appears in assembler.  */
+                   char *name;
+                   /* strlen (name), precomputed for speed */
+                   int len;
+                   /* The reloc this pseudo-op translates to.  */
+                   int reloc;
+                   /* 1 if call.  */
+                   int call;
+                 }
+                 tls_ops[] =
+                 {
+                   { "tgd_add", 7, BFD_RELOC_SPARC_TLS_GD_ADD, 0 },
+                   { "tgd_call", 8, BFD_RELOC_SPARC_TLS_GD_CALL, 1 },
+                   { "tldm_add", 8, BFD_RELOC_SPARC_TLS_LDM_ADD, 0 },
+                   { "tldm_call", 9, BFD_RELOC_SPARC_TLS_LDM_CALL, 1 },
+                   { "tldo_add", 8, BFD_RELOC_SPARC_TLS_LDO_ADD, 0 },
+                   { "tie_ldx", 7, BFD_RELOC_SPARC_TLS_IE_LDX, 0 },
+                   { "tie_ld", 6, BFD_RELOC_SPARC_TLS_IE_LD, 0 },
+                   { "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 },
+                   { NULL, 0, 0, 0 }
+                 };
+                 const struct tls_ops *o;
+                 char *s1;
+                 int npar = 0;
+
+                 for (o = tls_ops; o->name; o++)
+                   if (strncmp (s + 2, o->name, o->len) == 0)
+                     break;
+                 if (o->name == NULL)
+                   break;
+
+                 if (s[o->len + 2] != '(')
+                   {
+                     as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
+                     return special_case;
+                   }
+
+                 if (! o->call && the_insn.reloc != BFD_RELOC_NONE)
+                   {
+                     as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"),
+                             o->name);
+                     return special_case;
+                   }
+
+                 if (o->call
+                     && (the_insn.reloc != BFD_RELOC_32_PCREL_S2
+                         || the_insn.exp.X_add_number != 0
+                         || the_insn.exp.X_add_symbol
+                            != symbol_find_or_make ("__tls_get_addr")))
+                   {
+                     as_bad (_("Illegal operands: %%%s can be only used with call __tls_get_addr"),
+                             o->name);
+                     return special_case;
+                   }
+
+                 the_insn.reloc = o->reloc;
+                 memset (&the_insn.exp, 0, sizeof (the_insn.exp));
+                 s += o->len + 3;
+
+                 for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
+                   if (*s1 == '(')
+                     npar++;
+                   else if (*s1 == ')')
+                     {
+                       if (!npar)
+                         break;
+                       npar--;
+                     }
+
+                 if (*s1 != ')')
+                   {
+                     as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
+                     return special_case;
+                   }
+
+                 *s1 = '\0';
+                 (void) get_expression (s);
+                 *s1 = ')';
+                 s = s1 + 1;
                }
+             if (*s == '\0')
+               match = 1;
              break;
 
            case '+':
@@ -2063,6 +2199,12 @@ sparc_ip (str, pinsn)
                      {
                        if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
                          {
+                           if (*args == 'e' || *args == 'f' || *args == 'g')
+                             {
+                               error_message
+                                 = _(": There are only 32 single precision f registers; [0-31]");
+                               goto error;
+                             }
                            v9_arg_p = 1;
                            mask -= 31; /* wrap high bit */
                          }
@@ -2142,7 +2284,7 @@ sparc_ip (str, pinsn)
              {
                char *s1;
                char *op_arg = NULL;
-               expressionS op_exp;
+               static expressionS op_exp;
                bfd_reloc_code_real_type old_reloc = the_insn.reloc;
 
                /* Check for %hi, etc.  */
@@ -2174,6 +2316,18 @@ sparc_ip (str, pinsn)
                      { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
                      { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
                      { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
+                     { "tgd_hi22", 8, BFD_RELOC_SPARC_TLS_GD_HI22, 0, 0 },
+                     { "tgd_lo10", 8, BFD_RELOC_SPARC_TLS_GD_LO10, 0, 0 },
+                     { "tldm_hi22", 9, BFD_RELOC_SPARC_TLS_LDM_HI22, 0, 0 },
+                     { "tldm_lo10", 9, BFD_RELOC_SPARC_TLS_LDM_LO10, 0, 0 },
+                     { "tldo_hix22", 10, BFD_RELOC_SPARC_TLS_LDO_HIX22, 0,
+                                                                        0 },
+                     { "tldo_lox10", 10, BFD_RELOC_SPARC_TLS_LDO_LOX10, 0,
+                                                                        0 },
+                     { "tie_hi22", 8, BFD_RELOC_SPARC_TLS_IE_HI22, 0, 0 },
+                     { "tie_lo10", 8, BFD_RELOC_SPARC_TLS_IE_LO10, 0, 0 },
+                     { "tle_hix22", 9, BFD_RELOC_SPARC_TLS_LE_HIX22, 0, 0 },
+                     { "tle_lox10", 9, BFD_RELOC_SPARC_TLS_LE_LOX10, 0, 0 },
                      { NULL, 0, 0, 0, 0 }
                    };
                    const struct ops *o;
@@ -2376,12 +2530,19 @@ sparc_ip (str, pinsn)
                      goto error;
                    }
 
-                 /* Constants that won't fit are checked in md_apply_fix3
+                 if (the_insn.reloc >= BFD_RELOC_SPARC_TLS_GD_HI22
+                     && the_insn.reloc <= BFD_RELOC_SPARC_TLS_TPOFF64)
+                   {
+                     error_message = _(": TLS operand can't be a constant");
+                     goto error;
+                   }
+
+                 /* Constants that won't fit are checked in md_apply_fix
                     and bfd_install_relocation.
                     ??? It would be preferable to install the constants
                     into the insn here and save having to create a fixS
                     for each one.  There already exists code to handle
-                    all the various cases (e.g. in md_apply_fix3 and
+                    all the various cases (e.g. in md_apply_fix and
                     bfd_install_relocation) so duplicating all that code
                     here isn't right.  */
                }
@@ -2769,7 +2930,7 @@ output_insn (insn, the_insn)
                                 the_insn->pcrel,
                                 the_insn->reloc);
       /* Turn off overflow checking in fixup_segment.  We'll do our
-        own overflow checking in md_apply_fix3.  This is necessary because
+        own overflow checking in md_apply_fix.  This is necessary because
         the insn size is 4 and fixup_segment will signal an overflow for
         large 8 byte quantities.  */
       fixP->fx_no_overflow = 1;
@@ -2888,10 +3049,10 @@ md_number_to_chars (buf, val, n)
    hold.  */
 
 void
-md_apply_fix3 (fixP, valP, segment)
+md_apply_fix (fixP, valP, segment)
      fixS *fixP;
      valueT *valP;
-     segT segment;
+     segT segment ATTRIBUTE_UNUSED;
 {
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
   offsetT val = * (offsetT *) valP;
@@ -2902,31 +3063,40 @@ md_apply_fix3 (fixP, valP, segment)
   fixP->fx_addnumber = val;    /* Remember value for emit_reloc.  */
 
 #ifdef OBJ_ELF
-  /* FIXME: SPARC ELF relocations don't use an addend in the data
-     field itself.  This whole approach should be somehow combined
-     with the calls to bfd_install_relocation.  Also, the value passed
-     in by fixup_segment includes the value of a defined symbol.  We
-     don't want to include the value of an externally visible symbol.  */
+  /* SPARC ELF relocations don't use an addend in the data field.  */
   if (fixP->fx_addsy != NULL)
     {
-       symbolS * sym = fixP->fx_addsy;
-        segT      seg = S_GET_SEGMENT (sym);
-
-      if (symbol_used_in_reloc_p (sym)
-         && (S_IS_EXTERNAL (sym)
-             || S_IS_WEAK (sym)
-             || (seg->flags & SEC_MERGE)
-             || (seg->flags & SEC_THREAD_LOCAL)
-             || (sparc_pic_code && ! fixP->fx_pcrel)
-             || (seg != segment
-                 && (((bfd_get_section_flags (stdoutput, seg) & SEC_LINK_ONCE) != 0)
-                     || (strncmp (segment_name (seg),
-                                  ".gnu.linkonce",
-                                  sizeof ".gnu.linkonce" - 1) == 0))))
-         && seg != absolute_section
-         && seg != undefined_section
-         && ! bfd_is_com_section (seg))
-       fixP->fx_addnumber -= S_GET_VALUE (sym);
+      switch (fixP->fx_r_type)
+       {
+       case BFD_RELOC_SPARC_TLS_GD_HI22:
+       case BFD_RELOC_SPARC_TLS_GD_LO10:
+       case BFD_RELOC_SPARC_TLS_GD_ADD:
+       case BFD_RELOC_SPARC_TLS_GD_CALL:
+       case BFD_RELOC_SPARC_TLS_LDM_HI22:
+       case BFD_RELOC_SPARC_TLS_LDM_LO10:
+       case BFD_RELOC_SPARC_TLS_LDM_ADD:
+       case BFD_RELOC_SPARC_TLS_LDM_CALL:
+       case BFD_RELOC_SPARC_TLS_LDO_HIX22:
+       case BFD_RELOC_SPARC_TLS_LDO_LOX10:
+       case BFD_RELOC_SPARC_TLS_LDO_ADD:
+       case BFD_RELOC_SPARC_TLS_IE_HI22:
+       case BFD_RELOC_SPARC_TLS_IE_LO10:
+       case BFD_RELOC_SPARC_TLS_IE_LD:
+       case BFD_RELOC_SPARC_TLS_IE_LDX:
+       case BFD_RELOC_SPARC_TLS_IE_ADD:
+       case BFD_RELOC_SPARC_TLS_LE_HIX22:
+       case BFD_RELOC_SPARC_TLS_LE_LOX10:
+       case BFD_RELOC_SPARC_TLS_DTPMOD32:
+       case BFD_RELOC_SPARC_TLS_DTPMOD64:
+       case BFD_RELOC_SPARC_TLS_DTPOFF32:
+       case BFD_RELOC_SPARC_TLS_DTPOFF64:
+       case BFD_RELOC_SPARC_TLS_TPOFF32:
+       case BFD_RELOC_SPARC_TLS_TPOFF64:
+         S_SET_THREAD_LOCAL (fixP->fx_addsy);
+
+       default:
+         break;
+       }
 
       return;
     }
@@ -3143,9 +3313,9 @@ md_apply_fix3 (fixP, valP, segment)
          break;
 
        case BFD_RELOC_SPARC_WDISP16:
-         /* FIXME: simplify.  */
-         if (((val > 0) && (val & ~0x3fffc))
-             || ((val < 0) && (~(val - 1) & ~0x3fffc)))
+         if ((val & 3)
+             || val >= 0x1fffc
+             || val <= -(offsetT) 0x20008)
            as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("relocation overflow"));
          /* FIXME: The +1 deserves a comment.  */
@@ -3154,9 +3324,9 @@ md_apply_fix3 (fixP, valP, segment)
          break;
 
        case BFD_RELOC_SPARC_WDISP19:
-         /* FIXME: simplify.  */
-         if (((val > 0) && (val & ~0x1ffffc))
-             || ((val < 0) && (~(val - 1) & ~0x1ffffc)))
+         if ((val & 3)
+             || val >= 0xffffc
+             || val <= -(offsetT) 0x100008)
            as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("relocation overflow"));
          /* FIXME: The +1 deserves a comment.  */
@@ -3328,6 +3498,26 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_SPARC_PLT64:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
+    case BFD_RELOC_SPARC_TLS_GD_HI22:
+    case BFD_RELOC_SPARC_TLS_GD_LO10:
+    case BFD_RELOC_SPARC_TLS_GD_ADD:
+    case BFD_RELOC_SPARC_TLS_GD_CALL:
+    case BFD_RELOC_SPARC_TLS_LDM_HI22:
+    case BFD_RELOC_SPARC_TLS_LDM_LO10:
+    case BFD_RELOC_SPARC_TLS_LDM_ADD:
+    case BFD_RELOC_SPARC_TLS_LDM_CALL:
+    case BFD_RELOC_SPARC_TLS_LDO_HIX22:
+    case BFD_RELOC_SPARC_TLS_LDO_LOX10:
+    case BFD_RELOC_SPARC_TLS_LDO_ADD:
+    case BFD_RELOC_SPARC_TLS_IE_HI22:
+    case BFD_RELOC_SPARC_TLS_IE_LO10:
+    case BFD_RELOC_SPARC_TLS_IE_LD:
+    case BFD_RELOC_SPARC_TLS_IE_LDX:
+    case BFD_RELOC_SPARC_TLS_IE_ADD:
+    case BFD_RELOC_SPARC_TLS_LE_HIX22:
+    case BFD_RELOC_SPARC_TLS_LE_LOX10:
+    case BFD_RELOC_SPARC_TLS_DTPOFF32:
+    case BFD_RELOC_SPARC_TLS_DTPOFF64:
       code = fixp->fx_r_type;
       break;
     default:
@@ -3343,6 +3533,10 @@ tc_gen_reloc (section, fixp)
 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
 #else
 #define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
+#endif
+#ifdef TE_VXWORKS
+#define GOTT_BASE "__GOTT_BASE__"
+#define GOTT_INDEX "__GOTT_INDEX__"
 #endif
 
   /* This code must be parallel to the OBJ_ELF tc_fix_adjustable.  */
@@ -3352,25 +3546,34 @@ tc_gen_reloc (section, fixp)
       switch (code)
        {
        case BFD_RELOC_32_PCREL_S2:
-         if (! S_IS_DEFINED (fixp->fx_addsy)
-             || S_IS_COMMON (fixp->fx_addsy)
-             || S_IS_EXTERNAL (fixp->fx_addsy)
-             || S_IS_WEAK (fixp->fx_addsy))
+         if (generic_force_reloc (fixp))
            code = BFD_RELOC_SPARC_WPLT30;
          break;
        case BFD_RELOC_HI22:
-         if (fixp->fx_addsy != NULL
-             && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
-           code = BFD_RELOC_SPARC_PC22;
-         else
-           code = BFD_RELOC_SPARC_GOT22;
+         code = BFD_RELOC_SPARC_GOT22;
+         if (fixp->fx_addsy != NULL)
+           {
+             if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
+               code = BFD_RELOC_SPARC_PC22;
+#ifdef TE_VXWORKS
+             if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
+                 || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
+               code = BFD_RELOC_HI22; /* Unchanged.  */
+#endif
+           }
          break;
        case BFD_RELOC_LO10:
-         if (fixp->fx_addsy != NULL
-             && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
-           code = BFD_RELOC_SPARC_PC10;
-         else
-           code = BFD_RELOC_SPARC_GOT10;
+         code = BFD_RELOC_SPARC_GOT10;
+         if (fixp->fx_addsy != NULL)
+           {
+             if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
+               code = BFD_RELOC_SPARC_PC10;
+#ifdef TE_VXWORKS
+             if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
+                 || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
+               code = BFD_RELOC_LO10; /* Unchanged.  */
+#endif
+           }
          break;
        case BFD_RELOC_SPARC13:
          code = BFD_RELOC_SPARC_GOT13;
@@ -3381,6 +3584,16 @@ tc_gen_reloc (section, fixp)
     }
 #endif /* defined (OBJ_ELF) || defined (OBJ_AOUT)  */
 
+  /* Nothing is aligned in DWARF debugging sections.  */
+  if (bfd_get_section_flags (stdoutput, section) & SEC_DEBUGGING)
+    switch (code)
+      {
+      case BFD_RELOC_16: code = BFD_RELOC_SPARC_UA16; break;
+      case BFD_RELOC_32: code = BFD_RELOC_SPARC_UA32; break;
+      case BFD_RELOC_64: code = BFD_RELOC_SPARC_UA64; break;
+      default: break;
+      }
+
   if (code == BFD_RELOC_SPARC_OLO10)
     reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO10);
   else
@@ -3419,7 +3632,9 @@ tc_gen_reloc (section, fixp)
       && code != BFD_RELOC_SPARC_WDISP22
       && code != BFD_RELOC_SPARC_WDISP16
       && code != BFD_RELOC_SPARC_WDISP19
-      && code != BFD_RELOC_SPARC_WPLT30)
+      && code != BFD_RELOC_SPARC_WPLT30
+      && code != BFD_RELOC_SPARC_TLS_GD_CALL
+      && code != BFD_RELOC_SPARC_TLS_LDM_CALL)
     reloc->addend = fixp->fx_addnumber;
   else if (symbol_section_p (fixp->fx_addsy))
     reloc->addend = (section->vma
@@ -3501,7 +3716,7 @@ md_pcrel_from (fixP)
    of two.  */
 
 static int
-log2 (value)
+mylog2 (value)
      int value;
 {
   int shift;
@@ -3603,7 +3818,7 @@ s_reserve (ignore)
 
       if (align != 0)
        {
-         temp = log2 (align);
+         temp = mylog2 (align);
          if (temp < 0)
            {
              as_bad (_("alignment not a power of 2"));
@@ -3673,7 +3888,7 @@ s_common (ignore)
   char *name;
   char c;
   char *p;
-  int temp, size;
+  offsetT temp, size;
   symbolS *symbolP;
 
   name = input_line_pointer;
@@ -3694,7 +3909,8 @@ s_common (ignore)
 
   if ((temp = get_absolute_expression ()) < 0)
     {
-      as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
+      as_bad (_(".COMMon length (%lu) out of range ignored"),
+             (unsigned long) temp);
       ignore_rest_of_line ();
       return;
     }
@@ -3712,8 +3928,8 @@ s_common (ignore)
     {
       if (S_GET_VALUE (symbolP) != (valueT) size)
        {
-         as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
-                  S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+         as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
+                  S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) size);
        }
     }
   else
@@ -3740,7 +3956,7 @@ s_common (ignore)
       if (temp > max_alignment)
        {
          temp = max_alignment;
-         as_warn (_("alignment too large; assuming %d"), temp);
+         as_warn (_("alignment too large; assuming %ld"), (long) temp);
        }
 #endif
 
@@ -3765,7 +3981,7 @@ s_common (ignore)
          if (temp == 0)
            align = 0;
          else
-           align = log2 (temp);
+           align = mylog2 (temp);
 
          if (align < 0)
            {
@@ -3822,9 +4038,7 @@ s_common (ignore)
       goto allocate_common;
     }
 
-#ifdef BFD_ASSEMBLER
   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
-#endif
 
   demand_empty_rest_of_line ();
   return;
@@ -3844,7 +4058,7 @@ s_common (ignore)
   }
 }
 
-/* Handle the .empty pseudo-op.  This supresses the warnings about
+/* Handle the .empty pseudo-op.  This suppresses the warnings about
    invalid delay slot usage.  */
 
 static void
@@ -3911,7 +4125,7 @@ s_proc (ignore)
 }
 
 /* This static variable is set by s_uacons to tell sparc_cons_align
-   that the expession does not need to be aligned.  */
+   that the expression does not need to be aligned.  */
 
 static int sparc_no_align_cons = 0;
 
@@ -4088,7 +4302,7 @@ sparc_cons_align (nbytes)
   if (sparc_no_align_cons)
     return;
 
-  nalign = log2 (nbytes);
+  nalign = mylog2 (nbytes);
   if (nalign == 0)
     return;
 
@@ -4222,6 +4436,16 @@ sparc_cons (exp, size)
              sparc_cons_special_reloc = "plt";
            }
        }
+      else if (strncmp (input_line_pointer + 3, "tls_dtpoff", 10) == 0)
+       {
+         if (size != 4 && size != 8)
+           as_bad (_("Illegal operands: %%r_tls_dtpoff in %d-byte data field"), size);
+         else
+           {
+             input_line_pointer += 13;
+             sparc_cons_special_reloc = "tls_dtpoff";
+           }
+       }
       if (sparc_cons_special_reloc)
        {
          int bad = 0;
@@ -4355,12 +4579,18 @@ cons_fix_new_sparc (frag, where, nbytes, exp)
          case 8: r = BFD_RELOC_64_PCREL; break;
          default: abort ();
          }
-      else
+      else if (*sparc_cons_special_reloc == 'p')
        switch (nbytes)
          {
          case 4: r = BFD_RELOC_SPARC_PLT32; break;
          case 8: r = BFD_RELOC_SPARC_PLT64; break;
          }
+      else
+       switch (nbytes)
+         {
+         case 4: r = BFD_RELOC_SPARC_TLS_DTPOFF32; break;
+         case 8: r = BFD_RELOC_SPARC_TLS_DTPOFF64; break;
+         }
     }
   else if (sparc_no_align_cons)
     {
@@ -4374,17 +4604,63 @@ cons_fix_new_sparc (frag, where, nbytes, exp)
    }
 
   fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
+  sparc_cons_special_reloc = NULL;
+}
+
+void
+sparc_cfi_frame_initial_instructions ()
+{
+  cfi_add_CFA_def_cfa (14, sparc_arch_size == 64 ? 0x7ff : 0);
 }
 
-#ifdef OBJ_ELF
 int
-elf32_sparc_force_relocation (fixp)
-     struct fix *fixp;
+sparc_regname_to_dw2regnum (char *regname)
 {
-  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
-    return 1;
+  char *p, *q;
 
-  return 0;
+  if (!regname[0])
+    return -1;
+
+  q = "goli";
+  p = strchr (q, regname[0]);
+  if (p)
+    {
+      if (regname[1] < '0' || regname[1] > '8' || regname[2])
+       return -1;
+      return (p - q) * 8 + regname[1] - '0';
+    }
+  if (regname[0] == 's' && regname[1] == 'p' && !regname[2])
+    return 14;
+  if (regname[0] == 'f' && regname[1] == 'p' && !regname[2])
+    return 30;
+  if (regname[0] == 'f' || regname[0] == 'r')
+    {
+      unsigned int regnum;
+
+      regnum = strtoul (regname + 1, &q, 10);
+      if (p == q || *q)
+        return -1;
+      if (regnum >= ((regname[0] == 'f'
+                     && SPARC_OPCODE_ARCH_V9_P (max_architecture))
+                    ? 64 : 32))
+       return -1;
+      if (regname[0] == 'f')
+       {
+          regnum += 32;
+          if (regnum >= 64 && (regnum & 1))
+           return -1;
+        }
+      return regnum;
+    }
+  return -1;
+}
+
+void
+sparc_cfi_emit_pcrel_expr (expressionS *exp, unsigned int nbytes)
+{
+  sparc_cons_special_reloc = "disp";
+  sparc_no_align_cons = 1;
+  emit_expr (exp, nbytes);
+  sparc_no_align_cons = 0;
+  sparc_cons_special_reloc = NULL;
 }
-#endif
This page took 0.03375 seconds and 4 git commands to generate.