2000-12-03 Kazu Hirata <kazu@hxi.com>
[deliverable/binutils-gdb.git] / gas / config / tc-hppa.c
index c78d9132559a6b696e83f22738b0bf597d132eb3..2f889b284d5cdbb04b494c03499d777fe3ddf4ee 100644 (file)
@@ -42,7 +42,6 @@ error only one of OBJ_ELF and OBJ_SOM can be defined
    then we want to use the assembler support for compact line numbers.  */
 #ifdef OBJ_ELF
 #include "dwarf2dbg.h"
-struct dwarf2_line_info debug_line;
 
 /* A "convient" place to put object file dependencies which do
    not need to be seen outside of tc-hppa.c.  */
@@ -1492,20 +1491,7 @@ md_assemble (str)
                  the_insn.format, the_insn.arg_reloc, NULL);
 
 #ifdef OBJ_ELF
-  if (debug_type == DEBUG_DWARF2)
-    {
-      bfd_vma addr;
-
-      /* First update the notion of the current source line.  */
-      dwarf2_where (&debug_line);
-
-      /* We want the offset of the start of this instruction within the
-        the current frag.  */
-      addr = frag_now->fr_address + frag_now_fix () - 4;
-
-      /* And record the information.  */
-      dwarf2_gen_line_info (addr, &debug_line);
-    }
+  dwarf2_emit_insn (4);
 #endif
 }
 
@@ -4011,7 +3997,10 @@ tc_gen_reloc (section, fixp)
                               symbol_get_bfdsym (fixp->fx_addsy));
 
   if (codes == NULL)
-    abort ();
+    {
+      as_bad (_("Cannot handle fixup at %s:%d"), fixp->fx_file, fixp->fx_line);
+      abort ();
+    }
 
   for (n_relocs = 0; codes[n_relocs]; n_relocs++)
     ;
@@ -4272,7 +4261,7 @@ struct option md_longopts[] = {
 #endif
   {NULL, no_argument, NULL, 0}
 };
-size_t md_longopts_size = sizeof(md_longopts);
+size_t md_longopts_size = sizeof (md_longopts);
 
 int
 md_parse_option (c, arg)
@@ -4323,8 +4312,10 @@ md_undefined_symbol (name)
 }
 
 #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
+#define nonzero_dibits(x) \
+  ((x) | (((x) & 0x55555555) << 1) | (((x) & 0xAAAAAAAA) >> 1))
 #define arg_reloc_stub_needed(CALLER, CALLEE) \
-  ((CALLEE) && (CALLER) && ((CALLEE) != (CALLER)))
+  (((CALLER) ^ (CALLEE)) & nonzero_dibits (CALLER) & nonzero_dibits (CALLEE))
 #else
 #define arg_reloc_stub_needed(CALLER, CALLEE) 0
 #endif
@@ -4336,12 +4327,11 @@ md_apply_fix (fixP, valp)
      fixS *fixP;
      valueT *valp;
 {
-  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+  unsigned char *buf;
   struct hppa_fix_struct *hppa_fixP;
   offsetT new_val;
-  int insn, val;
+  int insn, val, fmt;
 
-  hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
   /* 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.  */
@@ -4368,177 +4358,185 @@ md_apply_fix (fixP, valp)
     return 1;
 #endif
 
-  insn = bfd_get_32 (stdoutput, (unsigned char *) buf);
   /* There should have been an HPPA specific fixup associated
      with the GAS fixup.  */
-  if (hppa_fixP)
+  hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
+  if (hppa_fixP == NULL)
     {
-      int fmt = bfd_hppa_insn2fmt (stdoutput, insn);
-
-      /* If there is a symbol associated with this fixup, then it's something
-        which will need a SOM relocation (except for some PC-relative relocs).
-        In such cases we should treat the "val" or "addend" as zero since it
-        will be added in as needed from fx_offset in tc_gen_reloc.  */
-      if ((fixP->fx_addsy != NULL
-          || fixP->fx_r_type == (int) R_HPPA_NONE)
+      printf (_("no hppa_fixup entry for fixup type 0x%x at %s:%d"),
+             fixP->fx_r_type, fixP->fx_file, fixP->fx_line);
+      return 0;
+    }
+
+  buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+  insn = bfd_get_32 (stdoutput, buf);
+  fmt = bfd_hppa_insn2fmt (stdoutput, insn);
+
+  /* If there is a symbol associated with this fixup, then it's something
+     which will need a SOM relocation (except for some PC-relative relocs).
+     In such cases we should treat the "val" or "addend" as zero since it
+     will be added in as needed from fx_offset in tc_gen_reloc.  */
+  if ((fixP->fx_addsy != NULL
+       || fixP->fx_r_type == (int) R_HPPA_NONE)
 #ifdef OBJ_SOM
-         && fmt != 32
+      && fmt != 32
 #endif
-         )
-       new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0);
+      )
+    new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0);
 #ifdef OBJ_SOM
