From d28b6364b1fba1c0270c001f0d82a69e351e1922 Mon Sep 17 00:00:00 2001 From: "Jose E. Marchesi" Date: Tue, 25 Apr 2017 02:40:43 -0700 Subject: [PATCH] gas: sparc: fix relaxation of CALL instruction into branches in a.out targets This patch avoids CALL instructions to be optimized into branches if the symbols referred to in the CALL instruction are not fully resolved at the time the assembler writes its output. Tested in sparc64-linux-gnu and sparc-sun-sunos4.1.3 targets. No regressions. gas/ChangeLog: 2017-04-25 Jose E. Marchesi PR gas/21407 * config/tc-sparc.c (md_apply_fix): Do not transform `call' instructions into branch instructions in fixups generating additional relocations. * testsuite/gas/sparc/call-relax.s: New file. * testsuite/gas/sparc/call-relax.d: Likewise. * testsuite/gas/sparc/call-relax-aout.d: Likewise. * testsuite/gas/sparc/sparc.exp: Test call-relax and call-relax-aout. --- gas/ChangeLog | 11 +++++++++++ gas/config/tc-sparc.c | 9 +++++++-- gas/testsuite/gas/sparc/call-relax-aout.d | 19 +++++++++++++++++++ gas/testsuite/gas/sparc/call-relax.d | 18 ++++++++++++++++++ gas/testsuite/gas/sparc/call-relax.s | 10 ++++++++++ gas/testsuite/gas/sparc/sparc.exp | 4 ++++ 6 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 gas/testsuite/gas/sparc/call-relax-aout.d create mode 100644 gas/testsuite/gas/sparc/call-relax.d create mode 100644 gas/testsuite/gas/sparc/call-relax.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 7c9697bd045..f85422353f2 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2017-04-25 Jose E. Marchesi + + PR gas/21407 + * config/tc-sparc.c (md_apply_fix): Do not transform `call' + instructions into branch instructions in fixups generating + additional relocations. + * testsuite/gas/sparc/call-relax.s: New file. + * testsuite/gas/sparc/call-relax.d: Likewise. + * testsuite/gas/sparc/call-relax-aout.d: Likewise. + * testsuite/gas/sparc/sparc.exp: Test call-relax and call-relax-aout. + 2017-04-24 Thomas Preud'homme * config/tc-arm.c (move_or_literal_pool): Remove code generating MOVS. diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index 030e10d7749..4c930b5ddfc 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -3584,8 +3584,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED) insn |= val & 0x3fffffff; - /* See if we have a delay slot. */ - if (sparc_relax && fixP->fx_where + 8 <= fixP->fx_frag->fr_fix) + /* See if we have a delay slot. In that case we attempt to + optimize several cases transforming CALL instructions + into branches. But we can only do that if the relocation + can be completely resolved here, i.e. if no undefined + symbol is associated with it. */ + if (sparc_relax && fixP->fx_addsy == NULL + && fixP->fx_where + 8 <= fixP->fx_frag->fr_fix) { #define G0 0 #define O7 15 diff --git a/gas/testsuite/gas/sparc/call-relax-aout.d b/gas/testsuite/gas/sparc/call-relax-aout.d new file mode 100644 index 00000000000..8afcf5e8572 --- /dev/null +++ b/gas/testsuite/gas/sparc/call-relax-aout.d @@ -0,0 +1,19 @@ +#as: -Av9 -relax +#source: call-relax.s +#objdump: -dr +#name: sparc relax CALL (a.out) + +.*: +file format .*a\.out.* + +Disassembly of section .text: + +0+ : + 0: 31 00 00 00 sethi %hi\(0\), %i0 + 4: 10 80 00 02 b c + 8: 91 ee 20 00 restore %i0, 0, %o0 + +0+c : + c: 31 00 00 00 sethi %hi\(0\), %i0 + 10: 40 00 00 00 call 10 + 10: WDISP30 _undefined-0x10 + 14: 91 ee 20 00 restore %i0, 0, %o0 diff --git a/gas/testsuite/gas/sparc/call-relax.d b/gas/testsuite/gas/sparc/call-relax.d new file mode 100644 index 00000000000..de52274484f --- /dev/null +++ b/gas/testsuite/gas/sparc/call-relax.d @@ -0,0 +1,18 @@ +#as: -Av9 -relax +#objdump: -dr +#name: sparc relax CALL + +.*: +file format .*sparc.* + +Disassembly of section .text: + +0+ : + 0: 31 00 00 00 sethi %hi\(0\), %i0 + 4: 10 68 00 02 b %xcc, c + 8: 91 ee 20 00 restore %i0, 0, %o0 + +0+c : + c: 31 00 00 00 sethi %hi\(0\), %i0 + 10: 40 00 00 00 call 10 + 10: R_SPARC_WDISP30 _undefined + 14: 91 ee 20 00 restore %i0, 0, %o0 diff --git a/gas/testsuite/gas/sparc/call-relax.s b/gas/testsuite/gas/sparc/call-relax.s new file mode 100644 index 00000000000..f5ebbb68032 --- /dev/null +++ b/gas/testsuite/gas/sparc/call-relax.s @@ -0,0 +1,10 @@ +# Test relaxation of CALL instructions into branches. + .text +foo: + sethi %hi(0), %i0 + call bar, 0 + restore %i0, %lo(0), %o0 +bar: + sethi %hi(0), %i0 + call _undefined, 0 + restore %i0, %lo(0), %o0 diff --git a/gas/testsuite/gas/sparc/sparc.exp b/gas/testsuite/gas/sparc/sparc.exp index eb69e505158..1e9cc2cbddd 100644 --- a/gas/testsuite/gas/sparc/sparc.exp +++ b/gas/testsuite/gas/sparc/sparc.exp @@ -72,6 +72,10 @@ if [istarget sparc*-*-*] { run_dump_test "v9branch1" run_dump_test "imm-plus-rreg" run_dump_test "dcti-couples-v9" + run_dump_test "call-relax" + } else { + # The next tests are a.out only. + run_dump_test "call-relax-aout" } if [gas_64_check] { -- 2.30.2