Change target of hppa-netbsd port
[deliverable/binutils-gdb.git] / gas / config / tc-hppa.c
index c4401834f311d71027554e2171c9782c9a64a736..1f365b0f733f223fe6fee928f21dce58795ea00b 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-hppa.c -- Assemble for the PA
-   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, 2003 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -23,9 +23,9 @@
    at the University of Utah.  */
 
 #include <stdio.h>
-#include <ctype.h>
 
 #include "as.h"
+#include "safe-ctype.h"
 #include "subsegs.h"
 
 #include "bfd/libhppa.h"
@@ -57,8 +57,10 @@ typedef elf_symbol_type obj_symbol_type;
 #if TARGET_ARCH_SIZE == 64
 /* How to generate a relocation.  */
 #define hppa_gen_reloc_type _bfd_elf64_hppa_gen_reloc_type
+#define elf_hppa_reloc_final_type elf64_hppa_reloc_final_type
 #else
 #define hppa_gen_reloc_type _bfd_elf32_hppa_gen_reloc_type
+#define elf_hppa_reloc_final_type elf32_hppa_reloc_final_type
 #endif
 
 /* ELF objects can have versions, but apparently do not have anywhere
@@ -488,7 +490,7 @@ struct selector_entry
 static void pa_check_current_space_and_subspace PARAMS ((void));
 #endif
 
-#if !(defined (OBJ_ELF) && defined (TE_LINUX))
+#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
 static void pa_text PARAMS ((int));
 static void pa_data PARAMS ((int));
 static void pa_comm PARAMS ((int));
@@ -508,10 +510,10 @@ static int evaluate_absolute PARAMS ((struct pa_it *));
 static unsigned int pa_build_arg_reloc PARAMS ((char *));
 static unsigned int pa_align_arg_reloc PARAMS ((unsigned int, unsigned int));
 static int pa_parse_nullif PARAMS ((char **));
-static int pa_parse_nonneg_cmpsub_cmpltr PARAMS ((char **, int));
-static int pa_parse_neg_cmpsub_cmpltr PARAMS ((char **, int));
-static int pa_parse_neg_add_cmpltr PARAMS ((char **, int));
-static int pa_parse_nonneg_add_cmpltr PARAMS ((char **, int));
+static int pa_parse_nonneg_cmpsub_cmpltr PARAMS ((char **));
+static int pa_parse_neg_cmpsub_cmpltr PARAMS ((char **));
+static int pa_parse_neg_add_cmpltr PARAMS ((char **));
+static int pa_parse_nonneg_add_cmpltr PARAMS ((char **));
 static int pa_parse_cmpb_64_cmpltr PARAMS ((char **));
 static int pa_parse_cmpib_64_cmpltr PARAMS ((char **));
 static int pa_parse_addb_64_cmpltr PARAMS ((char **));
@@ -620,6 +622,11 @@ static struct call_desc last_call_desc;
 /* handle of the OPCODE hash table */
 static struct hash_control *op_hash = NULL;
 
+/* These characters can be suffixes of opcode names and they may be
+   followed by meaningful whitespace.  We don't include `,' and `!'
+   as they never appear followed by meaningful whitespace.  */
+const char hppa_symbol_chars[] = "*?=<>";
+
 /* Table of pseudo ops for the PA.  FIXME -- how many of these
    are now redundant with the overall GAS and the object file
    dependent tables?  */
@@ -640,7 +647,7 @@ const pseudo_typeS md_pseudo_table[] =
   {"byte", pa_cons, 1},
   {"call", pa_call, 0},
   {"callinfo", pa_callinfo, 0},
-#if defined (OBJ_ELF) && defined (TE_LINUX)
+#if defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))
   {"code", obj_elf_text, 0},
 #else
   {"code", pa_text, 0},
@@ -650,14 +657,14 @@ const pseudo_typeS md_pseudo_table[] =
   {"compiler", pa_compiler, 0},
 #endif
   {"copyright", pa_copyright, 0},
-#if !(defined (OBJ_ELF) && defined (TE_LINUX))
+#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
   {"data", pa_data, 0},
 #endif
   {"double", pa_float_cons, 'd'},
   {"dword", pa_cons, 8},
   {"end", pa_end, 0},
   {"end_brtab", pa_brtab, 0},
-#if !(defined (OBJ_ELF) && defined (TE_LINUX))
+#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
   {"end_try", pa_try, 0},
 #endif
   {"enter", pa_enter, 0},
@@ -665,9 +672,6 @@ const pseudo_typeS md_pseudo_table[] =
   {"equ", pa_equ, 0},
   {"exit", pa_exit, 0},
   {"export", pa_export, 0},
-#ifdef OBJ_ELF
-  {"file", dwarf2_directive_file, 0 },
-#endif
   {"fill", pa_fill, 0},
   {"float", pa_float_cons, 'f'},
   {"half", pa_cons, 2},
@@ -677,9 +681,6 @@ const pseudo_typeS md_pseudo_table[] =
   {"lcomm", pa_lcomm, 0},
   {"leave", pa_leave, 0},
   {"level", pa_level, 0},
-#ifdef OBJ_ELF
-  {"loc", dwarf2_directive_loc, 0 },
-#endif
   {"long", pa_cons, 4},
   {"lsym", pa_lsym, 0},
 #ifdef OBJ_SOM
