* config/tc-mips.c (mips16_extended_frag): Avoid an infinite loop
authorIan Lance Taylor <ian@airs.com>
Mon, 9 Dec 1996 23:34:20 +0000 (23:34 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 9 Dec 1996 23:34:20 +0000 (23:34 +0000)
when extending because the value is exactly maxtiny + 1.

gas/ChangeLog
gas/config/tc-mips.c

index 03f5bbbefe4a74bd1bfe21bf64bfdc6955b7a215..cf501df923077f5ab61e4298a05400f08254aada 100644 (file)
@@ -1,5 +1,8 @@
 Mon Dec  9 17:09:42 1996  Ian Lance Taylor  <ian@cygnus.com>
 
+       * config/tc-mips.c (mips16_extended_frag): Avoid an infinite loop
+       when extending because the value is exactly maxtiny + 1.
+
        * config/tc-mips.c (RELAX_MIPS16_ENCODE): Add small and ext
        arguments, and store them.  Adjust other RELAX_MIPS16 macros.
        (RELAX_MIPS16_USER_SMALL): Define.
index c1a348e4066e98376ff595826c7ec8c79d90fd85..954d047052dd8d141ed329baf2a1a0a13ace725c 100644 (file)
@@ -9154,8 +9154,30 @@ mips16_extended_frag (fragp, sec, stretch)
       /* If any of the shifted bits are set, we must use an extended
          opcode.  If the address depends on the size of this
          instruction, this can lead to a loop, so we arrange to always
-         use an extended opcode.  */
-      if ((val & ((1 << op->shift) - 1)) != 0)
+         use an extended opcode.  We only check this when we are in
+         the main relaxation loop, when SEC is NULL.  */
+      if ((val & ((1 << op->shift) - 1)) != 0 && sec == NULL)
+       {
+         fragp->fr_subtype =
+           RELAX_MIPS16_MARK_LONG_BRANCH (fragp->fr_subtype);
+         return 1;
+       }
+
+      /* If we are about to mark a frag as extended because the value
+         is precisely maxtiny + 1, then there is a chance of an
+         infinite loop as in the following code:
+            la $4,foo
+            .skip      1020
+            .align     2
+          foo:
+        In this case when the la is extended, foo is 0x3fc bytes
+        away, so the la can be shrunk, but then foo is 0x400 away, so
+        the la must be extended.  To avoid this loop, we mark the
+        frag as extended if it was small, and is about to become
+        extended with a value of maxtiny + 1.  */
+      if (val == ((maxtiny + 1) << op->shift)
+         && ! RELAX_MIPS16_EXTENDED (fragp->fr_subtype)
+         && sec == NULL)
        {
          fragp->fr_subtype =
            RELAX_MIPS16_MARK_LONG_BRANCH (fragp->fr_subtype);