public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* MIPS assembler branch relaxations
@ 2002-09-14  4:49 Alexandre Oliva
  2002-09-14 14:28 ` Daniel Jacobowitz
                   ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Alexandre Oliva @ 2002-09-14  4:49 UTC (permalink / raw)
  To: binutils, echristo

[-- Attachment #1: Type: text/plain, Size: 258 bytes --]

This patch arranges for the MIPS assembler to turn out-of-range
branches into jumps.  No regressions are introduced in the binutils
testsuites for a mips-linux build.  Details on how it is done are in
comments in the beginning of the patch.  Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gas-mips-branch-relax.patch --]
[-- Type: text/x-patch, Size: 30878 bytes --]

Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* config/tc-mips.h (mips_relax_frag): Take segment as argument.
	(md_relax_frag): Adjust macro.
	* config/tc-mips.c (RELAX_BRANCH_ENCODE, RELAX_BRANCH_P,
	RELAX_BRANCH_LIKELY, RELAX_BRANCH_LINK, RELAX_BRANCH_TOOBAR): New.
	(RELAX_MIPS16_P): Adjust.
	(append_insn): Emit branch to non-constant in a frag_var.
	(relaxed_branch_length): New function.
	(md_estimate_size_before_relax): Handle branch frags.
	(mips_relax_frag): Likewise.
	(md_convert_frag): Handle branch frags.

Index: gas/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* gas/mips/mips.exp: Don't xfail relax.
	* gas/mips/relax.s: Increase coverage.
	* gas/mips/relax.d: Add expected output.

Index: gas/config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.16
diff -u -p -r1.16 tc-mips.h
--- gas/config/tc-mips.h 5 Sep 2002 00:01:18 -0000 1.16
+++ gas/config/tc-mips.h 14 Sep 2002 05:53:26 -0000
@@ -49,8 +49,9 @@ struct expressionS;
    relocation: */
 #define MAX_GPREL_OFFSET (0x7FF0)
 
-#define md_relax_frag(segment, fragp, stretch) mips_relax_frag(fragp, stretch)
-extern int mips_relax_frag PARAMS ((struct frag *, long));
+#define md_relax_frag(segment, fragp, stretch) \
+  mips_relax_frag(segment, fragp, stretch)
+extern int mips_relax_frag PARAMS ((asection *, struct frag *, long));
 
 #define md_undefined_symbol(name)	(0)
 #define md_operand(x)
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.162
diff -u -p -r1.162 tc-mips.c
--- gas/config/tc-mips.c 5 Sep 2002 00:01:18 -0000 1.162
+++ gas/config/tc-mips.c 14 Sep 2002 05:53:33 -0000
@@ -626,6 +626,88 @@ static const unsigned int mips16_to_32_r
 #define RELAX_RELOC3(i) (((i) >> 1) & 1)
 #define RELAX_WARN(i) ((i) & 1)
 
+/* Branch without likely bit.  If label is out of range, we turn:
+
+ 	beq reg1, reg2, label
+	delay slot
+
+   into
+
+        bne reg1, reg2, 0f
+        nop
+        j label
+     0: delay slot
+
+   with the following opcode replacements:
+
+	beq <-> bne
+	blez <-> bgtz
+	bltz <-> bgez
+	bc1f <-> bc1t
+
+	bltzal <-> bgezal  (with jal label instead of j label)
+
+   Even though keeping the delay slot instruction in the delay slot of
+   the branch would be more efficient, it would be very tricky to do
+   correctly, because we'd have to introduce a variable frag *after*
+   the delay slot instruction, and expand that instead.  Let's do it
+   the easy way for now, even if the branch-not-taken case now costs
+   one additional instruction.  Out-of-range branches are not supposed
+   to be common, anyway.
+
+   Branch likely.  If label is out of range, we turn:
+
+	beql reg1, reg2, label
+	delay slot (annulled if branch not taken)
+
+   into
+
+        beql reg1, reg2, 1f
+        nop
+        beqzl $0, 2f
+        nop
+     1: j[al] label
+        delay slot (executed only if branch taken)
+     2:
+
+   It would be possible to generate a shorter sequence by losing the
+   likely bit, generating something like:
+     
+	bne reg1, reg2, 0f
+	nop
+	j[al] label
+	delay slot (executed only if branch taken)
+     0:
+
+	beql -> bne
+	bnel -> beq
+	blezl -> bgtz
+	bgtzl -> blez
+	bltzl -> bgez
+	bgezl -> bltz
+	bc1fl -> bc1t
+	bc1tl -> bc1f
+
+	bltzall -> bgezal  (with jal label instead of j label)
+	bgezall -> bltzal  (ditto)
+
+
+   but it's not clear that it would actually improve performance.  */
+#define RELAX_BRANCH_ENCODE(reloc_s2, uncond, likely, link, toofar) \
+  ((relax_substateT) \
+   (0xc0000000 \
+    | ((toofar) ? 1 : 0) \
+    | ((link) ? 2 : 0) \
+    | ((likely) ? 4 : 0) \
+    | ((uncond) ? 8 : 0) \
+    | ((reloc_s2) ? 16 : 0)))
+#define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000)
+#define RELAX_BRANCH_RELOC_S2(i) (((i) & 16) != 0)
+#define RELAX_BRANCH_UNCOND(i) (((i) & 8) != 0)
+#define RELAX_BRANCH_LIKELY(i) (((i) & 4) != 0)
+#define RELAX_BRANCH_LINK(i) (((i) & 2) != 0)
+#define RELAX_BRANCH_TOOFAR(i) (((i) & 1))
+
 /* For mips16 code, we use an entirely different form of relaxation.
    mips16 supports two versions of most instructions which take
    immediate values: a small one which takes some small value, and a
@@ -653,7 +735,7 @@ static const unsigned int mips16_to_32_r
    | ((ext) ? 0x200 : 0)					\
    | ((dslot) ? 0x400 : 0)					\
    | ((jal_dslot) ? 0x800 : 0))
-#define RELAX_MIPS16_P(i) (((i) & 0x80000000) != 0)
+#define RELAX_MIPS16_P(i) (((i) & 0xc0000000) == 0x80000000)
 #define RELAX_MIPS16_TYPE(i) ((i) & 0xff)
 #define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x100) != 0)
 #define RELAX_MIPS16_USER_EXT(i) (((i) & 0x200) != 0)
@@ -757,6 +839,7 @@ static void s_mips_weakext PARAMS ((int)
 static void s_mips_file PARAMS ((int));
 static void s_mips_loc PARAMS ((int));
 static int mips16_extended_frag PARAMS ((fragS *, asection *, long));
+static int relaxed_branch_length (fragS *, asection *, int);
 static int validate_mips_insn PARAMS ((const struct mips_opcode *));
 static void show PARAMS ((FILE *, const char *, int *, int *));
 #ifdef OBJ_ELF
@@ -1766,7 +1849,32 @@ append_insn (place, ip, address_expr, re
 	}
     }
 
-  if (*reloc_type > BFD_RELOC_UNUSED)
+  if (place == NULL
+      && address_expr
+      && ((*reloc_type == BFD_RELOC_16_PCREL
+	   && address_expr->X_op != O_constant)
+	  || *reloc_type == BFD_RELOC_16_PCREL_S2)
+      && (pinfo & INSN_UNCOND_BRANCH_DELAY || pinfo & INSN_COND_BRANCH_DELAY
+	  || pinfo & INSN_COND_BRANCH_LIKELY)
+      && !mips_opts.mips16)
+    {
+      f = frag_var (rs_machine_dependent,
+		    relaxed_branch_length
+		    (NULL, NULL,
+		     (pinfo & INSN_UNCOND_BRANCH_DELAY) ? -1
+		     : (pinfo & INSN_COND_BRANCH_LIKELY) ? 1 : 0), 4,
+		    RELAX_BRANCH_ENCODE
+		    (*reloc_type == BFD_RELOC_16_PCREL_S2,
+		     pinfo & INSN_UNCOND_BRANCH_DELAY,
+		     pinfo & INSN_COND_BRANCH_LIKELY,
+		     pinfo & INSN_WRITE_GPR_31,
+		     0),
+		    address_expr->X_add_symbol,
+		    address_expr->X_add_number,
+		    0);
+      *reloc_type = BFD_RELOC_UNUSED;
+    }
+  else if (*reloc_type > BFD_RELOC_UNUSED)
     {
       /* We need to set up a variant frag.  */
       assert (mips_opts.mips16 && address_expr != NULL);
@@ -12428,6 +12536,74 @@ mips16_extended_frag (fragp, sec, stretc
     return 0;
 }
 
+/* Compute the length of a branch sequence, and adjust the
+   RELAX_BRANCH_TOOFAR bit accordingly.  If FRAGP is NULL, the
+   worst-case length is computed, with UPDATE being used to indicate
+   whether an unconditional (-1), branch-likely (+1) or regular (0)
+   branch is to be computed.  */
+static int
+relaxed_branch_length (fragp, sec, update)
+     fragS *fragp;
+     asection *sec;
+     int update;
+{
+  boolean toofar;
+  int length;
+
+  if (fragp
+      && S_IS_DEFINED (fragp->fr_symbol)
+      && sec == S_GET_SEGMENT (fragp->fr_symbol))
+    {
+      addressT addr;
+      offsetT val;
+
+      val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
+
+      addr = fragp->fr_address + fragp->fr_fix;
+
+      val -= addr;
+
+      toofar = val < - (0x8000 << 2) || val >= (0x8000 << 2);
+    }
+  else if (fragp)
+    /* If the symbol is not defined or it's in a different segment,
+       assume the user knows what's going on and emit a short
+       branch.  */
+    toofar = false;
+  else
+    toofar = true;
+
+  if (fragp && update && toofar != RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
+    fragp->fr_subtype
+      = RELAX_BRANCH_ENCODE (RELAX_BRANCH_RELOC_S2 (fragp->fr_subtype),
+			     RELAX_BRANCH_UNCOND (fragp->fr_subtype),
+			     RELAX_BRANCH_LIKELY (fragp->fr_subtype),
+			     RELAX_BRANCH_LINK (fragp->fr_subtype),
+			     toofar);
+
+  length = 4;
+  if (toofar)
+    {
+      if (fragp ? RELAX_BRANCH_LIKELY (fragp->fr_subtype) : (update > 0))
+	length += 8;
+
+      if (mips_pic != NO_PIC)
+	{
+	  /* Additional space for PIC loading of target address.  */
+	  length += 8;
+	  if (mips_opts.isa == ISA_MIPS1)
+	    /* Additional space for $at-stabilizing nop.  */
+	    length += 4;
+	}
+
+      /* If branch is conditional.  */
+      if (fragp ? !RELAX_BRANCH_UNCOND (fragp->fr_subtype) : (update >= 0))
+	length += 8;
+    }
+  
+  return length;
+}
+
 /* Estimate the size of a frag before relaxing.  Unless this is the
    mips16, we are not really relaxing here, and the final size is
    encoded in the subtype information.  For the mips16, we have to
@@ -12441,6 +12617,14 @@ md_estimate_size_before_relax (fragp, se
   int change = 0;
   boolean linkonce = false;
 
+  if (RELAX_BRANCH_P (fragp->fr_subtype))
+    {
+
+      fragp->fr_var = relaxed_branch_length (fragp, segtype, false);
+      
+      return fragp->fr_var;
+    }
+
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     /* We don't want to modify the EXTENDED bit here; it might get us
        into infinite loops.  We change it only in mips_relax_frag().  */
@@ -12797,10 +12981,20 @@ tc_gen_reloc (section, fixp)
    the current size of the frag should change.  */
 
 int
-mips_relax_frag (fragp, stretch)
+mips_relax_frag (sec, fragp, stretch)
+     asection *sec;
      fragS *fragp;
      long stretch;
 {
+  if (RELAX_BRANCH_P (fragp->fr_subtype))
+    {
+      offsetT old_var = fragp->fr_var;
+      
+      fragp->fr_var = relaxed_branch_length (fragp, sec, true);
+
+      return fragp->fr_var - old_var;
+    }
+
   if (! RELAX_MIPS16_P (fragp->fr_subtype))
     return 0;
 
@@ -12832,6 +13026,213 @@ md_convert_frag (abfd, asec, fragp)
 {
   int old, new;
   char *fixptr;
+
+  if (RELAX_BRANCH_P (fragp->fr_subtype))
+    {
+      bfd_byte *buf;
+      unsigned long insn;
+      expressionS exp;
+      fixS *fixp;
+      
+      buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
+
+      if (target_big_endian)
+	insn = bfd_getb32 (buf);
+      else
+	insn = bfd_getl32 (buf);
+	  
+      if (!RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
+	{
+	  /* We generate a fixup instead of applying it right now
+	     because, if there are linker relaxations, we're going to
+	     need the relocations.  */
+	  exp.X_op = O_symbol;
+	  exp.X_add_symbol = fragp->fr_symbol;
+	  exp.X_add_number = fragp->fr_offset;
+
+	  fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+			      4, &exp, 1,
+			      RELAX_BRANCH_RELOC_S2 (fragp->fr_subtype)
+			      ? BFD_RELOC_16_PCREL_S2
+			      : BFD_RELOC_16_PCREL);
+	  fixp->fx_file = fragp->fr_file;
+	  fixp->fx_line = fragp->fr_line;
+	  
+	  md_number_to_chars ((char *)buf, insn, 4);
+	  buf += 4;
+	}
+      else
+	{
+	  int i;
+
+	  if (RELAX_BRANCH_UNCOND (fragp->fr_subtype))
+	    goto uncond;
+
+	  if (!RELAX_BRANCH_LIKELY (fragp->fr_subtype))
+	    {
+	      /* Reverse the branch.  */
+	      switch ((insn >> 28) & 0xf)
+		{
+		case 4:
+		  /* bc[0-3][tf]l? and bc1any[24][ft] instructions can
+		     have the condition reversed by tweaking a single
+		     bit, and their opcodes all have 0x4???????.  */
+		  assert ((insn & 0xf1000000) == 0x41000000);
+		  insn ^= 0x00010000;
+		  break;
+
+		case 0:
+		  /* bltz	0x04000000	bgez	0x04010000
+		     bltzal	0x04100000	bgezal	0x04110000 */
+		  assert ((insn & 0xfc0e0000) == 0x04000000);
+		  insn ^= 0x00010000;
+		  break;
+		  
+		case 1:
+		  /* beq	0x10000000	bne	0x14000000
+		     blez	0x18000000	bgtz	0x1c000000 */
+		  insn ^= 0x04000000;
+		  break;
+
+		default:
+		  abort ();
+		}
+	    }
+
+	  if (RELAX_BRANCH_LINK (fragp->fr_subtype))
+	    {
+	      /* Clear the and-link bit.  */
+	      assert ((insn & 0xfc1c0000) == 0x04100000);
+
+	      /* bltzal	0x04100000	bgezal	0x04110000
+		bltzall	0x04120000     bgezall	0x04130000 */
+	      insn &= ~0x00100000;
+	    }
+
+	  /* Branch over the branch (if the branch was likely) or the
+	     full jump (not likely case).  Compute the offset from the
+	     current instruction to branch to.  */
+	  if (RELAX_BRANCH_LIKELY (fragp->fr_subtype))
+	    i = 16;
+	  else
+	    {
+	      /* How many bytes in instructions we've already emitted?  */
+	      i = buf - (bfd_byte *)fragp->fr_literal - fragp->fr_fix;
+	      /* How many bytes in instructions from here to the end?  */
+	      i = fragp->fr_var - i;
+	    }
+	  /* Convert to instruction count.  */
+	  i >>= 2;
+	  /* Branch counts from the next instruction.  */
+	  i--; 
+	  insn |= i;
+	  /* Branch over the jump.  */
+	  md_number_to_chars ((char *)buf, insn, 4);
+	  buf += 4;
+
+	  /* Nop */
+	  md_number_to_chars ((char*)buf, 0, 4);
+	  buf += 4;
+
+	  if (RELAX_BRANCH_LIKELY (fragp->fr_subtype))
+	    {
+	      /* beqzl $0, 2f */
+	      insn = 0x50000000;
+	      /* Compute the PC offset from the current instruction to
+		 the end of the variable frag.  */
+	      /* How many bytes in instructions we've already emitted?  */
+	      i = buf - (bfd_byte *)fragp->fr_literal - fragp->fr_fix;
+	      /* How many bytes in instructions from here to the end?  */
+	      i = fragp->fr_var - i;
+	      /* Convert to instruction count.  */
+	      i >>= 2;
+	      /* Don't decrement i, because we want to branch over the
+		 delay slot.  */
+
+	      insn |= i;
+	      md_number_to_chars ((char *)buf, insn, 4);
+	      buf += 4;
+
+	      md_number_to_chars ((char *)buf, 0, 4);
+	      buf += 4;
+	    }
+
+	uncond:
+	  if (mips_pic == NO_PIC)
+	    {
+	      /* j or jal.  */
+	      insn = (RELAX_BRANCH_LINK (fragp->fr_subtype)
+		      ? 0x0c000000 : 0x08000000);
+	      exp.X_op = O_symbol;
+	      exp.X_add_symbol = fragp->fr_symbol;
+	      exp.X_add_number = fragp->fr_offset;
+
+	      fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+				  4, &exp, 0, BFD_RELOC_MIPS_JMP);
+	      fixp->fx_file = fragp->fr_file;
+	      fixp->fx_line = fragp->fr_line;
+
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+	    }
+	  else
+	    {
+	      /* lw/ld $at, <sym>($gp)  R_MIPS_GOT16 */
+	      insn = HAVE_64BIT_ADDRESSES ? 0xdf810000 : 0x8f810000;
+	      exp.X_op = O_symbol;
+	      exp.X_add_symbol = fragp->fr_symbol;
+	      exp.X_add_number = fragp->fr_offset;
+
+	      if (fragp->fr_offset)
+		{
+		  exp.X_add_symbol = make_expr_symbol (&exp);
+		  exp.X_add_number = 0;
+		}
+
+	      fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+				  4, &exp, 0, BFD_RELOC_MIPS_GOT16);
+	      fixp->fx_file = fragp->fr_file;
+	      fixp->fx_line = fragp->fr_line;
+
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+	      
+	      if (mips_opts.isa == ISA_MIPS1)
+		{
+		  /* nop */
+		  md_number_to_chars ((char*)buf, 0, 4);
+		  buf += 4;
+		}
+
+	      /* d/addiu $at, $at, <sym>  R_MIPS_LO16 */
+	      insn = HAVE_64BIT_ADDRESSES ? 0x64210000 : 0x24210000;
+
+	      fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+				  4, &exp, 0, BFD_RELOC_LO16);
+	      fixp->fx_file = fragp->fr_file;
+	      fixp->fx_line = fragp->fr_line;
+	      
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+
+	      /* j(al)r $at.  */
+	      if (RELAX_BRANCH_LINK (fragp->fr_subtype))
+		insn = 0x0020f809;
+	      else
+		insn = 0x00200008;
+
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+	    }
+	}
+
+      assert (buf == (bfd_byte *)fragp->fr_literal
+	      + fragp->fr_fix + fragp->fr_var);
+
+      fragp->fr_fix += fragp->fr_var;
+
+      return;
+    }
 
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     {
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.40
diff -u -p -r1.40 mips.exp
--- gas/testsuite/gas/mips/mips.exp 12 Aug 2002 08:30:50 -0000 1.40
+++ gas/testsuite/gas/mips/mips.exp 14 Sep 2002 05:53:33 -0000
@@ -154,8 +154,6 @@ if { [istarget mips*-*-*] } then {
     run_dump_test "sb1-ext-mdmx"
     run_dump_test "sb1-ext-ps"
 
-    # It will always fail until someone fixes it.
-    setup_xfail "mips*-*-*"
     run_dump_test "relax"
 
     run_list_test "illegal" ""
Index: gas/testsuite/gas/mips/relax.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/relax.d,v
retrieving revision 1.1
diff -u -p -r1.1 relax.d
--- gas/testsuite/gas/mips/relax.d 9 Jun 2001 06:25:55 -0000 1.1
+++ gas/testsuite/gas/mips/relax.d 14 Sep 2002 05:53:33 -0000
@@ -1,3 +1,4 @@
+#as: -KPIC -mips3 -32
 #objdump: -dr --prefix-addresses -mmips:4000
 #name: MIPS relax
 
@@ -5,4 +6,389 @@
 
 .*: +file format .*mips.*
 
-Disassembly of section .text:
+Disassembly of section \.text:
+00000000 <foo> lw	at,2\(gp\)
+			0: R_MIPS_GOT16	\.text
+00000004 <foo\+0x4> addiu	at,at,592
+			4: R_MIPS_LO16	\.text
+00000008 <foo\+0x8> jr	at
+0000000c <foo\+0xc> nop
+00000010 <foo\+0x10> lw	at,2\(gp\)
+			10: R_MIPS_GOT16	\.text
+00000014 <foo\+0x14> addiu	at,at,592
+			14: R_MIPS_LO16	\.text
+00000018 <foo\+0x18> jalr	at
+0000001c <foo\+0x1c> nop
+00000020 <foo\+0x20> bne	v0,v1,00000034 <foo\+0x34>
+00000024 <foo\+0x24> nop
+00000028 <foo\+0x28> lw	at,2\(gp\)
+			28: R_MIPS_GOT16	\.text
+0000002c <foo\+0x2c> addiu	at,at,592
+			2c: R_MIPS_LO16	\.text
+00000030 <foo\+0x30> jr	at
+00000034 <foo\+0x34> nop
+00000038 <foo\+0x38> beq	a0,a1,0000004c <foo\+0x4c>
+0000003c <foo\+0x3c> nop
+00000040 <foo\+0x40> lw	at,2\(gp\)
+			40: R_MIPS_GOT16	\.text
+00000044 <foo\+0x44> addiu	at,at,592
+			44: R_MIPS_LO16	\.text
+00000048 <foo\+0x48> jr	at
+0000004c <foo\+0x4c> nop
+00000050 <foo\+0x50> bgtz	v0,00000064 <foo\+0x64>
+00000054 <foo\+0x54> nop
+00000058 <foo\+0x58> lw	at,2\(gp\)
+			58: R_MIPS_GOT16	\.text
+0000005c <foo\+0x5c> addiu	at,at,592
+			5c: R_MIPS_LO16	\.text
+00000060 <foo\+0x60> jr	at
+00000064 <foo\+0x64> nop
+00000068 <foo\+0x68> blez	v1,0000007c <foo\+0x7c>
+0000006c <foo\+0x6c> nop
+00000070 <foo\+0x70> lw	at,2\(gp\)
+			70: R_MIPS_GOT16	\.text
+00000074 <foo\+0x74> addiu	at,at,592
+			74: R_MIPS_LO16	\.text
+00000078 <foo\+0x78> jr	at
+0000007c <foo\+0x7c> nop
+00000080 <foo\+0x80> bgez	a0,00000094 <foo\+0x94>
+00000084 <foo\+0x84> nop
+00000088 <foo\+0x88> lw	at,2\(gp\)
+			88: R_MIPS_GOT16	\.text
+0000008c <foo\+0x8c> addiu	at,at,592
+			8c: R_MIPS_LO16	\.text
+00000090 <foo\+0x90> jr	at
+00000094 <foo\+0x94> nop
+00000098 <foo\+0x98> bltz	a1,000000ac <foo\+0xac>
+0000009c <foo\+0x9c> nop
+000000a0 <foo\+0xa0> lw	at,2\(gp\)
+			a0: R_MIPS_GOT16	\.text
+000000a4 <foo\+0xa4> addiu	at,at,592
+			a4: R_MIPS_LO16	\.text
+000000a8 <foo\+0xa8> jr	at
+000000ac <foo\+0xac> nop
+000000b0 <foo\+0xb0> bc1t	000000c4 <foo\+0xc4>
+000000b4 <foo\+0xb4> nop
+000000b8 <foo\+0xb8> lw	at,2\(gp\)
+			b8: R_MIPS_GOT16	\.text
+000000bc <foo\+0xbc> addiu	at,at,592
+			bc: R_MIPS_LO16	\.text
+000000c0 <foo\+0xc0> jr	at
+000000c4 <foo\+0xc4> nop
+000000c8 <foo\+0xc8> bc1f	000000dc <foo\+0xdc>
+000000cc <foo\+0xcc> nop
+000000d0 <foo\+0xd0> lw	at,2\(gp\)
+			d0: R_MIPS_GOT16	\.text
+000000d4 <foo\+0xd4> addiu	at,at,592
+			d4: R_MIPS_LO16	\.text
+000000d8 <foo\+0xd8> jr	at
+000000dc <foo\+0xdc> nop
+000000e0 <foo\+0xe0> bgez	v0,000000f4 <foo\+0xf4>
+000000e4 <foo\+0xe4> nop
+000000e8 <foo\+0xe8> lw	at,2\(gp\)
+			e8: R_MIPS_GOT16	\.text
+000000ec <foo\+0xec> addiu	at,at,592
+			ec: R_MIPS_LO16	\.text
+000000f0 <foo\+0xf0> jalr	at
+000000f4 <foo\+0xf4> nop
+000000f8 <foo\+0xf8> bltz	v1,0000010c <foo\+0x10c>
+000000fc <foo\+0xfc> nop
+00000100 <foo\+0x100> lw	at,2\(gp\)
+			100: R_MIPS_GOT16	\.text
+00000104 <foo\+0x104> addiu	at,at,592
+			104: R_MIPS_LO16	\.text
+00000108 <foo\+0x108> jalr	at
+0000010c <foo\+0x10c> nop
+00000110 <foo\+0x110> beql	v0,v1,00000120 <foo\+0x120>
+00000114 <foo\+0x114> nop
+00000118 <foo\+0x118> beqzl	zero,00000130 <foo\+0x130>
+0000011c <foo\+0x11c> nop
+00000120 <foo\+0x120> lw	at,2\(gp\)
+			120: R_MIPS_GOT16	\.text
+00000124 <foo\+0x124> addiu	at,at,592
+			124: R_MIPS_LO16	\.text
+00000128 <foo\+0x128> jr	at
+0000012c <foo\+0x12c> nop
+00000130 <foo\+0x130> bnel	a0,a1,00000140 <foo\+0x140>
+00000134 <foo\+0x134> nop
+00000138 <foo\+0x138> beqzl	zero,00000150 <foo\+0x150>
+0000013c <foo\+0x13c> nop
+00000140 <foo\+0x140> lw	at,2\(gp\)
+			140: R_MIPS_GOT16	\.text
+00000144 <foo\+0x144> addiu	at,at,592
+			144: R_MIPS_LO16	\.text
+00000148 <foo\+0x148> jr	at
+0000014c <foo\+0x14c> nop
+00000150 <foo\+0x150> blezl	v0,00000160 <foo\+0x160>
+00000154 <foo\+0x154> nop
+00000158 <foo\+0x158> beqzl	zero,00000170 <foo\+0x170>
+0000015c <foo\+0x15c> nop
+00000160 <foo\+0x160> lw	at,2\(gp\)
+			160: R_MIPS_GOT16	\.text
+00000164 <foo\+0x164> addiu	at,at,592
+			164: R_MIPS_LO16	\.text
+00000168 <foo\+0x168> jr	at
+0000016c <foo\+0x16c> nop
+00000170 <foo\+0x170> bgtzl	v1,00000180 <foo\+0x180>
+00000174 <foo\+0x174> nop
+00000178 <foo\+0x178> beqzl	zero,00000190 <foo\+0x190>
+0000017c <foo\+0x17c> nop
+00000180 <foo\+0x180> lw	at,2\(gp\)
+			180: R_MIPS_GOT16	\.text
+00000184 <foo\+0x184> addiu	at,at,592
+			184: R_MIPS_LO16	\.text
+00000188 <foo\+0x188> jr	at
+0000018c <foo\+0x18c> nop
+00000190 <foo\+0x190> bltzl	a0,000001a0 <foo\+0x1a0>
+00000194 <foo\+0x194> nop
+00000198 <foo\+0x198> beqzl	zero,000001b0 <foo\+0x1b0>
+0000019c <foo\+0x19c> nop
+000001a0 <foo\+0x1a0> lw	at,2\(gp\)
+			1a0: R_MIPS_GOT16	\.text
+000001a4 <foo\+0x1a4> addiu	at,at,592
+			1a4: R_MIPS_LO16	\.text
+000001a8 <foo\+0x1a8> jr	at
+000001ac <foo\+0x1ac> nop
+000001b0 <foo\+0x1b0> bgezl	a1,000001c0 <foo\+0x1c0>
+000001b4 <foo\+0x1b4> nop
+000001b8 <foo\+0x1b8> beqzl	zero,000001d0 <foo\+0x1d0>
+000001bc <foo\+0x1bc> nop
+000001c0 <foo\+0x1c0> lw	at,2\(gp\)
+			1c0: R_MIPS_GOT16	\.text
+000001c4 <foo\+0x1c4> addiu	at,at,592
+			1c4: R_MIPS_LO16	\.text
+000001c8 <foo\+0x1c8> jr	at
+000001cc <foo\+0x1cc> nop
+000001d0 <foo\+0x1d0> bc1fl	000001e0 <foo\+0x1e0>
+000001d4 <foo\+0x1d4> nop
+000001d8 <foo\+0x1d8> beqzl	zero,000001f0 <foo\+0x1f0>
+000001dc <foo\+0x1dc> nop
+000001e0 <foo\+0x1e0> lw	at,2\(gp\)
+			1e0: R_MIPS_GOT16	\.text
+000001e4 <foo\+0x1e4> addiu	at,at,592
+			1e4: R_MIPS_LO16	\.text
+000001e8 <foo\+0x1e8> jr	at
+000001ec <foo\+0x1ec> nop
+000001f0 <foo\+0x1f0> bc1tl	00000200 <foo\+0x200>
+000001f4 <foo\+0x1f4> nop
+000001f8 <foo\+0x1f8> beqzl	zero,00000210 <foo\+0x210>
+000001fc <foo\+0x1fc> nop
+00000200 <foo\+0x200> lw	at,2\(gp\)
+			200: R_MIPS_GOT16	\.text
+00000204 <foo\+0x204> addiu	at,at,592
+			204: R_MIPS_LO16	\.text
+00000208 <foo\+0x208> jr	at
+0000020c <foo\+0x20c> nop
+00000210 <foo\+0x210> bltzl	v0,00000220 <foo\+0x220>
+00000214 <foo\+0x214> nop
+00000218 <foo\+0x218> beqzl	zero,00000230 <foo\+0x230>
+0000021c <foo\+0x21c> nop
+00000220 <foo\+0x220> lw	at,2\(gp\)
+			220: R_MIPS_GOT16	\.text
+00000224 <foo\+0x224> addiu	at,at,592
+			224: R_MIPS_LO16	\.text
+00000228 <foo\+0x228> jalr	at
+0000022c <foo\+0x22c> nop
+00000230 <foo\+0x230> bgezl	v1,00000240 <foo\+0x240>
+00000234 <foo\+0x234> nop
+00000238 <foo\+0x238> beqzl	zero,00000250 <foo\+0x250>
+0000023c <foo\+0x23c> nop
+00000240 <foo\+0x240> lw	at,2\(gp\)
+			240: R_MIPS_GOT16	\.text
+00000244 <foo\+0x244> addiu	at,at,592
+			244: R_MIPS_LO16	\.text
+00000248 <foo\+0x248> jalr	at
+0000024c <foo\+0x24c> nop
+	\.\.\.
+00020250 <bar> lw	at,0\(gp\)
+			20250: R_MIPS_GOT16	\.text
+00020254 <bar\+0x4> addiu	at,at,0
+			20254: R_MIPS_LO16	\.text
+00020258 <bar\+0x8> jr	at
+0002025c <bar\+0xc> nop
+00020260 <bar\+0x10> lw	at,0\(gp\)
+			20260: R_MIPS_GOT16	\.text
+00020264 <bar\+0x14> addiu	at,at,0
+			20264: R_MIPS_LO16	\.text
+00020268 <bar\+0x18> jalr	at
+0002026c <bar\+0x1c> nop
+00020270 <bar\+0x20> bne	v0,v1,00020284 <bar\+0x34>
+00020274 <bar\+0x24> nop
+00020278 <bar\+0x28> lw	at,0\(gp\)
+			20278: R_MIPS_GOT16	\.text
+0002027c <bar\+0x2c> addiu	at,at,0
+			2027c: R_MIPS_LO16	\.text
+00020280 <bar\+0x30> jr	at
+00020284 <bar\+0x34> nop
+00020288 <bar\+0x38> beq	a0,a1,0002029c <bar\+0x4c>
+0002028c <bar\+0x3c> nop
+00020290 <bar\+0x40> lw	at,0\(gp\)
+			20290: R_MIPS_GOT16	\.text
+00020294 <bar\+0x44> addiu	at,at,0
+			20294: R_MIPS_LO16	\.text
+00020298 <bar\+0x48> jr	at
+0002029c <bar\+0x4c> nop
+000202a0 <bar\+0x50> bgtz	v0,000202b4 <bar\+0x64>
+000202a4 <bar\+0x54> nop
+000202a8 <bar\+0x58> lw	at,0\(gp\)
+			202a8: R_MIPS_GOT16	\.text
+000202ac <bar\+0x5c> addiu	at,at,0
+			202ac: R_MIPS_LO16	\.text
+000202b0 <bar\+0x60> jr	at
+000202b4 <bar\+0x64> nop
+000202b8 <bar\+0x68> blez	v1,000202cc <bar\+0x7c>
+000202bc <bar\+0x6c> nop
+000202c0 <bar\+0x70> lw	at,0\(gp\)
+			202c0: R_MIPS_GOT16	\.text
+000202c4 <bar\+0x74> addiu	at,at,0
+			202c4: R_MIPS_LO16	\.text
+000202c8 <bar\+0x78> jr	at
+000202cc <bar\+0x7c> nop
+000202d0 <bar\+0x80> bgez	a0,000202e4 <bar\+0x94>
+000202d4 <bar\+0x84> nop
+000202d8 <bar\+0x88> lw	at,0\(gp\)
+			202d8: R_MIPS_GOT16	\.text
+000202dc <bar\+0x8c> addiu	at,at,0
+			202dc: R_MIPS_LO16	\.text
+000202e0 <bar\+0x90> jr	at
+000202e4 <bar\+0x94> nop
+000202e8 <bar\+0x98> bltz	a1,000202fc <bar\+0xac>
+000202ec <bar\+0x9c> nop
+000202f0 <bar\+0xa0> lw	at,0\(gp\)
+			202f0: R_MIPS_GOT16	\.text
+000202f4 <bar\+0xa4> addiu	at,at,0
+			202f4: R_MIPS_LO16	\.text
+000202f8 <bar\+0xa8> jr	at
+000202fc <bar\+0xac> nop
+00020300 <bar\+0xb0> bc1t	00020314 <bar\+0xc4>
+00020304 <bar\+0xb4> nop
+00020308 <bar\+0xb8> lw	at,0\(gp\)
+			20308: R_MIPS_GOT16	\.text
+0002030c <bar\+0xbc> addiu	at,at,0
+			2030c: R_MIPS_LO16	\.text
+00020310 <bar\+0xc0> jr	at
+00020314 <bar\+0xc4> nop
+00020318 <bar\+0xc8> bc1f	0002032c <bar\+0xdc>
+0002031c <bar\+0xcc> nop
+00020320 <bar\+0xd0> lw	at,0\(gp\)
+			20320: R_MIPS_GOT16	\.text
+00020324 <bar\+0xd4> addiu	at,at,0
+			20324: R_MIPS_LO16	\.text
+00020328 <bar\+0xd8> jr	at
+0002032c <bar\+0xdc> nop
+00020330 <bar\+0xe0> bgez	v0,00020344 <bar\+0xf4>
+00020334 <bar\+0xe4> nop
+00020338 <bar\+0xe8> lw	at,0\(gp\)
+			20338: R_MIPS_GOT16	\.text
+0002033c <bar\+0xec> addiu	at,at,0
+			2033c: R_MIPS_LO16	\.text
+00020340 <bar\+0xf0> jalr	at
+00020344 <bar\+0xf4> nop
+00020348 <bar\+0xf8> bltz	v1,0002035c <bar\+0x10c>
+0002034c <bar\+0xfc> nop
+00020350 <bar\+0x100> lw	at,0\(gp\)
+			20350: R_MIPS_GOT16	\.text
+00020354 <bar\+0x104> addiu	at,at,0
+			20354: R_MIPS_LO16	\.text
+00020358 <bar\+0x108> jalr	at
+0002035c <bar\+0x10c> nop
+00020360 <bar\+0x110> beql	v0,v1,00020370 <bar\+0x120>
+00020364 <bar\+0x114> nop
+00020368 <bar\+0x118> beqzl	zero,00020380 <bar\+0x130>
+0002036c <bar\+0x11c> nop
+00020370 <bar\+0x120> lw	at,0\(gp\)
+			20370: R_MIPS_GOT16	\.text
+00020374 <bar\+0x124> addiu	at,at,0
+			20374: R_MIPS_LO16	\.text
+00020378 <bar\+0x128> jr	at
+0002037c <bar\+0x12c> nop
+00020380 <bar\+0x130> bnel	a0,a1,00020390 <bar\+0x140>
+00020384 <bar\+0x134> nop
+00020388 <bar\+0x138> beqzl	zero,000203a0 <bar\+0x150>
+0002038c <bar\+0x13c> nop
+00020390 <bar\+0x140> lw	at,0\(gp\)
+			20390: R_MIPS_GOT16	\.text
+00020394 <bar\+0x144> addiu	at,at,0
+			20394: R_MIPS_LO16	\.text
+00020398 <bar\+0x148> jr	at
+0002039c <bar\+0x14c> nop
+000203a0 <bar\+0x150> blezl	v0,000203b0 <bar\+0x160>
+000203a4 <bar\+0x154> nop
+000203a8 <bar\+0x158> beqzl	zero,000203c0 <bar\+0x170>
+000203ac <bar\+0x15c> nop
+000203b0 <bar\+0x160> lw	at,0\(gp\)
+			203b0: R_MIPS_GOT16	\.text
+000203b4 <bar\+0x164> addiu	at,at,0
+			203b4: R_MIPS_LO16	\.text
+000203b8 <bar\+0x168> jr	at
+000203bc <bar\+0x16c> nop
+000203c0 <bar\+0x170> bgtzl	v1,000203d0 <bar\+0x180>
+000203c4 <bar\+0x174> nop
+000203c8 <bar\+0x178> beqzl	zero,000203e0 <bar\+0x190>
+000203cc <bar\+0x17c> nop
+000203d0 <bar\+0x180> lw	at,0\(gp\)
+			203d0: R_MIPS_GOT16	\.text
+000203d4 <bar\+0x184> addiu	at,at,0
+			203d4: R_MIPS_LO16	\.text
+000203d8 <bar\+0x188> jr	at
+000203dc <bar\+0x18c> nop
+000203e0 <bar\+0x190> bltzl	a0,000203f0 <bar\+0x1a0>
+000203e4 <bar\+0x194> nop
+000203e8 <bar\+0x198> beqzl	zero,00020400 <bar\+0x1b0>
+000203ec <bar\+0x19c> nop
+000203f0 <bar\+0x1a0> lw	at,0\(gp\)
+			203f0: R_MIPS_GOT16	\.text
+000203f4 <bar\+0x1a4> addiu	at,at,0
+			203f4: R_MIPS_LO16	\.text
+000203f8 <bar\+0x1a8> jr	at
+000203fc <bar\+0x1ac> nop
+00020400 <bar\+0x1b0> bgezl	a1,00020410 <bar\+0x1c0>
+00020404 <bar\+0x1b4> nop
+00020408 <bar\+0x1b8> beqzl	zero,00020420 <bar\+0x1d0>
+0002040c <bar\+0x1bc> nop
+00020410 <bar\+0x1c0> lw	at,0\(gp\)
+			20410: R_MIPS_GOT16	\.text
+00020414 <bar\+0x1c4> addiu	at,at,0
+			20414: R_MIPS_LO16	\.text
+00020418 <bar\+0x1c8> jr	at
+0002041c <bar\+0x1cc> nop
+00020420 <bar\+0x1d0> bc1fl	00020430 <bar\+0x1e0>
+00020424 <bar\+0x1d4> nop
+00020428 <bar\+0x1d8> beqzl	zero,00020440 <bar\+0x1f0>
+0002042c <bar\+0x1dc> nop
+00020430 <bar\+0x1e0> lw	at,0\(gp\)
+			20430: R_MIPS_GOT16	\.text
+00020434 <bar\+0x1e4> addiu	at,at,0
+			20434: R_MIPS_LO16	\.text
+00020438 <bar\+0x1e8> jr	at
+0002043c <bar\+0x1ec> nop
+00020440 <bar\+0x1f0> bc1tl	00020450 <bar\+0x200>
+00020444 <bar\+0x1f4> nop
+00020448 <bar\+0x1f8> beqzl	zero,00020460 <bar\+0x210>
+0002044c <bar\+0x1fc> nop
+00020450 <bar\+0x200> lw	at,0\(gp\)
+			20450: R_MIPS_GOT16	\.text
+00020454 <bar\+0x204> addiu	at,at,0
+			20454: R_MIPS_LO16	\.text
+00020458 <bar\+0x208> jr	at
+0002045c <bar\+0x20c> nop
+00020460 <bar\+0x210> bltzl	v0,00020470 <bar\+0x220>
+00020464 <bar\+0x214> nop
+00020468 <bar\+0x218> beqzl	zero,00020480 <bar\+0x230>
+0002046c <bar\+0x21c> nop
+00020470 <bar\+0x220> lw	at,0\(gp\)
+			20470: R_MIPS_GOT16	\.text
+00020474 <bar\+0x224> addiu	at,at,0
+			20474: R_MIPS_LO16	\.text
+00020478 <bar\+0x228> jalr	at
+0002047c <bar\+0x22c> nop
+00020480 <bar\+0x230> bgezl	v1,00020490 <bar\+0x240>
+00020484 <bar\+0x234> nop
+00020488 <bar\+0x238> beqzl	zero,000204a0 <bar\+0x250>
+0002048c <bar\+0x23c> nop
+00020490 <bar\+0x240> lw	at,0\(gp\)
+			20490: R_MIPS_GOT16	\.text
+00020494 <bar\+0x244> addiu	at,at,0
+			20494: R_MIPS_LO16	\.text
+00020498 <bar\+0x248> jalr	at
+0002049c <bar\+0x24c> nop
Index: gas/testsuite/gas/mips/relax.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/relax.s,v
retrieving revision 1.1
diff -u -p -r1.1 relax.s
--- gas/testsuite/gas/mips/relax.s 9 Jun 2001 06:25:55 -0000 1.1
+++ gas/testsuite/gas/mips/relax.s 14 Sep 2002 05:53:33 -0000
@@ -2,6 +2,56 @@
 
 	.text
 foo:
-	move    $2, $3          # just something
+	b	bar
+	bal	bar
+	beq	$2, $3, bar
+	bne	$4, $5, bar
+	blez	$2, bar
+	bgtz	$3, bar
+	bltz	$4, bar
+	bgez	$5, bar
+	bc1f	bar
+	bc1t	bar
+
+	bltzal	$2, bar
+	bgezal	$3, bar
+
+	beql	$2, $3, bar
+	bnel	$4, $5, bar
+	blezl	$2, bar
+	bgtzl	$3, bar
+	bltzl	$4, bar
+	bgezl	$5, bar
+	bc1fl	bar
+	bc1tl	bar
+
+	bltzall	$2, bar
+	bgezall	$3, bar
+	
         .space  0x20000         # to make a 128kb loop body
-        beq     $2, $3, foo
+bar:
+	b	foo
+	bal	foo
+	beq	$2, $3, foo
+	bne	$4, $5, foo
+	blez	$2, foo
+	bgtz	$3, foo
+	bltz	$4, foo
+	bgez	$5, foo
+	bc1f	foo
+	bc1t	foo
+
+	bltzal	$2, foo
+	bgezal	$3, foo
+
+	beql	$2, $3, foo
+	bnel	$4, $5, foo
+	blezl	$2, foo
+	bgtzl	$3, foo
+	bltzl	$4, foo
+	bgezl	$5, foo
+	bc1fl	foo
+	bc1tl	foo
+
+	bltzall	$2, foo
+	bgezall	$3, foo

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14  4:49 MIPS assembler branch relaxations Alexandre Oliva
@ 2002-09-14 14:28 ` Daniel Jacobowitz
  2002-09-14 14:46   ` Eric Christopher
                     ` (3 more replies)
  2002-09-14 14:39 ` H. J. Lu
  2002-09-15  1:00 ` Alexandre Oliva
  2 siblings, 4 replies; 28+ messages in thread
