This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] m68k: Relax 32-bit relative unconditional branches


Hi,

Attached is a patch to relax 32-bit relative unconditional branches.

ColdFire ISAC is almost but not quite a superset of ISAB because ISAC
does not have 32-bit relative unconditional branches even though ISAB
does.  This is a little inconvenient because if an executable ends up
big, then some branch destinations may not be reachable with available
relative branch instructions.

This patch teaches tc-m68k to relax relative unconditional branches

  bral

into

  bnel
  beql  

as shown in the last hunk of this patch.

Nathan says:

  "I chose a bne/beq pair on the basis that the Z flag only gets set
  when two values are the same, which I guessed happens more rarely
  than any other available condition. Thus the first branch should be
  taken most of the time.

Without this patch, glibc fails to build when we encoutner a branch
that jumps too far.

Tested on m68k-linux.  OK to apply?

Kazu Hirata

gas/
2007-08-27  Nathan Sidwell  <nathan@codesourcery.com>

	* config/tc-m68k.c (LONG_BRANCH_VIA_COND): New.
	(BRANCHBWPL, FRAG_VAR_SIZE): New.
	(md_relax_table): Add BRANCHBWPL entries.
	(m68k_ip): Choose BRANCHBWPL relaxation if necessary.
	(md_assemble): Use FRAG_VAR_SIZE.
	(md_convert_frag_1): Add BRANCHBWPL cases.
	(md_estimate_size_before_relaz): Likewise.

gas/testsuite/
2007-08-27  Nathan Sidwell  <nathan@codesourcery.com>

	* gas/m68k/br-isaa.d: Dump relocs too.
	* gas/m68k/br-isab.d: Likewise.
	* gas/m68k/br-isac.d: Likewise.  Adjust for long branch relaxation.

Index: gas/config/tc-m68k.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68k.c,v
retrieving revision 1.94
diff -u -d -p -r1.94 tc-m68k.c
--- gas/config/tc-m68k.c	3 Jul 2007 11:01:04 -0000	1.94
+++ gas/config/tc-m68k.c	27 Aug 2007 19:32:12 -0000
@@ -367,6 +367,7 @@ struct m68k_it
 	((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
 #define HAVE_LONG_BRANCH(x)	\
 	((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b))
+#define LONG_BRANCH_VIA_COND(x) (HAVE_LONG_COND(x) && !HAVE_LONG_BRANCH(x))
 
 static struct m68k_it the_ins;	/* The instruction being assembled.  */
 
@@ -719,8 +720,14 @@ static void m68k_init_arch (void);
 #define PCINDEX		8	/* PC + displacement + index. */
 #define ABSTOPCREL	9	/* Absolute relax down to 16-bit PC-relative.  */
 
+/* This relaxation is required for branches where there is no long
+   branch and we are in pcrel mode.  We generate a bne/beq pair.  */
+#define BRANCHBWPL	10      /* Branch byte, word or pair of longs
+				   */
+
 /* Note that calls to frag_var need to specify the maximum expansion
-   needed; this is currently 10 bytes for DBCC.  */
+   needed; this is currently 12 bytes for bne/beq pair.  */
+#define FRAG_VAR_SIZE 12
 
 /* The fields are:
    How far Forward this mode will reach:
@@ -780,6 +787,11 @@ relax_typeS md_relax_table[] =
   { 32767, -32768,  2, TAB (ABSTOPCREL, LONG) },
   {	0,	0,  4, 0 },
   {	1,	1,  0, 0 },
+  
+  {   127,   -128,  0, TAB (BRANCHBWPL, SHORT) },
+  { 32767, -32768,  2, TAB (BRANCHBWPL, LONG) },
+  {     0,	0,  10, 0 },
+  {     1,	1,  0, 0 },
 };
 
 /* These are the machine dependent pseudo-ops.  These are included so
@@ -2257,6 +2269,7 @@ m68k_ip (char *instring)
   for (s = the_ins.args, opP = &the_ins.operands[0]; *s; s += 2, opP++)
     {
       int have_disp = 0;
+      int use_pl = 0;
       
       /* This switch is a doozy.
 	 Watch the first step; its a big one! */
@@ -2940,6 +2953,7 @@ m68k_ip (char *instring)
 	      
 	    case 'b': /* Unconditional branch */
 	      have_disp = HAVE_LONG_BRANCH (current_architecture);
+	      use_pl = LONG_BRANCH_VIA_COND (current_architecture);
 	      goto var_branch;
 	      
 	    case 's': /* Unconditional subroutine */
@@ -3003,7 +3017,8 @@ m68k_ip (char *instring)
 	      else
 		add_frag (adds (&opP->disp),
 			  SEXT (offs (&opP->disp)),
-			  TAB (BRANCHBW, SZ_UNDEF));
+			  (use_pl ? TAB (BRANCHBWPL, SZ_UNDEF)
+			   : TAB (BRANCHBW, SZ_UNDEF)));
 	      break;
 	    case 'w':
 	      if (isvar (&opP->disp))
@@ -3553,10 +3568,9 @@ reverse_8_bits (int in)
   return out;
 }				/* reverse_8_bits() */
 
