+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,
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;
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. */
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:
/* 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()