@@ -704,7 +705,7 @@ const pseudo_typeS md_pseudo_table[] =
 #ifdef OBJ_SOM
   {"subspa", pa_subspace, 0},
 #endif
-#if !(defined (OBJ_ELF) && defined (TE_LINUX))
+#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
   {"text", pa_text, 0},
 #endif
   {"version", pa_version, 0},
@@ -851,6 +852,10 @@ static const struct pd_reg pre_defined_registers[] =
   {"%dp",    27},
   {"%eiem",  15},
   {"%eirr",  23},
+  {"%farg0",  5},
+  {"%farg1",  6},
+  {"%farg2",  7},
+  {"%farg3",  8},
   {"%fr0",    0 + FP_REG_BASE},
   {"%fr0l",   0 + FP_REG_BASE},
   {"%fr0r",   0 + FP_REG_BASE + FP_REG_RSEL},
@@ -947,6 +952,7 @@ static const struct pd_reg pre_defined_registers[] =
   {"%fr9",    9 + FP_REG_BASE},
   {"%fr9l",   9 + FP_REG_BASE},
   {"%fr9r",   9 + FP_REG_BASE + FP_REG_RSEL},
+  {"%fret",   4},
   {"%hta",   25},
   {"%iir",   19},
   {"%ior",   21},
@@ -1012,6 +1018,14 @@ static const struct pd_reg pre_defined_registers[] =
   {"%sr5",    5},
   {"%sr6",    6},
   {"%sr7",    7},
+  {"%t1",    22},
+  {"%t2",    21},
+  {"%t3",    20},
+  {"%t4",    19},
+  {"%tf1",   11},
+  {"%tf2",   10},
+  {"%tf3",    9},
+  {"%tf4",    8},
   {"%tr0",   24},
   {"%tr1",   25},
   {"%tr2",   26},
@@ -1158,7 +1172,7 @@ static struct default_space_dict pa_def_spaces[] =
       } \
   }
 
-/* Variant of CHECK_FIELD for use in md_apply_fix and other places where
+/* Variant of CHECK_FIELD for use in md_apply_fix3 and other places where
    the current file and line number are not valid.  */
 
 #define CHECK_FIELD_WHERE(FIELD, HIGH, LOW, FILENAME, LINE) \