From: Daniel Jacobowitz @ 2002-09-14 14:28 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: binutils, echristo

On Sat, Sep 14, 2002 at 02:59:45AM -0300, Alexandre Oliva wrote:
> This patch arranges for the MIPS assembler to turn out-of-range
> branches into jumps.  No regressions are introduced in the binutils
> testsuites for a mips-linux build.  Details on how it is done are in
> comments in the beginning of the patch.  Ok to install?

A couple of thoughts:

+        beql reg1, reg2, 1f
+        nop
+        beqzl $0, 2f
+        nop
+     1: j[al] label
+        delay slot (executed only if branch taken)
+     2:

Why beqzl?  Admittedly, I don't know much about MIPS hardware, but I'd
think that just "b" would probably be faster, since that's the normal
unconditional branch.


+   Even though keeping the delay slot instruction in the delay slot of
+   the branch would be more efficient, it would be very tricky to do
+   correctly, because we'd have to introduce a variable frag *after*
+   the delay slot instruction, and expand that instead.  Let's do it
+   the easy way for now, even if the branch-not-taken case now costs
+   one additional instruction.  Out-of-range branches are not supposed
+   to be common, anyway.


If this goes in as-is, I doubt that it'll ever be done the right way. 
My cynicism speaking.


The above aren't really objections, mind - I agree that performance of
this isn't important.  Just observations.


