* doc/Makefile.am (config.texi): Set top_srcdir.
[binutils-gdb.git] / gas / config / tc-sparc.c
index 2278411d61535e3011c95532334a1bcba1e599eb..1f2b2f998fcc7142656567d5b5024508426b79ea 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-sparc.c -- Assemble for the SPARC
    Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003
+   1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    This file is part of GAS, the GNU Assembler.
 
@@ -16,8 +16,8 @@
 
    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.  */
+   to the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include <stdio.h>
 
@@ -26,6 +26,7 @@
 #include "subsegs.h"
 
 #include "opcode/sparc.h"
+#include "dw2gencfi.h"
 
 #ifdef OBJ_ELF
 #include "elf/sparc.h"
@@ -116,6 +117,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 +133,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));
@@ -170,9 +174,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
@@ -723,7 +724,7 @@ struct
   {NULL, NULL, NULL},
 };
 \f
-/* sparc64 priviledged registers.  */
+/* sparc64 privileged registers.  */
 
 struct priv_reg_entry
 {
@@ -798,6 +799,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 +1301,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 +1319,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 +1414,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;
@@ -2141,6 +2145,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 */
                          }
@@ -2220,7 +2230,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.  */
@@ -2473,12 +2483,12 @@ sparc_ip (str, pinsn)
                      goto error;
                    }
 
-                 /* Constants that won't fit are checked in md_apply_fix3
+                 /* 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.  */
                }
@@ -2866,7 +2876,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;
@@ -2985,7 +2995,7 @@ 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 ATTRIBUTE_UNUSED;
@@ -3001,7 +3011,41 @@ md_apply_fix3 (fixP, valP, segment)
 #ifdef OBJ_ELF
   /* SPARC ELF relocations don't use an addend in the data field.  */
   if (fixP->fx_addsy != NULL)
-    return;
+    {
+      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;
+    }
 #endif
 
   /* This is a hack.  There should be a better way to
@@ -3592,7 +3636,7 @@ md_pcrel_from (fixP)
    of two.  */
 
 static int
-log2 (value)
+mylog2 (value)
      int value;
 {
   int shift;
@@ -3694,7 +3738,7 @@ s_reserve (ignore)
 
       if (align != 0)
        {
-         temp = log2 (align);
+         temp = mylog2 (align);
          if (temp < 0)
            {
              as_bad (_("alignment not a power of 2"));
@@ -3804,8 +3848,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
@@ -3832,7 +3876,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
 
@@ -3857,7 +3901,7 @@ s_common (ignore)
          if (temp == 0)
            align = 0;
          else
-           align = log2 (temp);
+           align = mylog2 (temp);
 
          if (align < 0)
            {
@@ -3914,9 +3958,7 @@ s_common (ignore)
       goto allocate_common;
     }
 
-#ifdef BFD_ASSEMBLER
   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
-#endif
 
   demand_empty_rest_of_line ();
   return;
@@ -3936,7 +3978,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
@@ -4003,7 +4045,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;
 
@@ -4180,7 +4222,7 @@ sparc_cons_align (nbytes)
   if (sparc_no_align_cons)
     return;
 
-  nalign = log2 (nbytes);
+  nalign = mylog2 (nbytes);
   if (nalign == 0)
     return;
 
@@ -4482,4 +4524,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);
+}
+
+int
+sparc_regname_to_dw2regnum (const char *regname)
+{
+  char *p, *q;
+
+  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;
 }