@@ -1287,10 +1301,10 @@ pa_undefine_label ()
     {
       if (1
 #ifdef OBJ_SOM
-         && current_space == label_chain->lss_space && label_chain->lss_label
+         && current_space == label_chain->lss_space && label_chain->lss_label
 #endif
 #ifdef OBJ_ELF
-         && now_seg == label_chain->lss_segment && label_chain->lss_label
+         && now_seg == label_chain->lss_segment && label_chain->lss_label
 #endif
          )
        {
@@ -1571,11 +1585,12 @@ pa_ip (str)
   /* Convert everything up to the first whitespace character into lower
      case.  */
   for (s = str; *s != ' ' && *s != '\t' && *s != '\n' && *s != '\0'; s++)
-    if (isupper (*s))
-      *s = tolower (*s);
+    *s = TOLOWER (*s);
 
   /* Skip to something interesting.  */
-  for (s = str; isupper (*s) || islower (*s) || (*s >= '0' && *s <= '3'); ++s)
+  for (s = str;
+       ISUPPER (*s) || ISLOWER (*s) || (*s >= '0' && *s <= '3');
+       ++s)
     ;
 
   switch (*s)
@@ -1597,8 +1612,6 @@ pa_ip (str)
       as_fatal (_("Unknown opcode: `%s'"), str);
     }
 
-  save_s = str;
-
   /* Look up the opcode in the has table.  */
   if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL)
     {
@@ -1691,12 +1704,12 @@ pa_ip (str)
              while (*s == ' ' || *s == '\t')
                s = s + 1;
 
-             if (!strncasecmp(s, "%sar", 4))
+             if (!strncasecmp (s, "%sar", 4))
                {
                  s += 4;
                  continue;
                }
-             else if (!strncasecmp(s, "%cr11", 5))
+             else if (!strncasecmp (s, "%cr11", 5))
                {
                  s += 5;
                  continue;
@@ -1811,6 +1824,7 @@ pa_ip (str)
                {
 
                /* Handle a completer for an indexing load or store.  */
+               case 'X':
                case 'x':
                  {
                    int uu = 0;
@@ -1849,6 +1863,7 @@ pa_ip (str)
                  }
 
                /* Handle a short load/store completer.  */
+               case 'M':
                case 'm':
                case 'q':
                case 'J':
@@ -1888,9 +1903,9 @@ pa_ip (str)
                    else if (*args == 'e')
                      break;
 
-                  /* 'J', 'm' and 'q' are the same, except for where they
+                  /* 'J', 'm', 'M' and 'q' are the same, except for where they
                       encode the before/after field.  */
-                  if (*args == 'm')
+                  if (*args == 'm' || *args == 'M')
                      {
                        opcode |= m << 5;
                        INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
@@ -1916,6 +1931,7 @@ pa_ip (str)
                  }
 
                /* Handle a stbys completer.  */
+               case 'A':
                case 's':
                  {
                    int a = 0;
@@ -1951,7 +1967,7 @@ pa_ip (str)
                /* Handle load cache hint completer.  */
                case 'c':
                  cmpltr = 0;
-                 if (!strncmp(s, ",sl", 3))
+                 if (!strncmp (s, ",sl", 3))
                    {
                      s += 3;
                      cmpltr = 2;
@@ -1961,12 +1977,12 @@ pa_ip (str)
                /* Handle store cache hint completer.  */
                case 'C':
                  cmpltr = 0;
-                 if (!strncmp(s, ",sl", 3))
+                 if (!strncmp (s, ",sl", 3))
                    {
                      s += 3;
                      cmpltr = 2;
                    }
-                 else if (!strncmp(s, ",bc", 3))
+                 else if (!strncmp (s, ",bc", 3))
                    {
                      s += 3;
                      cmpltr = 1;
@@ -1976,7 +1992,7 @@ pa_ip (str)
                /* Handle load and clear cache hint completer.  */
                case 'd':
                  cmpltr = 0;
-                 if (!strncmp(s, ",co", 3))
+                 if (!strncmp (s, ",co", 3))
                    {
                      s += 3;
                      cmpltr = 1;
@@ -1985,7 +2001,7 @@ pa_ip (str)
 
                /* Handle load ordering completer.  */
                case 'o':
-                 if (strncmp(s, ",o", 2) != 0)
+                 if (strncmp (s, ",o", 2) != 0)
                    break;
                  s += 2;
                  continue;
@@ -2254,13 +2270,13 @@ pa_ip (str)
                      else if (*s == 'l')
                        lr = 0;
                      else
-                       as_bad(_("Invalid left/right combination completer"));
+                       as_bad (_("Invalid left/right combination completer"));
 
                      s++;
                      INSERT_FIELD_AND_CONTINUE (opcode, lr, 13);
                    }
                  else
-                   as_bad(_("Invalid left/right combination completer"));
+                   as_bad (_("Invalid left/right combination completer"));
                  break;
 
                /* Handle saturation at 24:25.  */
@@ -2309,14 +2325,14 @@ pa_ip (str)
                              perm = 3;
                              break;
                            default:
-                             as_bad(_("Invalid permutation completer"));
+                             as_bad (_("Invalid permutation completer"));
                            }
                          opcode |= perm << permloc[i];
                        }
                      continue;
                    }
                  else
-                   as_bad(_("Invalid permutation completer"));
+                   as_bad (_("Invalid permutation completer"));
                  break;
 
                default:
@@ -2330,16 +2346,16 @@ pa_ip (str)
                args++;
                switch (*args)
                  {
-                 /* Handle FP compare conditions.  */
-                 case 'f':
-                   cond = pa_parse_fp_cmp_cond (&s);
-                   INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
+                 /* Handle FP compare conditions.  */
+                 case 'f':
+                   cond = pa_parse_fp_cmp_cond (&s);
+                   INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
 
                  /* Handle an add condition.  */
                  case 'A':
                  case 'a':
-                   cmpltr = 0;
-                   flag = 0;
+                   cmpltr = 0;
+                   flag = 0;
                    if (*s == ',')
                      {
                        s++;
@@ -2354,7 +2370,6 @@ pa_ip (str)
                          }
                        else if (*s == '*')
                          break;
-                       name = s;
 
                        name = s;
                        while (*s != ',' && *s != ' ' && *s != '\t')
@@ -2416,7 +2431,7 @@ pa_ip (str)
                            flag = 1;
                          }
                        /* ",*" is a valid condition.  */
-                       else if (*args == 'a')
+                       else if (*args == 'a' || *name)
                          as_bad (_("Invalid Add Condition: %s"), name);
                        *s = c;
                      }
@@ -2425,10 +2440,10 @@ pa_ip (str)
 
                  /* Handle non-negated add and branch condition.  */
                  case 'd':
-                   cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
+                   cmpltr = pa_parse_nonneg_add_cmpltr (&s);
                    if (cmpltr < 0)
                      {
-                       as_bad (_("Invalid Add and Branch Condition: %c"), *s);
+                       as_bad (_("Invalid Add and Branch Condition"));
                        cmpltr = 0;
                      }
                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
@@ -2438,7 +2453,7 @@ pa_ip (str)
                    cmpltr = pa_parse_addb_64_cmpltr (&s);
                    if (cmpltr < 0)
                      {
-                       as_bad (_("Invalid Add and Branch Condition: %c"), *s);
+                       as_bad (_("Invalid Add and Branch Condition"));
                        cmpltr = 0;
                      }
                    else
@@ -2452,11 +2467,11 @@ pa_ip (str)
                     condition.  */
                  case '@':
                    save_s = s;
-                   cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
+                   cmpltr = pa_parse_nonneg_add_cmpltr (&s);
                    if (cmpltr < 0)
                      {
                        s = save_s;
-                       cmpltr = pa_parse_neg_add_cmpltr (&s, 1);
+                       cmpltr = pa_parse_neg_add_cmpltr (&s);
                        if (cmpltr < 0)
                          {
                            as_bad (_("Invalid Compare/Subtract Condition"));
@@ -2522,7 +2537,6 @@ pa_ip (str)
                          }
                        else if (*s == '*')
                          break;
-                       name = s;
 
                        name = s;
                        while (*s != ',' && *s != ' ' && *s != '\t')
@@ -2584,7 +2598,7 @@ pa_ip (str)
                            flag = 1;
                          }
                        /* ",*" is a valid condition.  */
-                       else if (*args != 'S')
+                       else if (*args != 'S' || *name)
                          as_bad (_("Invalid Compare/Subtract Condition: %s"),
                                  name);
                        *s = c;
@@ -2594,10 +2608,10 @@ pa_ip (str)
 
                  /* Handle a non-negated compare condition.  */
                  case 't':
-                   cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
+                   cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
                    if (cmpltr < 0)
                      {
-                       as_bad (_("Invalid Compare/Subtract Condition: %c"), *s);
+                       as_bad (_("Invalid Compare/Subtract Condition"));
                        cmpltr = 0;
                      }
                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
@@ -2605,14 +2619,14 @@ pa_ip (str)
                  /* Handle a 32 bit compare and branch condition.  */
                  case 'n':
                    save_s = s;
-                   cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
+                   cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
                    if (cmpltr < 0)
                      {
                        s = save_s;
-                       cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 1);
+                       cmpltr = pa_parse_neg_cmpsub_cmpltr (&s);
                        if (cmpltr < 0)
                          {
-                           as_bad (_("Invalid Compare and Branch Condition."));
+                           as_bad (_("Invalid Compare and Branch Condition"));
                            cmpltr = 0;
                          }
                        else
@@ -2707,7 +2721,7 @@ pa_ip (str)
                            flag = 1;
                          }
                        /* ",*" is a valid condition.  */
-                       else if (*args != 'L')
+                       else if (*args != 'L' || *name)
                          as_bad (_("Invalid Logical Instruction Condition."));
                        *s = c;
                      }