-      /* These field selectors imply that we do not want an addend.  */
-      else if (hppa_fixP->fx_r_field == e_psel
-              || hppa_fixP->fx_r_field == e_rpsel
-              || hppa_fixP->fx_r_field == e_lpsel
-              || hppa_fixP->fx_r_field == e_tsel
-              || 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 truely 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);
+  /* These field selectors imply that we do not want an addend.  */
+  else if (hppa_fixP->fx_r_field == e_psel
+          || hppa_fixP->fx_r_field == e_rpsel
+          || hppa_fixP->fx_r_field == e_lpsel
+          || hppa_fixP->fx_r_field == e_tsel
+          || 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);
-
-      /* Handle pc-relative exceptions from above.  */
-      if ((fmt == 12 || fmt == 17 || fmt == 22)
-         && fixP->fx_addsy
-         && fixP->fx_pcrel
-         && !arg_reloc_stub_needed (symbol_arg_reloc_info (fixP->fx_addsy),
-                                    hppa_fixP->fx_arg_reloc)
-         && ((*valp + 8192) < 16384
-             || (fmt == 17 && (*valp + 262144) < 524288)
-             || (fmt == 22 && (*valp + 8388608) < 16777216))
-         && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment
-         && !(fixP->fx_subsy
-              && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment))
-       {
-         new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field);
-       }
+  else
+    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)
+      && fixP->fx_addsy
+      && fixP->fx_pcrel
+      && !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))
+#endif
+#ifdef OBJ_SOM
+      && (*valp - 8 + 262144 < 524288
+         || (fmt == 22 && *valp - 8 + 8388608 < 16777216))
+#endif
+      && !S_IS_EXTERNAL (fixP->fx_addsy)
+      && !S_IS_WEAK (fixP->fx_addsy)
+      && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment
+      && !(fixP->fx_subsy
+          && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment))
+    {
+      new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field);
+    }
 
