* elf32-hppa.c (hppa_elf_gen_reloc_type): Handle 'T' field
authorJeff Law <law@redhat.com>
Tue, 14 Dec 1993 07:36:15 +0000 (07:36 +0000)
committerJeff Law <law@redhat.com>
Tue, 14 Dec 1993 07:36:15 +0000 (07:36 +0000)
        selectors for PIC code.

        * som.c (hppa_som_gen_reloc_type): Handle 'T' field selectors.
        (som_write_fixups): Handle R_DLT_REL, R_FSEL, R_RSEL, R_LSEL
        relocations needed by PIC.

bfd/ChangeLog
bfd/elf32-hppa.c
bfd/som.c

index c29f2fe..b045532 100644 (file)
@@ -1,3 +1,12 @@
+Mon Dec 13 23:34:48 1993  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * elf32-hppa.c (hppa_elf_gen_reloc_type): Handle 'T' field
+       selectors for PIC code.
+
+       * som.c (hppa_som_gen_reloc_type): Handle 'T' field selectors.
+       (som_write_fixups): Handle R_DLT_REL, R_FSEL, R_RSEL, R_LSEL
+       relocations needed by PIC.
+
 Tue Dec  7 15:47:51 1993  Stu Grossman  (grossman at cygnus.com)
 
        * nlmcode.h:  Fixes to avoid compiler warnings...
index b677e4d..4f15c62 100644 (file)
@@ -524,11 +524,15 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field)
            case e_rpsel:
              final_type = R_HPPA_PLABEL_R11;
              break;
-           case e_lpsel:
            case e_tsel:
-           case e_ltsel:
+             final_type = R_HPPA_DLT_11;
+             break;
            case e_rtsel:
+             final_type = R_HPPA_DLT_R11;
+             break;
 
+           case e_lpsel:
+           case e_ltsel:
            case e_lsel:
            case e_lrsel:
            case e_lssel:
@@ -564,10 +568,15 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field)
            case e_rpsel:
              final_type = R_HPPA_PLABEL_R14;
              break;
-           case e_lpsel:
            case e_tsel:
-           case e_ltsel:
+             final_type = R_HPPA_DLT_14;
+             break;
            case e_rtsel:
+             final_type = R_HPPA_DLT_R14;
+             break;
+
+           case e_lpsel:
+           case e_ltsel:
 
            case e_fsel:
            case e_lsel:
@@ -626,6 +635,9 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field)
            case e_lpsel:
              final_type = R_HPPA_PLABEL_L21;
              break;
+           case e_ltsel:
+             final_type = R_HPPA_PLABEL_L21;
+             break;
            case e_rsel:
            case e_rssel:
            case e_rdsel:
@@ -646,6 +658,9 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field)
            case e_psel:
              final_type = R_HPPA_PLABEL_32;
              break;
+           case e_tsel:
+             final_type == R_HPPA_DLT_32;
+             break;
            default:
              UNDEFINED;
              final_type = base_type;
@@ -1561,7 +1576,16 @@ hppa_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd)
         jump after the call returns (GCC optimization).  */
         
       if (insn & 2)
-       insn = BLE_N_XXX_0_0;
+        {
+         insn = BLE_N_XXX_0_0;
+         bfd_put_32 (abfd, insn, hit_data);
+         r_type = R_HPPA_ABS_CALL_17;
+         r_pcrel = 0;
+         insn = hppa_elf_relocate_insn (abfd, input_section, insn,
+                                        addr, symbol_in, sym_value,
+                                        r_addend, r_type, r_format,
+                                        r_field, r_pcrel);
+        }
       else
        {
          unsigned long old_delay_slot_insn = bfd_get_32 (abfd, hit_data + 4);
@@ -1584,16 +1608,29 @@ hppa_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd)
                  new_delay_slot_insn |= ((31 << 21) | (31 << 16));
                  bfd_put_32 (abfd, new_delay_slot_insn, hit_data + 4);
                  insn = BLE_XXX_0_0;
