* som.c (NO_PCREL_MODES): Define if the system does not define
authorJeff Law <law@redhat.com>
Sun, 19 Sep 1999 18:22:20 +0000 (18:22 +0000)
committerJeff Law <law@redhat.com>
Sun, 19 Sep 1999 18:22:20 +0000 (18:22 +0000)
        R_SHORT_PCREL_MODE.
        (hppa_som_gen_reloc_type): Handle both short and long pcrel branches.
        (som_write_fixups): Eliminate redundant pcrel mode relocs.  Handle
        R_LONG_PCREL_MODE and R_SHORT_PCREL_MODE
        * libhppa.h (dis_assemble_22): New function.
        (bfd_hppa_insn2fmt): Handle long branch.

        * libhppa.h (bfd_hppa_insn2fmt): Decode and handle formats found
        in PA2.0.

bfd/ChangeLog
bfd/libhppa.h
bfd/som.c

index 503f15908720b880571153d227f20dc43b4c329f..ef66d8d80f028eae789c4aebebe115075eec8bfa 100644 (file)
@@ -1,3 +1,16 @@
+Sun Sep 19 12:16:47 1999  Jeffrey A Law  (law@cygnus.com)
+
+       * som.c (NO_PCREL_MODES): Define if the system does not define
+       R_SHORT_PCREL_MODE.
+       (hppa_som_gen_reloc_type): Handle both short and long pcrel branches.
+       (som_write_fixups): Eliminate redundant pcrel mode relocs.  Handle
+       R_LONG_PCREL_MODE and R_SHORT_PCREL_MODE
+       * libhppa.h (dis_assemble_22): New function.
+       (bfd_hppa_insn2fmt): Handle long branch.
+
+        * libhppa.h (bfd_hppa_insn2fmt): Decode and handle formats found
+        in PA2.0.
+
 1999-09-17  Alan Modra  <alan@spri.levels.unisa.edu.au>
 
        * coff-i386.c (coff_i386_reloc_type_lookup): Support BFD_RELOC_16,
index 4ce82ea4e2ef189e1b7cf252312831ce1f24f358..15181088addb72fab58baf12fe551fa64391c71a 100644 (file)
@@ -52,6 +52,10 @@ static INLINE unsigned long assemble_17 (unsigned int, unsigned int,
 static INLINE void dis_assemble_17 (unsigned int, unsigned int *,
                                    unsigned int *, unsigned int *)
      __attribute__ ((__unused__));
+static INLINE void dis_assemble_22 (unsigned int, unsigned int *,
+                                   unsigned int *, unsigned int *,
+                                   unsigned int *)
+     __attribute__ ((__unused__));
 static INLINE unsigned long assemble_21 (unsigned int)
      __attribute ((__unused__));
 static INLINE void dis_assemble_21 (unsigned int, unsigned int *)
@@ -332,6 +336,18 @@ dis_assemble_17 (as17, x, y, z)
   *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
 }
 
+static INLINE void
+dis_assemble_22 (as22, a, b, c, d)
+     unsigned int as22;
+     unsigned int *a, *b, *c, *d;
+{
+
+  *d = (as22 & 0x200000) >> 21;
+  *a = (as22 & 0x1f0000) >> 16;
+  *b = (as22 & 0x0f800) >> 11;
+  *c = (((as22 & 0x00400) >> 10) | ((as22 & 0x3ff) << 1)) & 0x7ff;
+}
+
 static INLINE unsigned long
 assemble_21 (x)
      unsigned int x;
@@ -548,6 +564,15 @@ hppa_field_adjust (value, constant_value, r_field)
 #define BLE    0x39
 #define BE     0x38
 
