* config/tc-mips.c (HAVE_64BIT_ADDRESS_CONSTANTS): Remove.
authorThiemo Seufer <ths@networkno.de>
Sun, 14 Sep 2003 15:24:49 +0000 (15:24 +0000)
committerThiemo Seufer <ths@networkno.de>
Sun, 14 Sep 2003 15:24:49 +0000 (15:24 +0000)
(macro_build_ldst_constoffset): Sign-extend 32-bit constants. Change
the function prototype.
(load_register): Likewise. Simplify the checks for sign-extended
constants.
(macro): Likewise. Fix code generation for 64-bit address constants
outside the 32-bit compatibility space. Adjust
macro_build_ldst_constoffset calls.
(s_cprestore): Adjust macro_build_ldst_constoffset call.

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

index e4183dd0e9971b2205e4d0881ba7fb47ebaa4e19..328f139b28ffb684366f1c47d1c174697c017658 100644 (file)
@@ -1,3 +1,15 @@
+2003-09-14  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
+
+       * config/tc-mips.c (HAVE_64BIT_ADDRESS_CONSTANTS): Remove.
+       (macro_build_ldst_constoffset): Sign-extend 32-bit constants. Change
+       the function prototype.
+       (load_register): Likewise. Simplify the checks for sign-extended
+       constants.
+       (macro): Likewise. Fix code generation for 64-bit address constants
+       outside the 32-bit compatibility space. Adjust
+       macro_build_ldst_constoffset calls.
+       (s_cprestore): Adjust macro_build_ldst_constoffset call.
+
 2003-09-11  Bob Wilson  <bob.wilson@acm.org>
 
        * config/tc-xtensa.c (insn_labels, free_insn_labels, saved_insn_labels,
index e2e3f4a3294ecfedfd3e214047fd949ef7780977..8c7c69e7c382c866a5288231883e469c0ac4fb62 100644 (file)
@@ -302,8 +302,6 @@ static int mips_32bitmode = 0;
         && mips_pic != EMBEDDED_PIC))
 
 #define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES)
-#define HAVE_64BIT_ADDRESS_CONSTANTS (HAVE_64BIT_ADDRESSES \
-                                     || HAVE_64BIT_GPRS)
 
 /* Addresses are loaded in different ways, depending on the address size
    in use.  The n32 ABI Documentation also mandates the use of additions
@@ -3225,10 +3223,15 @@ macro_build_lui (char *place, int *counter, expressionS *ep, int regnum)
    using AT if necessary.  */
 static void
 macro_build_ldst_constoffset (char *place, int *counter, expressionS *ep,
-                             const char *op, int treg, int breg)
+                             const char *op, int treg, int breg, int dbl)
 {
   assert (ep->X_op == O_constant);
 
+  /* Sign-extending 32-bit constants makes their handling easier.  */
+  if (! dbl)
+    ep->X_add_number = (((ep->X_add_number & 0xffffffff) ^ 0x80000000)
+                       - 0x80000000);
+
   /* Right now, this routine can only handle signed 32-bit contants.  */
   if (! IS_SEXT_32BIT_NUM(ep->X_add_number))
     as_warn (_("operand overflow"));
@@ -3381,12 +3384,13 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
   if (ep->X_op != O_big)
     {
       assert (ep->X_op == O_constant);
-      if (ep->X_add_number < 0x8000
-         && (ep->X_add_number >= 0
-             || (ep->X_add_number >= -0x8000
-                 && (! dbl
-                     || ! ep->X_unsigned
-                     || sizeof (ep->X_add_number) > 4))))
+
+      /* Sign-extending 32-bit constants makes their handling easier.  */
+      if (! dbl)
+       ep->X_add_number = (((ep->X_add_number & 0xffffffff) ^ 0x80000000)
+                           - 0x80000000);
+
+      if (IS_SEXT_16BIT_NUM (ep->X_add_number))
        {
          /* We can handle 16 bit signed values with an addiu to
             $zero.  No need to ever use daddiu here, since $zero and
@@ -3403,17 +3407,7 @@ load_register (int *counter, int reg, expressionS *ep, int dbl)
                       BFD_RELOC_LO16);
          return;
        }
-      else if ((IS_SEXT_32BIT_NUM (ep->X_add_number)
-               && (! dbl
-                   || ! ep->X_unsigned
-                   || sizeof (ep->X_add_number) > 4
-                   || (ep->X_add_number & 0x80000000) == 0))
-              || ((HAVE_32BIT_GPRS || ! dbl)
-                  && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0)
-              || (HAVE_32BIT_GPRS
-                  && ! dbl
-                  && ((ep->X_add_number &~ (offsetT) 0xffffffff)
-                      == ~ (offsetT) 0xffffffff)))
+      else if ((IS_SEXT_32BIT_NUM (ep->X_add_number)))
        {
          /* 32 bit values require an lui.  */
          macro_build (NULL, counter, ep, "lui", "t,u", reg, BFD_RELOC_HI16);
@@ -5450,7 +5444,8 @@ macro (struct mips_cl_insn *ip)
                  macro_build_ldst_constoffset (NULL, &icnt, &expr1,
                                                ADDRESS_LOAD_INSN,
                                                mips_gp_register,
-                                               mips_frame_reg);
+                                               mips_frame_reg,
+                                               HAVE_64BIT_ADDRESSES);
                }
            }
        }
