aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-mips.c
diff options
context:
space:
mode:
authorFredrik Noring <noring@nocrew.org>2018-10-19 09:47:55 +0100
committerNick Clifton <nickc@redhat.com>2018-10-19 09:47:55 +0100
commit33d64ca5db656f1f377de18f94403d8b3b91e3a1 (patch)
tree898e440de0a4f6763f3a17b8c9cc0391b43304cc /gas/config/tc-mips.c
parent08acaf5caf47225ff94dc5e64ce8edce6664615a (diff)
downloadgdb-33d64ca5db656f1f377de18f94403d8b3b91e3a1.zip
gdb-33d64ca5db656f1f377de18f94403d8b3b91e3a1.tar.gz
gdb-33d64ca5db656f1f377de18f94403d8b3b91e3a1.tar.bz2
This set of changes clarifies the conditions for the R5900 short loop fix and extends its test with the border cases of six and seven instructions.
* testsuite/gas/mips/r5900.s: Extend the R5900 short loop fix test with border cases. * testsuite/gas/mips/r5900.d: Add extra expected disassembly. * config/tc-mips.c (can_swap_branch_p): Clarify the R5900 short loop hardware bug conditions. Correct note on the R5900 instruction count short loop fix.
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r--gas/config/tc-mips.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index c9fc6c6..918525b 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -6982,9 +6982,21 @@ can_swap_branch_p (struct mips_cl_insn *ip, expressionS *address_expr,
&& insn_length (history) != 4)
return FALSE;
- /* On R5900 short loops need to be fixed by inserting a nop in
- the branch delay slots.
- A short loop can be terminated too early. */
+ /* On the R5900 short loops need to be fixed by inserting a NOP in the
+ branch delay slot.
+
+ The short loop bug under certain conditions causes loops to execute
+ only once or twice. We must ensure that the assembler never
+ generates loops that satisfy all of the following conditions:
+
+ - a loop consists of less than or equal to six instructions
+ (including the branch delay slot);
+ - a loop contains only one conditional branch instruction at the end
+ of the loop;
+ - a loop does not contain any other branch or jump instructions;
+ - a branch delay slot of the loop is not NOP (EE 2.9 or later).
+
+ We need to do this because of a hardware bug in the R5900 chip. */
if (mips_opts.arch == CPU_R5900
/* Check if instruction has a parameter, ignore "j $31". */
&& (address_expr != NULL)
@@ -7002,8 +7014,8 @@ can_swap_branch_p (struct mips_cl_insn *ip, expressionS *address_expr,
|| (ip->insn_opcode & 0xffff0000) == 0x04110000)) /* bgezal $0 */
{
int distance;
- /* Check if loop is shorter than 6 instructions including
- branch and delay slot. */
+ /* Check if loop is shorter than or equal to 6 instructions
+ including branch and delay slot. */
distance = frag_now_fix () - S_GET_VALUE (address_expr->X_add_symbol);
if (distance <= 20)
{