* config/tc-mips.c (mips_ip): For case 'o', when generating
authorIan Lance Taylor <ian@airs.com>
Tue, 5 Apr 1994 19:57:32 +0000 (19:57 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 5 Apr 1994 19:57:32 +0000 (19:57 +0000)
embedded PIC code, accept the difference between two local symbols
as being constant.
(mips_force_relocation): Only force a reloc to be generated for a
PC relative fixup.
(md_apply_fix): For BFD_RELOC_32 and BFD_RELOC_LO16, put the fixup
value into the file if the fixup will not generate a reloc.

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

index c8c80a4..0c46784 100644 (file)
@@ -1,3 +1,13 @@
+Tue Apr  5 15:48:03 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * config/tc-mips.c (mips_ip): For case 'o', when generating
+       embedded PIC code, accept the difference between two local symbols
+       as being constant.
+       (mips_force_relocation): Only force a reloc to be generated for a
+       PC relative fixup.
+       (md_apply_fix): For BFD_RELOC_32 and BFD_RELOC_LO16, put the fixup
+       value into the file if the fixup will not generate a reloc.
+
 Tue Apr  5 11:14:14 1994  Ken Raeburn  (raeburn@rtl.cygnus.com)
 
        * config/tc-sparc.c (s_reserve): If section passed isn't bss,
index 08c5bb6..b118316 100644 (file)
@@ -4534,14 +4534,25 @@ mips_ip (str, ip)
 
            case 'o':           /* 16 bit offset */
              c = my_getSmallExpression (&offset_expr, s);
-             /*
-              * If this value won't fit into a 16 bit offset, then
-              * go find a macro that will generate the 32 bit offset
-              * code pattern.
-              */
-             if (offset_expr.X_op != O_constant
-                 || offset_expr.X_add_number >= 0x8000
-                 || offset_expr.X_add_number < -0x8000)
+
+             /* If this value won't fit into a 16 bit offset, then go
+                find a macro that will generate the 32 bit offset
+                code pattern.  As a special hack, we accept the
+                difference of two local symbols as a constant.  This
+                is required to suppose embedded PIC switches, which
+                use an instruction which looks like
+                    lw $4,$L12-$LS12($4)
+                The problem with handling this in a more general
+                fashion is that the macro function doesn't expect to
+                see anything which can be handled in a single
+                constant instruction.  */
+             if ((offset_expr.X_op != O_constant
+                  || offset_expr.X_add_number >= 0x8000
+                  || offset_expr.X_add_number < -0x8000)
+                 && (mips_pic != EMBEDDED_PIC
+                     || offset_expr.X_op != O_subtract
+                     || ! S_IS_LOCAL (offset_expr.X_add_symbol)
+                     || ! S_IS_LOCAL (offset_expr.X_op_symbol)))
                break;
 
              offset_reloc = BFD_RELOC_LO16;
@@ -5060,7 +5071,7 @@ int
 mips_force_relocation (fixp)
      fixS *fixp;
 {
-  return mips_pic == EMBEDDED_PIC;
+  return fixp->fx_pcrel && mips_pic == EMBEDDED_PIC;
 }
 
 /* Apply a fixup to the object file.  */
@@ -5083,11 +5094,9 @@ md_apply_fix (fixP, valueP)
 
   switch (fixP->fx_r_type)
     {
-    case BFD_RELOC_32:
     case BFD_RELOC_MIPS_JMP:
     case BFD_RELOC_HI16:
     case BFD_RELOC_HI16_S:
-    case BFD_RELOC_LO16:
     case BFD_RELOC_MIPS_GPREL:
     case BFD_RELOC_MIPS_LITERAL:
     case BFD_RELOC_MIPS_CALL16:
@@ -5096,6 +5105,30 @@ md_apply_fix (fixP, valueP)
       /* Nothing needed to do. The value comes from the reloc entry */
       break;
 
+    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)
+       md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+                           value, 4);
+      break;
+
+    case BFD_RELOC_LO16:
+      /* When handling an embedded PIC switch statement, we can wind
+        up deleting a LO16 reloc.  See the 'o' case in mips_ip.  */
+      if (fixP->fx_done)
+       {
+         if (value < -0x8000 || value > 0x7fff)
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         "relocation overflow");
+         buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+         if (byte_order == BIG_ENDIAN)
+           buf += 2;
+         md_number_to_chars (buf, value, 2);
+       }
+      break;
+
     case BFD_RELOC_16_PCREL_S2:
       /*
        * We need to save the bits in the instruction since fixup_segment()