MIPS/GAS: Relax branches to symbols resolved at link time
authorMaciej W. Rozycki <macro@imgtec.com>
Fri, 8 Apr 2016 23:20:35 +0000 (00:20 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Wed, 13 Apr 2016 12:32:41 +0000 (13:32 +0100)
Where branch relaxation is enabled emit the long sequence for branches
whose distance cannot be determined, i.e. to symbols that are undefined
or in a different segment.  These symbols are only resolved at link time
and therefore the longer sequence ensures the branch target is in range,
which cannot be guaranteed with a direct branch.

This is the opposite to the current implementation, originally proposed
here: <https://sourceware.org/ml/binutils/2002-09/msg00218.html>.  The
proposal was then extensively discussed before the final version was
posted here: <https://sourceware.org/ml/binutils/2002-10/msg00191.html>
and eventually committed:

commit 4a6a3df43dbb37853a7b88b10ae97d9ec5daf987
Author: Alexandre Oliva <aoliva@redhat.com>
Date:   Sat Oct 12 05:23:33 2002 +0000

The case considered here was not commented in the review however and the
original version remains.  With branch relaxation enabled it makes more
sense to do it consistently, so that all code impure with respect to
branch distances can be linked.  Direct branches are still produced for
the cases concerned where branch relaxation is disabled, which is the
default.

gas/
* config/tc-mips.c (relaxed_branch_length): Use the long
sequence where the distance cannot be determined.
(relaxed_micromips_32bit_branch_length): Likewise.
* testsuite/gas/mips/branch-extern-1.d: New test.
* testsuite/gas/mips/branch-extern-2.d: New test.
* testsuite/gas/mips/branch-extern-3.d: New test.
* testsuite/gas/mips/branch-extern-4.d: New test.
* testsuite/gas/mips/branch-extern.l: New stderr output.
* testsuite/gas/mips/branch-extern.s: New test source.
* testsuite/gas/mips/branch-section-1.d: New test.
* testsuite/gas/mips/branch-section-2.d: New test.
* testsuite/gas/mips/branch-section-3.d: New test.
* testsuite/gas/mips/branch-section-4.d: New test.
* testsuite/gas/mips/branch-section.l: New stderr output.
* testsuite/gas/mips/branch-section.s: New test source.
* testsuite/gas/mips/mips.exp: Run the new tests.

15 files changed:
gas/ChangeLog
gas/config/tc-mips.c
gas/testsuite/gas/mips/branch-extern-1.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-extern-2.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-extern-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-extern-4.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-extern.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-extern.s [new file with mode: 0644]
gas/testsuite/gas/mips/branch-section-1.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-section-2.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-section-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-section-4.d [new file with mode: 0644]
gas/testsuite/gas/mips/branch-section.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-section.s [new file with mode: 0644]
gas/testsuite/gas/mips/mips.exp

index 827130f..b5548b3 100644 (file)
@@ -1,3 +1,22 @@
+2016-04-13  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * config/tc-mips.c (relaxed_branch_length): Use the long
+       sequence where the distance cannot be determined.
+       (relaxed_micromips_32bit_branch_length): Likewise.
+       * testsuite/gas/mips/branch-extern-1.d: New test.
+       * testsuite/gas/mips/branch-extern-2.d: New test.
+       * testsuite/gas/mips/branch-extern-3.d: New test.
+       * testsuite/gas/mips/branch-extern-4.d: New test.
+       * testsuite/gas/mips/branch-extern.l: New stderr output.
+       * testsuite/gas/mips/branch-extern.s: New test source.
+       * testsuite/gas/mips/branch-section-1.d: New test.
+       * testsuite/gas/mips/branch-section-2.d: New test.
+       * testsuite/gas/mips/branch-section-3.d: New test.
+       * testsuite/gas/mips/branch-section-4.d: New test.
+       * testsuite/gas/mips/branch-section.l: New stderr output.
+       * testsuite/gas/mips/branch-section.s: New test source.
+       * testsuite/gas/mips/mips.exp: Run the new tests.
+
 2016-04-12  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * testsuite/gas/arc/textauxregister.d: New file.
index db3ec67..dba147a 100644 (file)
@@ -16811,12 +16811,9 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update)
 
       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