+#define CMPBDT 0x27
+#define CMPBDF 0x2f
+#define CMPIBD 0x3b
+#define LDD    0x14
+#define STD    0x1c
+#define LDWL   0x17
+#define STWL   0x1f
+#define FDLW    0x16
+#define FSTW    0x1e
   
 /* Given a machine instruction, return its format.
 
@@ -580,6 +605,9 @@ bfd_hppa_insn2fmt (insn)
     case ADDIBF:
     case BVB:
     case BB:
+    case CMPBDT:
+    case CMPBDF:
+    case CMPIBD:
       fmt = 12;
       break;
     case LDO:
@@ -593,9 +621,24 @@ bfd_hppa_insn2fmt (insn)
     case STWM:
       fmt = 14;
       break;
+    case LDWL:
+    case STWL:
+    case FDLW:
+    case FSTW:
+      /* This is a hack.  Unfortunately, format 11 is already taken
+        and we're using integers rather than an enum, so it's hard
+        to describe the 10a format.  */
+      fmt = -11;
+      break;
+    case LDD:
+    case STD:
+      fmt = 10;
+      break;
     case BL:
     case BE:
     case BLE:
+      if ((insn & 0x00008000) == 0x00008000)
+       return 22;
       fmt = 17;
       break;
     case LDIL:
index 16a5e4a7cf92f9ad73b5703849be0d11ea23252d..77de9583f933b186b0f8a7a5fd626599978f431e 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -751,6 +751,7 @@ static const int comp3_opcodes[] =
 
 /* And these first appeared in hpux10.  */
 #ifndef R_SHORT_PCREL_MODE
+#define NO_PCREL_MODES
 #define R_SHORT_PCREL_MODE 0x3e
 #endif
 
@@ -1684,9 +1685,28 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff, sym)
 
     case R_HPPA_NONE:
     case R_HPPA_ABS_CALL:
-    case R_HPPA_PCREL_CALL:
       /* Right now we can default all these.  */
       break;
+
+    case R_HPPA_PCREL_CALL:
+      {
+#ifndef NO_PCREL_MODES
+       /* If we have short and long pcrel modes, then generate the proper
+          mode selector, then the pcrel relocation.  Redundant selectors
+          will be eliminted as the relocs are sized and emitted.  */
+       final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
+       if (!final_types[0])
+         return NULL;
+       if (format == 17)
+         *final_types[0] = R_SHORT_PCREL_MODE;
+       else
+         *final_types[0] = R_LONG_PCREL_MODE;
+       final_types[1] = final_type;
+       final_types[2] = NULL;
+       *final_type = base_type;
+#endif
+       break;
+      }
     }
   return final_types;
 }
@@ -2665,6 +2685,9 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
           subsection = subsection->next)
        {
          int reloc_offset, current_rounding_mode;
+#ifndef NO_PCREL_MODES
+         int current_call_mode;
+#endif
 
          /* Find a subspace of this space.  */
          if (!som_is_subspace (subsection)
@@ -2699,6 +2722,9 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
          reloc_offset = 0;
          som_initialize_reloc_queue (reloc_queue);
          current_rounding_mode = R_N_MODE;
+#ifndef NO_PCREL_MODES
+         current_call_mode = R_SHORT_PCREL_MODE;
+#endif
 
          /* Translate each BFD relocation into one or more SOM 
             relocations.  */
@@ -2763,6 +2789,10 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                case R_END_TRY:
                case R_N0SEL:
                case R_N1SEL:
+#ifndef NO_PCREL_MODES
+               case R_SHORT_PCREL_MODE:
+               case R_LONG_PCREL_MODE:
+#endif
                  reloc_offset = bfd_reloc->address;
                  break;
 
@@ -2887,6 +2917,19 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                    }
                  break;
 
+#ifndef NO_PCREL_MODES
+               case R_LONG_PCREL_MODE:
+               case R_SHORT_PCREL_MODE:
+                 if (bfd_reloc->howto->type != current_call_mode)
+                   {
+                     bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+                     subspace_reloc_size += 1;
+                     p += 1;
+                     current_call_mode = bfd_reloc->howto->type;
+                   }
+                 break;
+#endif
+
                case R_EXIT:
                case R_ALT_ENTRY:
                case R_FSEL: