Change target of hppa-netbsd port
[deliverable/binutils-gdb.git] / gas / config / tc-hppa.c
index 9db438f5798960c9ca586db40ee8f16661700ca7..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,
-   2002 Free Software Foundation, Inc.
+   2002, 2003 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -490,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));
@@ -622,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?  */
@@ -642,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},
@@ -652,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},
@@ -667,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},
@@ -679,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
@@ -706,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},
@@ -853,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},
@@ -949,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},
@@ -1014,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},
@@ -2358,7 +2370,6 @@ pa_ip (str)
                          }
                        else if (*s == '*')
                          break;
-                       name = s;
 
                        name = s;
                        while (*s != ',' && *s != ' ' && *s != '\t')
@@ -2420,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;
                      }
@@ -2526,7 +2537,6 @@ pa_ip (str)
                          }
                        else if (*s == '*')
                          break;
-                       name = s;
 
                        name = s;
                        while (*s != ',' && *s != ' ' && *s != '\t')
@@ -2588,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;
@@ -2711,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;
                      }
@@ -2766,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;
                      }
@@ -2878,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;
@@ -3251,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)
@@ -3283,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)
@@ -3314,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)
@@ -3344,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)
@@ -3949,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))
@@ -4419,9 +4429,6 @@ md_apply_fix3 (fixP, valP, seg)
   offsetT new_val;
   int insn, val, fmt;
 
-  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
-    fixP->fx_done = 1;
-
   /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can
      never be "applied" (they are just markers).  Likewise for
      R_HPPA_BEGIN_BRTAB and R_HPPA_END_BRTAB.  */
@@ -4448,6 +4455,9 @@ md_apply_fix3 (fixP, valP, seg)
     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;
@@ -4483,13 +4493,6 @@ md_apply_fix3 (fixP, valP, seg)
           || 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);
@@ -4687,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')
@@ -4826,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);
@@ -6314,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
@@ -6394,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.  */
 
@@ -8426,10 +8429,6 @@ hppa_fix_adjustable (fixp)
     }
 #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.
 
@@ -8439,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.
 
@@ -8533,7 +8528,7 @@ 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
@@ -8547,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;
     }
@@ -8570,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.028785 seconds and 4 git commands to generate.