[PATCH] microMIPS/GAS: Remove forced 16-bit branch relaxation

Maciej W. Rozycki macro@codesourcery.com
Tue Aug 2 17:05:00 GMT 2011


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))



More information about the Binutils mailing list