@@ -2762,7 +2776,7 @@ pa_ip (str)
                            continue;
                          }
                        /* ",*" is a valid condition.  */
-                       else if (*args != 'X')
+                       else if (*args != 'X' || *name)
                          as_bad (_("Invalid Shift/Extract/Deposit Condition."));
                        *s = c;
                      }
@@ -2874,7 +2888,7 @@ pa_ip (str)
                            s += 3;
                          }
                        /* ",*" is a valid condition.  */
-                       else if (*args != 'U')
+                       else if (*args != 'U' || (*s != ' ' && *s != '\t'))
                          as_bad (_("Invalid Unit Instruction Condition."));
                      }
                    opcode |= cmpltr << 13;
@@ -3247,7 +3261,7 @@ pa_ip (str)
              the_insn.pcrel = 1;
              if (!the_insn.exp.X_add_symbol
                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
-                             "L$0\001"))
+                             FAKE_LABEL_NAME))
                {
                  num = evaluate_absolute (&the_insn);
                  if (num % 4)
@@ -3279,7 +3293,7 @@ pa_ip (str)
              the_insn.pcrel = 1;
              if (!the_insn.exp.X_add_symbol
                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
-                             "L$0\001"))
+                             FAKE_LABEL_NAME))
                {
                  num = evaluate_absolute (&the_insn);
                  if (num % 4)
@@ -3310,7 +3324,7 @@ pa_ip (str)
              the_insn.pcrel = 1;
              if (!the_insn.exp.X_add_symbol
                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
-                             "L$0\001"))
+                             FAKE_LABEL_NAME))
                {
                  num = evaluate_absolute (&the_insn);
                  if (num % 4)
@@ -3340,7 +3354,7 @@ pa_ip (str)
              the_insn.pcrel = 0;
              if (!the_insn.exp.X_add_symbol
                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
-                             "L$0\001"))
+                             FAKE_LABEL_NAME))
                {
                  num = evaluate_absolute (&the_insn);
                  if (num % 4)
@@ -3945,7 +3959,7 @@ pa_ip (str)
 
  failed:
       /* Check if the args matched.  */
-      if (match == FALSE)
+      if (!match)
        {
          if (&insn[1] - pa_opcodes < (int) NUMOPCODES
              && !strcmp (insn->name, insn[1].name))
@@ -4236,8 +4250,8 @@ tc_gen_reloc (section, fixp)
        case R_N0SEL:
        case R_N1SEL:
          /* There is no symbol or addend associated with these fixups.  */
-          relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
-          *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
+         relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+         *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
          relocs[i]->addend = 0;
          break;
 
@@ -4245,8 +4259,8 @@ tc_gen_reloc (section, fixp)
        case R_ENTRY:
        case R_EXIT:
          /* There is no symbol associated with these fixups.  */
-          relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
-          *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
+         relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+         *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
          relocs[i]->addend = fixp->fx_offset;
          break;
 
@@ -4404,10 +4418,11 @@ md_undefined_symbol (name)
 
 /* Apply a fixup to an instruction.  */
 
-int
-md_apply_fix (fixP, valp)
+void
+md_apply_fix3 (fixP, valP, seg)
      fixS *fixP;
-     valueT *valp;
+     valueT *valP;
+     segT seg ATTRIBUTE_UNUSED;
 {
   unsigned char *buf;
   struct hppa_fix_struct *hppa_fixP;
@@ -4423,23 +4438,26 @@ md_apply_fix (fixP, valp)
       || fixP->fx_r_type == R_HPPA_BEGIN_BRTAB
       || fixP->fx_r_type == R_HPPA_END_BRTAB
       || fixP->fx_r_type == R_HPPA_BEGIN_TRY)
-    return 1;
+    return;
 
   /* Disgusting.  We must set fx_offset ourselves -- R_HPPA_END_TRY
      fixups are considered not adjustable, which in turn causes
      adjust_reloc_syms to not set fx_offset.  Ugh.  */
   if (fixP->fx_r_type == R_HPPA_END_TRY)
     {
-      fixP->fx_offset = *valp;
-      return 1;
+      fixP->fx_offset = * valP;
+      return;
     }
 #endif
 #ifdef OBJ_ELF
   if (fixP->fx_r_type == (int) R_PARISC_GNU_VTENTRY
       || fixP->fx_r_type == (int) R_PARISC_GNU_VTINHERIT)
-    return 1;
+    return;
 #endif
 
+  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+    fixP->fx_done = 1;
+
   /* There should have been an HPPA specific fixup associated
      with the GAS fixup.  */
   hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
@@ -4448,10 +4466,10 @@ md_apply_fix (fixP, valp)
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("no hppa_fixup entry for fixup type 0x%x"),
                    fixP->fx_r_type);
-      return 0;
+      return;
     }
 
