PR25125, relaxation chooses wrong branch size
authorAlan Modra <amodra@gmail.com>
Fri, 25 Oct 2019 09:16:24 +0000 (19:46 +1030)
committerAlan Modra <amodra@gmail.com>
Fri, 25 Oct 2019 12:49:24 +0000 (23:19 +1030)
The patch I made for PR12049 didn't test for a "negative" branch
properly.  "if (target < address)" ought to have been
"if (target < address + fragP->fr_fix)".  Rather than making that
change, this patch adds fragP->fr_fix into address earlier.  The patch
also avoids running into a bad interaction with the m68k
md_prepare_relax_scan by returning zero growth immediately, since the
adjusted target expression would result in a zero "aim".

PR gas/25125
PR gas/12049
* write.c (relax_frag): Correct calculation of delta for
positive branches where "stretch" would make the branch
negative.  Return zero immediately in that case.  Correct
TC_PCREL_ADJUST comment.

gas/ChangeLog
gas/write.c

index ac2e3d75aa211023119687eb5421b5f26ed26c2a..8b78037430555b011d1fef184bae380076a6145c 100644 (file)
@@ -1,3 +1,12 @@
+2019-10-25  Alan Modra  <amodra@gmail.com>
+
+       PR gas/25125
+       PR gas/12049
+       * write.c (relax_frag): Correct calculation of delta for
+       positive branches where "stretch" would make the branch
+       negative.  Return zero immediately in that case.  Correct
+       TC_PCREL_ADJUST comment.
+
 2019-10-16  Alan Modra  <amodra@gmail.com>
 
        * config/tc-xtensa.c (xg_order_trampoline_chain_entry): Don't
index 9b5ae6ff32a3b43453bdf03da62bbb12adda569c..8f7786eb367cc646e031cd8f46e8a00914e5336f 100644 (file)
@@ -2497,7 +2497,7 @@ relax_frag (segT segment, fragS *fragP, long stretch)
   const relax_typeS *table;
 
   target = fragP->fr_offset;
-  address = fragP->fr_address;
+  address = fragP->fr_address + fragP->fr_fix;
   table = TC_GENERIC_RELAX_TABLE;
   this_state = fragP->fr_subtype;
   start_type = this_type = table + this_state;
@@ -2537,13 +2537,13 @@ relax_frag (segT segment, fragS *fragP, long stretch)
             negative.  Don't allow this in case the negative reach is
             large enough to require a larger branch instruction.  */
          else if (target < address)
-           target = fragP->fr_next->fr_address + stretch;
+           return 0;
        }
     }
 
-  aim = target - address - fragP->fr_fix;
+  aim = target - address;
 #ifdef TC_PCREL_ADJUST
-  /* Currently only the ns32k family needs this.  */
+  /* Currently only the ns32k and arc needs this.  */
   aim += TC_PCREL_ADJUST (fragP);
 #endif