MIPS/GAS: Fix `.option picX' handling with relaxation

Correct the handling of `.option pic0' and `.option pic2' GAS pseudo-ops
in relaxation and use the setting of `mips_pic' (which these directives
control) as at the time a relaxed frag has been created rather than the
final `mips_pic' setting at the end of the source file processed.

To do so record whether `mips_pic' is NO_PIC or not in the frag itself
and use this information throughout relaxation instead of `mips_pic' to
decide which of NO_PIC or SVR4_PIC to produce machine code for, fixing
code generation and removing a possible fatal failure reproducible with:

$ as -32 --relax-branch -o option-pic-relax-3.o option-pic-relax-3.s
option-pic-relax-3.s: Assembler messages:
option-pic-relax-3.s:7: Warning: relaxed out-of-range branch into a jump
option-pic-relax-3.s: Internal error in cvt_frag_to_fill at .../gas/write.c:490.
Please report this bug.
$

using the test source included, due to a buffer overrun in filling the
variable part of a frag.

Likewise use the `fx_tcbit2' flag of a BFD_RELOC_16_PCREL_S2 fixup to
handle the simple case of substituting an out of range unconditional
branch with an equivalent absolute jump in NO_PIC code.

Retain the current way of VXWORKS_PIC use, which commit 41a1578ed17c
("MIPS/GAS: Sanitize `.option picX' pseudo-op") has forbidden the use of
`.option picX' with.

	gas/
	* config/tc-mips.c (RELAX_ENCODE): Add `PIC' flag.
	(RELAX_PIC): New macro.
	(RELAX_USE_SECOND, RELAX_SECOND_LONGER, RELAX_NOMACRO)
	(RELAX_DELAY_SLOT, RELAX_DELAY_SLOT_16BIT)
	(RELAX_DELAY_SLOT_SIZE_FIRST, RELAX_DELAY_SLOT_SIZE_SECOND):
	Shift bits.
	(RELAX_BRANCH_ENCODE): Add `pic' flag.
	(RELAX_BRANCH_UNCOND, RELAX_BRANCH_LIKELY, RELAX_BRANCH_LINK)
	(RELAX_BRANCH_TOOFAR): Shift bits.
	(RELAX_BRANCH_PIC): New macro.
	(RELAX_MICROMIPS_ENCODE): Add `pic' flag.
	(RELAX_MICROMIPS_PIC): New macro.
	(RELAX_MICROMIPS_UNCOND, RELAX_MICROMIPS_COMPACT)
	(RELAX_MICROMIPS_LINK, RELAX_MICROMIPS_NODS)
	(RELAX_MICROMIPS_RELAX32): Shift bits.
	(relax_close_frag): Pass `mips_pic' setting to RELAX_ENCODE.
	(append_insn): Pass `mips_pic' setting to RELAX_BRANCH_ENCODE
	and RELAX_MICROMIPS_ENCODE, and record it in `fx_tcbit2' of the
	first fixup created.
	(md_apply_fix) <BFD_RELOC_16_PCREL_S2>: Use `fx_tcbit2' of the
	fixup processed rather than `mips_pic' in choosing to relax an
	out of range branch to a jump.
	(relaxed_branch_length): Use the `pic' flag of the relaxed frag
	rather than `mips_pic'.
	(relaxed_micromips_32bit_branch_length): Likewise.
	(md_estimate_size_before_relax): Likewise.
	(md_convert_frag): Likewise.

	* testsuite/gas/mips/option-pic-relax-0.d: New test.
	* testsuite/gas/mips/option-pic-relax-1.d: New test.
	* testsuite/gas/mips/option-pic-relax-2.d: New test.
	* testsuite/gas/mips/option-pic-relax-3.d: New test.
	* testsuite/gas/mips/option-pic-relax-3a.d: New test.
	* testsuite/gas/mips/option-pic-relax-4.d: New test.
	* testsuite/gas/mips/option-pic-relax-5.d: New test.
	* testsuite/gas/mips/option-pic-relax-2.l: New stderr output.
	* testsuite/gas/mips/option-pic-relax-3.l: New stderr output.
	* testsuite/gas/mips/option-pic-relax-4.l: New stderr output.
	* testsuite/gas/mips/option-pic-relax-5.l: New stderr output.
	* testsuite/gas/mips/option-pic-relax-0.s: New test source.
	* testsuite/gas/mips/option-pic-relax-1.s: New test source.
	* testsuite/gas/mips/option-pic-relax-2.s: New test source.
	* testsuite/gas/mips/option-pic-relax-3.s: New test source.
	* testsuite/gas/mips/option-pic-relax-4.s: New test source.
	* testsuite/gas/mips/option-pic-relax-5.s: New test source.
	* testsuite/gas/mips/mips.exp: Run the new tests.
This commit is contained in:
Maciej W. Rozycki
2017-04-27 00:47:15 +01:00
parent 97d343d400
commit ce8ad87213
20 changed files with 374 additions and 51 deletions

View File

@ -1,3 +1,52 @@
2017-04-26 Maciej W. Rozycki <macro@imgtec.com>
* config/tc-mips.c (RELAX_ENCODE): Add `PIC' flag.
(RELAX_PIC): New macro.
(RELAX_USE_SECOND, RELAX_SECOND_LONGER, RELAX_NOMACRO)
(RELAX_DELAY_SLOT, RELAX_DELAY_SLOT_16BIT)
(RELAX_DELAY_SLOT_SIZE_FIRST, RELAX_DELAY_SLOT_SIZE_SECOND):
Shift bits.
(RELAX_BRANCH_ENCODE): Add `pic' flag.
(RELAX_BRANCH_UNCOND, RELAX_BRANCH_LIKELY, RELAX_BRANCH_LINK)
(RELAX_BRANCH_TOOFAR): Shift bits.
(RELAX_BRANCH_PIC): New macro.
(RELAX_MICROMIPS_ENCODE): Add `pic' flag.
(RELAX_MICROMIPS_PIC): New macro.
(RELAX_MICROMIPS_UNCOND, RELAX_MICROMIPS_COMPACT)
(RELAX_MICROMIPS_LINK, RELAX_MICROMIPS_NODS)
(RELAX_MICROMIPS_RELAX32): Shift bits.
(relax_close_frag): Pass `mips_pic' setting to RELAX_ENCODE.
(append_insn): Pass `mips_pic' setting to RELAX_BRANCH_ENCODE
and RELAX_MICROMIPS_ENCODE, and record it in `fx_tcbit2' of the
first fixup created.
(md_apply_fix) <BFD_RELOC_16_PCREL_S2>: Use `fx_tcbit2' of the
fixup processed rather than `mips_pic' in choosing to relax an
out of range branch to a jump.
(relaxed_branch_length): Use the `pic' flag of the relaxed frag
rather than `mips_pic'.
(relaxed_micromips_32bit_branch_length): Likewise.
(md_estimate_size_before_relax): Likewise.
(md_convert_frag): Likewise.
* testsuite/gas/mips/option-pic-relax-0.d: New test.
* testsuite/gas/mips/option-pic-relax-1.d: New test.
* testsuite/gas/mips/option-pic-relax-2.d: New test.
* testsuite/gas/mips/option-pic-relax-3.d: New test.
* testsuite/gas/mips/option-pic-relax-3a.d: New test.
* testsuite/gas/mips/option-pic-relax-4.d: New test.
* testsuite/gas/mips/option-pic-relax-5.d: New test.
* testsuite/gas/mips/option-pic-relax-2.l: New stderr output.
* testsuite/gas/mips/option-pic-relax-3.l: New stderr output.
* testsuite/gas/mips/option-pic-relax-4.l: New stderr output.
* testsuite/gas/mips/option-pic-relax-5.l: New stderr output.
* testsuite/gas/mips/option-pic-relax-0.s: New test source.
* testsuite/gas/mips/option-pic-relax-1.s: New test source.
* testsuite/gas/mips/option-pic-relax-2.s: New test source.
* testsuite/gas/mips/option-pic-relax-3.s: New test source.
* testsuite/gas/mips/option-pic-relax-4.s: New test source.
* testsuite/gas/mips/option-pic-relax-5.s: New test source.
* testsuite/gas/mips/mips.exp: Run the new tests.
2017-04-25 Claudiu Zissulescu <claziss@synopsys.com> 2017-04-25 Claudiu Zissulescu <claziss@synopsys.com>
* testsuite/gas/arc/leave_enter.d: Update test. * testsuite/gas/arc/leave_enter.d: Update test.

View File

@ -967,6 +967,9 @@ static bfd_boolean mips_ignore_branch_isa;
can be extracted using RELAX_FIRST() and RELAX_SECOND(). In addition, can be extracted using RELAX_FIRST() and RELAX_SECOND(). In addition,
the subtype has the following flags: the subtype has the following flags:
RELAX_PIC
Set if generating PIC code.
RELAX_USE_SECOND RELAX_USE_SECOND
Set if it has been decided that we should use the second Set if it has been decided that we should use the second
sequence instead of the first. sequence instead of the first.
@ -1008,17 +1011,19 @@ static bfd_boolean mips_ignore_branch_isa;
The code and fixups for the unwanted alternative are discarded The code and fixups for the unwanted alternative are discarded
by md_convert_frag. */ by md_convert_frag. */
#define RELAX_ENCODE(FIRST, SECOND) (((FIRST) << 8) | (SECOND)) #define RELAX_ENCODE(FIRST, SECOND, PIC) \
(((FIRST) << 8) | (SECOND) | ((PIC) ? 0x10000 : 0))
#define RELAX_FIRST(X) (((X) >> 8) & 0xff) #define RELAX_FIRST(X) (((X) >> 8) & 0xff)
#define RELAX_SECOND(X) ((X) & 0xff) #define RELAX_SECOND(X) ((X) & 0xff)
#define RELAX_USE_SECOND 0x10000 #define RELAX_PIC(X) (((X) & 0x10000) != 0)
#define RELAX_SECOND_LONGER 0x20000 #define RELAX_USE_SECOND 0x20000
#define RELAX_NOMACRO 0x40000 #define RELAX_SECOND_LONGER 0x40000
#define RELAX_DELAY_SLOT 0x80000 #define RELAX_NOMACRO 0x80000
#define RELAX_DELAY_SLOT_16BIT 0x100000 #define RELAX_DELAY_SLOT 0x100000
#define RELAX_DELAY_SLOT_SIZE_FIRST 0x200000 #define RELAX_DELAY_SLOT_16BIT 0x200000
#define RELAX_DELAY_SLOT_SIZE_SECOND 0x400000 #define RELAX_DELAY_SLOT_SIZE_FIRST 0x400000
#define RELAX_DELAY_SLOT_SIZE_SECOND 0x800000
/* Branch without likely bit. If label is out of range, we turn: /* Branch without likely bit. If label is out of range, we turn:
@ -1087,19 +1092,22 @@ static bfd_boolean mips_ignore_branch_isa;
but it's not clear that it would actually improve performance. */ but it's not clear that it would actually improve performance. */
#define RELAX_BRANCH_ENCODE(at, uncond, likely, link, toofar) \ #define RELAX_BRANCH_ENCODE(at, pic, \
uncond, likely, link, toofar) \
((relax_substateT) \ ((relax_substateT) \
(0xc0000000 \ (0xc0000000 \
| ((at) & 0x1f) \ | ((at) & 0x1f) \
| ((toofar) ? 0x20 : 0) \ | ((pic) ? 0x20 : 0) \
| ((link) ? 0x40 : 0) \ | ((toofar) ? 0x40 : 0) \
| ((likely) ? 0x80 : 0) \ | ((link) ? 0x80 : 0) \
| ((uncond) ? 0x100 : 0))) | ((likely) ? 0x100 : 0) \
| ((uncond) ? 0x200 : 0)))
#define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000) #define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000)
#define RELAX_BRANCH_UNCOND(i) (((i) & 0x100) != 0) #define RELAX_BRANCH_UNCOND(i) (((i) & 0x200) != 0)
#define RELAX_BRANCH_LIKELY(i) (((i) & 0x80) != 0) #define RELAX_BRANCH_LIKELY(i) (((i) & 0x100) != 0)
#define RELAX_BRANCH_LINK(i) (((i) & 0x40) != 0) #define RELAX_BRANCH_LINK(i) (((i) & 0x80) != 0)
#define RELAX_BRANCH_TOOFAR(i) (((i) & 0x20) != 0) #define RELAX_BRANCH_TOOFAR(i) (((i) & 0x40) != 0)
#define RELAX_BRANCH_PIC(i) (((i) & 0x20) != 0)
#define RELAX_BRANCH_AT(i) ((i) & 0x1f) #define RELAX_BRANCH_AT(i) ((i) & 0x1f)
/* For mips16 code, we use an entirely different form of relaxation. /* For mips16 code, we use an entirely different form of relaxation.
@ -1164,36 +1172,38 @@ static bfd_boolean mips_ignore_branch_isa;
instructions is enabled, and whether the displacement of a branch is instructions is enabled, and whether the displacement of a branch is
too large to fit as an immediate argument of a 16-bit and a 32-bit too large to fit as an immediate argument of a 16-bit and a 32-bit
branch, respectively. */ branch, respectively. */
#define RELAX_MICROMIPS_ENCODE(type, at, insn32, \ #define RELAX_MICROMIPS_ENCODE(type, at, insn32, pic, \
uncond, compact, link, nods, \ uncond, compact, link, nods, \
relax32, toofar16, toofar32) \ relax32, toofar16, toofar32) \
(0x40000000 \ (0x40000000 \
| ((type) & 0xff) \ | ((type) & 0xff) \
| (((at) & 0x1f) << 8) \ | (((at) & 0x1f) << 8) \
| ((insn32) ? 0x2000 : 0) \ | ((insn32) ? 0x2000 : 0) \
| ((uncond) ? 0x4000 : 0) \ | ((pic) ? 0x4000 : 0) \
| ((compact) ? 0x8000 : 0) \ | ((uncond) ? 0x8000 : 0) \
| ((link) ? 0x10000 : 0) \ | ((compact) ? 0x10000 : 0) \
| ((nods) ? 0x20000 : 0) \ | ((link) ? 0x20000 : 0) \
| ((relax32) ? 0x40000 : 0) \ | ((nods) ? 0x40000 : 0) \
| ((toofar16) ? 0x80000 : 0) \ | ((relax32) ? 0x80000 : 0) \
| ((toofar32) ? 0x100000 : 0)) | ((toofar16) ? 0x100000 : 0) \
| ((toofar32) ? 0x200000 : 0))
#define RELAX_MICROMIPS_P(i) (((i) & 0xc0000000) == 0x40000000) #define RELAX_MICROMIPS_P(i) (((i) & 0xc0000000) == 0x40000000)
#define RELAX_MICROMIPS_TYPE(i) ((i) & 0xff) #define RELAX_MICROMIPS_TYPE(i) ((i) & 0xff)
#define RELAX_MICROMIPS_AT(i) (((i) >> 8) & 0x1f) #define RELAX_MICROMIPS_AT(i) (((i) >> 8) & 0x1f)
#define RELAX_MICROMIPS_INSN32(i) (((i) & 0x2000) != 0) #define RELAX_MICROMIPS_INSN32(i) (((i) & 0x2000) != 0)
#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x4000) != 0) #define RELAX_MICROMIPS_PIC(i) (((i) & 0x4000) != 0)
#define RELAX_MICROMIPS_COMPACT(i) (((i) & 0x8000) != 0) #define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x8000) != 0)
#define RELAX_MICROMIPS_LINK(i) (((i) & 0x10000) != 0) #define RELAX_MICROMIPS_COMPACT(i) (((i) & 0x10000) != 0)
#define RELAX_MICROMIPS_NODS(i) (((i) & 0x20000) != 0) #define RELAX_MICROMIPS_LINK(i) (((i) & 0x20000) != 0)
#define RELAX_MICROMIPS_RELAX32(i) (((i) & 0x40000) != 0) #define RELAX_MICROMIPS_NODS(i) (((i) & 0x40000) != 0)
#define RELAX_MICROMIPS_RELAX32(i) (((i) & 0x80000) != 0)
#define RELAX_MICROMIPS_TOOFAR16(i) (((i) & 0x80000) != 0) #define RELAX_MICROMIPS_TOOFAR16(i) (((i) & 0x100000) != 0)
#define RELAX_MICROMIPS_MARK_TOOFAR16(i) ((i) | 0x80000) #define RELAX_MICROMIPS_MARK_TOOFAR16(i) ((i) | 0x100000)
#define RELAX_MICROMIPS_CLEAR_TOOFAR16(i) ((i) & ~0x80000) #define RELAX_MICROMIPS_CLEAR_TOOFAR16(i) ((i) & ~0x100000)
#define RELAX_MICROMIPS_TOOFAR32(i) (((i) & 0x100000) != 0) #define RELAX_MICROMIPS_TOOFAR32(i) (((i) & 0x200000) != 0)
#define RELAX_MICROMIPS_MARK_TOOFAR32(i) ((i) | 0x100000) #define RELAX_MICROMIPS_MARK_TOOFAR32(i) ((i) | 0x200000)
#define RELAX_MICROMIPS_CLEAR_TOOFAR32(i) ((i) & ~0x100000) #define RELAX_MICROMIPS_CLEAR_TOOFAR32(i) ((i) & ~0x200000)
/* Sign-extend 16-bit value X. */ /* Sign-extend 16-bit value X. */
#define SEXT_16BIT(X) ((((X) + 0x8000) & 0xffff) - 0x8000) #define SEXT_16BIT(X) ((((X) + 0x8000) & 0xffff) - 0x8000)
@ -4345,7 +4355,8 @@ relax_close_frag (void)
{ {
mips_macro_warning.first_frag = frag_now; mips_macro_warning.first_frag = frag_now;
frag_var (rs_machine_dependent, 0, 0, frag_var (rs_machine_dependent, 0, 0,
RELAX_ENCODE (mips_relax.sizes[0], mips_relax.sizes[1]), RELAX_ENCODE (mips_relax.sizes[0], mips_relax.sizes[1],
mips_pic != NO_PIC),
mips_relax.symbol, 0, (char *) mips_relax.first_fixup); mips_relax.symbol, 0, (char *) mips_relax.first_fixup);
memset (&mips_relax.sizes, 0, sizeof (mips_relax.sizes)); memset (&mips_relax.sizes, 0, sizeof (mips_relax.sizes));
@ -7332,7 +7343,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
: branch_likely_p (ip) ? 1 : branch_likely_p (ip) ? 1
: 0)), 4, : 0)), 4,
RELAX_BRANCH_ENCODE RELAX_BRANCH_ENCODE
(AT, (AT, mips_pic != NO_PIC,
uncond_branch_p (ip), uncond_branch_p (ip),
branch_likely_p (ip), branch_likely_p (ip),
pinfo & INSN_WRITE_GPR_31, pinfo & INSN_WRITE_GPR_31,
@ -7369,6 +7380,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
length32 = relaxed_micromips_32bit_branch_length (NULL, NULL, uncond); length32 = relaxed_micromips_32bit_branch_length (NULL, NULL, uncond);
add_relaxed_insn (ip, length32, relax16 ? 2 : 4, add_relaxed_insn (ip, length32, relax16 ? 2 : 4,
RELAX_MICROMIPS_ENCODE (type, AT, mips_opts.insn32, RELAX_MICROMIPS_ENCODE (type, AT, mips_opts.insn32,
mips_pic != NO_PIC,
uncond, compact, al, nods, uncond, compact, al, nods,
relax32, 0, 0), relax32, 0, 0),
address_expr->X_add_symbol, address_expr->X_add_symbol,
@ -7490,6 +7502,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
address_expr, address_expr,
howto0 && howto0->pc_relative, howto0 && howto0->pc_relative,
final_type[0]); final_type[0]);
/* Record non-PIC mode in `fx_tcbit2' for `md_apply_fix'. */
ip->fixp[0]->fx_tcbit2 = mips_pic == NO_PIC;
/* Tag symbols that have a R_MIPS16_26 relocation against them. */ /* Tag symbols that have a R_MIPS16_26 relocation against them. */
if (final_type[0] == BFD_RELOC_MIPS16_JMP && ip->fixp[0]->fx_addsy) if (final_type[0] == BFD_RELOC_MIPS16_JMP && ip->fixp[0]->fx_addsy)
@ -15582,7 +15596,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
insn |= (*valP >> 2) & 0xffff; insn |= (*valP >> 2) & 0xffff;
write_insn (buf, insn); write_insn (buf, insn);
} }
else if (mips_pic == NO_PIC else if (fixP->fx_tcbit2
&& fixP->fx_done && fixP->fx_done
&& fixP->fx_frag->fr_address >= text_section->vma && fixP->fx_frag->fr_address >= text_section->vma
&& (fixP->fx_frag->fr_address && (fixP->fx_frag->fr_address
@ -17339,6 +17353,7 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update)
if (fragp && update && toofar != RELAX_BRANCH_TOOFAR (fragp->fr_subtype)) if (fragp && update && toofar != RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
fragp->fr_subtype fragp->fr_subtype
= RELAX_BRANCH_ENCODE (RELAX_BRANCH_AT (fragp->fr_subtype), = RELAX_BRANCH_ENCODE (RELAX_BRANCH_AT (fragp->fr_subtype),
RELAX_BRANCH_PIC (fragp->fr_subtype),
RELAX_BRANCH_UNCOND (fragp->fr_subtype), RELAX_BRANCH_UNCOND (fragp->fr_subtype),
RELAX_BRANCH_LIKELY (fragp->fr_subtype), RELAX_BRANCH_LIKELY (fragp->fr_subtype),
RELAX_BRANCH_LINK (fragp->fr_subtype), RELAX_BRANCH_LINK (fragp->fr_subtype),
@ -17350,7 +17365,7 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update)
if (fragp ? RELAX_BRANCH_LIKELY (fragp->fr_subtype) : (update > 0)) if (fragp ? RELAX_BRANCH_LIKELY (fragp->fr_subtype) : (update > 0))
length += 8; length += 8;
if (mips_pic != NO_PIC) if (!fragp || RELAX_BRANCH_PIC (fragp->fr_subtype))
{ {
/* Additional space for PIC loading of target address. */ /* Additional space for PIC loading of target address. */
length += 8; length += 8;
@ -17393,6 +17408,7 @@ relaxed_micromips_32bit_branch_length (fragS *fragp, asection *sec, int update)
{ {
bfd_boolean insn32 = TRUE; bfd_boolean insn32 = TRUE;
bfd_boolean nods = TRUE; bfd_boolean nods = TRUE;
bfd_boolean pic = TRUE;
bfd_boolean al = TRUE; bfd_boolean al = TRUE;
int short_insn_size; int short_insn_size;
bfd_boolean toofar; bfd_boolean toofar;
@ -17402,6 +17418,7 @@ relaxed_micromips_32bit_branch_length (fragS *fragp, asection *sec, int update)
{ {
insn32 = RELAX_MICROMIPS_INSN32 (fragp->fr_subtype); insn32 = RELAX_MICROMIPS_INSN32 (fragp->fr_subtype);
nods = RELAX_MICROMIPS_NODS (fragp->fr_subtype); nods = RELAX_MICROMIPS_NODS (fragp->fr_subtype);
pic = RELAX_MICROMIPS_PIC (fragp->fr_subtype);
al = RELAX_MICROMIPS_LINK (fragp->fr_subtype); al = RELAX_MICROMIPS_LINK (fragp->fr_subtype);
} }
short_insn_size = insn32 ? 4 : 2; short_insn_size = insn32 ? 4 : 2;
@ -17464,7 +17481,7 @@ relaxed_micromips_32bit_branch_length (fragS *fragp, asection *sec, int update)
# compact && (!PIC || insn32) # compact && (!PIC || insn32)
0: 0:
*/ */
if ((mips_pic == NO_PIC || insn32) && (!compact_known || compact)) if ((!pic || insn32) && (!compact_known || compact))
length += short_insn_size; length += short_insn_size;
/* If assembling PIC code, we further turn: /* If assembling PIC code, we further turn:
@ -17477,12 +17494,12 @@ relaxed_micromips_32bit_branch_length (fragS *fragp, asection *sec, int update)
d/addiu at, %lo(label) # 4 bytes d/addiu at, %lo(label) # 4 bytes
jr/c at # 2/4 bytes jr/c at # 2/4 bytes
*/ */
if (mips_pic != NO_PIC) if (pic)
length += 4 + short_insn_size; length += 4 + short_insn_size;
/* Add an extra nop if the jump has no compact form and we need /* Add an extra nop if the jump has no compact form and we need
to fill the delay slot. */ to fill the delay slot. */
if ((mips_pic == NO_PIC || al) && nods) if ((!pic || al) && nods)
length += (fragp length += (fragp
? frag_branch_delay_slot_size (fragp, al, short_insn_size) ? frag_branch_delay_slot_size (fragp, al, short_insn_size)
: short_insn_size); : short_insn_size);
@ -17597,15 +17614,13 @@ md_estimate_size_before_relax (fragS *fragp, asection *segtype)
return length; return length;
} }
if (mips_pic == NO_PIC) if (mips_pic == VXWORKS_PIC)
change = nopic_need_relax (fragp->fr_symbol, 0);
else if (mips_pic == SVR4_PIC)
change = pic_need_relax (fragp->fr_symbol);
else if (mips_pic == VXWORKS_PIC)
/* For vxworks, GOT16 relocations never have a corresponding LO16. */ /* For vxworks, GOT16 relocations never have a corresponding LO16. */
change = 0; change = 0;
else if (RELAX_PIC (fragp->fr_subtype))
change = pic_need_relax (fragp->fr_symbol);
else else
abort (); change = nopic_need_relax (fragp->fr_symbol, 0);
if (change) if (change)
{ {
@ -17988,7 +18003,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
} }
uncond: uncond:
if (mips_pic == NO_PIC) if (!RELAX_BRANCH_PIC (fragp->fr_subtype))
{ {
/* j or jal. */ /* j or jal. */
insn = (RELAX_BRANCH_LINK (fragp->fr_subtype) insn = (RELAX_BRANCH_LINK (fragp->fr_subtype)
@ -18066,6 +18081,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
bfd_boolean compact = RELAX_MICROMIPS_COMPACT (fragp->fr_subtype); bfd_boolean compact = RELAX_MICROMIPS_COMPACT (fragp->fr_subtype);
bfd_boolean insn32 = RELAX_MICROMIPS_INSN32 (fragp->fr_subtype); bfd_boolean insn32 = RELAX_MICROMIPS_INSN32 (fragp->fr_subtype);
bfd_boolean nods = RELAX_MICROMIPS_NODS (fragp->fr_subtype); bfd_boolean nods = RELAX_MICROMIPS_NODS (fragp->fr_subtype);
bfd_boolean pic = RELAX_MICROMIPS_PIC (fragp->fr_subtype);
bfd_boolean al = RELAX_MICROMIPS_LINK (fragp->fr_subtype); bfd_boolean al = RELAX_MICROMIPS_LINK (fragp->fr_subtype);
int type = RELAX_MICROMIPS_TYPE (fragp->fr_subtype); int type = RELAX_MICROMIPS_TYPE (fragp->fr_subtype);
bfd_boolean short_ds; bfd_boolean short_ds;
@ -18241,7 +18257,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
} }
} }
if (mips_pic == NO_PIC) if (!pic)
{ {
unsigned long jal = (short_ds || nods unsigned long jal = (short_ds || nods
? 0x74000000 : 0xf4000000); /* jal/s */ ? 0x74000000 : 0xf4000000); /* jal/s */

View File

@ -1800,6 +1800,13 @@ if { [istarget mips*-*-vxworks*] } {
"MIPS invalid PIC option in VxWorks PIC" "MIPS invalid PIC option in VxWorks PIC"
run_list_test "option-pic-vxworks-2" "-mvxworks-pic" \ run_list_test "option-pic-vxworks-2" "-mvxworks-pic" \
"MIPS invalid switch to SVR4 PIC from VxWorks PIC" "MIPS invalid switch to SVR4 PIC from VxWorks PIC"
run_dump_test "option-pic-relax-0"
run_dump_test "option-pic-relax-1"
run_dump_test "option-pic-relax-2"
run_dump_test "option-pic-relax-3"
run_dump_test "option-pic-relax-3a"
run_dump_test "option-pic-relax-4"
run_dump_test "option-pic-relax-5"
run_dump_test_arches "isa-override-1" "" [mips_arch_list_matching mips1] run_dump_test_arches "isa-override-1" "" [mips_arch_list_matching mips1]
run_list_test_arches "isa-override-2" "-32" [mips_arch_list_matching mips1] run_list_test_arches "isa-override-2" "-32" [mips_arch_list_matching mips1]

View File

@ -0,0 +1,21 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS `.option picX' with relaxation 0
#as: -32
# Verify that relaxation is done according to the `.option picX' setting
# at the time the relevant instruction was assembled rather than at
# relaxation time.
.*: +file format .*mips.*
Disassembly of section \.text:
[0-9a-f]+ <[^>]*> 3c1c0000 lui gp,0x0
[ ]*[0-9a-f]+: R_MIPS_HI16 _gp_disp
[0-9a-f]+ <[^>]*> 279c0000 addiu gp,gp,0
[ ]*[0-9a-f]+: R_MIPS_LO16 _gp_disp
[0-9a-f]+ <[^>]*> 0399e021 addu gp,gp,t9
[0-9a-f]+ <[^>]*> 8f820000 lw v0,0\(gp\)
[ ]*[0-9a-f]+: R_MIPS_GOT16 bar
[0-9a-f]+ <[^>]*> 03e00008 jr ra
[0-9a-f]+ <[^>]*> 00000000 nop
\.\.\.

View File

@ -0,0 +1,15 @@
.text
.ent foo
.option pic2
foo:
.set noreorder
.cpload $25
.set reorder
la $2, bar
jr $31
.option pic0
.end foo
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16

View File

@ -0,0 +1,18 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS `.option picX' with relaxation 1
#as: -32
# Verify that relaxation is done according to the `.option picX' setting
# at the time the relevant instruction was assembled rather than at
# relaxation time.
.*: +file format .*mips.*
Disassembly of section \.text:
[0-9a-f]+ <[^>]*> 3c020000 lui v0,0x0
[ ]*[0-9a-f]+: R_MIPS_HI16 bar
[0-9a-f]+ <[^>]*> 24420000 addiu v0,v0,0
[ ]*[0-9a-f]+: R_MIPS_LO16 bar
[0-9a-f]+ <[^>]*> 03e00008 jr ra
[0-9a-f]+ <[^>]*> 00000000 nop
\.\.\.

View File

@ -0,0 +1,12 @@
.text
.ent foo
.option pic0
foo:
la $2, bar
jr $31
.option pic2
.end foo
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16

View File

@ -0,0 +1,28 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS `.option picX' with relaxation 2
#as: -32 -mips2 --relax-branch
#stderr: option-pic-relax-2.l
# Verify that relaxation is done according to the `.option picX' setting
# at the time the relevant instruction was assembled rather than at
# relaxation time.
.*: +file format .*mips.*
Disassembly of section \.text:
[0-9a-f]+ <[^>]*> 3c1c0000 lui gp,0x0
[ ]*[0-9a-f]+: R_MIPS_HI16 _gp_disp
[0-9a-f]+ <[^>]*> 279c0000 addiu gp,gp,0
[ ]*[0-9a-f]+: R_MIPS_LO16 _gp_disp
[0-9a-f]+ <[^>]*> 0399e021 addu gp,gp,t9
[0-9a-f]+ <[^>]*> 00801025 move v0,a0
[0-9a-f]+ <[^>]*> 8f810002 lw at,2\(gp\)
[ ]*[0-9a-f]+: R_MIPS_GOT16 \.text
[0-9a-f]+ <[^>]*> 2421001c addiu at,at,28
[ ]*[0-9a-f]+: R_MIPS_LO16 \.text
[0-9a-f]+ <[^>]*> 00200008 jr at
[0-9a-f]+ <[^>]*> 00a01825 move v1,a1
\.\.\.
[0-9a-f]+ <[^>]*> 03e00008 jr ra
[0-9a-f]+ <[^>]*> 00000000 nop
\.\.\.

View File

@ -0,0 +1,2 @@
.*: Assembler messages:
.*:10: Warning: relaxed out-of-range branch into a jump

View File

@ -0,0 +1,19 @@
.text
.ent foo
.option pic2
foo:
.set noreorder
.cpload $25
.set reorder
move $2, $4
move $3, $5
b bar
.space 0x7fff << 2
bar:
jr $31
.option pic0
.end foo
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16

View File

@ -0,0 +1,20 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS `.option picX' with relaxation 3
#as: -32 --relax-branch
#stderr: option-pic-relax-3.l
# Verify that relaxation is done according to the `.option picX' setting
# at the time the relevant instruction was assembled rather than at
# relaxation time.
.*: +file format .*mips.*
Disassembly of section \.text:
[0-9a-f]+ <[^>]*> 00801025 move v0,a0
[0-9a-f]+ <[^>]*> 08008002 j 00020008 <.*>
[ ]*[0-9a-f]+: R_MIPS_26 \.text
[0-9a-f]+ <[^>]*> 00a01825 move v1,a1
\.\.\.
[0-9a-f]+ <[^>]*> 03e00008 jr ra
[0-9a-f]+ <[^>]*> 00000000 nop
\.\.\.

View File

@ -0,0 +1,2 @@
.*: Assembler messages:
.*:7: Warning: relaxed out-of-range branch into a jump

View File

@ -0,0 +1,16 @@
.text
.ent foo
.option pic0
foo:
move $2, $4
move $3, $5
b bar
.space 0x7fff << 2
bar:
jr $31
.option pic2
.end foo
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16

View File

@ -0,0 +1,9 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS `.option picX' with relaxation 3a
#as: -32
#source: option-pic-relax-3.s
#dump: option-pic-relax-3.d
# Verify that relaxation is done according to the `.option picX' setting
# at the time the relevant instruction was assembled rather than at
# relaxation time.

View File

@ -0,0 +1,28 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS `.option picX' with relaxation 4
#as: -32 -mmicromips --relax-branch
#stderr: option-pic-relax-4.l
# Verify that relaxation is done according to the `.option picX' setting
# at the time the relevant instruction was assembled rather than at
# relaxation time.
.*: +file format .*mips.*
Disassembly of section \.text:
[0-9a-f]+ <[^>]*> 41bc 0000 lui gp,0x0
[ ]*[0-9a-f]+: R_MICROMIPS_HI16 _gp_disp
[0-9a-f]+ <[^>]*> 339c 0000 addiu gp,gp,0
[ ]*[0-9a-f]+: R_MICROMIPS_LO16 _gp_disp
[0-9a-f]+ <[^>]*> 033c e150 addu gp,gp,t9
[0-9a-f]+ <[^>]*> 0c44 move v0,a0
[0-9a-f]+ <[^>]*> fc3c 0001 lw at,1\(gp\)
[ ]*[0-9a-f]+: R_MICROMIPS_GOT16 \.text
[0-9a-f]+ <[^>]*> 3021 0019 addiu at,at,25
[ ]*[0-9a-f]+: R_MICROMIPS_LO16 \.text
[0-9a-f]+ <[^>]*> 4581 jr at
[0-9a-f]+ <[^>]*> 0c65 move v1,a1
[0-9a-f]+ <[^>]*> 0c00 nop
\.\.\.
[0-9a-f]+ <[^>]*> 45bf jrc ra
\.\.\.

View File

@ -0,0 +1,2 @@
.*: Assembler messages:
.*:10: Warning: relaxed out-of-range branch into a jump

View File

@ -0,0 +1,20 @@
.text
.ent foo
.option pic2
foo:
.set noreorder
.cpload $25
.set reorder
move $2, $4
move $3, $5
b bar
nop
.space 0x7ffe << 1
bar:
jr $31
.option pic0
.end foo
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16

View File

@ -0,0 +1,20 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS `.option picX' with relaxation 5
#as: -32 -mmicromips --relax-branch
#stderr: option-pic-relax-5.l
# Verify that relaxation is done according to the `.option picX' setting
# at the time the relevant instruction was assembled rather than at
# relaxation time.
.*: +file format .*mips.*
Disassembly of section \.text:
[0-9a-f]+ <[^>]*> 0c44 move v0,a0
[0-9a-f]+ <[^>]*> d400 0000 j 00000000 <foo>
[ ]*[0-9a-f]+: R_MICROMIPS_26_S1 bar
[0-9a-f]+ <[^>]*> 0c65 move v1,a1
[0-9a-f]+ <[^>]*> 0c00 nop
\.\.\.
[0-9a-f]+ <[^>]*> 45bf jrc ra
\.\.\.

View File

@ -0,0 +1,2 @@
.*: Assembler messages:
.*:7: Warning: relaxed out-of-range branch into a jump

View File

@ -0,0 +1,17 @@
.text
.ent foo
.option pic0
foo:
move $2, $4
move $3, $5
b bar
nop
.space 0x7ffe << 1
bar:
jr $31
.option pic2
.end foo
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16