-  buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+  buf = (unsigned char *) (fixP->fx_frag->fr_literal + fixP->fx_where);
   insn = bfd_get_32 (stdoutput, buf);
   fmt = bfd_hppa_insn2fmt (stdoutput, insn);
 
@@ -4475,16 +4493,9 @@ md_apply_fix (fixP, valp)
           || hppa_fixP->fx_r_field == e_rtsel
           || hppa_fixP->fx_r_field == e_ltsel)
     new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0);
-  /* This is truly disgusting.  The machine independent code blindly
-     adds in the value of the symbol being relocated against.  Damn!  */
-  else if (fmt == 32
-          && fixP->fx_addsy != NULL
-          && S_GET_SEGMENT (fixP->fx_addsy) != bfd_com_section_ptr)
-    new_val = hppa_field_adjust (*valp - S_GET_VALUE (fixP->fx_addsy),
-                                0, hppa_fixP->fx_r_field);
 #endif
   else
-    new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field);
+    new_val = hppa_field_adjust (* valP, 0, hppa_fixP->fx_r_field);
 
   /* Handle pc-relative exceptions from above.  */
   if ((fmt == 12 || fmt == 17 || fmt == 22)
@@ -4493,13 +4504,13 @@ md_apply_fix (fixP, valp)
       && !arg_reloc_stub_needed (symbol_arg_reloc_info (fixP->fx_addsy),
                                 hppa_fixP->fx_arg_reloc)
 #ifdef OBJ_ELF
-      && (*valp - 8 + 8192 < 16384
-         || (fmt == 17 && *valp - 8 + 262144 < 524288)
-         || (fmt == 22 && *valp - 8 + 8388608 < 16777216))
+      && (* valP - 8 + 8192 < 16384
+         || (fmt == 17 && * valP - 8 + 262144 < 524288)
+         || (fmt == 22 && * valP - 8 + 8388608 < 16777216))
 #endif
 #ifdef OBJ_SOM
-      && (*valp - 8 + 262144 < 524288
-         || (fmt == 22 && *valp - 8 + 8388608 < 16777216))
+      && (* valP - 8 + 262144 < 524288
+         || (fmt == 22 && * valP - 8 + 8388608 < 16777216))
 #endif
       && !S_IS_EXTERNAL (fixP->fx_addsy)
       && !S_IS_WEAK (fixP->fx_addsy)
@@ -4507,7 +4518,7 @@ md_apply_fix (fixP, valp)
       && !(fixP->fx_subsy
           && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment))
     {
-      new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field);
+      new_val = hppa_field_adjust (* valP, 0, hppa_fixP->fx_r_field);
     }
 
   switch (fmt)
@@ -4567,7 +4578,7 @@ md_apply_fix (fixP, valp)
       /* Handle some of the opcodes with the 'W' operand type.  */
     case 17:
       {
-       offsetT distance = *valp;
+       offsetT distance = * valP;
 
        /* If this is an absolute branch (ie no link) with an out of
           range target, then we want to complain.  */
@@ -4586,7 +4597,7 @@ md_apply_fix (fixP, valp)
 
     case 22:
       {
-       offsetT distance = *valp;
+       offsetT distance = * valP;
 
        /* If this is an absolute branch (ie no link) with an out of
           range target, then we want to complain.  */
@@ -4625,12 +4636,11 @@ md_apply_fix (fixP, valp)
     default:
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("Unknown relocation encountered in md_apply_fix."));
-      return 0;
+      return;
     }
 
   /* Insert the relocation.  */
   bfd_put_32 (stdoutput, insn, buf);
-  return 1;
 }
 
 /* Exactly what point is a PC-relative offset relative TO?
@@ -4680,7 +4690,7 @@ pa_parse_number (s, is_float)
   symbolS *sym;
   int status;
   char *p = *s;
-  boolean have_prefix;
+  bfd_boolean have_prefix;
 
   /* Skip whitespace before the number.  */
   while (*p == ' ' || *p == '\t')