-/* Cause an extra frag to be generated here, inserting up to 10 bytes
-   (that value is chosen in the frag_var call in md_assemble).  TYPE
-   is the subtype of the frag to be generated; its primary type is
-   rs_machine_dependent.
+/* Cause an extra frag to be generated here, inserting up to
+   FRAG_VAR_SIZE bytes.  TYPE is the subtype of the frag to be
+   generated; its primary type is rs_machine_dependent.
 
    The TYPE parameter is also used by md_convert_frag_1 and
    md_estimate_size_before_relax.  The appropriate type of fixup will
@@ -4229,7 +4243,7 @@ md_assemble (char *str)
     for (n = 1; n < the_ins.nfrag; n++)
       wid += 2 * (the_ins.numo - the_ins.fragb[n - 1].fragoff);
     /* frag_var part.  */
-    wid += 10;
+    wid += FRAG_VAR_SIZE;
     /* Make sure the whole insn fits in one chunk, in particular that
        the var part is attached, as we access one byte before the
        variable frag for byte branches.  */
@@ -4277,7 +4291,7 @@ md_assemble (char *str)
 					      the_ins.reloc[m].pic_reloc));
 	  fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
 	}
-      (void) frag_var (rs_machine_dependent, 10, 0,
+      (void) frag_var (rs_machine_dependent, FRAG_VAR_SIZE, 0,
 		       (relax_substateT) (the_ins.fragb[n].fragty),
 		       the_ins.fragb[n].fadd, the_ins.fragb[n].foff, to_beg_P);
     }
@@ -4849,6 +4863,7 @@ md_convert_frag_1 (fragS *fragP)
     case TAB (BRABSJUNC, BYTE):
     case TAB (BRABSJCOND, BYTE):
     case TAB (BRANCHBW, BYTE):
+    case TAB (BRANCHBWPL, BYTE):
       know (issbyte (disp));
       if (disp == 0)
 	as_bad_where (fragP->fr_file, fragP->fr_line,
@@ -4861,6 +4876,7 @@ md_convert_frag_1 (fragS *fragP)
     case TAB (BRABSJUNC, SHORT):
     case TAB (BRABSJCOND, SHORT):
     case TAB (BRANCHBW, SHORT):
+    case TAB (BRANCHBWPL, SHORT):
       fragP->fr_opcode[1] = 0x00;
       fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
 		      fragP->fr_offset, 1, RELAX_RELOC_PC16);
@@ -4872,6 +4888,24 @@ md_convert_frag_1 (fragS *fragP)
 		      fragP->fr_offset, 1, RELAX_RELOC_PC32);
       fragP->fr_fix += 4;
       break;