-                 bfd_put_32 (abfd, insn, hit_data);
                  r_type = R_HPPA_ABS_CALL_17;
                  r_pcrel = 0;
                  insn = hppa_elf_relocate_insn (abfd, input_section, insn,
                                                 addr, symbol_in, sym_value,
                                                 r_addend, r_type, r_format,
                                                 r_field, r_pcrel);
-                 bfd_put_32 (abfd, insn, hit_data + 4);
+                 bfd_put_32 (abfd, insn, hit_data);
                  return bfd_reloc_ok;
                }
+              else if (rtn_reg == 31)
+                {
+                  /* The return register is r31, so this is a millicode
+                    call.  Do not perform any instruction reordering.  */
+                 insn = BLE_XXX_0_0;
+                 r_type = R_HPPA_ABS_CALL_17;
+                 r_pcrel = 0;
+                 insn = hppa_elf_relocate_insn (abfd, input_section, insn,
+                                                addr, symbol_in, sym_value,
+                                                r_addend, r_type, r_format,
+                                                r_field, r_pcrel);
+                 bfd_put_32 (abfd, insn, hit_data);
+                 return bfd_reloc_ok;
+                }
              else
                {
                  /* Check to see if the delay slot instruction has a
@@ -1619,6 +1656,20 @@ hppa_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd)
                  return bfd_reloc_ok;
                }
            }
+          else if (rtn_reg == 31)
+            {
+              /* The return register is r31, so this is a millicode call.
+                Perform no instruction reordering in this case.  */
+             insn = BLE_XXX_0_0;
+             r_type = R_HPPA_ABS_CALL_17;
+             r_pcrel = 0;
+             insn = hppa_elf_relocate_insn (abfd, input_section, insn,
+                                            addr, symbol_in, sym_value,
+                                            r_addend, r_type, r_format,
+                                            r_field, r_pcrel);
+             bfd_put_32 (abfd, insn, hit_data);
+             return bfd_reloc_ok;
+            }
          else
            {
              /* Check to see if the delay slot instruction has a
@@ -2363,7 +2414,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry,
                                                          sizeof (asymbol *));
       reloc_entry->sym_ptr_ptr[0] = stub_sym;
       if (reloc_entry->howto->type != R_HPPA_PLABEL_32
-         && (get_opcode(insn) == BLE || get_opcode (insn) == BE))
+         && (get_opcode(insn) == BLE
+             || get_opcode (insn) == BE
+             || get_opcode (insn) == BL))
        reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17);
     }
   else
@@ -2385,7 +2438,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry,
                                                          sizeof (asymbol *));
       reloc_entry->sym_ptr_ptr[0] = stub_sym;
       if (reloc_entry->howto->type != R_HPPA_PLABEL_32
-         && (get_opcode (insn) == BLE || get_opcode (insn) == BE))
+         && (get_opcode (insn) == BLE
+             || get_opcode (insn) == BE
+             || get_opcode (insn) == BL))
        reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17);
 
       /* Generate common code for all stubs.  */
@@ -2796,6 +2851,20 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
   
   if (strcmp (symbol->name, "$$dyncall") == 0)
     dyncall = true;
+
+  /* If we are creating a call from a stub to another stub, then
+     never do the instruction reordering.  We can tell if we are
+     going to be calling one stub from another by the fact that
+     the symbol name has '_stub_' (arg. reloc. stub) or '_lb_stub_'
+     prepended to the name.  Alternatively, the section of the
+     symbol will be '.hppa_linker_stubs'.  */
+
+  if ((strncmp (symbol->name, "_stub_", 6) == 0)
+      || (strncmp (symbol->name, "_lb_stub_", 9) == 0))
+    {
+      BFD_ASSERT (strcmp (symbol->section->name, ".hppa_linker_stubs") == 0);
+      rtn_adjust = false;
+    }
   
   /* Check to see if we modify the return pointer
      in the delay slot of the branch.  */
@@ -2812,6 +2881,8 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
        if (get_opcode (delay_insn) == LDO
            && (((delay_insn & 0x001f0000) >> 16) == rtn_reg))
          rtn_adjust = false;
+        if (milli)
+          rtn_adjust = false;
       }
   }
   
