* ld-srec/srec.exp: Add setup_xfail for i960 COFF targets.
[deliverable/binutils-gdb.git] / gas / config / tc-sparc.c
index 1691d3d8180e4a4c90498dcbeb7b616548d47f27..2ed4267f85d8993e85f8e07cebbe76e52786178b 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-sparc.c -- Assemble for the SPARC
-   Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1989, 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -15,9 +15,7 @@
 
    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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#define cypress 1234
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
 #include <stdio.h>
 #include <ctype.h>
 
 static void sparc_ip PARAMS ((char *));
 
+#ifdef sparcv9
+static enum sparc_architecture current_architecture = v9;
+#else
 static enum sparc_architecture current_architecture = v6;
+#endif
 static int architecture_requested;
 static int warn_on_bump;
 
-extern int target_big_endian;
+/* Non-zero if we are generating PIC code.  */
+int sparc_pic_code;
 
-const relax_typeS md_relax_table[1];
+extern int target_big_endian;
 
 /* handle of the OPCODE hash table */
-static struct hash_control *op_hash = NULL;
+static struct hash_control *op_hash;
 
 static void s_data1 PARAMS ((void));
 static void s_seg PARAMS ((int));
@@ -59,14 +62,12 @@ const pseudo_typeS md_pseudo_table[] =
   {"seg", s_seg, 0},
   {"skip", s_space, 0},
   {"word", cons, 4},
-/* start-sanitize-v9 */
 #ifndef NO_V9
   {"xword", cons, 8},
 #ifdef OBJ_ELF
   {"uaxword", cons, 8},
 #endif
 #endif
-/* end-sanitize-v9 */
 #ifdef OBJ_ELF
   /* these are specific to sparc/svr4 */
   {"pushsection", obj_elf_section, 0},
@@ -77,8 +78,6 @@ const pseudo_typeS md_pseudo_table[] =
   {NULL, 0, 0},
 };
 
-const int md_short_jump_size = 4;
-const int md_long_jump_size = 4;
 const int md_reloc_size = 12;  /* Size of relocation record */
 
 /* This array holds the chars that always start a comment.  If the
@@ -202,7 +201,7 @@ s_reserve (ignore)
   if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
       && strncmp (input_line_pointer, ",\".bss\"", 7) != 0)
     {
-      as_bad ("bad .reserve segment -- expected BSS segment", input_line_pointer);
+      as_bad ("bad .reserve segment -- expected BSS segment");
       return;
     }
 
@@ -254,8 +253,7 @@ s_reserve (ignore)
   else
     align = 0;
 
-  if ((S_GET_SEGMENT (symbolP) == bss_section
-       || !S_IS_DEFINED (symbolP))
+  if (!S_IS_DEFINED (symbolP)
 #ifdef OBJ_AOUT
       && S_GET_OTHER (symbolP) == 0
       && S_GET_DESC (symbolP) == 0
@@ -289,7 +287,8 @@ s_reserve (ignore)
     }
   else
     {
-      as_warn("Ignoring attempt to re-define symbol %s.", name);
+      as_warn("Ignoring attempt to re-define symbol %s",
+             S_GET_NAME (symbolP));
     }                          /* if not redefining */
 
   demand_empty_rest_of_line ();
@@ -404,9 +403,12 @@ s_common (ignore)
        {
        allocate_common:
          S_SET_VALUE (symbolP, (valueT) size);
+#ifdef OBJ_ELF
+         S_SET_ALIGN (symbolP, temp);
+#endif
          S_SET_EXTERNAL (symbolP);
          /* should be common, but this is how gas does it for now */
-         S_SET_SEGMENT (symbolP, &bfd_und_section);
+         S_SET_SEGMENT (symbolP, bfd_und_section_ptr);
        }
     }
   else
@@ -500,7 +502,6 @@ s_proc (ignore)
   ++input_line_pointer;
 }
 
-/* start-sanitize-v9 */
 #ifndef NO_V9
 
 struct priv_reg_entry
@@ -540,7 +541,7 @@ struct membar_masks
 
 #define MEMBAR_MASKS_SIZE 7
 
-struct membar_masks membar_masks[MEMBAR_MASKS_SIZE] =
+static const struct membar_masks membar_masks[MEMBAR_MASKS_SIZE] =
 {
   {"Sync", 4, 0x40},
   {"MemIssue", 8, 0x20},
@@ -559,7 +560,6 @@ cmp_reg_entry (p, q)
 }
 
 #endif
-/* end-sanitize-v9 */
 
 /* This function is called once, at assembler startup time.  It should
    set up all the tables, etc. that the MD part of the assembler will need. */
@@ -608,16 +608,10 @@ md_begin ()
   for (i = 'A'; i <= 'F'; ++i)
     toHex[i] = i + 10 - 'A';
 
-  /* start-sanitize-v9 */
 #ifndef NO_V9
-#ifdef sparcv9
-  current_architecture = v9;
-#endif
-
   qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
         sizeof (priv_reg_table[0]), cmp_reg_entry);
 #endif
-  /* end-sanitize-v9 */
 
   target_big_endian = 1;
 }
@@ -705,6 +699,17 @@ md_assemble (str)
     }
 }
 
+/* Implement big shift right.  */
+static bfd_vma
+BSR (val, amount)
+     bfd_vma val;
+     int amount;
+{
+  if (sizeof (bfd_vma) <= 4 && amount >= 32)
+    as_fatal ("Support for 64-bit arithmetic not compiled in.");
+  return val >> amount;
+}
+
 static void
 sparc_ip (str)
      char *str;
@@ -713,7 +718,7 @@ sparc_ip (str)
   char *s;
   const char *args;
   char c;
-  struct sparc_opcode *insn;
+  const struct sparc_opcode *insn;
   char *argsStart;
   unsigned long opcode;
   unsigned int mask = 0;
@@ -739,10 +744,10 @@ sparc_ip (str)
       break;
 
     default:
-      as_bad ("Unknown opcode: `%s'", str);
-      exit (1);
+      as_fatal ("Unknown opcode: `%s'", str);
     }
-  if ((insn = (struct sparc_opcode *) hash_find (op_hash, str)) == NULL)
+  insn = (struct sparc_opcode *) hash_find (op_hash, str);
+  if (insn == NULL)
     {
       as_bad ("Unknown opcode: `%s'", str);
       return;
@@ -766,8 +771,6 @@ sparc_ip (str)
        {
          switch (*args)
            {
-
-             /* start-sanitize-v9 */
 #ifndef NO_V9
            case 'K':
              {
@@ -909,7 +912,6 @@ sparc_ip (str)
                  goto error;
                }
 #endif
-             /* end-sanitize-v9 */
 
            case 'M':
            case 'm':
@@ -945,7 +947,6 @@ sparc_ip (str)
                }               /* if %asr */
              break;
 
-             /* start-sanitize-v9 */
 #ifndef NO_V9
            case 'I':
              the_insn.reloc = BFD_RELOC_SPARC_11;
@@ -1071,7 +1072,6 @@ sparc_ip (str)
                }
              break;
 #endif /* NO_V9 */
-             /* end-sanitize-v9 */
 
            case '\0':          /* end of args */
              if (*s == '\0')
@@ -1310,7 +1310,6 @@ sparc_ip (str)
                        break;
                      }         /* register must be multiple of 4 */
 
-/* start-sanitize-v9 */
 #ifndef NO_V9
                    if (mask >= 64)
                      {
@@ -1322,15 +1321,12 @@ sparc_ip (str)
                        mask -= 31;
                      } /* wrap high bit */
 #else
-/* end-sanitize-v9 */
                    if (mask >= 32)
                      {
                        error_message = ": There are only 32 f registers; [0-31]";
                        goto error;
                      } /* on error */
-/* start-sanitize-v9 */
 #endif
-/* end-sanitize-v9 */
                  }
                else
                  {
@@ -1411,7 +1407,6 @@ sparc_ip (str)
                      the_insn.reloc = BFD_RELOC_LO10;
                      s += 3;
                    }
-                 /* start-sanitize-v9 */
 #ifndef NO_V9
                  else if (c == 'u'
                           && s[2] == 'h'
@@ -1428,7 +1423,6 @@ sparc_ip (str)
                      s += 4;
                    }
 #endif /* NO_V9 */
-                 /* end-sanitize-v9 */
                  else
                    break;
                }
@@ -1475,7 +1469,6 @@ sparc_ip (str)
                  && the_insn.exp.X_add_symbol == 0
                  && the_insn.exp.X_op_symbol == 0)
                {
-                 /* start-sanitize-v9 */
 #ifndef NO_V9
                  /* Handle %uhi/%ulo by moving the upper word to the lower
                     one and pretending it's %hi/%lo.  We also need to watch
@@ -1485,11 +1478,11 @@ sparc_ip (str)
                    {
                    case BFD_RELOC_SPARC_HH22:
                      the_insn.reloc = BFD_RELOC_HI22;
-                     the_insn.exp.X_add_number >>= 32;
+                     the_insn.exp.X_add_number = BSR (the_insn.exp.X_add_number, 32);
                      break;
                    case BFD_RELOC_SPARC_HM10:
                      the_insn.reloc = BFD_RELOC_LO10;
-                     the_insn.exp.X_add_number >>= 32;
+                     the_insn.exp.X_add_number = BSR (the_insn.exp.X_add_number, 32);
                      break;
                    default:
                      break;
@@ -1499,7 +1492,6 @@ sparc_ip (str)
                      break;
                    }
 #endif
-                 /* end-sanitize-v9 */
                  /* For pc-relative call instructions, we reject
                     constants to get better code.  */
                  if (the_insn.pcrel
@@ -1551,55 +1543,39 @@ sparc_ip (str)
 
            case 'A':
              {
-/* start-sanitize-v9 */
-#ifdef NO_V9
-/* end-sanitize-v9 */
-               char *push = input_line_pointer;
-               expressionS e;
-
-               input_line_pointer = s;
-
-               expression (&e);
-               if (e.X_op == O_constant)
-                 {
-                   opcode |= e.X_add_number << 5;
-                   s = input_line_pointer;
-                   input_line_pointer = push;
-                   continue;
-                 }             /* if absolute */
-
-               break;
-/* start-sanitize-v9 */
-#else
                int asi = 0;
 
                /* Parse an asi.  */
                if (*s == '#')
                  {
-                   s += 1;
-                   if (!strncmp (s, "ASI_AIUP", 8))
-                     asi = 0x10, s += 8;
-                   else if (!strncmp (s, "ASI_AIUS", 8))
-                     asi = 0x11, s += 8;
-                   else if (!strncmp (s, "ASI_PNF", 7))
-                     asi = 0x82, s += 7;
-                   else if (!strncmp (s, "ASI_SNF", 7))
-                     asi = 0x83, s += 7;
-                   else if (!strncmp (s, "ASI_P", 5))
-                     asi = 0x80, s += 5;
-                   else if (!strncmp (s, "ASI_S", 5))
-                     asi = 0x81, s += 5;
-                   else
+                   char c, *p;
+
+                   for (p = s + 1; isalpha (*p) || *p == '_'; ++p)
+                     continue;
+                   c = *p;
+                   *p = 0;
+                   asi = sparc_encode_asi (s);
+                   *p = c;
+                   if (asi == -1)
                      {
                        error_message = ": invalid asi name";
                        goto error;
                      }
+                   s = p;
                  }
-               else if (isdigit (*s))
+               else
                  {
                    char *push = input_line_pointer;
+                   expressionS e;
                    input_line_pointer = s;
-                   asi = get_absolute_expression ();
+
+                   expression (&e);
+                   if (e.X_op != O_constant)
+                     {
+                       error_message = ": constant required for ASI";
+                       goto error;
+                     }
+                   asi = e.X_add_number;
                    s = input_line_pointer;
                    input_line_pointer = push;
                    
@@ -1609,15 +1585,8 @@ sparc_ip (str)
                        goto error;
                      }
                  }
-               else
-                 {
-                   error_message = ": unrecognizable asi";
-                   goto error;
-                 }
                opcode |= ASI (asi);
                continue;
-#endif
-/* end-sanitize-v9 */
              }                 /* alternate space */
 
            case 'p':
@@ -1657,7 +1626,6 @@ sparc_ip (str)
                }
              break;
 
