From: Maciej W. Rozycki Date: Fri, 8 Apr 2016 23:20:35 +0000 (+0100) Subject: MIPS/GAS: Relax branches to symbols resolved at link time X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c1f61bd2b0644fc710dcfbb378a63f0b34be8903;p=binutils-gdb.git MIPS/GAS: Relax branches to symbols resolved at link time 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: . The proposal was then extensively discussed before the final version was posted here: and eventually committed: commit 4a6a3df43dbb37853a7b88b10ae97d9ec5daf987 Author: Alexandre Oliva 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 827130fc671..b5548b354a8 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,22 @@ +2016-04-13 Maciej W. Rozycki + + * 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 * testsuite/gas/arc/textauxregister.d: New file. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index db3ec6775e2..dba147a9895 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -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 index 00000000000..8f553f86e47 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-extern-1.d @@ -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 +[ ]*[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 index 00000000000..b0bab70f2c1 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-extern-2.d @@ -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 +[ ]*[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 index 00000000000..eb83f1724e3 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-extern-3.d @@ -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 index 00000000000..67182716bd4 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-extern-4.d @@ -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 index 00000000000..8d7e2284da7 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-extern.l @@ -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 index 00000000000..bbb67007ccc --- /dev/null +++ b/gas/testsuite/gas/mips/branch-extern.s @@ -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 index 00000000000..7782d0c0754 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-section-1.d @@ -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 +[ ]*[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 index 00000000000..5de7cec16f0 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-section-2.d @@ -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 +[ ]*[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 index 00000000000..63b42b59fea --- /dev/null +++ b/gas/testsuite/gas/mips/branch-section-3.d @@ -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 +[ ]*[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 index 00000000000..6eb2b6d167a --- /dev/null +++ b/gas/testsuite/gas/mips/branch-section-4.d @@ -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 +[ ]*[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 index 00000000000..8d7e2284da7 --- /dev/null +++ b/gas/testsuite/gas/mips/branch-section.l @@ -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 index 00000000000..8be1fa3745c --- /dev/null +++ b/gas/testsuite/gas/mips/branch-section.s @@ -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 diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index 4d770cb7000..ad3cdfe80da 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -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"