@@ -2896,12 +2967,13 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
          /* 2. Make the call. */
          if (!milli)
            {
-             NEW_INSTRUCTION (stub_entry, BE_N_XXX_0_31);
+             NEW_INSTRUCTION (stub_entry, BE_XXX_0_31);
              hppa_elf_stub_reloc (stub_desc,
                                   abfd,
                                   target_sym,
                                   CURRENT_STUB_OFFSET (stub_entry),
                                   R_HPPA_ABS_CALL_R17);
+             NEW_INSTRUCTION (stub_entry, COPY_2_31);
            }
          else
            {
@@ -2931,12 +3003,13 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
                               CURRENT_STUB_OFFSET (stub_entry),
                               R_HPPA_L21);
          
-         NEW_INSTRUCTION (stub_entry, BE_N_XXX_0_31);
+         NEW_INSTRUCTION (stub_entry, BE_XXX_0_31);
          hppa_elf_stub_reloc (stub_desc,
                               abfd,
                               target_sym,
                               CURRENT_STUB_OFFSET (stub_entry),
                               R_HPPA_ABS_CALL_R17);
+         NEW_INSTRUCTION (stub_entry, COPY_2_31);
        }
     }
   return stub_sym;
index 08ef811..de23ef4 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -1356,11 +1356,18 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_psel:
       case e_lpsel:
       case e_rpsel:
+       final_types[0] = final_type;
+       final_types[1] = NULL;
+       final_types[2] = NULL;
+       *final_type = base_type;
+       break;
+
       case e_tsel:
       case e_ltsel:
       case e_rtsel:
-       final_types[0] = final_type;
-       final_types[1] = NULL;
+       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       *final_types[0] = R_FSEL;
+       final_types[1] = final_type;
        final_types[2] = NULL;
        *final_type = base_type;
        break;
@@ -1409,15 +1416,20 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       if (field == e_psel
          || field == e_lpsel
          || field == e_rpsel)
-         {
-           /* A PLABEL relocation that has a size of 32 bits must
-              be a R_DATA_PLABEL.  All others are R_CODE_PLABELs.  */
-           if (format == 32)
-             *final_type = R_DATA_PLABEL;
-           else
-             *final_type = R_CODE_PLABEL;
-         }
-      /* A relocatoin in the data space is always a full 32bits.  */
+       {
+         /* A PLABEL relocation that has a size of 32 bits must
+            be a R_DATA_PLABEL.  All others are R_CODE_PLABELs.  */
+         if (format == 32)
+           *final_type = R_DATA_PLABEL;
+         else
+           *final_type = R_CODE_PLABEL;
+       }
+      /* PIC stuff.  */
+      else if (field == e_tsel
+         || field == e_ltsel
+         || field == e_rtsel)
+       *final_type = R_DLT_REL;
+      /* A relocation in the data space is always a full 32bits.  */
       else if (format == 32)
        *final_type = R_DATA_ONE_SYMBOL;
 
@@ -2197,6 +2209,9 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                case R_S_MODE:
                case R_D_MODE:
                case R_R_MODE:
+               case R_FSEL:
+               case R_LSEL:
+               case R_RSEL:
                  reloc_offset = bfd_reloc->address;
                  break;
 
@@ -2249,6 +2264,7 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                case R_DATA_ONE_SYMBOL:
                case R_DATA_PLABEL:
                case R_CODE_PLABEL:
+               case R_DLT_REL:
                  /* Account for any addend.  */
                  if (bfd_reloc->addend)
                    p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
@@ -2306,6 +2322,14 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                    }
                  break;
 
+               case R_FSEL:
+               case R_LSEL:
+               case R_RSEL:
+                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+                 subspace_reloc_size += 1;
+                 p += 1;
+                 break;
+
                /* Put a "R_RESERVED" relocation in the stream if
                   we hit something we do not understand.  The linker
                   will complain loudly if this ever happens.  */