-             /* start-sanitize-v9 */
 #ifndef NO_V9
            case 'o':
              if (strncmp (s, "%asi", 4) != 0)
@@ -1677,7 +1645,6 @@ sparc_ip (str)
              s += 4;
              continue;
 #endif /* NO_V9 */
-             /* end-sanitize-v9 */
 
            case 't':
              if (strncmp (s, "%tbr", 4) != 0)
@@ -1691,6 +1658,30 @@ sparc_ip (str)
              s += 4;
              continue;
 
+#ifndef NO_V9
+           case 'x':
+             {
+               char *push = input_line_pointer;
+               expressionS e;
+
+               input_line_pointer = s;
+               expression (&e);
+               if (e.X_op == O_constant)
+                 {
+                   int n = e.X_add_number;
+                   if (n != e.X_add_number || (n & ~0x1ff) != 0)
+                     as_bad ("OPF immediate operand out of range (0-0x1ff)");
+                   else
+                     opcode |= e.X_add_number << 5;
+                 }
+               else
+                 as_bad ("non-immediate OPF operand, ignored");
+               s = input_line_pointer;
+               input_line_pointer = push;
+               continue;
+             }
+#endif
+
            case 'y':
              if (strncmp (s, "%y", 2) != 0)
                break;
@@ -1707,7 +1698,8 @@ sparc_ip (str)
        {
          /* Args don't match. */
          if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
-             && !strcmp (insn->name, insn[1].name))
+             && (insn->name == insn[1].name
+                 || !strcmp (insn->name, insn[1].name)))
            {
              ++insn;
              s = argsStart;
@@ -1721,21 +1713,15 @@ sparc_ip (str)
        }
       else
        {
-         if (insn->architecture > current_architecture)
+         if (insn->architecture > current_architecture
+             || (insn->architecture != current_architecture
+                 && current_architecture > v8))
            {
              if ((!architecture_requested || warn_on_bump)
-                 &&
-             /* start-sanitize-v9 */
-#ifndef NO_V9
-                 !ARCHITECTURES_CONFLICT_P (current_architecture,
-                                            insn->architecture)
-#else
-             /* end-sanitize-v9 */
-                 1
-             /* start-sanitize-v9 */
-#endif
-             /* end-sanitize-v9 */
-               )
+                 && !ARCHITECTURES_CONFLICT_P (current_architecture,
+                                               insn->architecture)
+                 && !ARCHITECTURES_CONFLICT_P (insn->architecture,
+                                               current_architecture))
                {
                  if (warn_on_bump)
                    {
@@ -1749,10 +1735,10 @@ sparc_ip (str)
                }
              else
                {
-                 as_bad ("architecture mismatch on \"%s\" (\"%s\").  current architecture is \"%s\"",
-                         str,
-                         architecture_pname[insn->architecture],
-                         architecture_pname[current_architecture]);
+                 as_bad ("Architecture mismatch on \"%s\".", str);
+                 as_tsktsk (" (Requires %s; current architecture is %s.)",
+                            architecture_pname[insn->architecture],
+                            architecture_pname[current_architecture]);
                  return;
                }               /* if bump ok else error */
            }                   /* if architecture higher */
@@ -1890,9 +1876,19 @@ md_apply_fix (fixP, value)
 #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_perform_relocation.  */
+     with the calls to bfd_perform_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.  */
   if (fixP->fx_addsy != NULL)
-    return 1;
+    {
+      if ((S_IS_EXTERN (fixP->fx_addsy)
+          || (sparc_pic_code && ! fixP->fx_pcrel))
+         && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section
+         && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
+         && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy)))
+       fixP->fx_addnumber -= S_GET_VALUE (fixP->fx_addsy);
+      return 1;
+    }
 #endif
 
   /* This is a hack.  There should be a better way to
@@ -1901,6 +1897,30 @@ md_apply_fix (fixP, value)
   if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy)
     val += fixP->fx_where + fixP->fx_frag->fr_address;
 
+#ifdef OBJ_AOUT
+  /* FIXME: More ridiculous gas reloc hacking.  If we are going to
+     generate a reloc, then we just want to let the reloc addend set
+     the value.  We do not want to also stuff the addend into the
+     object file.  Including the addend in the object file works when
+     doing a static link, because the linker will ignore the object
+     file contents.  However, the dynamic linker does not ignore the
+     object file contents.  */
+  if (fixP->fx_addsy != NULL
+      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2)
+    val = 0;
+
+  /* When generating PIC code, we do not want an addend for a reloc
+     against a local symbol.  We adjust fx_addnumber to cancel out the
+     value already included in val, and to also cancel out the
+     adjustment which bfd_install_relocation will create.  */
+  if (sparc_pic_code
+      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2
+      && fixP->fx_addsy != NULL
+      && ! S_IS_COMMON (fixP->fx_addsy)
+      && (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0)
+    fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
+#endif
+
   switch (fixP->fx_r_type)
     {
     case BFD_RELOC_16:
@@ -1916,24 +1936,30 @@ md_apply_fix (fixP, value)
       break;
 
     case BFD_RELOC_32_PCREL_S2:
-      val = (val >>= 2) + 1;
+      val = (val >>= 2);
+      if (! sparc_pic_code
+         || fixP->fx_addsy == NULL
+         || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+       ++val;
       buf[0] |= (val >> 24) & 0x3f;
       buf[1] = (val >> 16);
       buf[2] = val >> 8;
       buf[3] = val;
       break;
 
-      /* start-sanitize-v9 */
 #ifndef NO_V9
     case BFD_RELOC_64:
-      buf[0] = val >> 56;
-      buf[1] = val >> 48;
-      buf[2] = val >> 40;
-      buf[3] = val >> 32;
-      buf[4] = val >> 24;
-      buf[5] = val >> 16;
-      buf[6] = val >> 8;
-      buf[7] = val;
+      {
+       bfd_vma valh = BSR (val, 32);
+       buf[0] = valh >> 24;
+       buf[1] = valh >> 16;
+       buf[2] = valh >> 8;
+       buf[3] = valh;
+       buf[4] = val >> 24;
+       buf[5] = val >> 16;
+       buf[6] = val >> 8;
+       buf[7] = val;
+      }
       break;
 
     case BFD_RELOC_SPARC_11:
@@ -1985,16 +2011,13 @@ md_apply_fix (fixP, value)
       break;
 
     case BFD_RELOC_SPARC_HH22:
-      val >>= 32;
+      val = BSR (val, 32);
       /* intentional fallthrough */
 #endif /* NO_V9 */
-      /* end-sanitize-v9 */
 
-      /* start-sanitize-v9 */
 #ifndef NO_V9
     case BFD_RELOC_SPARC_LM22:
 #endif
-      /* end-sanitize-v9 */
     case BFD_RELOC_HI22:
       if (!fixP->fx_addsy)
        {
@@ -2019,13 +2042,11 @@ md_apply_fix (fixP, value)
       buf[3] = val & 0xff;
       break;
 
-      /* start-sanitize-v9 */
 #ifndef NO_V9
     case BFD_RELOC_SPARC_HM10:
-      val >>= 32;
+      val = BSR (val, 32);
       /* intentional fallthrough */
 #endif /* NO_V9 */
-      /* end-sanitize-v9 */
 
     case BFD_RELOC_LO10:
       if (!fixP->fx_addsy)
@@ -2046,7 +2067,7 @@ md_apply_fix (fixP, value)
       break;
 
     case BFD_RELOC_SPARC_WDISP22:
-      val = (val >>= 2) + 1;
+      val = (val >> 2) + 1;
       /* FALLTHROUGH */
     case BFD_RELOC_SPARC_BASE22:
       buf[1] |= (val >> 16) & 0x3f;
@@ -2092,8 +2113,9 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_32_PCREL_S2:
     case BFD_RELOC_SPARC13:
     case BFD_RELOC_SPARC_BASE13:
+    case BFD_RELOC_SPARC_WDISP16:
+    case BFD_RELOC_SPARC_WDISP19:
     case BFD_RELOC_SPARC_WDISP22:
-      /* start-sanitize-v9 */
     case BFD_RELOC_64:
     case BFD_RELOC_SPARC_10:
     case BFD_RELOC_SPARC_11:
@@ -2103,33 +2125,86 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_SPARC_PC_HH22:
     case BFD_RELOC_SPARC_PC_HM10:
     case BFD_RELOC_SPARC_PC_LM22:
-      /* end-sanitize-v9 */
       code = fixp->fx_r_type;
       break;
     default:
       abort ();
     }
+
+#if defined (OBJ_ELF) || defined (OBJ_AOUT)
+  /* If we are generating PIC code, we need to generate a different
+     set of relocs.  */
+
+#ifdef OBJ_ELF
+#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
+#else
+#define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
+#endif
+
+  if (sparc_pic_code)
+    {
+      switch (code)
+       {
+       case BFD_RELOC_32_PCREL_S2:
+         if (! S_IS_DEFINED (fixp->fx_addsy)
+             || S_IS_EXTERNAL (fixp->fx_addsy))
+           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;
+         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;
+         break;
+       case BFD_RELOC_SPARC13:
+         code = BFD_RELOC_SPARC_GOT13;
+         break;
+       default:
+         break;
+       }
+    }
+#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT) */
+
   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   if (reloc->howto == 0)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
-                   "internal error: can't export reloc type %d",
-                   fixp->fx_r_type);
+                   "internal error: can't export reloc type %d (`%s')",
+                   fixp->fx_r_type, bfd_get_reloc_code_name (code));
       return 0;
     }
-  assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
 
   /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
-  if (reloc->howto->pc_relative == 0)
+#ifdef OBJ_AOUT
+
+  if (reloc->howto->pc_relative == 0
+      || code == BFD_RELOC_SPARC_PC10
+      || code == BFD_RELOC_SPARC_PC22)
+    reloc->addend = fixp->fx_addnumber;
+  else
+    reloc->addend = fixp->fx_offset - reloc->address;
+
+#else /* elf or coff */
+
+  if (reloc->howto->pc_relative == 0
+      || code == BFD_RELOC_SPARC_PC10
+      || code == BFD_RELOC_SPARC_PC22)
     reloc->addend = fixp->fx_addnumber;
-#if defined (OBJ_ELF) || defined (OBJ_COFF)
   else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
     reloc->addend = (section->vma
                     + fixp->fx_addnumber
                     + md_pcrel_from (fixp));
-#endif
   else
-    reloc->addend = fixp->fx_offset - reloc->address;
+    reloc->addend = fixp->fx_offset;
+#endif
 
   return reloc;
 }
@@ -2200,7 +2275,7 @@ print_insn (insn)
  *     -bump
  *             Warn on architecture bumps.  See also -A.
  *
- *     -Av6, -Av7, -Av8, -Asparclite
+ *     -Av6, -Av7, -Av8, -Av9, -Asparclite
  *             Select the architecture.  Instructions or features not
  *             supported by the selected architecture cause fatal errors.
  *
@@ -2218,21 +2293,20 @@ print_insn (insn)
  *             architecture starts at the specified level, but bumps are
  *             warnings.
  *
- * start-sanitize-v9
- *     -Av9
- *             Another architecture switch.
- *
  * Note:
  *             Bumping between incompatible architectures is always an
  *             error.  For example, from sparclite to v9.
- * end-sanitize-v9
  */
 
 #ifdef OBJ_ELF
-CONST char *md_shortopts = "A:VQ:sq";
+CONST char *md_shortopts = "A:K:VQ:sq";
+#else
+#ifdef OBJ_AOUT
+CONST char *md_shortopts = "A:k";
 #else
 CONST char *md_shortopts = "A:";
 #endif
+#endif
 struct option md_longopts[] = {
 #define OPTION_BUMP (OPTION_MD_BASE)
   {"bump", no_argument, NULL, OPTION_BUMP},
@@ -2271,8 +2345,15 @@ md_parse_option (c, arg)
          }
        else
          {
-           current_architecture = (enum sparc_architecture)
-             (arch - architecture_pname);
+           enum sparc_architecture new_arch = arch - architecture_pname;
+#ifdef NO_V9
+           if (new_arch == v9)
+             {
+               as_error ("v9 support not compiled in");
+               return 0;
+             }
+#endif
+           current_architecture = new_arch;
            architecture_requested = 1;
          }
       }