@@ -5601,7 +5596,8 @@ macro (struct mips_cl_insn *ip)
                  macro_build_ldst_constoffset (NULL, &icnt, &expr1,
                                                ADDRESS_LOAD_INSN,
                                                mips_gp_register,
-                                               mips_frame_reg);
+                                               mips_frame_reg,
+                                               HAVE_64BIT_ADDRESSES);
                }
            }
        }
@@ -5791,6 +5787,15 @@ macro (struct mips_cl_insn *ip)
       else
        fmt = "t,o(b)";
 
+      /* Sign-extending 32-bit constants makes their handling easier.
+         The HAVE_64BIT_GPRS... part is due to the linux kernel hack
+         described below.  */
+      if ((! HAVE_64BIT_ADDRESSES
+          && (! HAVE_64BIT_GPRS && offset_expr.X_op == O_constant))
+          && (offset_expr.X_op == O_constant))
+       offset_expr.X_add_number = (((offset_expr.X_add_number & 0xffffffff)
+                                    ^ 0x80000000) - 0x80000000);
+
       /* For embedded PIC, we allow loads where the offset is calculated
          by subtracting a symbol in the current segment from an unknown
          symbol, relative to a base register, e.g.:
@@ -5923,10 +5928,12 @@ macro (struct mips_cl_insn *ip)
             end up converting the binary to ELF32 for a number of
             platforms whose boot loaders don't support ELF64
             binaries.  */
-         if ((offset_expr.X_op != O_constant && HAVE_64BIT_ADDRESSES)
-             || (offset_expr.X_op == O_constant
-                 && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)
-                 && HAVE_64BIT_ADDRESS_CONSTANTS))
+         if ((HAVE_64BIT_ADDRESSES
+              && ! (offset_expr.X_op == O_constant
+                    && IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)))
+             || (HAVE_64BIT_GPRS
+                 && offset_expr.X_op == O_constant
+                 && ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)))
            {
              p = NULL;
 
@@ -5973,9 +5980,9 @@ macro (struct mips_cl_insn *ip)
 
              return;
            }
-         else if (offset_expr.X_op == O_constant
-                  && !HAVE_64BIT_ADDRESS_CONSTANTS
-                  && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number))
+
+         if (offset_expr.X_op == O_constant
+             && ! IS_SEXT_32BIT_NUM (offset_expr.X_add_number))
            as_bad (_("load/store address overflow (max 32 bits)"));
 
          if (breg == 0)
@@ -12302,7 +12309,7 @@ s_cprestore (int ignore ATTRIBUTE_UNUSED)
   ex.X_add_number = mips_cprestore_offset;
 
   macro_build_ldst_constoffset (NULL, &icnt, &ex, ADDRESS_STORE_INSN,
-                               mips_gp_register, SP);
+                               mips_gp_register, SP, HAVE_64BIT_ADDRESSES);
 
   demand_empty_rest_of_line ();
 }