More importantly, because the performance of this is not important or
particularly good, it's important to avoid it.  When will it trigger? 
Does it require -relax?  [Not sure.] Does it happen inside .set
nomacro? [I think so - should it?  I'd say not!] I think there should
be a command-line option to disable this, and/or warn about it.  Most
out-of-range branches represent bugs in GCC's calculations of
instruction lengths.  I know there are some in 3.2, because I've run
into them.  I don't know if they're fixed in HEAD, and if this goes in
I may never find out.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14  4:49 MIPS assembler branch relaxations Alexandre Oliva
  2002-09-14 14:28 ` Daniel Jacobowitz
@ 2002-09-14 14:39 ` H. J. Lu
  2002-09-14 23:12   ` Alexandre Oliva
  2002-09-15  1:00 ` Alexandre Oliva
  2 siblings, 1 reply; 28+ messages in thread
From: H. J. Lu @ 2002-09-14 14:39 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: binutils, echristo

On Sat, Sep 14, 2002 at 02:59:45AM -0300, Alexandre Oliva wrote:
> This patch arranges for the MIPS assembler to turn out-of-range
> branches into jumps.  No regressions are introduced in the binutils
> testsuites for a mips-linux build.  Details on how it is done are in
> comments in the beginning of the patch.  Ok to install?
> 

Have you checked it against g++.dg/opt/longbranch1.C in gcc 3.2 on
Linux/mips? It should pass now.


H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 14:28 ` Daniel Jacobowitz
@ 2002-09-14 14:46   ` Eric Christopher
  2002-09-14 21:33     ` Daniel Jacobowitz
  2002-09-14 15:00   ` Paul Koning
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 28+ messages in thread
From: Eric Christopher @ 2002-09-14 14:46 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Alexandre Oliva, binutils


> +   Even though keeping the delay slot instruction in the delay slot of
> +   the branch would be more efficient, it would be very tricky to do
> +   correctly, because we'd have to introduce a variable frag *after*
> +   the delay slot instruction, and expand that instead.  Let's do it
> +   the easy way for now, even if the branch-not-taken case now costs
> +   one additional instruction.  Out-of-range branches are not supposed
> +   to be common, anyway.
> 
> 
> If this goes in as-is, I doubt that it'll ever be done the right way. 
> My cynicism speaking.
> 

It's a good comment, however, a couple of other comments:

1) If this bites assembler programmers then they screwed themselves.
2) gcc is going towards .set nomacro, so, hopefully this is just
temporary.