+    /* If the symbol is not defined or it's in a different segment,
+       we emit the long sequence.  */
     toofar = TRUE;
 
   if (fragp && update && toofar != RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
@@ -16881,12 +16878,9 @@ relaxed_micromips_32bit_branch_length (fragS *fragp, asection *sec, int update)
 
       toofar = val < - (0x8000 << 1) || val >= (0x8000 << 1);
     }
-  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
+    /* If the symbol is not defined or it's in a different segment,
+       we emit the long sequence.  */
     toofar = TRUE;
 
   if (fragp && update
diff --git a/gas/testsuite/gas/mips/branch-extern-1.d b/gas/testsuite/gas/mips/branch-extern-1.d
new file mode 100644 (file)
index 0000000..8f553f8
--- /dev/null
@@ -0,0 +1,12 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPS branch to an external symbol
+#as: -32 -KPIC
+#source: branch-extern.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 1000ffff     b       00000000 <foo>
+[      ]*[0-9a-f]+: R_MIPS_PC16        bar
+[0-9a-f]+ <[^>]*> 00000000     nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-extern-2.d b/gas/testsuite/gas/mips/branch-extern-2.d
new file mode 100644 (file)
index 0000000..b0bab70
--- /dev/null
@@ -0,0 +1,12 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: microMIPS branch to an external symbol
+#as: -32 -KPIC -mmicromips
+#source: branch-extern.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 9400 fffe    b       00000000 <foo>
+[      ]*[0-9a-f]+: R_MICROMIPS_PC16_S1        bar
+[0-9a-f]+ <[^>]*> 0c00         nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-extern-3.d b/gas/testsuite/gas/mips/branch-extern-3.d
new file mode 100644 (file)
index 0000000..eb83f17
--- /dev/null
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPS relaxed branch to an external symbol
+#as: -32 -KPIC -mips1 --relax-branch
+#source: branch-extern.s
+#stderr: branch-extern.l
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 8f810000     lw      at,0\(gp\)
+[      ]*[0-9a-f]+: R_MIPS_GOT16       bar
+[0-9a-f]+ <[^>]*> 00000000     nop
+[0-9a-f]+ <[^>]*> 24210000     addiu   at,at,0
+[      ]*[0-9a-f]+: R_MIPS_LO16        bar
+[0-9a-f]+ <[^>]*> 00200008     jr      at
+[0-9a-f]+ <[^>]*> 00000000     nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-extern-4.d b/gas/testsuite/gas/mips/branch-extern-4.d
new file mode 100644 (file)
index 0000000..6718271
--- /dev/null
@@ -0,0 +1,16 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: microMIPS relaxed branch to an external symbol
+#as: -32 -KPIC -mmicromips --relax-branch
+#source: branch-extern.s
+#stderr: branch-extern.l
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> fc3c 0000    lw      at,0\(gp\)
+[      ]*[0-9a-f]+: R_MICROMIPS_GOT16  bar
+[0-9a-f]+ <[^>]*> 3021 0000    addiu   at,at,0
+[      ]*[0-9a-f]+: R_MICROMIPS_LO16   bar
+[0-9a-f]+ <[^>]*> 4581         jr      at
+[0-9a-f]+ <[^>]*> 0c00         nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-extern.l b/gas/testsuite/gas/mips/branch-extern.l
new file mode 100644 (file)
index 0000000..8d7e228
--- /dev/null
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:5: Warning: relaxed out-of-range branch into a jump
diff --git a/gas/testsuite/gas/mips/branch-extern.s b/gas/testsuite/gas/mips/branch-extern.s
new file mode 100644 (file)
index 0000000..bbb6700
--- /dev/null
@@ -0,0 +1,10 @@
+       .text
+       .globl  foo
+       .ent    foo
+foo:
+       b       bar
+       .end    foo
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+       .align  4, 0
+       .space  16
diff --git a/gas/testsuite/gas/mips/branch-section-1.d b/gas/testsuite/gas/mips/branch-section-1.d
new file mode 100644 (file)
index 0000000..7782d0c
--- /dev/null
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPS branch to a different section
+#as: -32
+#source: branch-section.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 1000ffff     b       00000000 <foo>
+[      ]*[0-9a-f]+: R_MIPS_PC16        bar
+[0-9a-f]+ <[^>]*> 00000000     nop
+       \.\.\.
+
+Disassembly of section \.init:
+[0-9a-f]+ <[^>]*> 03e00008     jr      ra
+[0-9a-f]+ <[^>]*> 00000000     nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-section-2.d b/gas/testsuite/gas/mips/branch-section-2.d
new file mode 100644 (file)
index 0000000..5de7cec
--- /dev/null
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: microMIPS branch to a different section
+#as: -32 -mmicromips
+#source: branch-section.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 9400 fffe    b       00000000 <foo>
+[      ]*[0-9a-f]+: R_MICROMIPS_PC16_S1        bar
+[0-9a-f]+ <[^>]*> 0c00         nop
+       \.\.\.
+
+Disassembly of section \.init:
+[0-9a-f]+ <[^>]*> 459f         jr      ra
+[0-9a-f]+ <[^>]*> 0c00         nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-section-3.d b/gas/testsuite/gas/mips/branch-section-3.d
new file mode 100644 (file)
index 0000000..63b42b5
--- /dev/null
@@ -0,0 +1,18 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPS relaxed branch to a different section
+#as: -32 --relax-branch
+#source: branch-section.s
+#stderr: branch-section.l
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 08000000     j       00000000 <foo>
+[      ]*[0-9a-f]+: R_MIPS_26  \.init
+[0-9a-f]+ <[^>]*> 00000000     nop
+       \.\.\.
+
+Disassembly of section \.init:
+[0-9a-f]+ <[^>]*> 03e00008     jr      ra
+[0-9a-f]+ <[^>]*> 00000000     nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-section-4.d b/gas/testsuite/gas/mips/branch-section-4.d
new file mode 100644 (file)
index 0000000..6eb2b6d
--- /dev/null
@@ -0,0 +1,18 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: microMIPS relaxed branch to a different section
+#as: -32 -mmicromips --relax-branch
+#source: branch-section.s
+#stderr: branch-section.l
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> d400 0000    j       00000000 <foo>
+[      ]*[0-9a-f]+: R_MICROMIPS_26_S1  bar
+[0-9a-f]+ <[^>]*> 0c00         nop
+       \.\.\.
+
+Disassembly of section \.init:
+[0-9a-f]+ <[^>]*> 459f         jr      ra
+[0-9a-f]+ <[^>]*> 0c00         nop
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-section.l b/gas/testsuite/gas/mips/branch-section.l
new file mode 100644 (file)
index 0000000..8d7e228
--- /dev/null
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:5: Warning: relaxed out-of-range branch into a jump
diff --git a/gas/testsuite/gas/mips/branch-section.s b/gas/testsuite/gas/mips/branch-section.s
new file mode 100644 (file)
index 0000000..8be1fa3
--- /dev/null
@@ -0,0 +1,20 @@
+       .text
+       .globl  foo
+       .ent    foo
+foo:
+       b       bar
+       .end    foo
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+       .align  4, 0
+       .space  16
+
+       .section .init, "ax", @progbits
+       .ent    bar
+bar:
+       jr      $ra
+       .end    bar
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+       .align  4, 0
+       .space  16
index 4d770cb..ad3cdfe 100644 (file)
@@ -575,6 +575,15 @@ if { [istarget mips*-*-vxworks*] } {
            "MIPS branch swapping ($count)"
     }
 
+    run_dump_test "branch-section-1"
+    run_dump_test "branch-section-2"
+    run_dump_test "branch-section-3"
+    run_dump_test "branch-section-4"
+    run_dump_test "branch-extern-1"
+    run_dump_test "branch-extern-2"
+    run_dump_test "branch-extern-3"
+    run_dump_test "branch-extern-4"
+
     run_dump_test "compact-eh-eb-1"
     run_dump_test "compact-eh-eb-2"
     run_dump_test "compact-eh-eb-3"