+    case TAB (BRANCHBWPL, LONG):
+      /* Here we are converting an unconditional branch into a pair of
+	 conditional branches, in order to get the range.  */
+      fragP->fr_opcode[0] = 0x66; /* bne */
+      fragP->fr_opcode[1] = 0xFF;
+      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+		      fragP->fr_offset, 1, RELAX_RELOC_PC32);
+      fixP->fx_file = fragP->fr_file;
+      fixP->fx_line = fragP->fr_line;
+      fragP->fr_fix += 4;  /* Skip first offset */
+      buffer_address += 4;
+      *buffer_address++ = 0x67; /* beq */
+      *buffer_address++ = 0xff;
+      fragP->fr_fix += 2;  /* Skip second branch opcode */
+      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+		      fragP->fr_offset, 1, RELAX_RELOC_PC32);
+      fragP->fr_fix += 4;
+      break;
     case TAB (BRABSJUNC, LONG):
       if (fragP->fr_opcode[0] == 0x61)		/* jbsr */
 	{
@@ -5067,6 +5101,7 @@ md_estimate_size_before_relax (fragS *fr
   switch (fragP->fr_subtype)
     {
     case TAB (BRANCHBWL, SZ_UNDEF):
+    case TAB (BRANCHBWPL, SZ_UNDEF):
     case TAB (BRABSJUNC, SZ_UNDEF):
     case TAB (BRABSJCOND, SZ_UNDEF):
       {
Index: gas/testsuite/gas/m68k/br-isaa.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/m68k/br-isaa.d,v
retrieving revision 1.1
diff -u -d -p -r1.1 br-isaa.d
--- gas/testsuite/gas/m68k/br-isaa.d	23 Apr 2007 07:51:27 -0000	1.1
+++ gas/testsuite/gas/m68k/br-isaa.d	27 Aug 2007 19:32:12 -0000
@@ -1,5 +1,5 @@
 #name: br-isaa.d
-#objdump: -d
+#objdump: -dr
 #as: -march=isaa -pcrel
 
 .*:     file format .*
@@ -10,6 +10,8 @@ Disassembly of section .text:
    0:	4e71           	nop
    2:	60fc           	bras 0 <foo>
    4:	6000 0000      	braw 6 <foo\+0x6>
+			6: R_68K_PC16	bar
    8:	61f6           	bsrs 0 <foo>
    a:	6100 0000      	bsrw c <foo\+0xc>
+			c: R_68K_PC16	bar
    e:	4e71           	nop
Index: gas/testsuite/gas/m68k/br-isab.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/m68k/br-isab.d,v
retrieving revision 1.2
diff -u -d -p -r1.2 br-isab.d
--- gas/testsuite/gas/m68k/br-isab.d	15 May 2007 09:21:24 -0000	1.2
+++ gas/testsuite/gas/m68k/br-isab.d	27 Aug 2007 19:32:12 -0000
@@ -1,5 +1,5 @@
 #name: br-isab.d
-#objdump: -d
+#objdump: -dr
 #as: -march=isab -pcrel
 
 .*:     file format .*
@@ -11,6 +11,8 @@ Disassembly of section .text:
    2:	61ff ffff fffc 	bsrl 0 <foo>
    8:	60f6           	bras 0 <foo>
    a:	60ff 0000 0000 	bral c <foo\+0xc>
+			c: R_68K_PC32	bar
   10:	61ee           	bsrs 0 <foo>
   12:	61ff 0000 0000 	bsrl 14 <foo\+0x14>
+			14: R_68K_PC32	bar
   18:	4e71           	nop
Index: gas/testsuite/gas/m68k/br-isac.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/m68k/br-isac.d,v
retrieving revision 1.2
diff -u -d -p -r1.2 br-isac.d
--- gas/testsuite/gas/m68k/br-isac.d	15 May 2007 09:21:24 -0000	1.2
+++ gas/testsuite/gas/m68k/br-isac.d	27 Aug 2007 19:32:12 -0000
@@ -1,5 +1,5 @@
 #name: br-isac.d
-#objdump: -d
+#objdump: -dr
 #as: -march=isac -pcrel
 
 .*:     file format .*
@@ -10,7 +10,11 @@ Disassembly of section .text:
    0:	4e71           	nop
    2:	61ff ffff fffc 	bsrl 0 <foo>
    8:	60f6           	bras 0 <foo>
-   a:	6000 0000      	braw c <foo\+0xc>
-   e:	61f0           	bsrs 0 <foo>
-  10:	61ff 0000 0000 	bsrl 12 <foo\+0x12>
-  16:	4e71           	nop
+   a:	66ff 0000 0000 	bnel c <foo\+0xc>
+			c: R_68K_PC32	bar
+  10:	67ff 0000 0000 	beql 12 <foo\+0x12>
+			12: R_68K_PC32	bar
+  16:	61e8           	bsrs 0 <foo>
+  18:	61ff 0000 0000 	bsrl 1a <foo\+0x1a>
+			1a: R_68K_PC32	bar
+  1e:	4e71           	nop


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]