> 
> The above aren't really objections, mind - I agree that performance of
> this isn't important.  Just observations.
> 
> 
> More importantly, because the performance of this is not important or
> particularly good, it's important to avoid it.  When will it trigger? 
> Does it require -relax?  [Not sure.] Does it happen inside .set
> nomacro? [I think so - should it?  I'd say not!] I think there should
> be a command-line option to disable this, and/or warn about it.  Most
> out-of-range branches represent bugs in GCC's calculations of
> instruction lengths.  I know there are some in 3.2, because I've run
> into them.  I don't know if they're fixed in HEAD, and if this goes in
> I may never find out.
> 

1) None of the other relaxations require a command line.
2) always.
3) no
4) shouldn't - good catch.
5) not always, macros are partially to blame.
6) you and i had a conversation about this very thing yesterday :)

Anyhow, if 4 is I'm pretty happy with it going in.

-eric

-- 
Yuppies wear socks.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 14:28 ` Daniel Jacobowitz
  2002-09-14 14:46   ` Eric Christopher
@ 2002-09-14 15:00   ` Paul Koning
  2002-09-14 16:35     ` Daniel Jacobowitz
  2002-09-14 21:39   ` Thiemo Seufer
  2002-09-15  0:49   ` Alexandre Oliva
  3 siblings, 1 reply; 28+ messages in thread
From: Paul Koning @ 2002-09-14 15:00 UTC (permalink / raw)
  To: drow; +Cc: aoliva, binutils, echristo

>>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:

 Daniel> On Sat, Sep 14, 2002 at 02:59:45AM -0300, Alexandre Oliva
 Daniel> wrote:
 >> This patch arranges for the MIPS assembler to turn out-of-range
 >> branches into jumps.  No regressions are introduced in the
 >> binutils testsuites for a mips-linux build.  Details on how it is
 >> done are in comments in the beginning of the patch.  Ok to
 >> install?

 Daniel> A couple of thoughts:

 Daniel> + beql reg1, reg2, 1f + nop + beqzl $0, 2f + nop + 1: j[al]
 Daniel> label + delay slot (executed only if branch taken) + 2:

 Daniel> Why beqzl?  Admittedly, I don't know much about MIPS
 Daniel> hardware, but I'd think that just "b" would probably be
 Daniel> faster, since that's the normal unconditional branch.

Not only that, but MIPS64 explicitly deprecates all flavors of "branch
likely" which is why gcc has a way to avoid generating them.  So the
assembler should either have the same conditional stuff, or avoid them
entirely.  

	   paul

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 15:00   ` Paul Koning
@ 2002-09-14 16:35     ` Daniel Jacobowitz
  2002-09-14 18:43       ` Paul Koning
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Jacobowitz @ 2002-09-14 16:35 UTC (permalink / raw)
  To: Paul Koning; +Cc: aoliva, binutils, echristo

On Sat, Sep 14, 2002 at 05:21:32PM -0400, Paul Koning wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:
> 
>  Daniel> On Sat, Sep 14, 2002 at 02:59:45AM -0300, Alexandre Oliva
>  Daniel> wrote:
>  >> This patch arranges for the MIPS assembler to turn out-of-range
>  >> branches into jumps.  No regressions are introduced in the
>  >> binutils testsuites for a mips-linux build.  Details on how it is
>  >> done are in comments in the beginning of the patch.  Ok to
>  >> install?
> 
>  Daniel> A couple of thoughts:
> 
>  Daniel> + beql reg1, reg2, 1f + nop + beqzl $0, 2f + nop + 1: j[al]
>  Daniel> label + delay slot (executed only if branch taken) + 2:
> 
>  Daniel> Why beqzl?  Admittedly, I don't know much about MIPS
>  Daniel> hardware, but I'd think that just "b" would probably be
>  Daniel> faster, since that's the normal unconditional branch.
> 
> Not only that, but MIPS64 explicitly deprecates all flavors of "branch
> likely" which is why gcc has a way to avoid generating them.  So the
> assembler should either have the same conditional stuff, or avoid them
> entirely.  

That's not a problem here - Alex's patch only generated branch-likely
in response to existing branch-likely in the source.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 16:35     ` Daniel Jacobowitz
@ 2002-09-14 18:43       ` Paul Koning
  0 siblings, 0 replies; 28+ messages in thread
From: Paul Koning @ 2002-09-14 18:43 UTC (permalink / raw)
  To: drow; +Cc: aoliva, binutils, echristo

>>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:

 Daniel> Why beqzl?  Admittedly, I don't know much about MIPS
 Daniel> hardware, but I'd think that just "b" would probably be
 Daniel> faster, since that's the normal unconditional branch.
 >> Not only that, but MIPS64 explicitly deprecates all flavors of
 >> "branch likely" which is why gcc has a way to avoid generating
 >> them.  So the assembler should either have the same conditional
 >> stuff, or avoid them entirely.

 Daniel> That's not a problem here - Alex's patch only generated
 Daniel> branch-likely in response to existing branch-likely in the
 Daniel> source.

Oh, right, I overlooked that.  Agreed...

    paul

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 21:33     ` Daniel Jacobowitz
@ 2002-09-14 21:33       ` Eric Christopher
  0 siblings, 0 replies; 28+ messages in thread
From: Eric Christopher @ 2002-09-14 21:33 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: binutils


> > > More importantly, because the performance of this is not important or
> > > particularly good, it's important to avoid it.  When will it trigger? 
> > > Does it require -relax?  [Not sure.] Does it happen inside .set
> > > nomacro? [I think so - should it?  I'd say not!] I think there should
> > > be a command-line option to disable this, and/or warn about it.  Most
> > > out-of-range branches represent bugs in GCC's calculations of
> > > instruction lengths.  I know there are some in 3.2, because I've run
> > > into them.  I don't know if they're fixed in HEAD, and if this goes in
> > > I may never find out.
> > > 
> > 
> > 1) None of the other relaxations require a command line.
> > 2) always.
> > 3) no
> > 4) shouldn't - good catch.
> > 5) not always, macros are partially to blame.
> > 6) you and i had a conversation about this very thing yesterday :)
> > 
> > Anyhow, if 4 is I'm pretty happy with it going in.
> 
> Er... um... could I get that said again with more words?  I have no
> idea what you just said.
> 

How about "if relaxation doesn't happen within set nomacro" i'm pretty
happy with it going in. Or did you want all of them expanded? They were
just answers to your questions.

-eric

-- 
Yuppies wear socks.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 14:46   ` Eric Christopher
@ 2002-09-14 21:33     ` Daniel Jacobowitz
  2002-09-14 21:33       ` Eric Christopher
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Jacobowitz @ 2002-09-14 21:33 UTC (permalink / raw)
  To: binutils

On Sat, Sep 14, 2002 at 11:20:35AM -0700, Eric Christopher wrote:
> 
> > +   Even though keeping the delay slot instruction in the delay slot of
> > +   the branch would be more efficient, it would be very tricky to do
> > +   correctly, because we'd have to introduce a variable frag *after*
> > +   the delay slot instruction, and expand that instead.  Let's do it
> > +   the easy way for now, even if the branch-not-taken case now costs
> > +   one additional instruction.  Out-of-range branches are not supposed
> > +   to be common, anyway.
> > 
> > 
> > If this goes in as-is, I doubt that it'll ever be done the right way. 
> > My cynicism speaking.
> > 
> 
> It's a good comment, however, a couple of other comments:
> 
> 1) If this bites assembler programmers then they screwed themselves.
> 2) gcc is going towards .set nomacro, so, hopefully this is just
> temporary.

Fine.

> > 
> > The above aren't really objections, mind - I agree that performance of
> > this isn't important.  Just observations.
> > 
> > 
> > More importantly, because the performance of this is not important or
> > particularly good, it's important to avoid it.  When will it trigger? 
> > Does it require -relax?  [Not sure.] Does it happen inside .set
> > nomacro? [I think so - should it?  I'd say not!] I think there should
> > be a command-line option to disable this, and/or warn about it.  Most
> > out-of-range branches represent bugs in GCC's calculations of
> > instruction lengths.  I know there are some in 3.2, because I've run
> > into them.  I don't know if they're fixed in HEAD, and if this goes in
> > I may never find out.
> > 
> 
> 1) None of the other relaxations require a command line.
> 2) always.
> 3) no
> 4) shouldn't - good catch.
> 5) not always, macros are partially to blame.
> 6) you and i had a conversation about this very thing yesterday :)
> 
> Anyhow, if 4 is I'm pretty happy with it going in.

Er... um... could I get that said again with more words?  I have no
idea what you just said.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 14:28 ` Daniel Jacobowitz
  2002-09-14 14:46   ` Eric Christopher
  2002-09-14 15:00   ` Paul Koning
@ 2002-09-14 21:39   ` Thiemo Seufer
  2002-09-14 22:18     ` Alexandre Oliva
  2002-09-15  0:49   ` Alexandre Oliva
  3 siblings, 1 reply; 28+ messages in thread
From: Thiemo Seufer @ 2002-09-14 21:39 UTC (permalink / raw)
  To: binutils; +Cc: Alexandre Oliva, echristo

Daniel Jacobowitz wrote:
> On Sat, Sep 14, 2002 at 02:59:45AM -0300, Alexandre Oliva wrote:
> > This patch arranges for the MIPS assembler to turn out-of-range
> > branches into jumps.  No regressions are introduced in the binutils
> > testsuites for a mips-linux build.  Details on how it is done are in
> > comments in the beginning of the patch.  Ok to install?
> 
> A couple of thoughts:
> 
> +        beql reg1, reg2, 1f
> +        nop
> +        beqzl $0, 2f
> +        nop
> +     1: j[al] label
> +        delay slot (executed only if branch taken)
> +     2:
> 
> Why beqzl?  Admittedly, I don't know much about MIPS hardware, but I'd
> think that just "b" would probably be faster, since that's the normal
> unconditional branch.

"b" isn't a valid opcode. :-)
Btw, "beqzl" also isn't one. In this special case I'd prefer "beq".


Thiemo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 21:39   ` Thiemo Seufer
@ 2002-09-14 22:18     ` Alexandre Oliva
  2002-09-15  2:25       ` Thiemo Seufer
  0 siblings, 1 reply; 28+ messages in thread
From: Alexandre Oliva @ 2002-09-14 22:18 UTC (permalink / raw)
  To: Thiemo Seufer; +Cc: binutils, echristo

On Sep 14, 2002, Thiemo Seufer <ica2_ts@csv.ica.uni-stuttgart.de> wrote:

>> Why beqzl?  Admittedly, I don't know much about MIPS hardware, but I'd
>> think that just "b" would probably be faster, since that's the normal
>> unconditional branch.

> "b" isn't a valid opcode. :-)

Right.  `b foo' is just a shorthand for `beq $0, $0, foo'

> Btw, "beqzl" also isn't one.

Huh?  Please check your ISA manual again.  It surely is there.

> In this special case I'd prefer "beq".

Then other branch prediction forms would kick in, and the branch would
probably be considered unlikely for being a forward branch.  I don't
know whether mips has any such considerations, but indicating the
branch is likely if there is a way to do so is an obvious improvement
to me.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 14:39 ` H. J. Lu
@ 2002-09-14 23:12   ` Alexandre Oliva
  2002-09-15  9:13     ` H. J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Alexandre Oliva @ 2002-09-14 23:12 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils, echristo

On Sep 14, 2002, "H. J. Lu" <hjl@lucon.org> wrote:

> Have you checked it against g++.dg/opt/longbranch1.C in gcc 3.2 on
> Linux/mips? It should pass now.

Nope.  I'm still struggling to get a stable kernel for mips-linux
development, on which I'd be able to bootstrap gcc and test it.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 14:28 ` Daniel Jacobowitz
                     ` (2 preceding siblings ...)
  2002-09-14 21:39   ` Thiemo Seufer
@ 2002-09-15  0:49   ` Alexandre Oliva
  2002-09-15  9:15     ` Daniel Jacobowitz
  2002-09-16 11:56     ` Richard Henderson
  3 siblings, 2 replies; 28+ messages in thread
From: Alexandre Oliva @ 2002-09-15  0:49 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: binutils, echristo

On Sep 14, 2002, Daniel Jacobowitz <drow@mvista.com> wrote:

> If this goes in as-is, I doubt that it'll ever be done the right way. 

I agree.  I doubt it's worth doing it the right way.  It shouldn't
strike often enough to motivate anyone to do it.

> Does it happen inside .set nomacro? [I think so - should it?  I'd
> say not!]

I don't see why not.  It's not like we're expanding a macro.  We're
rather doing relaxation.  Does the linker refrain from doing
relaxations on machine code generated from opcodes assembled while
.set nomacro was in effect?  This is no different, except that the
relaxation is being performed in the assembler rather than in the
linker.

> I think there should be a command-line option to disable this,
> and/or warn about it.

That would be a nice improvement.  Just arrange for whatever option
you come up with to disable this block:

  if (place == NULL
      && address_expr
      && ((*reloc_type == BFD_RELOC_16_PCREL
	   && address_expr->X_op != O_constant)
	  || *reloc_type == BFD_RELOC_16_PCREL_S2)
      && (pinfo & INSN_UNCOND_BRANCH_DELAY || pinfo & INSN_COND_BRANCH_DELAY
	  || pinfo & INSN_COND_BRANCH_LIKELY)
+     && !whatever_option_you_come_up_with
      && !mips_opts.mips16)

This will switch all the rest off.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14  4:49 MIPS assembler branch relaxations Alexandre Oliva
  2002-09-14 14:28 ` Daniel Jacobowitz
  2002-09-14 14:39 ` H. J. Lu
@ 2002-09-15  1:00 ` Alexandre Oliva
  2 siblings, 0 replies; 28+ messages in thread
From: Alexandre Oliva @ 2002-09-15  1:00 UTC (permalink / raw)
  To: binutils; +Cc: echristo

On Sep 14, 2002, Alexandre Oliva <aoliva@redhat.com> wrote:

> +      val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
> +
> +      addr = fragp->fr_address + fragp->fr_fix;
> +
> +      val -= addr;
> +
> +      toofar = val < - (0x8000 << 2) || val >= (0x8000 << 2);

I just realized this test is off by 4.  The base address added to the
branch offset is the address of the instruction in the delay slot, not
that of the branch instruction.  I'm amending the patch as follows:

         addr = fragp->fr_address + fragp->fr_fix + 4;

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 22:18     ` Alexandre Oliva
@ 2002-09-15  2:25       ` Thiemo Seufer
  2002-09-15  3:38         ` Alexandre Oliva
  0 siblings, 1 reply; 28+ messages in thread
From: Thiemo Seufer @ 2002-09-15  2:25 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: binutils, echristo

Alexandre Oliva wrote:
> On Sep 14, 2002, Thiemo Seufer <ica2_ts@csv.ica.uni-stuttgart.de> wrote:
> 
> >> Why beqzl?  Admittedly, I don't know much about MIPS hardware, but I'd
> >> think that just "b" would probably be faster, since that's the normal
> >> unconditional branch.
> 
> > "b" isn't a valid opcode. :-)
> 
> Right.  `b foo' is just a shorthand for `beq $0, $0, foo'
> 
> > Btw, "beqzl" also isn't one.
> 
> Huh?  Please check your ISA manual again.  It surely is there.

Definitly not for MIPS IV and earlier.
Of course, "beql" is there, and with rt == $0 it equals "beqzl".
(/opcodes/mips-opc.c provides "beqzl" this way.)

It's a style issue, I like to use the official mnemnonic in such a case,
but probably that's only me.

> > In this special case I'd prefer "beq".
> 
> Then other branch prediction forms would kick in, and the branch would
> probably be considered unlikely for being a forward branch.  I don't
> know whether mips has any such considerations, but indicating the
> branch is likely if there is a way to do so is an obvious improvement
> to me.

Ok, then it would be "beql".


Thiemo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-15  2:25       ` Thiemo Seufer
@ 2002-09-15  3:38         ` Alexandre Oliva
  0 siblings, 0 replies; 28+ messages in thread
From: Alexandre Oliva @ 2002-09-15  3:38 UTC (permalink / raw)
  To: Thiemo Seufer; +Cc: binutils, echristo

On Sep 15, 2002, Thiemo Seufer <ica2_ts@csv.ica.uni-stuttgart.de> wrote:

> Alexandre Oliva wrote:
>> On Sep 14, 2002, Thiemo Seufer <ica2_ts@csv.ica.uni-stuttgart.de> wrote:
>> 
>> >> Why beqzl?  Admittedly, I don't know much about MIPS hardware, but I'd
>> >> think that just "b" would probably be faster, since that's the normal
>> >> unconditional branch.
>> 
>> > "b" isn't a valid opcode. :-)
>> 
>> Right.  `b foo' is just a shorthand for `beq $0, $0, foo'
>> 
>> > Btw, "beqzl" also isn't one.
>> 
>> Huh?  Please check your ISA manual again.  It surely is there.