@@ -4689,7 +4699,7 @@ pa_parse_number (s, is_float)
   pa_number = -1;
   have_prefix = 0;
   num = 0;
-  if (!strict && isdigit (*p))
+  if (!strict && ISDIGIT (*p))
     {
       /* Looks like a number.  */
 
@@ -4697,10 +4707,10 @@ pa_parse_number (s, is_float)
        {
          /* The number is specified in hex.  */
          p += 2;
-         while (isdigit (*p) || ((*p >= 'a') && (*p <= 'f'))
+         while (ISDIGIT (*p) || ((*p >= 'a') && (*p <= 'f'))
                 || ((*p >= 'A') && (*p <= 'F')))
            {
-             if (isdigit (*p))
+             if (ISDIGIT (*p))
                num = num * 16 + *p - '0';
              else if (*p >= 'a' && *p <= 'f')
                num = num * 16 + *p - 'a' + 10;
@@ -4712,7 +4722,7 @@ pa_parse_number (s, is_float)
       else
        {
          /* The number is specified in decimal.  */
-         while (isdigit (*p))
+         while (ISDIGIT (*p))
            {
              num = num * 10 + *p - '0';
              ++p;
@@ -4764,7 +4774,7 @@ pa_parse_number (s, is_float)
              num = 2;
              p++;
            }
-         else if (!isdigit (*p))
+         else if (!ISDIGIT (*p))
            {
              if (print_errors)
                as_bad (_("Undefined register: '%s'."), name);
@@ -4774,7 +4784,7 @@ pa_parse_number (s, is_float)
            {
              do
                num = num * 10 + *p++ - '0';
-             while (isdigit (*p));
+             while (ISDIGIT (*p));
            }
        }
       else
@@ -4819,7 +4829,7 @@ pa_parse_number (s, is_float)
              num = S_GET_VALUE (sym);
              /* Well, we don't really have one, but we do have a
                 register, so...  */
-             have_prefix = true;
+             have_prefix = TRUE;
            }
          else if (S_GET_SEGMENT (sym) == &bfd_abs_section)
            num = S_GET_VALUE (sym);
@@ -5126,16 +5136,16 @@ pa_chk_field_selector (str)
     *str = *str + 1;
 
   if ((*str)[1] == '\'' || (*str)[1] == '%')
-    name[0] = tolower ((*str)[0]),
+    name[0] = TOLOWER ((*str)[0]),
     name[1] = 0;
   else if ((*str)[2] == '\'' || (*str)[2] == '%')
-    name[0] = tolower ((*str)[0]),
-    name[1] = tolower ((*str)[1]),
+    name[0] = TOLOWER ((*str)[0]),
+    name[1] = TOLOWER ((*str)[1]),
     name[2] = 0;
   else if ((*str)[3] == '\'' || (*str)[3] == '%')
-    name[0] = tolower ((*str)[0]),
-    name[1] = tolower ((*str)[1]),
-    name[2] = tolower ((*str)[2]),
+    name[0] = TOLOWER ((*str)[0]),
+    name[1] = TOLOWER ((*str)[1]),
+    name[2] = TOLOWER ((*str)[2]),
     name[3] = 0;
   else
     return e_fsel;
@@ -5220,7 +5230,7 @@ pa_get_absolute_expression (insn, strp)
       input_line_pointer = *strp;
       s = *strp;
       while (*s != ',' && *s != ' ' && *s != '\t')
-        s++;
+       s++;
 
       c = *s;
       *s = 0;
@@ -5348,16 +5358,11 @@ pa_parse_nullif (s)
 }
 
 /* Parse a non-negated compare/subtract completer returning the
-   number (for encoding in instrutions) of the given completer.
-
-   ISBRANCH specifies whether or not this is parsing a condition
-   completer for a branch (vs a nullification completer for a
-   computational instruction.  */
+   number (for encoding in instrutions) of the given completer.  */
 
 static int
-pa_parse_nonneg_cmpsub_cmpltr (s, isbranch)
+pa_parse_nonneg_cmpsub_cmpltr (s)
      char **s;
-     int isbranch;
 {
   int cmpltr;
   char *name = *s + 1;
@@ -5404,7 +5409,7 @@ pa_parse_nonneg_cmpsub_cmpltr (s, isbranch)
        }
       /* If we have something like addb,n then there is no condition
          completer.  */
-      else if (strcasecmp (name, "n") == 0 && isbranch)
+      else if (strcasecmp (name, "n") == 0)
        {
          cmpltr = 0;
          nullify = 1;
@@ -5424,16 +5429,11 @@ pa_parse_nonneg_cmpsub_cmpltr (s, isbranch)
 }
 
 /* Parse a negated compare/subtract completer returning the
-   number (for encoding in instrutions) of the given completer.
-
-   ISBRANCH specifies whether or not this is parsing a condition
-   completer for a branch (vs a nullification completer for a
-   computational instruction.  */
+   number (for encoding in instrutions) of the given completer.  */
 
 static int
-pa_parse_neg_cmpsub_cmpltr (s, isbranch)
+pa_parse_neg_cmpsub_cmpltr (s)
      char **s;
-     int isbranch;
 {
   int cmpltr;
   char *name = *s + 1;
@@ -5484,7 +5484,7 @@ pa_parse_neg_cmpsub_cmpltr (s, isbranch)
        }
       /* If we have something like addb,n then there is no condition
          completer.  */
-      else if (strcasecmp (name, "n") == 0 && isbranch)
+      else if (strcasecmp (name, "n") == 0)
        {
          cmpltr = 0;
          nullify = 1;
@@ -5663,21 +5663,17 @@ pa_parse_cmpib_64_cmpltr (s)
 }
 
 /* Parse a non-negated addition completer returning the number
-   (for encoding in instrutions) of the given completer.
-
-   ISBRANCH specifies whether or not this is parsing a condition
-   completer for a branch (vs a nullification completer for a
-   computational instruction.  */
+   (for encoding in instrutions) of the given completer.  */
 
 static int
-pa_parse_nonneg_add_cmpltr (s, isbranch)
+pa_parse_nonneg_add_cmpltr (s)
      char **s;
-     int isbranch;
 {
   int cmpltr;
   char *name = *s + 1;
   char c;
   char *save_s = *s;
+  int nullify = 0;
 
   cmpltr = 0;
   if (**s == ',')
@@ -5717,9 +5713,10 @@ pa_parse_nonneg_add_cmpltr (s, isbranch)
        }
       /* If we have something like addb,n then there is no condition
          completer.  */
-      else if (strcasecmp (name, "n") == 0 && isbranch)
+      else if (strcasecmp (name, "n") == 0)
        {
          cmpltr = 0;
+         nullify = 1;
        }
       else
        {
@@ -5729,28 +5726,24 @@ pa_parse_nonneg_add_cmpltr (s, isbranch)
     }
 
   /* Reset pointers if this was really a ,n for a branch instruction.  */
-  if (cmpltr == 0 && *name == 'n' && isbranch)
+  if (nullify)
     *s = save_s;
 
   return cmpltr;
 }
 
 /* Parse a negated addition completer returning the number
-   (for encoding in instrutions) of the given completer.
-
-   ISBRANCH specifies whether or not this is parsing a condition
-   completer for a branch (vs a nullification completer for a
-   computational instruction).  */
+   (for encoding in instrutions) of the given completer.  */
 
 static int
-pa_parse_neg_add_cmpltr (s, isbranch)
+pa_parse_neg_add_cmpltr (s)
      char **s;
-     int isbranch;
 {
   int cmpltr;
   char *name = *s + 1;
   char c;
   char *save_s = *s;
+  int nullify = 0;
 
   cmpltr = 0;
   if (**s == ',')
@@ -5794,9 +5787,10 @@ pa_parse_neg_add_cmpltr (s, isbranch)
        }
       /* If we have something like addb,n then there is no condition
          completer.  */
-      else if (strcasecmp (name, "n") == 0 && isbranch)
+      else if (strcasecmp (name, "n") == 0)
        {
          cmpltr = 0;
+         nullify = 1;
        }
       else
        {
@@ -5806,7 +5800,7 @@ pa_parse_neg_add_cmpltr (s, isbranch)
     }
 
   /* Reset pointers if this was really a ,n for a branch instruction.  */
-  if (cmpltr == 0 && *name == 'n' && isbranch)
+  if (nullify)
     *s = save_s;
 
   return cmpltr;
@@ -6323,7 +6317,7 @@ pa_callinfo (unused)
   demand_empty_rest_of_line ();
 }
 
-#if !(defined (OBJ_ELF) && defined (TE_LINUX))
+#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
 /* Switch to the text space.  Like s_text, but delete our
    label when finished.  */
 static void
@@ -6403,7 +6397,7 @@ pa_comm (unused)
     }
   demand_empty_rest_of_line ();
 }
