* config/tc-mips.c (macro): Pass NULL for expression argument to
authorIan Lance Taylor <ian@airs.com>
Thu, 7 Apr 1994 18:33:09 +0000 (18:33 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 7 Apr 1994 18:33:09 +0000 (18:33 +0000)
macro_build for nori case.
(SWITCH_TABLE): Define.
(mips_force_relocation): Force a relocation for a switch table
entry.
(md_apply_fix): Write switch table entry value into file.
(tc_gen_reloc): Use BFD_RELOC_GPREL32 for a switch table entry,
and set the addend to the difference between the reloc address and
the subtrahend.

gas/ChangeLog
gas/config/tc-mips.c

index 1bc9f815f587c297c05a0e7ffbaf49ea45f372d0..8d09333851400038d28d12c41bacd81ded10e140 100644 (file)
@@ -1,3 +1,15 @@
+Thu Apr  7 14:28:30 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * config/tc-mips.c (macro): Pass NULL for expression argument to
+       macro_build for nori case.
+       (SWITCH_TABLE): Define.
+       (mips_force_relocation): Force a relocation for a switch table
+       entry.
+       (md_apply_fix): Write switch table entry value into file.
+       (tc_gen_reloc): Use BFD_RELOC_GPREL32 for a switch table entry,
+       and set the addend to the difference between the reloc address and
+       the subtrahend.
+
 Thu Apr  7 10:38:18 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
 
        * config/tc-hppa.h (elf_tc_symbol): Delete.  No longer used.
index b11831651dc33d55885514ee4835e14104893149..e13d74bdb72d747eb9316cb61d8228520b92c5dc 100644 (file)
@@ -1789,7 +1789,7 @@ macro (ip)
            {
              macro_build ((char *) NULL, &icnt, &imm_expr, "ori", "t,r,i",
                           treg, sreg, (int) BFD_RELOC_LO16);
-             macro_build ((char *) NULL, &icnt, &imm_expr, "nor", "d,v,t",
+             macro_build ((char *) NULL, &icnt, NULL, "nor", "d,v,t",
                           treg, treg, 0);
            }
          return;
@@ -5063,15 +5063,29 @@ cons_fix_new_mips (frag, where, nbytes, exp)
               nbytes == 2 ? BFD_RELOC_16 : BFD_RELOC_32);
 }
 
+/* When generating embedded PIC code we need to use a special
+   relocation to represent the difference of two symbols in the .text
+   section (switch tables use a difference of this sort).  See
+   include/coff/mips.h for details.  This macro checks whether this
+   fixup requires the special reloc.  */
+#define SWITCH_TABLE(fixp) \
+  ((fixp)->fx_r_type == BFD_RELOC_32 \
+   && (fixp)->fx_addsy != NULL \
+   && (fixp)->fx_subsy != NULL \
+   && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \
+   && S_GET_SEGMENT ((fixp)->fx_subsy) == text_section)
+
 /* When generating embedded PIC code we must keep all PC relative
-   relocations, in case the linker has to relax a call.  */
+   relocations, in case the linker has to relax a call.  We also need
+   to keep relocations for switch table entries.  */
 
 /*ARGSUSED*/
 int
 mips_force_relocation (fixp)
      fixS *fixp;
 {
-  return fixp->fx_pcrel && mips_pic == EMBEDDED_PIC;
+  return (mips_pic == EMBEDDED_PIC
+         && (fixp->fx_pcrel || SWITCH_TABLE (fixp)));
 }
 
 /* Apply a fixup to the object file.  */
@@ -5108,8 +5122,11 @@ md_apply_fix (fixP, valueP)
     case BFD_RELOC_32:
       /* If we are deleting this reloc entry, we must fill in the
         value now.  This can happen if we have a .word which is not
-        resolved when it appears but is later defined.  */
-      if (fixP->fx_done)
+        resolved when it appears but is later defined.  We also need
+        to fill in the value if this is an embedded PIC switch table
+        entry.  */
+      if (fixP->fx_done
+         || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
        md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                            value, 4);
       break;
@@ -5936,7 +5953,20 @@ tc_gen_reloc (section, fixp)
 
   reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
-  if (fixp->fx_pcrel == 0)
+
+  if (mips_pic == EMBEDDED_PIC
+      && SWITCH_TABLE (fixp))
+    {
+      /* For a switch table entry we use a special reloc.  The addend
+        is actually the difference between the reloc address and the
+        subtrahend.  */
+      reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
+#ifndef OBJ_ECOFF
+ #error Double check fx_r_type here
+#endif
+      fixp->fx_r_type = BFD_RELOC_GPREL32;
+    }
+  else if (fixp->fx_pcrel == 0)
     reloc->addend = fixp->fx_addnumber;
   else
     {