@@ -2282,6 +2363,12 @@ md_parse_option (c, arg)
       /* Ignore -sparc, used by SunOS make default .s.o rule.  */
       break;
 
+#ifdef OBJ_AOUT
+    case 'k':
+      sparc_pic_code = 1;
+      break;
+#endif
+
 #ifdef OBJ_ELF
     case 'V':
       print_version_id ();
@@ -2299,6 +2386,13 @@ md_parse_option (c, arg)
     case 'q':
       /* quick -- native assembler does fewer checks */
       break;
+
+    case 'K':
+      if (strcmp (arg, "PIC") != 0)
+       as_warn ("Unrecognized option following -K");
+      else
+       sparc_pic_code = 1;
+      break;
 #endif
 
     default:
@@ -2312,14 +2406,25 @@ void
 md_show_usage (stream)
      FILE *stream;
 {
-  fprintf(stream, "\
-SPARC options:\n\
--Av6 | -Av7 | -Av8 | -Asparclite\n\
+  const char **arch;
+  fprintf(stream, "SPARC options:\n");
+  for (arch = architecture_pname; *arch; arch++)
+    {
+      if (arch != architecture_pname)
+       fprintf (stream, " | ");
+      fprintf (stream, "-A%s", *arch);
+    }
+  fprintf (stream, "\n\
                        specify variant of SPARC architecture\n\
 -bump                  warn when assembler switches architectures\n\
 -sparc                 ignored\n");
+#ifdef OBJ_AOUT
+  fprintf (stream, "\
+-k                     generate PIC\n");
+#endif
 #ifdef OBJ_ELF
-  fprintf(stream, "\
+  fprintf (stream, "\
+-KPIC                  generate PIC\n\
 -V                     print assembler version number\n\
 -q                     ignored\n\
 -Qy, -Qn               ignored\n\
@@ -2337,17 +2442,6 @@ md_undefined_symbol (name)
   return 0;
 }                              /* md_undefined_symbol() */
 
-/* Parse an operand that is machine-specific.
-   We just return without modifying the expression if we have nothing
-   to do. */
-
-/* ARGSUSED */
-void 
-md_operand (expressionP)
-     expressionS *expressionP;
-{
-}
-
 /* Round up a section size to the appropriate boundary. */
 valueT
 md_section_align (segment, size)
@@ -2357,7 +2451,8 @@ md_section_align (segment, size)
 #ifndef OBJ_ELF
   /* This is not right for ELF; a.out wants it, and COFF will force
      the alignment anyways.  */
-  valueT align = (valueT) 1 << (valueT) (stdoutput->xvec->align_power_min);
+  valueT align = ((valueT) 1
+                 << (valueT) bfd_get_section_alignment (stdoutput, segment));
   valueT newsize;
   /* turn alignment value into a mask */
   align--;
@@ -2376,7 +2471,14 @@ long
 md_pcrel_from (fixP)
      fixS *fixP;
 {
-  return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+  long ret;
+
+  ret = fixP->fx_where + fixP->fx_frag->fr_address;
+  if (! sparc_pic_code
+      || fixP->fx_addsy == NULL
+      || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+    ret += fixP->fx_size;
+  return ret;
 }
 
 /* end of tc-sparc.c */
This page took 0.036138 seconds and 4 git commands to generate.