* config/tc-mips.c (macro): Handle constants for M_LI_D and
authorIan Lance Taylor <ian@airs.com>
Wed, 7 May 1997 19:41:17 +0000 (19:41 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 7 May 1997 19:41:17 +0000 (19:41 +0000)
M_LI_DD.
(mips_ip): For 'F', 'L', 'f', and 'l', generate a constant rather
than an address if the floating point value looks sufficiently
simple.
PR 12237.

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

index 38add049ea3e605100402abb9e95058838ded6a5..7e66d49fd973e08d5cee7f0911b98538b7c75038 100644 (file)
@@ -1,3 +1,11 @@
+Wed May  7 15:39:48 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * config/tc-mips.c (macro): Handle constants for M_LI_D and
+       M_LI_DD.
+       (mips_ip): For 'F', 'L', 'f', and 'l', generate a constant rather
+       than an address if the floating point value looks sufficiently
+       simple.
+
 Tue May  6 12:18:09 1997  Ian Lance Taylor  <ian@cygnus.com>
 
        * config/tc-i386.c (md_section_align): If a.out and BFD, force
index 8c7e24f24e61cbc850a750ff07725a483558129b..61623aed9ce237ed2dc3e3db41735a99dacd8ef2 100644 (file)
@@ -4897,6 +4897,27 @@ macro (ip)
        }
 
     case M_LI_D:
+      /* If we have a constant in IMM_EXPR, then in mips3 mode it is
+         the entire value, and in mips1 mode it is the high order 32
+         bits of the value and the low order 32 bits are either zero
+         or in offset_expr.  */
+      if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
+       {
+         load_register (&icnt, treg, &imm_expr, mips_opts.isa >= 3);
+         if (mips_opts.isa < 3 && treg != 31)
+           {
+             if (offset_expr.X_op == O_absent)
+               macro_build ((char *) NULL, &icnt, NULL, "move", "d,s",
+                            treg + 1, 0);
+             else
+               {
+                 assert (offset_expr.X_op == O_constant);
+                 load_register (&icnt, treg + 1, &offset_expr, 0);
+               }
+           }
+         return;
+       }
+
       /* We know that sym is in the .rdata section.  First we get the
         upper 16 bits of the address.  */
       if (mips_pic == NO_PIC)
@@ -4949,6 +4970,34 @@ macro (ip)
       break;
 
     case M_LI_DD:
+      /* If we have a constant in IMM_EXPR, then in mips3 mode it is
+         the entire value, and in mips1 mode it is the high order 32
+         bits of the value and the low order 32 bits are either zero
+         or in offset_expr.  */
+      if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
+       {
+         load_register (&icnt, AT, &imm_expr, mips_opts.isa >= 3);
+         if (mips_opts.isa >= 3)
+           macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+                        "dmtc1", "t,S", AT, treg);
+         else
+           {
+             macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+                          "mtc1", "t,G", AT, treg + 1);
+             if (offset_expr.X_op == O_absent)
+               macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+                            "mtc1", "t,G", 0, treg);
+             else
+               {
+                 assert (offset_expr.X_op == O_constant);
+                 load_register (&icnt, AT, &offset_expr, 0);
+                 macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+                              "mtc1", "t,G", AT, treg);
+               }
+           }
+         break;
+       }
+
       assert (offset_expr.X_op == O_symbol
              && offset_expr.X_add_number == 0);
       s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));
@@ -6911,22 +6960,72 @@ mips_ip (str, ip)
                    || (*args == 'l'
                        && (! USE_GLOBAL_POINTER_OPT
                            || mips_pic == EMBEDDED_PIC
-                           || g_switch_value < 4)
-                       ))
+                           || g_switch_value < 4
+                           || (temp[0] == 0 && temp[1] == 0)
+                           || (temp[2] == 0 && temp[3] == 0))))
                  {
                    imm_expr.X_op = O_constant;
                    if (! target_big_endian)
-                     imm_expr.X_add_number =
-                       (((((((int) temp[3] << 8)
-                            | temp[2]) << 8)
-                          | temp[1]) << 8)
-                        | temp[0]);
+                     imm_expr.X_add_number = bfd_getl32 (temp);
                    else
-                     imm_expr.X_add_number =
-                       (((((((int) temp[0] << 8)
-                            | temp[1]) << 8)
-                          | temp[2]) << 8)
-                        | temp[3]);
+                     imm_expr.X_add_number = bfd_getb32 (temp);
+                 }
+               else if (length > 4
+                        && ((temp[0] == 0 && temp[1] == 0)
+                            || (temp[2] == 0 && temp[3] == 0))
+                        && ((temp[4] == 0 && temp[5] == 0)
+                            || (temp[6] == 0 && temp[7] == 0)))
+                 {
+                   /* The value is simple enough to load with a
+                       couple of instructions.  In mips1 mode, set
+                       imm_expr to the high order 32 bits and
+                       offset_expr to the low order 32 bits.
+                       Otherwise, set imm_expr to the entire 64 bit
+                       constant.  */
+                   if (mips_opts.isa < 3)
+                     {
+                       imm_expr.X_op = O_constant;
+                       offset_expr.X_op = O_constant;
+                       if (! target_big_endian)
+                         {
+                           imm_expr.X_add_number = bfd_getl32 (temp + 4);
+                           offset_expr.X_add_number = bfd_getl32 (temp);
+                         }
+                       else
+                         {
+                           imm_expr.X_add_number = bfd_getb32 (temp);
+                           offset_expr.X_add_number = bfd_getb32 (temp + 4);
+                         }
+                       if (offset_expr.X_add_number == 0)
+                         offset_expr.X_op = O_absent;
+                     }
+                   else if (sizeof (imm_expr.X_add_number) > 4)
+                     {
+                       imm_expr.X_op = O_constant;
+                       if (! target_big_endian)
+                         imm_expr.X_add_number = bfd_getl64 (temp);
+                       else
+                         imm_expr.X_add_number = bfd_getb64 (temp);
+                     }
+                   else
+                     {
+                       imm_expr.X_op = O_big;
+                       imm_expr.X_add_number = 4;
+                       if (! target_big_endian)
+                         {
+                           generic_bignum[0] = bfd_getl16 (temp);
+                           generic_bignum[1] = bfd_getl16 (temp + 2);
+                           generic_bignum[2] = bfd_getl16 (temp + 4);
+                           generic_bignum[3] = bfd_getl16 (temp + 6);
+                         }
+                       else
+                         {
+                           generic_bignum[0] = bfd_getb16 (temp + 6);
+                           generic_bignum[1] = bfd_getb16 (temp + 4);
+                           generic_bignum[2] = bfd_getb16 (temp + 2);
+                           generic_bignum[3] = bfd_getb16 (temp);
+                         }
+                     }
                  }
                else
                  {
@@ -9772,11 +9871,15 @@ nopic_need_relax (sym, before_relaxing)
 #ifndef NO_ECOFF_DEBUGGING
                   || (sym->ecoff_extern_size != 0
                       && sym->ecoff_extern_size <= g_switch_value)
+#endif
                   /* We must defer this decision until after the whole
                      file has been read, since there might be a .extern
                      after the first use of this symbol.  */
-                  || (sym->ecoff_extern_size == 0 && before_relaxing)
+                  || (before_relaxing
+#ifndef NO_ECOFF_DEBUGGING
+                      && sym->ecoff_extern_size == 0
 #endif
+                      && S_GET_VALUE (sym) == 0)
                   || (S_GET_VALUE (sym) != 0
                       && S_GET_VALUE (sym) <= g_switch_value)))
        change = 0;