gas, sparc: Allow non-fpop2 instructions before floating point branches

Sparc V8 does not allow fpop2 instructions (floating point
comparisons) immediately before floating point branches.  From the
SPARC Architecture Manual Version 8, section B.22 "Branch on
Floating-point Condition Codes Instructions":

"If the instruction executed immediately before an FBfcc is an FPop2
instruction, the result of the FBfcc is undefined.  Therefore, at
least one non FPop2 instruction should be executed between the FPop2
instruction and the FBfcc instruction."

The existing check in GAS, however, does not allow any kind of
floating point instruction before the branch.  This patch adds an
extra condition to only disallow fpop2 instructions.

gas/ChangeLog:

2018-09-04  Daniel Cederman  <cederman@gaisler.com>

	* config/tc-sparc.c (md_assemble): Allow non-fpop2 instructions
            before floating point branches for Sparc V8 and earlier.
	* testsuite/gas/sparc/sparc.exp: Execute the new test.
	* testsuite/gas/sparc/v8branch.d: New test.
	* testsuite/gas/sparc/v8branch.s: New test.
This commit is contained in:
Daniel Cederman 2018-09-04 06:25:52 -07:00 committed by jemarch
parent 6c9d681b07
commit 618a8fdba6
5 changed files with 44 additions and 5 deletions

View File

@ -1,3 +1,11 @@
2018-09-04 Daniel Cederman <cederman@gaisler.com>
* config/tc-sparc.c (md_assemble): Allow non-fpop2 instructions
before floating point branches for Sparc V8 and earlier.
* testsuite/gas/sparc/sparc.exp: Execute the new test.
* testsuite/gas/sparc/v8branch.d: New test.
* testsuite/gas/sparc/v8branch.s: New test.
2018-09-03 Nick Clifton <nickc@redhat.com>
PR gas/23570

View File

@ -1557,20 +1557,21 @@ md_assemble (char *str)
as_warn (_("FP branch in delay slot"));
}
/* SPARC before v9 requires a nop instruction between a floating
point instruction and a floating point branch. We insert one
automatically, with a warning. */
/* SPARC before v9 does not allow a floating point compare
directly before a floating point branch. Insert a nop
instruction if needed, with a warning. */
if (max_architecture < SPARC_OPCODE_ARCH_V9
&& last_insn != NULL
&& (insn->flags & F_FBR) != 0
&& (last_insn->flags & F_FLOAT) != 0)
&& (last_insn->flags & F_FLOAT) != 0
&& (last_insn->match & OP3 (0x35)) == OP3 (0x35))
{
struct sparc_it nop_insn;
nop_insn.opcode = NOP_INSN;
nop_insn.reloc = BFD_RELOC_NONE;
output_insn (insn, &nop_insn);
as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
as_warn (_("FP branch preceded by FP compare; NOP inserted"));
}
switch (special_case)

View File

@ -66,6 +66,7 @@ if [istarget sparc*-*-*] {
run_dump_test "v8-movwr-imm"
run_dump_test "save-args"
run_dump_test "leon"
run_dump_test "v8branch"
set_tests_arch "v9c"
run_dump_test "ldtxa"

View File

@ -0,0 +1,18 @@
#as: -Av8
#objdump: -dr -m sparc
#warning: Warning: FP branch preceded by FP compare; NOP inserted
#name: v8 branch instructions
.*: +file format .*
Disassembly of section .text:
0+ <no_fpop2_before_fcmp>:
0: 81 a0 08 20 fadds %f0, %f0, %f0
4: 13 80 00 06 fbe 1c <no_fpop2_before_fcmp\+0x1c>
8: 01 00 00 00 nop
c: 81 a8 0a 20 fcmps %f0, %f0
10: 01 00 00 00 nop
14: 13 80 00 02 fbe 1c <no_fpop2_before_fcmp\+0x1c>
18: 01 00 00 00 nop
1c: 01 00 00 00 nop

View File

@ -0,0 +1,11 @@
.text
# Check that a nop instruction is inserted to prevent a floating
# point compare directly followed by a floating point branch.
no_fpop2_before_fcmp:
fadds %f0, %f0, %f0
fbe 1f
nop
fcmps %f0, %f0
fbe 1f
nop
1: nop