From: Ian Lance Taylor Date: Tue, 5 Apr 1994 19:57:32 +0000 (+0000) Subject: * config/tc-mips.c (mips_ip): For case 'o', when generating X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f3645945cfd49e1e1a33cc4273e4951cf6020202;p=binutils-gdb.git * 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index c8c80a41a23..0c46784bff0 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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, diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 08c5bb600a1..b11831651dc 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -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()