-      switch (fmt)
-       {
-       case 10:
-         CHECK_FIELD (new_val, 8191, -8192, 0);
-         val = new_val;
+  switch (fmt)
+    {
+    case 10:
+      CHECK_FIELD (new_val, 8191, -8192, 0);
+      val = new_val;
 
-         insn = (insn & ~ 0x3ff1) | (((val & 0x1ff8) << 1)
-                                     | ((val & 0x2000) >> 13));
-         break;
-       case -11:
-         CHECK_FIELD (new_val, 8191, -8192, 0);
-         val = new_val;
+      insn = (insn & ~ 0x3ff1) | (((val & 0x1ff8) << 1)
+                                 | ((val & 0x2000) >> 13));
+      break;
+    case -11:
+      CHECK_FIELD (new_val, 8191, -8192, 0);
+      val = new_val;
 
-         insn = (insn & ~ 0x3ff9) | (((val & 0x1ffc) << 1)
-                                     | ((val & 0x2000) >> 13));
-         break;
-       /* Handle all opcodes with the 'j' operand type.  */
-       case 14:
-         CHECK_FIELD (new_val, 8191, -8192, 0);
-         val = new_val;
+      insn = (insn & ~ 0x3ff9) | (((val & 0x1ffc) << 1)
+                                 | ((val & 0x2000) >> 13));
+      break;
+      /* Handle all opcodes with the 'j' operand type.  */
+    case 14:
+      CHECK_FIELD (new_val, 8191, -8192, 0);
+      val = new_val;
 
-         insn = ((insn & ~ 0x3fff) | low_sign_unext (val, 14));
-         break;
+      insn = ((insn & ~ 0x3fff) | low_sign_unext (val, 14));
+      break;
 
-       /* Handle all opcodes with the 'k' operand type.  */
-       case 21:
-         CHECK_FIELD (new_val, 1048575, -1048576, 0);
-         val = new_val;
+      /* Handle all opcodes with the 'k' operand type.  */
+    case 21:
+      CHECK_FIELD (new_val, 1048575, -1048576, 0);
+      val = new_val;
 
-         insn = (insn & ~ 0x1fffff) | re_assemble_21 (val);
-         break;
+      insn = (insn & ~ 0x1fffff) | re_assemble_21 (val);
+      break;
 
-       /* Handle all the opcodes with the 'i' operand type.  */
-       case 11:
-         CHECK_FIELD (new_val, 1023, -1023, 0);
-         val = new_val;
+      /* Handle all the opcodes with the 'i' operand type.  */
+    case 11:
+      CHECK_FIELD (new_val, 1023, -1023, 0);
+      val = new_val;
 
-         insn = (insn & ~ 0x7ff) | low_sign_unext (val, 11);
-         break;
+      insn = (insn & ~ 0x7ff) | low_sign_unext (val, 11);
+      break;
 
-       /* Handle all the opcodes with the 'w' operand type.  */
-       case 12:
-         CHECK_FIELD (new_val, 8199, -8184, 0);
-         val = new_val;
+      /* Handle all the opcodes with the 'w' operand type.  */
+    case 12:
+      CHECK_FIELD (new_val - 8, 8191, -8192, 0);
+      val = new_val - 8;
 
-         insn = (insn & ~ 0x1ffd) | re_assemble_12 ((val - 8) >> 2);
-         break;
+      insn = (insn & ~ 0x1ffd) | re_assemble_12 (val >> 2);
+      break;
 
-       /* Handle some of the opcodes with the 'W' operand type.  */
-       case 17:
-         {
-           offsetT distance = *valp;
+      /* Handle some of the opcodes with the 'W' operand type.  */
+    case 17:
+      {
+       offsetT distance = *valp;
 
-           /* If this is an absolute branch (ie no link) with an out of
-              range target, then we want to complain.  */
-           if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
-               && (insn & 0xffe00000) == 0xe8000000)
-             CHECK_FIELD (distance, 262143, -262144, 0);
+       /* If this is an absolute branch (ie no link) with an out of
+          range target, then we want to complain.  */
+       if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
+           && (insn & 0xffe00000) == 0xe8000000)
+         CHECK_FIELD (distance - 8, 262143, -262144, 0);
 
-           CHECK_FIELD (new_val, 262143, -262144, 0);
-           val = new_val;
+       CHECK_FIELD (new_val - 8, 262143, -262144, 0);
+       val = new_val - 8;
 
-           insn = (insn & ~ 0x1f1ffd) | re_assemble_17 ((val - 8) >> 2);
-           break;
-         }
+       insn = (insn & ~ 0x1f1ffd) | re_assemble_17 (val >> 2);
+       break;
+      }
 
-       case 22:
-         {
-           offsetT distance = *valp;
+    case 22:
+      {
+       offsetT distance = *valp;
 
-           /* If this is an absolute branch (ie no link) with an out of
-              range target, then we want to complain.  */
-           if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
-               && (insn & 0xffe00000) == 0xe8000000)
-             CHECK_FIELD (distance, 8388607, -8388608, 0);
+       /* If this is an absolute branch (ie no link) with an out of
+          range target, then we want to complain.  */
+       if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
+           && (insn & 0xffe00000) == 0xe8000000)
+         CHECK_FIELD (distance - 8, 8388607, -8388608, 0);
 
-           CHECK_FIELD (new_val, 8388607, -8388608, 0);
-           val = new_val;
+       CHECK_FIELD (new_val - 8, 8388607, -8388608, 0);
+       val = new_val - 8;
 
-           insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 ((val - 8) >> 2);
-           break;
-         }
-
-       case -10:
-         val = new_val;
-         insn = (insn & ~ 0xfff1) | re_assemble_16 (val & -8);
-         break;
+       insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 (val >> 2);
+       break;
+      }
 
-       case -16:
-         val = new_val;
-         insn = (insn & ~ 0xfff9) | re_assemble_16 (val & -4);
-         break;
+    case -10:
+      val = new_val;
+      insn = (insn & ~ 0xfff1) | re_assemble_16 (val & -8);
+      break;
 
-       case 16:
-         val = new_val;
-         insn = (insn & ~ 0xffff) | re_assemble_16 (val);
-         break;
+    case -16:
+      val = new_val;
+      insn = (insn & ~ 0xfff9) | re_assemble_16 (val & -4);
+      break;
 
-       case 32:
-         insn = new_val;
-         break;
+    case 16:
+      val = new_val;
+      insn = (insn & ~ 0xffff) | re_assemble_16 (val);
+      break;
 
-       default:
-         as_bad (_("Unknown relocation encountered in md_apply_fix."));
-         return 0;
-       }
+    case 32:
+      insn = new_val;
+      break;
 
-      /* Insert the relocation.  */
-      bfd_put_32 (stdoutput, insn, (unsigned char *) buf);
-      return 1;
-    }
-  else
-    {
-      printf (_("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n"),
-             (unsigned int) fixP, fixP->fx_r_type);
+    default:
+      as_bad (_("Unknown relocation encountered in md_apply_fix."));
       return 0;
     }
+
+  /* Insert the relocation.  */
+  bfd_put_32 (stdoutput, insn, buf);
+  return 1;
 }
 
 /* Exactly what point is a PC-relative offset relative TO?
@@ -4766,7 +4764,7 @@ pa_parse_number (s, is_float)
   return 0;
 }
 
-#define REG_NAME_CNT   (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
+#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
 
 /* Given NAME, find the register number associated with that name, return
    the integer value associated with the given name or -1 on failure.  */
@@ -5827,6 +5825,7 @@ pa_parse_addb_64_cmpltr (s)
    alignment of the subspace if necessary.  */
 static void
 pa_align (bytes)
+     int bytes;
 {
   /* We must have a valid space and subspace.  */
   pa_check_current_space_and_subspace ();
@@ -8312,6 +8311,10 @@ hppa_fix_adjustable (fixp)
     return 0;
 #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.
 
@@ -8372,19 +8375,15 @@ hppa_fix_adjustable (fixp)
       || hppa_fix->fx_r_field == e_lpsel)
     return 0;
 
-  if (fixp->fx_addsy && (S_IS_EXTERNAL (fixp->fx_addsy)
-                        || S_IS_WEAK (fixp->fx_addsy)))
-    return 0;
-
   /* Reject absolute calls (jumps).  */
   if (hppa_fix->fx_r_type == R_HPPA_ABS_CALL)
     return 0;
 
   /* Reject reductions of function symbols.  */
-  if (fixp->fx_addsy == 0 || ! S_IS_FUNCTION (fixp->fx_addsy))
-    return 1;
+  if (fixp->fx_addsy != 0 && S_IS_FUNCTION (fixp->fx_addsy))
+    return 0;
 
-  return 0;
+  return 1;
 }
 
 /* Return nonzero if the fixup in FIXP will require a relocation,
@@ -8396,7 +8395,6 @@ hppa_force_relocation (fixp)
      struct fix *fixp;
 {
   struct hppa_fix_struct *hppa_fixp;
-  int distance;
 
   hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data;
 #ifdef OBJ_SOM
@@ -8416,20 +8414,36 @@ hppa_force_relocation (fixp)
     return 1;
 #endif
 
+  assert (fixp->fx_addsy != NULL);
+
+  /* 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))
+    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
-     call stub.  FIXME.  Can't we need the same for absolute calls?  */
-  if (fixp->fx_pcrel && fixp->fx_addsy
-      && (arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy),
-                                hppa_fixp->fx_arg_reloc)))
+     call stub.  */
+  if (fixp->fx_pcrel
+      && arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy),
+                               hppa_fixp->fx_arg_reloc))
     return 1;
 
-  distance = (fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy)
-             - md_pcrel_from (fixp));
-  /* Now check and see if we're going to need a long-branch stub.  */
-  if (fixp->fx_r_type == (int) R_HPPA_PCREL_CALL
-      && (distance > 262143 || distance < -262144))
-    return 1;
+  /* 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;
+
+      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)
+#endif
+         )
+       return 1;
+    }
 
   if (fixp->fx_r_type == (int) R_HPPA_ABS_CALL)
     return 1;
@@ -8525,13 +8539,6 @@ elf_hppa_final_processing ()
     }
 }
 
-void
-pa_end_of_source ()
-{
-  if (debug_type == DEBUG_DWARF2)
-    dwarf2_finish ();
-}
-
 static void
 pa_vtable_entry (ignore)
      int ignore ATTRIBUTE_UNUSED;
This page took 0.033351 seconds and 4 git commands to generate.