> Definitly not for MIPS IV and earlier.

Eeek!  I apologize.  You're of course right.  I don't know where I got
this idea that beqzl existed but beql did not.  I even wrote about
beql myself, but apparently I did so in DMA mode :-)

> Ok, then it would be "beql".

Agreed, patch adjusted.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-14 23:12   ` Alexandre Oliva
@ 2002-09-15  9:13     ` H. J. Lu
  2002-09-15 15:32       ` Eric Christopher
  0 siblings, 1 reply; 28+ messages in thread
From: H. J. Lu @ 2002-09-15  9:13 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: binutils, echristo

On Sun, Sep 15, 2002 at 01:33:15AM -0300, Alexandre Oliva wrote:
> On Sep 14, 2002, "H. J. Lu" <hjl@lucon.org> wrote:
> 
> > Have you checked it against g++.dg/opt/longbranch1.C in gcc 3.2 on
> > Linux/mips? It should pass now.
> 
> Nope.  I'm still struggling to get a stable kernel for mips-linux

2.4 kernel from oss.sgi.com has been extremely stable for me on Malta.

> development, on which I'd be able to bootstrap gcc and test it.
> 

How about gas/mips/relax.s? I added it and marked it xfail, hoping
one day someone would fix it :-).


H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-15  0:49   ` Alexandre Oliva
@ 2002-09-15  9:15     ` Daniel Jacobowitz
  2002-09-16 11:56     ` Richard Henderson
  1 sibling, 0 replies; 28+ messages in thread
From: Daniel Jacobowitz @ 2002-09-15  9:15 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: binutils, echristo

On Sun, Sep 15, 2002 at 01:39:27AM -0300, Alexandre Oliva wrote:
> On Sep 14, 2002, Daniel Jacobowitz <drow@mvista.com> wrote:
> 
> > If this goes in as-is, I doubt that it'll ever be done the right way. 
> 
> I agree.  I doubt it's worth doing it the right way.  It shouldn't
> strike often enough to motivate anyone to do it.
> 
> > Does it happen inside .set nomacro? [I think so - should it?  I'd
> > say not!]
> 
> I don't see why not.  It's not like we're expanding a macro.  We're
> rather doing relaxation.  Does the linker refrain from doing
> relaxations on machine code generated from opcodes assembled while
> .set nomacro was in effect?  This is no different, except that the
> relaxation is being performed in the assembler rather than in the
> linker.

I suppose.  But, as I've been discussing with Eric, the eventual goal
is for GCC to not emit macros; which will let it have much more precise
control over the generated code.  That'll make overlong branches
significantly less likely, and more interesting to know about.  I guess
a warning would suffice.

> > I think there should be a command-line option to disable this,
> > and/or warn about it.
> 
> That would be a nice improvement.  Just arrange for whatever option
> you come up with to disable this block:
> 
>   if (place == NULL
>       && address_expr
>       && ((*reloc_type == BFD_RELOC_16_PCREL
> 	   && address_expr->X_op != O_constant)
> 	  || *reloc_type == BFD_RELOC_16_PCREL_S2)
>       && (pinfo & INSN_UNCOND_BRANCH_DELAY || pinfo & INSN_COND_BRANCH_DELAY
> 	  || pinfo & INSN_COND_BRANCH_LIKELY)
> +     && !whatever_option_you_come_up_with
>       && !mips_opts.mips16)
> 
> This will switch all the rest off.

Thanks.  How about something as simple as -mno-relax-branch?  (Or would
it be -no-mrelax-branch?  Gas is pretty inconsistent.)

I suppose warning by default would be a little too harsh, too.  With
the option to not relax it would be as simple as running a GCC testsuite
with unix/-Wa,-mno-relax-branch.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-15  9:13     ` H. J. Lu
@ 2002-09-15 15:32       ` Eric Christopher
  2002-09-15 16:53         ` H. J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Eric Christopher @ 2002-09-15 15:32 UTC (permalink / raw)
  To: H. J. Lu; +Cc: Alexandre Oliva, binutils


> > development, on which I'd be able to bootstrap gcc and test it.
> > 
> 
> How about gas/mips/relax.s? I added it and marked it xfail, hoping
> one day someone would fix it :-).

I thought the patch he posted had changes to mips.exp about relax.s :)

-eric

-- 
Yuppies wear socks.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-15 15:32       ` Eric Christopher
@ 2002-09-15 16:53         ` H. J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H. J. Lu @ 2002-09-15 16:53 UTC (permalink / raw)
  To: Eric Christopher; +Cc: Alexandre Oliva, binutils

On Sun, Sep 15, 2002 at 10:58:32AM -0700, Eric Christopher wrote:
> 
> > > development, on which I'd be able to bootstrap gcc and test it.
> > > 
> > 
> > How about gas/mips/relax.s? I added it and marked it xfail, hoping
> > one day someone would fix it :-).
> 
> I thought the patch he posted had changes to mips.exp about relax.s :)

Great.


H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-15  0:49   ` Alexandre Oliva
  2002-09-15  9:15     ` Daniel Jacobowitz
@ 2002-09-16 11:56     ` Richard Henderson
  2002-09-17  0:09       ` Alexandre Oliva
  1 sibling, 1 reply; 28+ messages in thread
From: Richard Henderson @ 2002-09-16 11:56 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Daniel Jacobowitz, binutils, echristo

On Sun, Sep 15, 2002 at 01:39:27AM -0300, Alexandre Oliva wrote:
> > Does it happen inside .set nomacro? [I think so - should it?  I'd
> > say not!]
> 
> I don't see why not.  It's not like we're expanding a macro.  We're
> rather doing relaxation.

Are we generating more than one instruction?  Yes.  Ergo
it's a macro.

> Does the linker refrain from doing relaxations on machine code
> generated from opcodes assembled while .set nomacro was in effect?

What linker relaxations?


r~

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-16 11:56     ` Richard Henderson
@ 2002-09-17  0:09       ` Alexandre Oliva
  2002-09-17  0:26         ` Richard Henderson
  2002-09-17  0:38         ` Thiemo Seufer
  0 siblings, 2 replies; 28+ messages in thread
From: Alexandre Oliva @ 2002-09-17  0:09 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Daniel Jacobowitz, binutils, echristo

On Sep 16, 2002, Richard Henderson <rth@redhat.com> wrote:

>> Does the linker refrain from doing relaxations on machine code
>> generated from opcodes assembled while .set nomacro was in effect?

> What linker relaxations?

coff-mips does them for embedded pic.  I thought we did more of those,
given the references to linker relaxations in comments in the
assembler.

Ok, I'm now convinced not doing such relaxations under certain
conditions is the way to go.  But what are the exact conditions?
nomacro (as suggested), noat (to avoid clobbering $at in the expanded
sequences) and no gp (to avoid depending on uninitialized values)?

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-17  0:09       ` Alexandre Oliva
@ 2002-09-17  0:26         ` Richard Henderson
  2002-09-17  0:38         ` Thiemo Seufer
  1 sibling, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2002-09-17  0:26 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Daniel Jacobowitz, binutils, echristo

On Tue, Sep 17, 2002 at 02:25:31AM -0300, Alexandre Oliva wrote:
> Ok, I'm now convinced not doing such relaxations under certain
> conditions is the way to go.  But what are the exact conditions?
> nomacro (as suggested), noat (to avoid clobbering $at in the expanded
> sequences) and no gp (to avoid depending on uninitialized values)?

Dunno what current behaviour is like for the mips assembler,
but for the alpha assembler the behaviour would be that only
nomacro would prevent the expansion, but if noat is present
you get an assembler error if it's needed.


r~

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-17  0:09       ` Alexandre Oliva
  2002-09-17  0:26         ` Richard Henderson
@ 2002-09-17  0:38         ` Thiemo Seufer
  2002-10-09 16:51           ` Alexandre Oliva
  1 sibling, 1 reply; 28+ messages in thread
From: Thiemo Seufer @ 2002-09-17  0:38 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Richard Henderson, Daniel Jacobowitz, binutils, echristo

Alexandre Oliva wrote:
> On Sep 16, 2002, Richard Henderson <rth@redhat.com> wrote:
> 
> >> Does the linker refrain from doing relaxations on machine code
> >> generated from opcodes assembled while .set nomacro was in effect?
> 
> > What linker relaxations?
> 
> coff-mips does them for embedded pic.  I thought we did more of those,
> given the references to linker relaxations in comments in the
> assembler.
> 
> Ok, I'm now convinced not doing such relaxations under certain
> conditions is the way to go.  But what are the exact conditions?
> nomacro (as suggested),

Always, as it should prevent expansions.

> noat (to avoid clobbering $at in the expanded
> sequences)

Only if $at is actually used. AFAICS this is the PIC case.

> and no gp (to avoid depending on uninitialized values)?

AFAICS $gp is only used for PIC, where it must be defined anyway.

Btw, your patch uses explicit binary patterns to create insns, is it
actually impossible to use mips_ip()/append_insn() instead?


Thiemo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-09-17  0:38         ` Thiemo Seufer
@ 2002-10-09 16:51           ` Alexandre Oliva
  2002-10-09 16:54             ` Alexandre Oliva
  2002-10-11 13:08             ` Eric Christopher
  0 siblings, 2 replies; 28+ messages in thread
From: Alexandre Oliva @ 2002-10-09 16:51 UTC (permalink / raw)
  To: Thiemo Seufer; +Cc: Richard Henderson, Daniel Jacobowitz, binutils, echristo

[-- Attachment #1: Type: text/plain, Size: 1483 bytes --]

On Sep 17, 2002, Thiemo Seufer <ica2_ts@csv.ica.uni-stuttgart.de> wrote:

> Alexandre Oliva wrote:

>> Ok, I'm now convinced not doing such relaxations under certain
>> conditions is the way to go.  But what are the exact conditions?
>> nomacro (as suggested),

> Always, as it should prevent expansions.

>> noat (to avoid clobbering $at in the expanded
>> sequences)

> Only if $at is actually used. AFAICS this is the PIC case.

Below you'll find a revised patch that prevents us from attempting to
do branch relaxation in the two cases above, and that introduces the 
-relax-branch and -no-relax-branch options.  -no-relax-branch is in
effect by default, because I found out the assembler generates worse
code for:

	la	$3,l2-l3	# -30

in gas/testsuite/gas/mips/empic.s, because by the time it computes the
offset between l3 and l2, it's already committed to a longer expansion
of `la', instead of the single-instruction it uses currently.  This
could probably be overcome using generic relaxation tables, but that's
too much work for now.

> Btw, your patch uses explicit binary patterns to create insns, is it
> actually impossible to use mips_ip()/append_insn() instead?

I haven't really tried to do it, out of fear of running into corner
cases such as the conversion of `j' to `b' in EMBEDDED_PIC.  I agree
it would be desirable, but I preferred not to take the risk, since
it's essential to know in advance exactly which instructions we're
going to emit.


Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gas-mips-branch-relax.patch --]
[-- Type: text/x-patch, Size: 36995 bytes --]

Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* config/tc-mips.h (mips_relax_frag): Take segment as argument.
	(md_relax_frag): Adjust macro.
	* config/tc-mips.c (mips_relax_branch): New variable.
	(RELAX_BRANCH_ENCODE, RELAX_BRANCH_P, RELAX_BRANCH_LIKELY,
	RELAX_BRANCH_LINK, RELAX_BRANCH_TOOBAR): New.
	(RELAX_MIPS16_P): Adjust.
	(append_insn): Emit branch to non-constant in a frag_var if
	branch-relaxation is desirable and possible.
	(OPTION_RELAX_BRANCH, OPTION_NO_RELAX_BRANCH): New options.
	(OPTION_ELF_BASE): Adjust.
	(md_parse_option): Handle new options.
	(md_apply_fix3): Update comment on EMBEDDED_PIC conditional
	branch relaxation.
	(relaxed_branch_length): New function.
	(md_estimate_size_before_relax): Handle branch frags.
	(mips_relax_frag): Likewise.
	(md_convert_frag): Handle branch frags.  Warn if branch is
	relaxed.

Index: gas/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* gas/mips/mips.exp: Don't xfail relax.
	* gas/mips/relax.s: Increase coverage.
	* gas/mips/relax.d: Add expected output.  Use relax.l for as stderr.
	* gas/mips/relax.l: New file.

Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.171
diff -u -p -r1.171 tc-mips.c
--- gas/config/tc-mips.c 30 Sep 2002 12:04:51 -0000 1.171
+++ gas/config/tc-mips.c 9 Oct 2002 23:33:34 -0000
@@ -563,6 +563,13 @@ static const unsigned int mips16_to_32_r
 };
 
 static int mips_fix_4122_bugs;