-#endif /* !(defined (OBJ_ELF) && defined (TE_LINUX)) */
+#endif /* !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) */
 
 /* Process a .END pseudo-op.  */
 
@@ -6844,7 +6838,7 @@ pa_import (unused)
        {
          /* Sigh.  To be compatable with the HP assembler and to help
             poorly written assembly code, we assign a type based on
-            the the current segment.  Note only BSF_FUNCTION really
+            the current segment.  Note only BSF_FUNCTION really
             matters, we do not need to set the full SYMBOL_TYPE_* info.  */
          if (now_seg == text_section)
            symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION;
@@ -8214,11 +8208,11 @@ pa_stringer (append_zero)
                s++;
                for (num_digit = 0, number = 0, dg = *s;
                     num_digit < 2
-                    && (isdigit (dg) || (dg >= 'a' && dg <= 'f')
+                    && (ISDIGIT (dg) || (dg >= 'a' && dg <= 'f')
                         || (dg >= 'A' && dg <= 'F'));
                     num_digit++)
                  {
-                   if (isdigit (dg))
+                   if (ISDIGIT (dg))
                      number = number * 16 + dg - '0';
                    else if (dg >= 'a' && dg <= 'f')
                      number = number * 16 + dg - 'a' + 10;
@@ -8384,6 +8378,7 @@ int
 hppa_fix_adjustable (fixp)
      fixS *fixp;
 {
+  reloc_type code;
   struct hppa_fix_struct *hppa_fix;
 
   hppa_fix = (struct hppa_fix_struct *) fixp->tc_fix_data;
@@ -8395,15 +8390,45 @@ hppa_fix_adjustable (fixp)
 #endif
 
 #ifdef OBJ_ELF
-  if (fixp->fx_r_type == (int) R_PARISC_GNU_VTINHERIT
-      || fixp->fx_r_type ==  (int) R_PARISC_GNU_VTENTRY)
-    return 0;
+  /* LR/RR selectors are implicitly used for a number of different relocation
+     types.  We must ensure that none of these types are adjusted (see below)
+     even if they occur with a different selector.  */
+  code = elf_hppa_reloc_final_type (stdoutput, fixp->fx_r_type,
+                                   hppa_fix->fx_r_format,
+                                   hppa_fix->fx_r_field);
+
+  switch (code)
+    {
+    /* Relocation types which use e_lrsel.  */
+    case R_PARISC_DIR21L:
+    case R_PARISC_DLTREL21L:
+    case R_PARISC_DPREL21L:
+    case R_PARISC_PLTOFF21L:
+
+    /* Relocation types which use e_rrsel.  */
+    case R_PARISC_DIR14R:
+    case R_PARISC_DIR14DR:
+    case R_PARISC_DIR14WR:
+    case R_PARISC_DIR17R:
+    case R_PARISC_DLTREL14R:
+    case R_PARISC_DLTREL14DR:
+    case R_PARISC_DLTREL14WR:
+    case R_PARISC_DPREL14R:
+    case R_PARISC_DPREL14DR:
+    case R_PARISC_DPREL14WR:
+    case R_PARISC_PLTOFF14R:
+    case R_PARISC_PLTOFF14DR:
+    case R_PARISC_PLTOFF14WR:
+
+    /* Other types that we reject for reduction.  */
+    case R_PARISC_GNU_VTENTRY:
+    case R_PARISC_GNU_VTINHERIT:
+      return 0;
+    default:
+      break;
+    }
 #endif
 
-  if (fixp->fx_addsy && (S_IS_EXTERNAL (fixp->fx_addsy)
-                        || S_IS_WEAK (fixp->fx_addsy)))
-    return 0;
-
   /* Reject reductions of symbols in sym1-sym2 expressions when
      the fixup will occur in a CODE subspace.
 
@@ -8413,11 +8438,7 @@ hppa_fix_adjustable (fixp)
   if (fixp->fx_addsy
       && fixp->fx_subsy
       && (hppa_fix->segment->flags & SEC_CODE))
-    {
-      /* Apparently sy_used_in_reloc never gets set for sub symbols.  */
-      symbol_mark_used_in_reloc (fixp->fx_subsy);
-      return 0;
-    }
+    return 0;
 
   /* We can't adjust any relocs that use LR% and RR% field selectors.
 
@@ -8507,11 +8528,11 @@ hppa_force_relocation (fixp)
 
   /* Ensure we emit a relocation for global symbols so that dynamic
      linking works.  */
-  if (S_IS_EXTERNAL (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy))
+  if (S_FORCE_RELOC (fixp->fx_addsy, 1))
     return 1;
 
   /* It is necessary to force PC-relative calls/jumps to have a relocation
-     entry if they're going to need either a argument relocation or long
+     entry if they're going to need either an argument relocation or long
      call stub.  */
   if (fixp->fx_pcrel
       && arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy),
@@ -8521,15 +8542,27 @@ hppa_force_relocation (fixp)
   /* Now check to see if we're going to need a long-branch stub.  */
   if (fixp->fx_r_type == (int) R_HPPA_PCREL_CALL)
     {
-      valueT distance;
+      long pc = md_pcrel_from (fixp);
+      valueT distance, min_stub_distance;
 
-      distance = (fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy)
-                 - md_pcrel_from (fixp) - 8);
-      if (distance + 8388608 >= 16777216
-         || (hppa_fixp->fx_r_format == 17 && distance + 262144 >= 524288)
-#ifdef OBJ_ELF
-         || (hppa_fixp->fx_r_format == 12 && distance + 8192 >= 16384)
+      distance = fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy) - pc - 8;
+
+      /* Distance to the closest possible stub.  This will detect most
+        but not all circumstances where a stub will not work.  */
+      min_stub_distance = pc + 16;
+#ifdef OBJ_SOM
+      if (last_call_info != NULL)
+       min_stub_distance -= S_GET_VALUE (last_call_info->start_symbol);
 #endif
+
+      if ((distance + 8388608 >= 16777216
+          && min_stub_distance <= 8388608)
+         || (hppa_fixp->fx_r_format == 17
+             && distance + 262144 >= 524288
+             && min_stub_distance <= 262144)
+         || (hppa_fixp->fx_r_format == 12
+             && distance + 8192 >= 16384
+             && min_stub_distance <= 8192)
          )
        return 1;
     }
@@ -8544,7 +8577,7 @@ hppa_force_relocation (fixp)
 /* Now for some ELF specific code.  FIXME.  */
 #ifdef OBJ_ELF
 /* Mark the end of a function so that it's possible to compute
-   the size of the function in hppa_elf_final_processing.  */
+   the size of the function in elf_hppa_final_processing.  */
 
 static void
 hppa_elf_mark_end_of_function ()
This page took 0.039345 seconds and 4 git commands to generate.