This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] microMIPS/GAS: Remove forced 16-bit branch relaxation
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: binutils at sourceware dot org, Chao-ying Fu <fu at mips dot com>, Rich Fuhler <rich at mips dot com>, David Lau <davidlau at mips dot com>, Kevin Mills <kevinm at mips dot com>, Ilie Garbacea <ilie at mips dot com>, Catherine Moore <clm at codesourcery dot com>, Nathan Sidwell <nathan at codesourcery dot com>, Joseph Myers <joseph at codesourcery dot com>
- Date: Tue, 2 Aug 2011 18:05:04 +0100 (BST)
- Subject: [PATCH] microMIPS/GAS: Remove forced 16-bit branch relaxation
Hi,
As noted before:
>> >> > +#define RELAX_MICROMIPS_ENCODE(type, is_16bit, uncond, link, toofar) \
>> >> > + (0x40000000 \
>> >> > + | ((type) & 0xff) \
>> >> > + | ((is_16bit) ? 0x100 : 0) \
>> >> > + | ((uncond) ? 0x200 : 0) \
>> >> > + | ((link) ? 0x400 : 0) \
>> >> > + | ((toofar) ? 0x800 : 0))
>> >> > +#define RELAX_MICROMIPS_P(i) (((i) & 0xc0000000) == 0x40000000)
>> >> > +#define RELAX_MICROMIPS_TYPE(i) ((i) & 0xff)
>> >> > +#define RELAX_MICROMIPS_USER_16BIT(i) (((i) & 0x100) != 0)
>> >> > +#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x200) != 0)
>> >> > +#define RELAX_MICROMIPS_LINK(i) (((i) & 0x400) != 0)
>> >> > +#define RELAX_MICROMIPS_TOOFAR(i) (((i) & 0x800) != 0)
>> >> > +#define RELAX_MICROMIPS_MARK_TOOFAR(i) ((i) | 0x800)
>> >> > +#define RELAX_MICROMIPS_CLEAR_TOOFAR(i) ((i) & ~0x800)
>> >>
>> >> Is there a need to create variant frags when the user has explicitly
>> >> specified the instruction size? I wouldn't have expected any relaxation
>> >> to be necessary in that case, and it looks like the relaxation code does
>> >> indeed return 2 whenever USER_16BIT is true.
>> >
>> > I suspect this has been copied over from MIPS16 code.
>> > RELAX_MIPS16_USER_SMALL seems to be used in a similar fashion. Do you
>> > happen to know for sure why it has been implemented this way for MIPS16
>> > assembly?
>>
>> Nope :-)
>
> With a sudden insight I realised this is a workaround for the lack of
> MIPS16 branch relocations. As no actual relocation can be encoded in
> offset_expr, relaxation is used unconditionally instead and the definition
> of the relocatable field carried through as a transformed argument code.
there is really no need to relax forced 16-bit branches, nor carry the
forced size information in the relaxation record (we don't do anything
about this anyway -- eventually we just emit a lone 16-bit branch in all
cases). The change below removes this relaxation information bit and then
adjusts code to emit such branches straight away.
No regressions for mips-sde-elf or mips-linux-gnu. OK to apply?
2011-08-02 Maciej W. Rozycki <macro@codesourcery.com>
gas/
* config/tc-mips.c (RELAX_MICROMIPS_ENCODE): Remove forced 16-bit
branch size information.
(RELAX_MICROMIPS_U16BIT): Remove macro.
(RELAX_MICROMIPS_UNCOND): Adjust accordingly.
(RELAX_MICROMIPS_COMPACT, RELAX_MICROMIPS_LINK): Likewise.
(RELAX_MICROMIPS_RELAX32): Likewise.
(RELAX_MICROMIPS_TOOFAR16): Likewise.
(RELAX_MICROMIPS_MARK_TOOFAR16): Likewise.
(RELAX_MICROMIPS_CLEAR_TOOFAR16): Likewise.
(RELAX_MICROMIPS_TOOFAR32): Likewise.
(RELAX_MICROMIPS_MARK_TOOFAR32): Likewise.
(RELAX_MICROMIPS_CLEAR_TOOFAR32): Likewise.
(append_insn): Always check forced_insn_length for microMIPS
relaxation. Adjust code for the removal of
RELAX_MICROMIPS_U16BIT.
(mips_ip) <'D', 'E'>: If forced_insn_length, then emit the
relocation straight away.
(relaxed_micromips_16bit_branch_length): Adjust code for the
removal of RELAX_MICROMIPS_U16BIT.
Maciej
binutils-umips-u16bit.diff
Index: binutils-fsf-trunk-quilt/gas/config/tc-mips.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/config/tc-mips.c 2011-08-02 15:29:16.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/config/tc-mips.c 2011-08-02 16:38:23.000000000 +0100
@@ -1153,40 +1153,37 @@ static int mips_relax_branch;
The information we store for this type of relaxation is the argument
code found in the opcode file for this relocation, the register
- selected as the assembler temporary, whether the user explicitly
- requested a 16-bit form, whether the branch is unconditional, whether
- it is compact, whether it stores the link address implicitly in $ra,
- whether relaxation of out-of-range 32-bit branches to a sequence of
- 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
- branch, respectively. */
-#define RELAX_MICROMIPS_ENCODE(type, at, u16bit, uncond, compact, link, \
- relax32, toofar16, toofar32) \
- (0x40000000 \
- | ((type) & 0xff) \
- | (((at) & 0x1f) << 8) \
- | ((u16bit) ? 0x2000 : 0) \
- | ((uncond) ? 0x4000 : 0) \
- | ((compact) ? 0x8000 : 0) \
- | ((link) ? 0x10000 : 0) \
- | ((relax32) ? 0x20000 : 0) \
- | ((toofar16) ? 0x40000 : 0) \
- | ((toofar32) ? 0x80000 : 0))
+ selected as the assembler temporary, whether the branch is
+ unconditional, whether it is compact, whether it stores the link
+ address implicitly in $ra, whether relaxation of out-of-range 32-bit
+ branches to a sequence of 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 branch, respectively. */
+#define RELAX_MICROMIPS_ENCODE(type, at, uncond, compact, link, \
+ relax32, toofar16, toofar32) \
+ (0x40000000 \
+ | ((type) & 0xff) \
+ | (((at) & 0x1f) << 8) \
+ | ((uncond) ? 0x2000 : 0) \
+ | ((compact) ? 0x4000 : 0) \
+ | ((link) ? 0x8000 : 0) \
+ | ((relax32) ? 0x10000 : 0) \
+ | ((toofar16) ? 0x20000 : 0) \
+ | ((toofar32) ? 0x40000 : 0))
#define RELAX_MICROMIPS_P(i) (((i) & 0xc0000000) == 0x40000000)
#define RELAX_MICROMIPS_TYPE(i) ((i) & 0xff)
#define RELAX_MICROMIPS_AT(i) (((i) >> 8) & 0x1f)
-#define RELAX_MICROMIPS_U16BIT(i) (((i) & 0x2000) != 0)
-#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x4000) != 0)
-#define RELAX_MICROMIPS_COMPACT(i) (((i) & 0x8000) != 0)
-#define RELAX_MICROMIPS_LINK(i) (((i) & 0x10000) != 0)
-#define RELAX_MICROMIPS_RELAX32(i) (((i) & 0x20000) != 0)
+#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x2000) != 0)
+#define RELAX_MICROMIPS_COMPACT(i) (((i) & 0x4000) != 0)
+#define RELAX_MICROMIPS_LINK(i) (((i) & 0x8000) != 0)
+#define RELAX_MICROMIPS_RELAX32(i) (((i) & 0x10000) != 0)
-#define RELAX_MICROMIPS_TOOFAR16(i) (((i) & 0x40000) != 0)
-#define RELAX_MICROMIPS_MARK_TOOFAR16(i) ((i) | 0x40000)
-#define RELAX_MICROMIPS_CLEAR_TOOFAR16(i) ((i) & ~0x40000)
-#define RELAX_MICROMIPS_TOOFAR32(i) (((i) & 0x80000) != 0)
-#define RELAX_MICROMIPS_MARK_TOOFAR32(i) ((i) | 0x80000)
-#define RELAX_MICROMIPS_CLEAR_TOOFAR32(i) ((i) & ~0x80000)
+#define RELAX_MICROMIPS_TOOFAR16(i) (((i) & 0x20000) != 0)
+#define RELAX_MICROMIPS_MARK_TOOFAR16(i) ((i) | 0x20000)
+#define RELAX_MICROMIPS_CLEAR_TOOFAR16(i) ((i) & ~0x20000)
+#define RELAX_MICROMIPS_TOOFAR32(i) (((i) & 0x40000) != 0)
+#define RELAX_MICROMIPS_MARK_TOOFAR32(i) ((i) | 0x40000)
+#define RELAX_MICROMIPS_CLEAR_TOOFAR32(i) ((i) & ~0x40000)
/* Is the given value a sign-extended 32-bit value? */
#define IS_SEXT_32BIT_NUM(x) \
@@ -4174,10 +4171,7 @@ append_insn (struct mips_cl_insn *ip, ex
&& (mips_opts.at || mips_pic == NO_PIC)
/* Don't relax BPOSGE32/64 as they have no complementing
branches. */
- && !(ip->insn_mo->membership & (INSN_DSP64 | INSN_DSP))
- /* Don't try 32-bit branch relaxation when users specify
- 16-bit/32-bit instructions. */
- && !forced_insn_length);
+ && !(ip->insn_mo->membership & (INSN_DSP64 | INSN_DSP)));
if (!HAVE_CODE_COMPRESSION
&& address_expr
@@ -4209,7 +4203,10 @@ append_insn (struct mips_cl_insn *ip, ex
&& (pinfo & INSN_UNCOND_BRANCH_DELAY
|| pinfo & INSN_COND_BRANCH_DELAY
|| (pinfo2 & ~INSN2_ALIAS) == INSN2_UNCOND_BRANCH
- || pinfo2 & INSN2_COND_BRANCH))
+ || pinfo2 & INSN2_COND_BRANCH)
+ /* Don't try branch relaxation when users specify
+ 16-bit/32-bit instructions. */
+ && !forced_insn_length)
{
bfd_boolean relax16 = *reloc_type > BFD_RELOC_UNUSED;
int type = relax16 ? *reloc_type - BFD_RELOC_UNUSED : 0;
@@ -4224,10 +4221,8 @@ append_insn (struct mips_cl_insn *ip, ex
length32 = relaxed_micromips_32bit_branch_length (NULL, NULL, uncond);
add_relaxed_insn (ip, relax32 ? length32 : 4, relax16 ? 2 : 4,
- RELAX_MICROMIPS_ENCODE (type, AT,
- forced_insn_length == 2,
- uncond, compact, al, relax32,
- 0, 0),
+ RELAX_MICROMIPS_ENCODE (type, AT, uncond, compact, al,
+ relax32, 0, 0),
address_expr->X_add_symbol,
address_expr->X_add_number);
*reloc_type = BFD_RELOC_UNUSED;
@@ -12668,7 +12663,12 @@ mips_ip (char *str, struct mips_cl_insn
if (offset_expr.X_op == O_register)
break;
- *offset_reloc = (int) BFD_RELOC_UNUSED + c;
+ if (!forced_insn_length)
+ *offset_reloc = (int) BFD_RELOC_UNUSED + c;
+ else if (c == 'D')
+ *offset_reloc = BFD_RELOC_MICROMIPS_10_PCREL_S1;
+ else
+ *offset_reloc = BFD_RELOC_MICROMIPS_7_PCREL_S1;
s = expr_end;
continue;
@@ -17234,9 +17234,6 @@ relaxed_micromips_16bit_branch_length (f
{
bfd_boolean toofar;
- if (RELAX_MICROMIPS_U16BIT (fragp->fr_subtype))
- return 2;
-
if (fragp
&& S_IS_DEFINED (fragp->fr_symbol)
&& sec == S_GET_SEGMENT (fragp->fr_symbol))