+
+/* We don't relax branches by default, since this causes us to expand
+   `la .l2 - .l1' if there's a branch between .l1 and .l2, because we
+   fail to compute the offset before expanding the macro to the most
+   efficient expansion.  */
+
+static int mips_relax_branch;
 \f
 /* Since the MIPS does not have multiple forms of PC relative
    instructions, we do not have to do relaxing as is done on other
@@ -640,6 +647,88 @@ static int mips_fix_4122_bugs;
 #define RELAX_RELOC3(i) (((i) >> 1) & 1)
 #define RELAX_WARN(i) ((i) & 1)
 
+/* Branch without likely bit.  If label is out of range, we turn:
+
+ 	beq reg1, reg2, label
+	delay slot
+
+   into
+
+        bne reg1, reg2, 0f
+        nop
+        j label
+     0: delay slot
+
+   with the following opcode replacements:
+
+	beq <-> bne
+	blez <-> bgtz
+	bltz <-> bgez
+	bc1f <-> bc1t
+
+	bltzal <-> bgezal  (with jal label instead of j label)
+
+   Even though keeping the delay slot instruction in the delay slot of
+   the branch would be more efficient, it would be very tricky to do
+   correctly, because we'd have to introduce a variable frag *after*
+   the delay slot instruction, and expand that instead.  Let's do it
+   the easy way for now, even if the branch-not-taken case now costs
+   one additional instruction.  Out-of-range branches are not supposed
+   to be common, anyway.
+
+   Branch likely.  If label is out of range, we turn:
+
+	beql reg1, reg2, label
+	delay slot (annulled if branch not taken)
+
+   into
+
+        beql reg1, reg2, 1f
+        nop
+        beql $0, $0, 2f
+        nop
+     1: j[al] label
+        delay slot (executed only if branch taken)
+     2:
+
+   It would be possible to generate a shorter sequence by losing the
+   likely bit, generating something like:
+     
+	bne reg1, reg2, 0f
+	nop
+	j[al] label
+	delay slot (executed only if branch taken)
+     0:
+
+	beql -> bne
+	bnel -> beq
+	blezl -> bgtz
+	bgtzl -> blez
+	bltzl -> bgez
+	bgezl -> bltz
+	bc1fl -> bc1t
+	bc1tl -> bc1f
+
+	bltzall -> bgezal  (with jal label instead of j label)
+	bgezall -> bltzal  (ditto)
+
+
+   but it's not clear that it would actually improve performance.  */
+#define RELAX_BRANCH_ENCODE(reloc_s2, uncond, likely, link, toofar) \
+  ((relax_substateT) \
+   (0xc0000000 \
+    | ((toofar) ? 1 : 0) \
+    | ((link) ? 2 : 0) \
+    | ((likely) ? 4 : 0) \
+    | ((uncond) ? 8 : 0) \
+    | ((reloc_s2) ? 16 : 0)))
+#define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000)
+#define RELAX_BRANCH_RELOC_S2(i) (((i) & 16) != 0)
+#define RELAX_BRANCH_UNCOND(i) (((i) & 8) != 0)
+#define RELAX_BRANCH_LIKELY(i) (((i) & 4) != 0)
+#define RELAX_BRANCH_LINK(i) (((i) & 2) != 0)
+#define RELAX_BRANCH_TOOFAR(i) (((i) & 1))
+
 /* For mips16 code, we use an entirely different form of relaxation.
    mips16 supports two versions of most instructions which take
    immediate values: a small one which takes some small value, and a
@@ -667,7 +756,7 @@ static int mips_fix_4122_bugs;
    | ((ext) ? 0x200 : 0)					\
    | ((dslot) ? 0x400 : 0)					\
    | ((jal_dslot) ? 0x800 : 0))
-#define RELAX_MIPS16_P(i) (((i) & 0x80000000) != 0)
+#define RELAX_MIPS16_P(i) (((i) & 0xc0000000) == 0x80000000)
 #define RELAX_MIPS16_TYPE(i) ((i) & 0xff)
 #define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x100) != 0)
 #define RELAX_MIPS16_USER_EXT(i) (((i) & 0x200) != 0)
@@ -785,6 +874,7 @@ static void s_mips_weakext PARAMS ((int)
 static void s_mips_file PARAMS ((int));
 static void s_mips_loc PARAMS ((int));
 static int mips16_extended_frag PARAMS ((fragS *, asection *, long));
+static int relaxed_branch_length (fragS *, asection *, int);
 static int validate_mips_insn PARAMS ((const struct mips_opcode *));
 static void show PARAMS ((FILE *, const char *, int *, int *));
 #ifdef OBJ_ELF
@@ -1840,7 +1930,38 @@ append_insn (place, ip, address_expr, re
 	}
     }
 
-  if (*reloc_type > BFD_RELOC_UNUSED)
+  if (place == NULL
+      && address_expr
+      && ((*reloc_type == BFD_RELOC_16_PCREL
+	   && address_expr->X_op != O_constant)
+	  || *reloc_type == BFD_RELOC_16_PCREL_S2)
+      && (pinfo & INSN_UNCOND_BRANCH_DELAY || pinfo & INSN_COND_BRANCH_DELAY
+	  || pinfo & INSN_COND_BRANCH_LIKELY)
+      && mips_relax_branch
+      /* Don't try branch relaxation within .set nomacro, or within
+	 .set noat if we use $at for PIC computations.  If it turns
+	 out that the branch was out-of-range, we'll get an error.  */
+      && !mips_opts.warn_about_macros
+      && !(mips_opts.noat && mips_pic != NO_PIC)
+      && !mips_opts.mips16)
+    {
+      f = frag_var (rs_machine_dependent,
+		    relaxed_branch_length
+		    (NULL, NULL,
+		     (pinfo & INSN_UNCOND_BRANCH_DELAY) ? -1
+		     : (pinfo & INSN_COND_BRANCH_LIKELY) ? 1 : 0), 4,
+		    RELAX_BRANCH_ENCODE
+		    (*reloc_type == BFD_RELOC_16_PCREL_S2,
+		     pinfo & INSN_UNCOND_BRANCH_DELAY,
+		     pinfo & INSN_COND_BRANCH_LIKELY,
+		     pinfo & INSN_WRITE_GPR_31,
+		     0),
+		    address_expr->X_add_symbol,
+		    address_expr->X_add_number,
+		    0);
+      *reloc_type = BFD_RELOC_UNUSED;
+    }
+  else if (*reloc_type > BFD_RELOC_UNUSED)
     {
       /* We need to set up a variant frag.  */
       assert (mips_opts.mips16 && address_expr != NULL);
@@ -10125,8 +10246,12 @@ struct option md_longopts[] =
 #define OPTION_NO_FIX_VR4122 (OPTION_MD_BASE + 38)
   {"mfix-vr4122-bugs",    no_argument, NULL, OPTION_FIX_VR4122},
   {"no-mfix-vr4122-bugs", no_argument, NULL, OPTION_NO_FIX_VR4122},
+#define OPTION_RELAX_BRANCH (OPTION_MD_BASE + 39)
+#define OPTION_NO_RELAX_BRANCH (OPTION_MD_BASE + 40)
+  {"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH},
+  {"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH},
 #ifdef OBJ_ELF
-#define OPTION_ELF_BASE    (OPTION_MD_BASE + 39)
+#define OPTION_ELF_BASE    (OPTION_MD_BASE + 41)
 #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
   {"KPIC",        no_argument, NULL, OPTION_CALL_SHARED},
   {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
@@ -10335,6 +10460,14 @@ md_parse_option (c, arg)
       mips_fix_4122_bugs = 0;
       break;
 
+    case OPTION_RELAX_BRANCH:
+      mips_relax_branch = 1;
+      break;
+
+    case OPTION_NO_RELAX_BRANCH:
+      mips_relax_branch = 0;
+      break;
+
 #ifdef OBJ_ELF
       /* When generating ELF code, we permit -KPIC and -call_shared to
 	 select SVR4_PIC, and -non_shared to select no PIC.  This is
@@ -11186,13 +11319,9 @@ md_apply_fix3 (fixP, valP, seg)
 	    }
 	  else
 	    {
-	      /* FIXME.  It would be possible in principle to handle
-                 conditional branches which overflow.  They could be
-                 transformed into a branch around a jump.  This would
-                 require setting up variant frags for each different
-                 branch type.  The native MIPS assembler attempts to
-                 handle these cases, but it appears to do it
-                 incorrectly.  */
+	      /* If we got here, we have branch-relaxation disabled,
+		 and there's nothing we can do to fix this instruction
+		 without turning it into a longer sequence.  */
 	      as_bad_where (fixP->fx_file, fixP->fx_line,
 			    _("Branch out of range"));
 	    }
@@ -12662,6 +12791,74 @@ mips16_extended_frag (fragp, sec, stretc
     return 0;
 }
 
+/* Compute the length of a branch sequence, and adjust the
+   RELAX_BRANCH_TOOFAR bit accordingly.  If FRAGP is NULL, the
+   worst-case length is computed, with UPDATE being used to indicate
+   whether an unconditional (-1), branch-likely (+1) or regular (0)
+   branch is to be computed.  */
+static int
+relaxed_branch_length (fragp, sec, update)
+     fragS *fragp;
+     asection *sec;
+     int update;
+{
+  boolean toofar;
+  int length;
+
+  if (fragp
+      && S_IS_DEFINED (fragp->fr_symbol)
+      && sec == S_GET_SEGMENT (fragp->fr_symbol))
+    {
+      addressT addr;
+      offsetT val;
+
+      val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
+
+      addr = fragp->fr_address + fragp->fr_fix + 4;
+
+      val -= addr;
+
+      toofar = val < - (0x8000 << 2) || val >= (0x8000 << 2);
+    }
+  else if (fragp)
+    /* If the symbol is not defined or it's in a different segment,
+       assume the user knows what's going on and emit a short
+       branch.  */
+    toofar = false;
+  else
+    toofar = true;
+
+  if (fragp && update && toofar != RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
+    fragp->fr_subtype
+      = RELAX_BRANCH_ENCODE (RELAX_BRANCH_RELOC_S2 (fragp->fr_subtype),
+			     RELAX_BRANCH_UNCOND (fragp->fr_subtype),
+			     RELAX_BRANCH_LIKELY (fragp->fr_subtype),
+			     RELAX_BRANCH_LINK (fragp->fr_subtype),
+			     toofar);
+
+  length = 4;
+  if (toofar)
+    {
+      if (fragp ? RELAX_BRANCH_LIKELY (fragp->fr_subtype) : (update > 0))
+	length += 8;
+
+      if (mips_pic != NO_PIC)
+	{
+	  /* Additional space for PIC loading of target address.  */
+	  length += 8;
+	  if (mips_opts.isa == ISA_MIPS1)
+	    /* Additional space for $at-stabilizing nop.  */
+	    length += 4;
+	}
+
+      /* If branch is conditional.  */
+      if (fragp ? !RELAX_BRANCH_UNCOND (fragp->fr_subtype) : (update >= 0))
+	length += 8;
+    }
+  
+  return length;
+}
+
 /* Estimate the size of a frag before relaxing.  Unless this is the
    mips16, we are not really relaxing here, and the final size is
    encoded in the subtype information.  For the mips16, we have to
@@ -12675,6 +12872,14 @@ md_estimate_size_before_relax (fragp, se
   int change = 0;
   boolean linkonce = false;
 
+  if (RELAX_BRANCH_P (fragp->fr_subtype))
+    {
+
+      fragp->fr_var = relaxed_branch_length (fragp, segtype, false);
+      
+      return fragp->fr_var;
+    }
+
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     /* We don't want to modify the EXTENDED bit here; it might get us
        into infinite loops.  We change it only in mips_relax_frag().  */
@@ -13049,10 +13254,20 @@ tc_gen_reloc (section, fixp)
    the current size of the frag should change.  */
 
 int
-mips_relax_frag (fragp, stretch)
+mips_relax_frag (sec, fragp, stretch)
+     asection *sec;
      fragS *fragp;
      long stretch;
 {
+  if (RELAX_BRANCH_P (fragp->fr_subtype))
+    {
+      offsetT old_var = fragp->fr_var;
+      
+      fragp->fr_var = relaxed_branch_length (fragp, sec, true);
+
+      return fragp->fr_var - old_var;
+    }
+
   if (! RELAX_MIPS16_P (fragp->fr_subtype))
     return 0;
 
@@ -13084,6 +13299,216 @@ md_convert_frag (abfd, asec, fragp)
 {
   int old, new;
   char *fixptr;
+
+  if (RELAX_BRANCH_P (fragp->fr_subtype))
+    {
+      bfd_byte *buf;
+      unsigned long insn;
+      expressionS exp;
+      fixS *fixp;
+      
+      buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
+
+      if (target_big_endian)
+	insn = bfd_getb32 (buf);
+      else
+	insn = bfd_getl32 (buf);
+	  
+      if (!RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
+	{
+	  /* We generate a fixup instead of applying it right now
+	     because, if there are linker relaxations, we're going to
+	     need the relocations.  */
+	  exp.X_op = O_symbol;
+	  exp.X_add_symbol = fragp->fr_symbol;
+	  exp.X_add_number = fragp->fr_offset;
+
+	  fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+			      4, &exp, 1,
+			      RELAX_BRANCH_RELOC_S2 (fragp->fr_subtype)
+			      ? BFD_RELOC_16_PCREL_S2
+			      : BFD_RELOC_16_PCREL);
+	  fixp->fx_file = fragp->fr_file;
+	  fixp->fx_line = fragp->fr_line;
+	  
+	  md_number_to_chars ((char *)buf, insn, 4);
+	  buf += 4;
+	}
+      else
+	{
+	  int i;
+
+	  as_warn_where (fragp->fr_file, fragp->fr_line,
+			 _("relaxed out-of-range branch into a jump"));
+
+	  if (RELAX_BRANCH_UNCOND (fragp->fr_subtype))
+	    goto uncond;
+
+	  if (!RELAX_BRANCH_LIKELY (fragp->fr_subtype))
+	    {
+	      /* Reverse the branch.  */
+	      switch ((insn >> 28) & 0xf)
+		{
+		case 4:
+		  /* bc[0-3][tf]l? and bc1any[24][ft] instructions can
+		     have the condition reversed by tweaking a single
+		     bit, and their opcodes all have 0x4???????.  */
+		  assert ((insn & 0xf1000000) == 0x41000000);
+		  insn ^= 0x00010000;
+		  break;
+
+		case 0:
+		  /* bltz	0x04000000	bgez	0x04010000
+		     bltzal	0x04100000	bgezal	0x04110000 */
+		  assert ((insn & 0xfc0e0000) == 0x04000000);
+		  insn ^= 0x00010000;
+		  break;
+		  
+		case 1:
+		  /* beq	0x10000000	bne	0x14000000
+		     blez	0x18000000	bgtz	0x1c000000 */
+		  insn ^= 0x04000000;
+		  break;
+
+		default:
+		  abort ();
+		}
+	    }
+
+	  if (RELAX_BRANCH_LINK (fragp->fr_subtype))
+	    {
+	      /* Clear the and-link bit.  */
+	      assert ((insn & 0xfc1c0000) == 0x04100000);
+
+	      /* bltzal	0x04100000	bgezal	0x04110000
+		bltzall	0x04120000     bgezall	0x04130000 */
+	      insn &= ~0x00100000;
+	    }
+
+	  /* Branch over the branch (if the branch was likely) or the
+	     full jump (not likely case).  Compute the offset from the
+	     current instruction to branch to.  */
+	  if (RELAX_BRANCH_LIKELY (fragp->fr_subtype))
+	    i = 16;
+	  else
+	    {
+	      /* How many bytes in instructions we've already emitted?  */
+	      i = buf - (bfd_byte *)fragp->fr_literal - fragp->fr_fix;
+	      /* How many bytes in instructions from here to the end?  */
+	      i = fragp->fr_var - i;
+	    }
+	  /* Convert to instruction count.  */
+	  i >>= 2;
+	  /* Branch counts from the next instruction.  */
+	  i--; 
+	  insn |= i;
+	  /* Branch over the jump.  */
+	  md_number_to_chars ((char *)buf, insn, 4);
+	  buf += 4;
+
+	  /* Nop */
+	  md_number_to_chars ((char*)buf, 0, 4);
+	  buf += 4;
+
+	  if (RELAX_BRANCH_LIKELY (fragp->fr_subtype))
+	    {
+	      /* beql $0, $0, 2f */
+	      insn = 0x50000000;
+	      /* Compute the PC offset from the current instruction to
+		 the end of the variable frag.  */
+	      /* How many bytes in instructions we've already emitted?  */
+	      i = buf - (bfd_byte *)fragp->fr_literal - fragp->fr_fix;
+	      /* How many bytes in instructions from here to the end?  */
+	      i = fragp->fr_var - i;
+	      /* Convert to instruction count.  */
+	      i >>= 2;
+	      /* Don't decrement i, because we want to branch over the
+		 delay slot.  */
+
+	      insn |= i;
+	      md_number_to_chars ((char *)buf, insn, 4);
+	      buf += 4;
+
+	      md_number_to_chars ((char *)buf, 0, 4);
+	      buf += 4;
+	    }
+
+	uncond:
+	  if (mips_pic == NO_PIC)
+	    {
+	      /* j or jal.  */
+	      insn = (RELAX_BRANCH_LINK (fragp->fr_subtype)
+		      ? 0x0c000000 : 0x08000000);
+	      exp.X_op = O_symbol;
+	      exp.X_add_symbol = fragp->fr_symbol;
+	      exp.X_add_number = fragp->fr_offset;
+
+	      fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+				  4, &exp, 0, BFD_RELOC_MIPS_JMP);
+	      fixp->fx_file = fragp->fr_file;
+	      fixp->fx_line = fragp->fr_line;
+
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+	    }
+	  else
+	    {
+	      /* lw/ld $at, <sym>($gp)  R_MIPS_GOT16 */
+	      insn = HAVE_64BIT_ADDRESSES ? 0xdf810000 : 0x8f810000;
+	      exp.X_op = O_symbol;
+	      exp.X_add_symbol = fragp->fr_symbol;
+	      exp.X_add_number = fragp->fr_offset;
+
+	      if (fragp->fr_offset)
+		{
+		  exp.X_add_symbol = make_expr_symbol (&exp);
+		  exp.X_add_number = 0;
+		}
+
+	      fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+				  4, &exp, 0, BFD_RELOC_MIPS_GOT16);
+	      fixp->fx_file = fragp->fr_file;
+	      fixp->fx_line = fragp->fr_line;
+
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+	      
+	      if (mips_opts.isa == ISA_MIPS1)
+		{
+		  /* nop */
+		  md_number_to_chars ((char*)buf, 0, 4);
+		  buf += 4;
+		}
+
+	      /* d/addiu $at, $at, <sym>  R_MIPS_LO16 */
+	      insn = HAVE_64BIT_ADDRESSES ? 0x64210000 : 0x24210000;
+
+	      fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+				  4, &exp, 0, BFD_RELOC_LO16);
+	      fixp->fx_file = fragp->fr_file;
+	      fixp->fx_line = fragp->fr_line;
+	      
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+
+	      /* j(al)r $at.  */
+	      if (RELAX_BRANCH_LINK (fragp->fr_subtype))
+		insn = 0x0020f809;
+	      else
+		insn = 0x00200008;
+
+	      md_number_to_chars ((char*)buf, insn, 4);
+	      buf += 4;
+	    }
+	}
+
+      assert (buf == (bfd_byte *)fragp->fr_literal
+	      + fragp->fr_fix + fragp->fr_var);
+
+      fragp->fr_fix += fragp->fr_var;
+
+      return;
+    }
 
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     {
Index: gas/config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.17
diff -u -p -r1.17 tc-mips.h
--- gas/config/tc-mips.h 1 Oct 2002 06:15:33 -0000 1.17
+++ gas/config/tc-mips.h 9 Oct 2002 23:33:34 -0000
@@ -49,8 +49,9 @@ struct expressionS;
    relocation: */
 #define MAX_GPREL_OFFSET (0x7FF0)
 
-#define md_relax_frag(segment, fragp, stretch) mips_relax_frag(fragp, stretch)
-extern int mips_relax_frag PARAMS ((struct frag *, long));
+#define md_relax_frag(segment, fragp, stretch) \
+  mips_relax_frag(segment, fragp, stretch)
+extern int mips_relax_frag PARAMS ((asection *, struct frag *, long));
 
 #define md_undefined_symbol(name)	(0)
 #define md_operand(x)
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.48
diff -u -p -r1.48 mips.exp
--- gas/testsuite/gas/mips/mips.exp 1 Oct 2002 04:37:47 -0000 1.48
+++ gas/testsuite/gas/mips/mips.exp 9 Oct 2002 23:33:35 -0000
@@ -168,8 +168,6 @@ if { [istarget mips*-*-*] } then {
     run_dump_test "sb1-ext-mdmx"
     run_dump_test "sb1-ext-ps"
 
-    # It will always fail until someone fixes it.
-    setup_xfail "mips*-*-*"
     run_dump_test "relax"
 
     run_list_test "illegal" ""
Index: gas/testsuite/gas/mips/relax.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/relax.d,v
retrieving revision 1.1
diff -u -p -r1.1 relax.d
--- gas/testsuite/gas/mips/relax.d 9 Jun 2001 06:25:55 -0000 1.1
+++ gas/testsuite/gas/mips/relax.d 9 Oct 2002 23:33:35 -0000
@@ -1,8 +1,395 @@
+#as: -KPIC -mips3 -32 -relax-branch
 #objdump: -dr --prefix-addresses -mmips:4000
 #name: MIPS relax
+#stderr: relax.l
 
 # Test relaxation.
 
 .*: +file format .*mips.*
 
-Disassembly of section .text:
+Disassembly of section \.text:
+00000000 <foo> lw	at,2\(gp\)
+			0: R_MIPS_GOT16	\.text
+00000004 <foo\+0x4> addiu	at,at,592
+			4: R_MIPS_LO16	\.text
+00000008 <foo\+0x8> jr	at
+0000000c <foo\+0xc> nop
+00000010 <foo\+0x10> lw	at,2\(gp\)
+			10: R_MIPS_GOT16	\.text
+00000014 <foo\+0x14> addiu	at,at,592
+			14: R_MIPS_LO16	\.text
+00000018 <foo\+0x18> jalr	at
+0000001c <foo\+0x1c> nop
+00000020 <foo\+0x20> bne	v0,v1,00000034 <foo\+0x34>
+00000024 <foo\+0x24> nop
+00000028 <foo\+0x28> lw	at,2\(gp\)
+			28: R_MIPS_GOT16	\.text
+0000002c <foo\+0x2c> addiu	at,at,592
+			2c: R_MIPS_LO16	\.text
+00000030 <foo\+0x30> jr	at
+00000034 <foo\+0x34> nop
+00000038 <foo\+0x38> beq	a0,a1,0000004c <foo\+0x4c>
+0000003c <foo\+0x3c> nop
+00000040 <foo\+0x40> lw	at,2\(gp\)
+			40: R_MIPS_GOT16	\.text
+00000044 <foo\+0x44> addiu	at,at,592
+			44: R_MIPS_LO16	\.text
+00000048 <foo\+0x48> jr	at
+0000004c <foo\+0x4c> nop
+00000050 <foo\+0x50> bgtz	v0,00000064 <foo\+0x64>
+00000054 <foo\+0x54> nop
+00000058 <foo\+0x58> lw	at,2\(gp\)
+			58: R_MIPS_GOT16	\.text
+0000005c <foo\+0x5c> addiu	at,at,592
+			5c: R_MIPS_LO16	\.text
+00000060 <foo\+0x60> jr	at
+00000064 <foo\+0x64> nop
+00000068 <foo\+0x68> blez	v1,0000007c <foo\+0x7c>
+0000006c <foo\+0x6c> nop
+00000070 <foo\+0x70> lw	at,2\(gp\)
+			70: R_MIPS_GOT16	\.text
+00000074 <foo\+0x74> addiu	at,at,592
+			74: R_MIPS_LO16	\.text
+00000078 <foo\+0x78> jr	at
+0000007c <foo\+0x7c> nop
+00000080 <foo\+0x80> bgez	a0,00000094 <foo\+0x94>
+00000084 <foo\+0x84> nop
+00000088 <foo\+0x88> lw	at,2\(gp\)
+			88: R_MIPS_GOT16	\.text
+0000008c <foo\+0x8c> addiu	at,at,592
+			8c: R_MIPS_LO16	\.text
+00000090 <foo\+0x90> jr	at
+00000094 <foo\+0x94> nop
+00000098 <foo\+0x98> bltz	a1,000000ac <foo\+0xac>
+0000009c <foo\+0x9c> nop
+000000a0 <foo\+0xa0> lw	at,2\(gp\)
+			a0: R_MIPS_GOT16	\.text
+000000a4 <foo\+0xa4> addiu	at,at,592
+			a4: R_MIPS_LO16	\.text
+000000a8 <foo\+0xa8> jr	at
+000000ac <foo\+0xac> nop
+000000b0 <foo\+0xb0> bc1t	000000c4 <foo\+0xc4>
+000000b4 <foo\+0xb4> nop
+000000b8 <foo\+0xb8> lw	at,2\(gp\)
+			b8: R_MIPS_GOT16	\.text
+000000bc <foo\+0xbc> addiu	at,at,592
+			bc: R_MIPS_LO16	\.text
+000000c0 <foo\+0xc0> jr	at
+000000c4 <foo\+0xc4> nop
+000000c8 <foo\+0xc8> bc1f	000000dc <foo\+0xdc>
+000000cc <foo\+0xcc> nop
+000000d0 <foo\+0xd0> lw	at,2\(gp\)
+			d0: R_MIPS_GOT16	\.text
+000000d4 <foo\+0xd4> addiu	at,at,592
+			d4: R_MIPS_LO16	\.text
+000000d8 <foo\+0xd8> jr	at
+000000dc <foo\+0xdc> nop
+000000e0 <foo\+0xe0> bgez	v0,000000f4 <foo\+0xf4>
+000000e4 <foo\+0xe4> nop
+000000e8 <foo\+0xe8> lw	at,2\(gp\)
+			e8: R_MIPS_GOT16	\.text
+000000ec <foo\+0xec> addiu	at,at,592
+			ec: R_MIPS_LO16	\.text
+000000f0 <foo\+0xf0> jalr	at
+000000f4 <foo\+0xf4> nop
+000000f8 <foo\+0xf8> bltz	v1,0000010c <foo\+0x10c>
+000000fc <foo\+0xfc> nop
+00000100 <foo\+0x100> lw	at,2\(gp\)
+			100: R_MIPS_GOT16	\.text
+00000104 <foo\+0x104> addiu	at,at,592
+			104: R_MIPS_LO16	\.text
+00000108 <foo\+0x108> jalr	at
+0000010c <foo\+0x10c> nop
+00000110 <foo\+0x110> beql	v0,v1,00000120 <foo\+0x120>
+00000114 <foo\+0x114> nop
+00000118 <foo\+0x118> beqzl	zero,00000130 <foo\+0x130>
+0000011c <foo\+0x11c> nop
+00000120 <foo\+0x120> lw	at,2\(gp\)
+			120: R_MIPS_GOT16	\.text
+00000124 <foo\+0x124> addiu	at,at,592
+			124: R_MIPS_LO16	\.text
+00000128 <foo\+0x128> jr	at
+0000012c <foo\+0x12c> nop
+00000130 <foo\+0x130> bnel	a0,a1,00000140 <foo\+0x140>
+00000134 <foo\+0x134> nop
+00000138 <foo\+0x138> beqzl	zero,00000150 <foo\+0x150>
+0000013c <foo\+0x13c> nop
+00000140 <foo\+0x140> lw	at,2\(gp\)
+			140: R_MIPS_GOT16	\.text
+00000144 <foo\+0x144> addiu	at,at,592
+			144: R_MIPS_LO16	\.text
+00000148 <foo\+0x148> jr	at
+0000014c <foo\+0x14c> nop
+00000150 <foo\+0x150> blezl	v0,00000160 <foo\+0x160>
+00000154 <foo\+0x154> nop
+00000158 <foo\+0x158> beqzl	zero,00000170 <foo\+0x170>
+0000015c <foo\+0x15c> nop
+00000160 <foo\+0x160> lw	at,2\(gp\)
+			160: R_MIPS_GOT16	\.text
+00000164 <foo\+0x164> addiu	at,at,592
+			164: R_MIPS_LO16	\.text
+00000168 <foo\+0x168> jr	at
+0000016c <foo\+0x16c> nop
+00000170 <foo\+0x170> bgtzl	v1,00000180 <foo\+0x180>
+00000174 <foo\+0x174> nop
+00000178 <foo\+0x178> beqzl	zero,00000190 <foo\+0x190>
+0000017c <foo\+0x17c> nop
+00000180 <foo\+0x180> lw	at,2\(gp\)
+			180: R_MIPS_GOT16	\.text
+00000184 <foo\+0x184> addiu	at,at,592
+			184: R_MIPS_LO16	\.text
+00000188 <foo\+0x188> jr	at
+0000018c <foo\+0x18c> nop
+00000190 <foo\+0x190> bltzl	a0,000001a0 <foo\+0x1a0>
+00000194 <foo\+0x194> nop
+00000198 <foo\+0x198> beqzl	zero,000001b0 <foo\+0x1b0>
+0000019c <foo\+0x19c> nop
+000001a0 <foo\+0x1a0> lw	at,2\(gp\)
+			1a0: R_MIPS_GOT16	\.text
+000001a4 <foo\+0x1a4> addiu	at,at,592
+			1a4: R_MIPS_LO16	\.text
+000001a8 <foo\+0x1a8> jr	at
+000001ac <foo\+0x1ac> nop
+000001b0 <foo\+0x1b0> bgezl	a1,000001c0 <foo\+0x1c0>
+000001b4 <foo\+0x1b4> nop
+000001b8 <foo\+0x1b8> beqzl	zero,000001d0 <foo\+0x1d0>
+000001bc <foo\+0x1bc> nop
+000001c0 <foo\+0x1c0> lw	at,2\(gp\)
+			1c0: R_MIPS_GOT16	\.text
+000001c4 <foo\+0x1c4> addiu	at,at,592
+			1c4: R_MIPS_LO16	\.text
+000001c8 <foo\+0x1c8> jr	at
+000001cc <foo\+0x1cc> nop
+000001d0 <foo\+0x1d0> bc1fl	000001e0 <foo\+0x1e0>
+000001d4 <foo\+0x1d4> nop
+000001d8 <foo\+0x1d8> beqzl	zero,000001f0 <foo\+0x1f0>
+000001dc <foo\+0x1dc> nop
+000001e0 <foo\+0x1e0> lw	at,2\(gp\)
+			1e0: R_MIPS_GOT16	\.text
+000001e4 <foo\+0x1e4> addiu	at,at,592
+			1e4: R_MIPS_LO16	\.text
+000001e8 <foo\+0x1e8> jr	at
+000001ec <foo\+0x1ec> nop
+000001f0 <foo\+0x1f0> bc1tl	00000200 <foo\+0x200>
+000001f4 <foo\+0x1f4> nop
+000001f8 <foo\+0x1f8> beqzl	zero,00000210 <foo\+0x210>
+000001fc <foo\+0x1fc> nop
+00000200 <foo\+0x200> lw	at,2\(gp\)
+			200: R_MIPS_GOT16	\.text
+00000204 <foo\+0x204> addiu	at,at,592
+			204: R_MIPS_LO16	\.text
+00000208 <foo\+0x208> jr	at
+0000020c <foo\+0x20c> nop
+00000210 <foo\+0x210> bltzl	v0,00000220 <foo\+0x220>
+00000214 <foo\+0x214> nop
+00000218 <foo\+0x218> beqzl	zero,00000230 <foo\+0x230>
+0000021c <foo\+0x21c> nop
+00000220 <foo\+0x220> lw	at,2\(gp\)
+			220: R_MIPS_GOT16	\.text
+00000224 <foo\+0x224> addiu	at,at,592
+			224: R_MIPS_LO16	\.text
+00000228 <foo\+0x228> jalr	at
+0000022c <foo\+0x22c> nop
+00000230 <foo\+0x230> bgezl	v1,00000240 <foo\+0x240>
+00000234 <foo\+0x234> nop
+00000238 <foo\+0x238> beqzl	zero,00000250 <foo\+0x250>
+0000023c <foo\+0x23c> nop
+00000240 <foo\+0x240> lw	at,2\(gp\)
+			240: R_MIPS_GOT16	\.text
+00000244 <foo\+0x244> addiu	at,at,592
+			244: R_MIPS_LO16	\.text
+00000248 <foo\+0x248> jalr	at
+0000024c <foo\+0x24c> nop
+	\.\.\.
+00020250 <bar> lw	at,0\(gp\)
+			20250: R_MIPS_GOT16	\.text
+00020254 <bar\+0x4> addiu	at,at,0
+			20254: R_MIPS_LO16	\.text
+00020258 <bar\+0x8> jr	at
+0002025c <bar\+0xc> nop
+00020260 <bar\+0x10> lw	at,0\(gp\)
+			20260: R_MIPS_GOT16	\.text
+00020264 <bar\+0x14> addiu	at,at,0
+			20264: R_MIPS_LO16	\.text
+00020268 <bar\+0x18> jalr	at
+0002026c <bar\+0x1c> nop
+00020270 <bar\+0x20> bne	v0,v1,00020284 <bar\+0x34>
+00020274 <bar\+0x24> nop
+00020278 <bar\+0x28> lw	at,0\(gp\)
+			20278: R_MIPS_GOT16	\.text
+0002027c <bar\+0x2c> addiu	at,at,0
+			2027c: R_MIPS_LO16	\.text
+00020280 <bar\+0x30> jr	at
+00020284 <bar\+0x34> nop
+00020288 <bar\+0x38> beq	a0,a1,0002029c <bar\+0x4c>
+0002028c <bar\+0x3c> nop
+00020290 <bar\+0x40> lw	at,0\(gp\)
+			20290: R_MIPS_GOT16	\.text
+00020294 <bar\+0x44> addiu	at,at,0
+			20294: R_MIPS_LO16	\.text
+00020298 <bar\+0x48> jr	at
+0002029c <bar\+0x4c> nop
+000202a0 <bar\+0x50> bgtz	v0,000202b4 <bar\+0x64>
+000202a4 <bar\+0x54> nop
+000202a8 <bar\+0x58> lw	at,0\(gp\)
+			202a8: R_MIPS_GOT16	\.text
+000202ac <bar\+0x5c> addiu	at,at,0
+			202ac: R_MIPS_LO16	\.text
+000202b0 <bar\+0x60> jr	at
+000202b4 <bar\+0x64> nop
+000202b8 <bar\+0x68> blez	v1,000202cc <bar\+0x7c>
+000202bc <bar\+0x6c> nop
+000202c0 <bar\+0x70> lw	at,0\(gp\)
+			202c0: R_MIPS_GOT16	\.text
+000202c4 <bar\+0x74> addiu	at,at,0
+			202c4: R_MIPS_LO16	\.text
+000202c8 <bar\+0x78> jr	at
+000202cc <bar\+0x7c> nop
+000202d0 <bar\+0x80> bgez	a0,000202e4 <bar\+0x94>
+000202d4 <bar\+0x84> nop
+000202d8 <bar\+0x88> lw	at,0\(gp\)
+			202d8: R_MIPS_GOT16	\.text
+000202dc <bar\+0x8c> addiu	at,at,0
+			202dc: R_MIPS_LO16	\.text
+000202e0 <bar\+0x90> jr	at
+000202e4 <bar\+0x94> nop
+000202e8 <bar\+0x98> bltz	a1,000202fc <bar\+0xac>
+000202ec <bar\+0x9c> nop
+000202f0 <bar\+0xa0> lw	at,0\(gp\)
+			202f0: R_MIPS_GOT16	\.text
+000202f4 <bar\+0xa4> addiu	at,at,0
+			202f4: R_MIPS_LO16	\.text
+000202f8 <bar\+0xa8> jr	at
+000202fc <bar\+0xac> nop
+00020300 <bar\+0xb0> bc1t	00020314 <bar\+0xc4>
+00020304 <bar\+0xb4> nop
+00020308 <bar\+0xb8> lw	at,0\(gp\)
+			20308: R_MIPS_GOT16	\.text
+0002030c <bar\+0xbc> addiu	at,at,0
+			2030c: R_MIPS_LO16	\.text
+00020310 <bar\+0xc0> jr	at
+00020314 <bar\+0xc4> nop
+00020318 <bar\+0xc8> bc1f	0002032c <bar\+0xdc>
+0002031c <bar\+0xcc> nop
+00020320 <bar\+0xd0> lw	at,0\(gp\)
+			20320: R_MIPS_GOT16	\.text
+00020324 <bar\+0xd4> addiu	at,at,0
+			20324: R_MIPS_LO16	\.text
+00020328 <bar\+0xd8> jr	at
+0002032c <bar\+0xdc> nop
+00020330 <bar\+0xe0> bgez	v0,00020344 <bar\+0xf4>
+00020334 <bar\+0xe4> nop
+00020338 <bar\+0xe8> lw	at,0\(gp\)
+			20338: R_MIPS_GOT16	\.text
+0002033c <bar\+0xec> addiu	at,at,0
+			2033c: R_MIPS_LO16	\.text
+00020340 <bar\+0xf0> jalr	at
+00020344 <bar\+0xf4> nop
+00020348 <bar\+0xf8> bltz	v1,0002035c <bar\+0x10c>
+0002034c <bar\+0xfc> nop
+00020350 <bar\+0x100> lw	at,0\(gp\)
+			20350: R_MIPS_GOT16	\.text
+00020354 <bar\+0x104> addiu	at,at,0
+			20354: R_MIPS_LO16	\.text
+00020358 <bar\+0x108> jalr	at
+0002035c <bar\+0x10c> nop
+00020360 <bar\+0x110> beql	v0,v1,00020370 <bar\+0x120>
+00020364 <bar\+0x114> nop
+00020368 <bar\+0x118> beqzl	zero,00020380 <bar\+0x130>
+0002036c <bar\+0x11c> nop
+00020370 <bar\+0x120> lw	at,0\(gp\)
+			20370: R_MIPS_GOT16	\.text
+00020374 <bar\+0x124> addiu	at,at,0
+			20374: R_MIPS_LO16	\.text
+00020378 <bar\+0x128> jr	at
+0002037c <bar\+0x12c> nop
+00020380 <bar\+0x130> bnel	a0,a1,00020390 <bar\+0x140>
+00020384 <bar\+0x134> nop
+00020388 <bar\+0x138> beqzl	zero,000203a0 <bar\+0x150>
+0002038c <bar\+0x13c> nop
+00020390 <bar\+0x140> lw	at,0\(gp\)
+			20390: R_MIPS_GOT16	\.text
+00020394 <bar\+0x144> addiu	at,at,0
+			20394: R_MIPS_LO16	\.text
+00020398 <bar\+0x148> jr	at
+0002039c <bar\+0x14c> nop
+000203a0 <bar\+0x150> blezl	v0,000203b0 <bar\+0x160>
+000203a4 <bar\+0x154> nop
+000203a8 <bar\+0x158> beqzl	zero,000203c0 <bar\+0x170>
+000203ac <bar\+0x15c> nop
+000203b0 <bar\+0x160> lw	at,0\(gp\)
+			203b0: R_MIPS_GOT16	\.text
+000203b4 <bar\+0x164> addiu	at,at,0
+			203b4: R_MIPS_LO16	\.text
+000203b8 <bar\+0x168> jr	at
+000203bc <bar\+0x16c> nop
+000203c0 <bar\+0x170> bgtzl	v1,000203d0 <bar\+0x180>
+000203c4 <bar\+0x174> nop
+000203c8 <bar\+0x178> beqzl	zero,000203e0 <bar\+0x190>
+000203cc <bar\+0x17c> nop
+000203d0 <bar\+0x180> lw	at,0\(gp\)
+			203d0: R_MIPS_GOT16	\.text
+000203d4 <bar\+0x184> addiu	at,at,0
+			203d4: R_MIPS_LO16	\.text
+000203d8 <bar\+0x188> jr	at
+000203dc <bar\+0x18c> nop
+000203e0 <bar\+0x190> bltzl	a0,000203f0 <bar\+0x1a0>
+000203e4 <bar\+0x194> nop
+000203e8 <bar\+0x198> beqzl	zero,00020400 <bar\+0x1b0>
+000203ec <bar\+0x19c> nop
+000203f0 <bar\+0x1a0> lw	at,0\(gp\)
+			203f0: R_MIPS_GOT16	\.text
+000203f4 <bar\+0x1a4> addiu	at,at,0
+			203f4: R_MIPS_LO16	\.text
+000203f8 <bar\+0x1a8> jr	at
+000203fc <bar\+0x1ac> nop
+00020400 <bar\+0x1b0> bgezl	a1,00020410 <bar\+0x1c0>
+00020404 <bar\+0x1b4> nop
+00020408 <bar\+0x1b8> beqzl	zero,00020420 <bar\+0x1d0>
+0002040c <bar\+0x1bc> nop
+00020410 <bar\+0x1c0> lw	at,0\(gp\)
+			20410: R_MIPS_GOT16	\.text
+00020414 <bar\+0x1c4> addiu	at,at,0
+			20414: R_MIPS_LO16	\.text
+00020418 <bar\+0x1c8> jr	at
+0002041c <bar\+0x1cc> nop
+00020420 <bar\+0x1d0> bc1fl	00020430 <bar\+0x1e0>
+00020424 <bar\+0x1d4> nop
+00020428 <bar\+0x1d8> beqzl	zero,00020440 <bar\+0x1f0>
+0002042c <bar\+0x1dc> nop
+00020430 <bar\+0x1e0> lw	at,0\(gp\)
+			20430: R_MIPS_GOT16	\.text
+00020434 <bar\+0x1e4> addiu	at,at,0
+			20434: R_MIPS_LO16	\.text
+00020438 <bar\+0x1e8> jr	at
+0002043c <bar\+0x1ec> nop
+00020440 <bar\+0x1f0> bc1tl	00020450 <bar\+0x200>
+00020444 <bar\+0x1f4> nop
+00020448 <bar\+0x1f8> beqzl	zero,00020460 <bar\+0x210>
+0002044c <bar\+0x1fc> nop
+00020450 <bar\+0x200> lw	at,0\(gp\)
+			20450: R_MIPS_GOT16	\.text
+00020454 <bar\+0x204> addiu	at,at,0
+			20454: R_MIPS_LO16	\.text
+00020458 <bar\+0x208> jr	at
+0002045c <bar\+0x20c> nop
+00020460 <bar\+0x210> bltzl	v0,00020470 <bar\+0x220>
+00020464 <bar\+0x214> nop
+00020468 <bar\+0x218> beqzl	zero,00020480 <bar\+0x230>
+0002046c <bar\+0x21c> nop
+00020470 <bar\+0x220> lw	at,0\(gp\)
+			20470: R_MIPS_GOT16	\.text
+00020474 <bar\+0x224> addiu	at,at,0
+			20474: R_MIPS_LO16	\.text
+00020478 <bar\+0x228> jalr	at
+0002047c <bar\+0x22c> nop
+00020480 <bar\+0x230> bgezl	v1,00020490 <bar\+0x240>
+00020484 <bar\+0x234> nop
+00020488 <bar\+0x238> beqzl	zero,000204a0 <bar\+0x250>
+0002048c <bar\+0x23c> nop
+00020490 <bar\+0x240> lw	at,0\(gp\)
+			20490: R_MIPS_GOT16	\.text
+00020494 <bar\+0x244> addiu	at,at,0
+			20494: R_MIPS_LO16	\.text
+00020498 <bar\+0x248> jalr	at
+0002049c <bar\+0x24c> nop
Index: gas/testsuite/gas/mips/relax.l
===================================================================
RCS file: gas/testsuite/gas/mips/relax.l
diff -N gas/testsuite/gas/mips/relax.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/relax.l 9 Oct 2002 23:33:35 -0000
@@ -0,0 +1,45 @@
+.*: Assembler messages:
+.*:5: Warning: relaxed out-of-range branch into a jump
+.*:6: Warning: relaxed out-of-range branch into a jump
+.*:7: Warning: relaxed out-of-range branch into a jump
+.*:8: Warning: relaxed out-of-range branch into a jump
+.*:9: Warning: relaxed out-of-range branch into a jump
+.*:10: Warning: relaxed out-of-range branch into a jump
+.*:11: Warning: relaxed out-of-range branch into a jump
+.*:12: Warning: relaxed out-of-range branch into a jump
+.*:13: Warning: relaxed out-of-range branch into a jump
+.*:14: Warning: relaxed out-of-range branch into a jump
+.*:16: Warning: relaxed out-of-range branch into a jump
+.*:17: Warning: relaxed out-of-range branch into a jump
+.*:19: Warning: relaxed out-of-range branch into a jump
+.*:20: Warning: relaxed out-of-range branch into a jump
+.*:21: Warning: relaxed out-of-range branch into a jump
+.*:22: Warning: relaxed out-of-range branch into a jump
+.*:23: Warning: relaxed out-of-range branch into a jump
+.*:24: Warning: relaxed out-of-range branch into a jump
+.*:25: Warning: relaxed out-of-range branch into a jump
+.*:26: Warning: relaxed out-of-range branch into a jump
+.*:28: Warning: relaxed out-of-range branch into a jump
+.*:29: Warning: relaxed out-of-range branch into a jump
+.*:33: Warning: relaxed out-of-range branch into a jump
+.*:34: Warning: relaxed out-of-range branch into a jump
+.*:35: Warning: relaxed out-of-range branch into a jump
+.*:36: Warning: relaxed out-of-range branch into a jump
+.*:37: Warning: relaxed out-of-range branch into a jump
+.*:38: Warning: relaxed out-of-range branch into a jump
+.*:39: Warning: relaxed out-of-range branch into a jump
+.*:40: Warning: relaxed out-of-range branch into a jump
+.*:41: Warning: relaxed out-of-range branch into a jump
+.*:42: Warning: relaxed out-of-range branch into a jump
+.*:44: Warning: relaxed out-of-range branch into a jump
+.*:45: Warning: relaxed out-of-range branch into a jump
+.*:47: Warning: relaxed out-of-range branch into a jump
+.*:48: Warning: relaxed out-of-range branch into a jump
+.*:49: Warning: relaxed out-of-range branch into a jump
+.*:50: Warning: relaxed out-of-range branch into a jump
+.*:51: Warning: relaxed out-of-range branch into a jump
+.*:52: Warning: relaxed out-of-range branch into a jump
+.*:53: Warning: relaxed out-of-range branch into a jump
+.*:54: Warning: relaxed out-of-range branch into a jump
+.*:56: Warning: relaxed out-of-range branch into a jump
+.*:57: Warning: relaxed out-of-range branch into a jump
Index: gas/testsuite/gas/mips/relax.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/relax.s,v
retrieving revision 1.1
diff -u -p -r1.1 relax.s
--- gas/testsuite/gas/mips/relax.s 9 Jun 2001 06:25:55 -0000 1.1
+++ gas/testsuite/gas/mips/relax.s 9 Oct 2002 23:33:35 -0000
@@ -2,6 +2,56 @@
 
 	.text
 foo:
-	move    $2, $3          # just something
+	b	bar
+	bal	bar
+	beq	$2, $3, bar
+	bne	$4, $5, bar
+	blez	$2, bar
+	bgtz	$3, bar
+	bltz	$4, bar
+	bgez	$5, bar
+	bc1f	bar
+	bc1t	bar
+
+	bltzal	$2, bar
+	bgezal	$3, bar
+
+	beql	$2, $3, bar
+	bnel	$4, $5, bar
+	blezl	$2, bar
+	bgtzl	$3, bar
+	bltzl	$4, bar
+	bgezl	$5, bar
+	bc1fl	bar
+	bc1tl	bar
+
+	bltzall	$2, bar
+	bgezall	$3, bar
+	
         .space  0x20000         # to make a 128kb loop body
-        beq     $2, $3, foo
+bar:
+	b	foo
+	bal	foo
+	beq	$2, $3, foo
+	bne	$4, $5, foo
+	blez	$2, foo
+	bgtz	$3, foo
+	bltz	$4, foo
+	bgez	$5, foo
+	bc1f	foo
+	bc1t	foo
+
+	bltzal	$2, foo
+	bgezal	$3, foo
+
+	beql	$2, $3, foo
+	bnel	$4, $5, foo
+	blezl	$2, foo
+	bgtzl	$3, foo
+	bltzl	$4, foo
+	bgezl	$5, foo
+	bc1fl	foo
+	bc1tl	foo
+
+	bltzall	$2, foo
+	bgezall	$3, foo

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-10-09 16:51           ` Alexandre Oliva
@ 2002-10-09 16:54             ` Alexandre Oliva
  2002-10-09 17:17               ` H. J. Lu
  2002-10-11 13:08             ` Eric Christopher
  1 sibling, 1 reply; 28+ messages in thread
From: Alexandre Oliva @ 2002-10-09 16:54 UTC (permalink / raw)
  To: Thiemo Seufer; +Cc: Richard Henderson, Daniel Jacobowitz, binutils, echristo

On Oct  9, 2002, Alexandre Oliva <aoliva@redhat.com> wrote:

> Ok to install?

I forgot to mention this introduced no regressions in a
athlon-pc-linux-gnu-hosted mips64-linux testsuite run.  I.e., MIPS
branch-misc-2 was broken before, and remains broken after the patch.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-10-09 16:54             ` Alexandre Oliva
@ 2002-10-09 17:17               ` H. J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H. J. Lu @ 2002-10-09 17:17 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Thiemo Seufer, Richard Henderson, Daniel Jacobowitz, binutils, echristo

On Wed, Oct 09, 2002 at 08:53:38PM -0300, Alexandre Oliva wrote:
> On Oct  9, 2002, Alexandre Oliva <aoliva@redhat.com> wrote:
> 
> > Ok to install?
> 
> I forgot to mention this introduced no regressions in a
> athlon-pc-linux-gnu-hosted mips64-linux testsuite run.  I.e., MIPS
> branch-misc-2 was broken before, and remains broken after the patch.

FYI, branch-misc-2 has been fixed in my Linux binutils.


H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: MIPS assembler branch relaxations
  2002-10-09 16:51           ` Alexandre Oliva
  2002-10-09 16:54             ` Alexandre Oliva
@ 2002-10-11 13:08             ` Eric Christopher
  1 sibling, 0 replies; 28+ messages in thread
From: Eric Christopher @ 2002-10-11 13:08 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Thiemo Seufer, Richard Henderson, Daniel Jacobowitz, binutils



> 
> Ok to install?
> 

OK. I really wish we could use the generic tables, but this is a start.

-eric

-- 
Yeah, I used to play basketball...

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2002-10-11 20:08 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-14  4:49 MIPS assembler branch relaxations Alexandre Oliva
2002-09-14 14:28 ` Daniel Jacobowitz
2002-09-14 14:46   ` Eric Christopher
2002-09-14 21:33     ` Daniel Jacobowitz
2002-09-14 21:33       ` Eric Christopher
2002-09-14 15:00   ` Paul Koning
2002-09-14 16:35     ` Daniel Jacobowitz
2002-09-14 18:43       ` Paul Koning
2002-09-14 21:39   ` Thiemo Seufer
2002-09-14 22:18     ` Alexandre Oliva
2002-09-15  2:25       ` Thiemo Seufer
2002-09-15  3:38         ` Alexandre Oliva
2002-09-15  0:49   ` Alexandre Oliva
2002-09-15  9:15     ` Daniel Jacobowitz
2002-09-16 11:56     ` Richard Henderson
2002-09-17  0:09       ` Alexandre Oliva
2002-09-17  0:26         ` Richard Henderson
2002-09-17  0:38         ` Thiemo Seufer
2002-10-09 16:51           ` Alexandre Oliva
2002-10-09 16:54             ` Alexandre Oliva
2002-10-09 17:17               ` H. J. Lu
2002-10-11 13:08             ` Eric Christopher
2002-09-14 14:39 ` H. J. Lu
2002-09-14 23:12   ` Alexandre Oliva
2002-09-15  9:13     ` H. J. Lu
2002-09-15 15:32       ` Eric Christopher
2002-09-15 16:53         ` H. J. Lu
2002-09-15  1:00 ` Alexandre Oliva

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).