]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
alpha.c (some_operand): Accept HIGH.
authorRichard Henderson <rth@redhat.com>
Fri, 4 Jan 2002 08:15:22 +0000 (00:15 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 4 Jan 2002 08:15:22 +0000 (00:15 -0800)
* config/alpha/alpha.c (some_operand): Accept HIGH.
(input_operand): Likewise; accept simple references to globals.
(alpha_const_ok_for_letter_p): New, outlined from alpha.h.
(alpha_const_double_ok_for_letter_p): Likewise.
(alpha_extra_constraint): Likewise.
(alpha_preferred_reload_class): Likewise.  Do not force
symbolic constants to memory.
(alpha_legitimate_address_p): Accept simple references
to small_symbolic_operand.
(alpha_legitimize_address): New arg scratch.  Be prepared to be
called when no_new_pseudos.  Emit simple symbolic references.
Split integers into low, high, and rest.
(alpha_expand_mov): Use alpha_legitimize_address.
(some_small_symbolic_mem_operand): New.
(split_small_symbolic_mem_operand): New.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line.
(CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
(EXTRA_CONSTRAINT): Likewise.
(PREFERRED_RELOAD_CLASS): Likewise.
(LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change.
(PREDICATE_CODES): Update.
* config/alpha/alpha.md: New post-reload splitters to convert
simplfied symbolic operands to the form that references $29.
(divide expanders): Use emit_move_insn, not gen_movdi_er_high_g.
(movdi_er_nofix, movdi_er_fix): Accept any symbolic operand.

From-SVN: r48531

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md

index 0c58a03cf68a5a0e07b25b64752d7a5436b1936e..044dce3043b91cc487c7c5a1bee32f7d3e40cf06 100644 (file)
@@ -1,3 +1,32 @@
+2002-01-04  Richard Henderson  <rth@redhat.com>
+
+       * config/alpha/alpha.c (some_operand): Accept HIGH.
+       (input_operand): Likewise; accept simple references to globals.
+       (alpha_const_ok_for_letter_p): New, outlined from alpha.h.
+       (alpha_const_double_ok_for_letter_p): Likewise.
+       (alpha_extra_constraint): Likewise.
+       (alpha_preferred_reload_class): Likewise.  Do not force
+       symbolic constants to memory.
+       (alpha_legitimate_address_p): Accept simple references
+       to small_symbolic_operand.
+       (alpha_legitimize_address): New arg scratch.  Be prepared to be
+       called when no_new_pseudos.  Emit simple symbolic references.
+       Split integers into low, high, and rest.
+       (alpha_expand_mov): Use alpha_legitimize_address.
+       (some_small_symbolic_mem_operand): New.
+       (split_small_symbolic_mem_operand): New.
+       * config/alpha/alpha-protos.h: Update.
+       * config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line.
+       (CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
+       (EXTRA_CONSTRAINT): Likewise.
+       (PREFERRED_RELOAD_CLASS): Likewise.
+       (LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change.
+       (PREDICATE_CODES): Update.
+       * config/alpha/alpha.md: New post-reload splitters to convert
+       simplfied symbolic operands to the form that references $29.
+       (divide expanders): Use emit_move_insn, not gen_movdi_er_high_g.
+       (movdi_er_nofix, movdi_er_fix): Accept any symbolic operand.
+
 2002-01-03  Richard Henderson  <rth@redhat.com>
 
        * local-alloc.c (function_invariant_p): Update commentary.
index e7da7d2e9805aba1818689da7c507a3346359d0b..2ff035092f2829d5f77f81349ff2e18ea728780c 100644 (file)
@@ -59,6 +59,7 @@ extern int current_file_function_operand PARAMS ((rtx, enum machine_mode));
 extern int direct_call_operand PARAMS ((rtx, enum machine_mode));
 extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int some_small_symbolic_mem_operand PARAMS ((rtx, enum machine_mode));
 extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int call_operand PARAMS ((rtx, enum machine_mode));
 extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
@@ -77,6 +78,10 @@ extern int normal_memory_operand PARAMS ((rtx, enum machine_mode));
 extern int reg_no_subreg_operand PARAMS ((rtx, enum machine_mode));
 extern int addition_operation PARAMS ((rtx, enum machine_mode));
 
+extern bool alpha_const_ok_for_letter_p PARAMS ((HOST_WIDE_INT, int));
+extern bool alpha_const_double_ok_for_letter_p PARAMS ((rtx, int));
+extern bool alpha_extra_constraint PARAMS ((rtx, int));
+
 extern rtx alpha_tablejump_addr_vec PARAMS ((rtx));
 extern rtx alpha_tablejump_best_label PARAMS ((rtx));
 
@@ -85,11 +90,16 @@ extern rtx alpha_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
 extern rtx alpha_legitimize_reload_address PARAMS ((rtx, enum machine_mode,
                                                    int, int, int));
 
+extern rtx split_small_symbolic_mem_operand PARAMS ((rtx));
+
 extern void get_aligned_mem PARAMS ((rtx, rtx *, rtx *));
 extern rtx get_unaligned_address PARAMS ((rtx, int));
+extern enum reg_class alpha_preferred_reload_class PARAMS ((rtx, 
+                                                           enum reg_class));
 extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
                                                     enum machine_mode, 
                                                     rtx, int));
+
 extern void alpha_set_memflags PARAMS ((rtx, rtx));
 extern rtx alpha_emit_set_const PARAMS ((rtx, enum machine_mode,
                                        HOST_WIDE_INT, int));
index dee844bb6d841983a6db4f9e628bf5267ad89b4a..b928609030c92ecda4e3b22ad41e2387676baaf7 100644 (file)
@@ -768,7 +768,7 @@ some_operand (op, mode)
   switch (GET_CODE (op))
     {
     case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
-    case SYMBOL_REF:  case CONST:
+    case SYMBOL_REF:  case CONST:  case HIGH:
       return 1;
 
     case SUBREG:
@@ -816,11 +816,22 @@ input_operand (op, mode)
     case SYMBOL_REF:
     case CONST:
       if (TARGET_EXPLICIT_RELOCS)
-       return 0;
+       {
+         /* We don't split symbolic operands into something unintelligable
+            until after reload, but we do not wish non-small, non-global
+            symbolic operands to be reconstructed from their high/lo_sum
+            form.  */
+         return (small_symbolic_operand (op, mode)
+                 || global_symbolic_operand (op, mode));
+       }
 
       /* This handles both the Windows/NT and OSF cases.  */
       return mode == ptr_mode || mode == DImode;
 
+    case HIGH:
+      return (TARGET_EXPLICIT_RELOCS
+             && local_symbolic_operand (XEXP (op, 0), mode));
+
     case REG:
     case ADDRESSOF:
       return 1;
@@ -1354,6 +1365,100 @@ addition_operation (op, mode)
   return 0;
 }
 
+/* Implements CONST_OK_FOR_LETTER_P.  Return true if the value matches
+   the range defined for C in [I-P].  */
+
+bool
+alpha_const_ok_for_letter_p (value, c)
+     HOST_WIDE_INT value;
+     int c;
+{
+  switch (c)
+    {
+    case 'I':
+      /* An unsigned 8 bit constant.  */
+      return (unsigned HOST_WIDE_INT) value < 0x100;
+    case 'J':
+      /* The constant zero.  */
+      return value == 0;
+    case 'K':
+      /* A signed 16 bit constant.  */
+      return (unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000;
+    case 'L':
+      /* A shifted signed 16 bit constant appropriate for LDAH.  */
+      return ((value & 0xffff) == 0
+              && ((value) >> 31 == -1 || value >> 31 == 0));
+    case 'M':
+      /* A constant that can be AND'ed with using a ZAP insn.  */
+      return zap_mask (value);
+    case 'N':
+      /* A complemented unsigned 8 bit constant.  */
+      return (unsigned HOST_WIDE_INT) (~ value) < 0x100;
+    case 'O':
+      /* A negated unsigned 8 bit constant.  */
+      return (unsigned HOST_WIDE_INT) (- value) < 0x100;
+    case 'P':
+      /* The constant 1, 2 or 3.  */
+      return value == 1 || value == 2 || value == 3;
+
+    default:
+      return false;
+    }
+}
+
+/* Implements CONST_DOUBLE_OK_FOR_LETTER_P.  Return true if VALUE
+   matches for C in [GH].  */
+
+bool
+alpha_const_double_ok_for_letter_p (value, c)
+     rtx value;
+     int c;
+{
+  switch (c)
+    {
+    case 'G':
+      /* The floating point zero constant.  */
+      return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
+             && value == CONST0_RTX (GET_MODE (value)));
+
+    case 'H':
+      /* A valid operand of a ZAP insn.  */
+      return (GET_MODE (value) == VOIDmode
+             && zap_mask (CONST_DOUBLE_LOW (value))
+             && zap_mask (CONST_DOUBLE_HIGH (value)));
+
+    default:
+      return false;
+    }
+}
+
+/* Implements CONST_DOUBLE_OK_FOR_LETTER_P.  Return true if VALUE
+   matches for C.  */
+
+bool
+alpha_extra_constraint (value, c)
+     rtx value;
+     int c;
+{
+  switch (c)
+    {
+    case 'Q':
+      return normal_memory_operand (value, VOIDmode);
+    case 'R':
+      return direct_call_operand (value, Pmode);
+    case 'S':
+      return (GET_CODE (value) == CONST_INT
+             && (unsigned HOST_WIDE_INT) INTVAL (value) < 64);
+    case 'T':
+      return GET_CODE (value) == HIGH;
+    case 'U':
+      return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
+
+    default:
+      return false;
+    }
+}
+
 /* Return 1 if this function can directly return via $26.  */
 
 int
@@ -1628,28 +1733,35 @@ alpha_legitimate_address_p (mode, x, strict)
        return true;
     }
 
-  /* If we're managing explicit relocations, LO_SUM is valid.  */
-  else if (TARGET_EXPLICIT_RELOCS && GET_CODE (x) == LO_SUM)
+  /* If we're managing explicit relocations, LO_SUM is valid, as
+     are small data symbols.  */
+  else if (TARGET_EXPLICIT_RELOCS)
     {
-      rtx ofs = XEXP (x, 1);
-      x = XEXP (x, 0);
-
-      /* Discard non-paradoxical subregs.  */
-      if (GET_CODE (x) == SUBREG
-          && (GET_MODE_SIZE (GET_MODE (x))
-             < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
-       x = SUBREG_REG (x);
-
-      /* Must have a valid base register.  */
-      if (! (REG_P (x)
-            && (strict
-                ? STRICT_REG_OK_FOR_BASE_P (x)
-                : NONSTRICT_REG_OK_FOR_BASE_P (x))))
-       return false;
-
-      /* The symbol must be local.  */
-      if (local_symbolic_operand (ofs, Pmode))
+      if (small_symbolic_operand (x, Pmode))
        return true;
+
+      if (GET_CODE (x) == LO_SUM)
+       {
+         rtx ofs = XEXP (x, 1);
+         x = XEXP (x, 0);
+
+         /* Discard non-paradoxical subregs.  */
+         if (GET_CODE (x) == SUBREG
+             && (GET_MODE_SIZE (GET_MODE (x))
+                 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
+           x = SUBREG_REG (x);
+
+         /* Must have a valid base register.  */
+         if (! (REG_P (x)
+                && (strict
+                    ? STRICT_REG_OK_FOR_BASE_P (x)
+                    : NONSTRICT_REG_OK_FOR_BASE_P (x))))
+           return false;
+
+         /* The symbol must be local.  */
+         if (local_symbolic_operand (ofs, Pmode))
+           return true;
+       }
     }
 
   return false;
@@ -1659,9 +1771,9 @@ alpha_legitimate_address_p (mode, x, strict)
    to be legitimate.  If we find one, return the new, valid address.  */
 
 rtx
-alpha_legitimize_address (x, oldx, mode)
+alpha_legitimize_address (x, scratch, mode)
      rtx x;
-     rtx oldx ATTRIBUTE_UNUSED;
+     rtx scratch;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
   HOST_WIDE_INT addend;
@@ -1683,7 +1795,8 @@ alpha_legitimize_address (x, oldx, mode)
      part of the CONST_INT.  Then load FOO plus any high-order part of the
      CONST_INT into a register.  Our address is (plus reg low-part-const).
      This is done to reduce the number of GOT entries.  */
-  if (GET_CODE (x) == CONST
+  if (!no_new_pseudos
+      && GET_CODE (x) == CONST
       && GET_CODE (XEXP (x, 0)) == PLUS
       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
     {
@@ -1695,7 +1808,8 @@ alpha_legitimize_address (x, oldx, mode)
   /* If we have a (plus reg const), emit the load as in (2), then add
      the two registers, and finally generate (plus reg low-part-const) as
      our address.  */
-  if (GET_CODE (x) == PLUS
+  if (!no_new_pseudos
+      && GET_CODE (x) == PLUS
       && GET_CODE (XEXP (x, 0)) == REG
       && GET_CODE (XEXP (x, 1)) == CONST
       && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
@@ -1711,33 +1825,18 @@ alpha_legitimize_address (x, oldx, mode)
   /* If this is a local symbol, split the address into HIGH/LO_SUM parts.  */
   if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
     {
-      rtx scratch;
       if (local_symbolic_operand (x, Pmode))
        {
          if (small_symbolic_operand (x, Pmode))
-           scratch = pic_offset_table_rtx;
+           return x;
          else
            {
-             rtx insn, tmp;
-
-             scratch = gen_reg_rtx (Pmode);
-
-             tmp = gen_rtx_HIGH (Pmode, x);
-             tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
-              insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
-             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
-                                                   REG_NOTES (insn));
+             if (!no_new_pseudos)
+               scratch = gen_reg_rtx (Pmode);
+             emit_insn (gen_rtx_SET (VOIDmode, scratch,
+                                     gen_rtx_HIGH (Pmode, x)));
+             return gen_rtx_LO_SUM (Pmode, scratch, x);
            }
-
-         return gen_rtx_LO_SUM (Pmode, scratch, x);
-       }
-      else
-       {
-         scratch = gen_reg_rtx (Pmode);
-         emit_insn (gen_movdi_er_high_g (scratch, pic_offset_table_rtx,
-                                         x, const0_rtx));
-         /* ??? FIXME: Tag the use of scratch with a lituse.  */
-         return scratch;
        }
     }
 
@@ -1745,14 +1844,65 @@ alpha_legitimize_address (x, oldx, mode)
 
  split_addend:
   {
-    HOST_WIDE_INT lowpart = (addend & 0xffff) - 2 * (addend & 0x8000);
-    HOST_WIDE_INT highpart = addend - lowpart;
-    x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (highpart),
-                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
-    return plus_constant (x, lowpart);
+    HOST_WIDE_INT low, high;
+
+    low = ((addend & 0xffff) ^ 0x8000) - 0x8000;
+    addend -= low;
+    high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000;
+    addend -= high;
+
+    if (addend)
+      x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),
+                              (no_new_pseudos ? scratch : NULL_RTX),
+                              1, OPTAB_LIB_WIDEN);
+    if (high)
+      x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),
+                              (no_new_pseudos ? scratch : NULL_RTX),
+                              1, OPTAB_LIB_WIDEN);
+
+    return plus_constant (x, low);
   }
 }
 
+/* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a
+   small symbolic operand until after reload.  At which point we need
+   to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref))
+   so that sched2 has the proper dependency information.  */
+
+int
+some_small_symbolic_mem_operand (x, mode)
+     rtx x;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  /* Get rid of SIGN_EXTEND, etc.  */
+  while (GET_RTX_CLASS (GET_CODE (x)) == '1')
+    x = XEXP (x, 0);
+
+  return (GET_CODE (x) == MEM
+         && small_symbolic_operand (XEXP (x, 0), Pmode));
+}
+
+rtx
+split_small_symbolic_mem_operand (x)
+     rtx x;
+{
+  rtx *p;
+
+  if (GET_CODE (x) == MEM)
+    {
+      rtx tmp = gen_rtx_LO_SUM (DImode, pic_offset_table_rtx, XEXP (x, 0));
+      return replace_equiv_address (x, tmp);
+    }
+
+  x = copy_rtx (x);
+  p = &x;
+  while (GET_RTX_CLASS (GET_CODE (*p)) == '1')
+    p = &XEXP (*p, 0);
+
+  *p = split_small_symbolic_mem_operand (*p);
+  return x;
+}
+
 /* Try a machine-dependent way of reloading an illegitimate address
    operand.  If we find one, push the reload and return the new rtx.  */
    
@@ -1886,6 +2036,39 @@ get_unaligned_address (ref, extra_offset)
   return plus_constant (base, offset + extra_offset);
 }
 
+/* On the Alpha, all (non-symbolic) constants except zero go into
+   a floating-point register via memory.  Note that we cannot 
+   return anything that is not a subset of CLASS, and that some
+   symbolic constants cannot be dropped to memory.  */
+
+enum reg_class
+alpha_preferred_reload_class(x, class)
+     rtx x;
+     enum reg_class class;
+{
+  /* Zero is present in any register class.  */
+  if (x == CONST0_RTX (GET_MODE (x)))
+    return class;
+
+  /* These sorts of constants we can easily drop to memory.  */
+  if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
+    {
+      if (class == FLOAT_REGS)
+       return NO_REGS;
+      if (class == ALL_REGS)
+       return GENERAL_REGS;
+      return class;
+    }
+
+  /* All other kinds of constants should not (and in the case of HIGH
+     cannot) be dropped to memory -- instead we use a GENERAL_REGS
+     secondary reload.  */
+  if (CONSTANT_P (x))
+    return (class == ALL_REGS ? GENERAL_REGS : class);
+
+  return class;
+}
+
 /* Loading and storing HImode or QImode values to and from memory
    usually requires a scratch register.  The exceptions are loading
    QImode and HImode from an aligned address to a general register
@@ -2294,36 +2477,15 @@ alpha_expand_mov (mode, operands)
       && ! reg_or_0_operand (operands[1], mode))
     operands[1] = force_reg (mode, operands[1]);
 
-  if (TARGET_EXPLICIT_RELOCS && symbolic_operand (operands[1], mode))
+  /* Allow legitimize_address to perform some simplifications.  */
+  if (symbolic_operand (operands[1], mode))
     {
-      if (local_symbolic_operand (operands[1], mode))
+      rtx tmp = alpha_legitimize_address (operands[1], operands[0], mode);
+      if (tmp)
        {
-         rtx scratch;
-
-         if (small_symbolic_operand (operands[1], Pmode))
-           scratch = pic_offset_table_rtx;
-         else
-           {
-             rtx insn, tmp;
-
-             scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
-
-             tmp = gen_rtx_HIGH (Pmode, operands[1]);
-             tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
-              insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
-             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
-                                                   REG_NOTES (insn));
-           }
-
-          operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]);
+         operands[1] = tmp;
          return false;
        }
-      else
-       {
-         emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx,
-                                         operands[1], const0_rtx));
-         return true;
-       }
     }
 
   /* Early out for non-constants and valid constants.  */
index de2428ffb6fdc5098bc28576928d5218f09a4970..e2d8b3820d146acf53e8f56d553c8d7eb7e9115a 100644 (file)
@@ -812,17 +812,7 @@ enum reg_class {
    `O' is used for negated 8-bit constants.
    `P' is used for the constants 1, 2 and 3.  */
 
-#define CONST_OK_FOR_LETTER_P(VALUE, C)                                \
-  ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VALUE) < 0x100       \
-   : (C) == 'J' ? (VALUE) == 0                                 \
-   : (C) == 'K' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000        \
-   : (C) == 'L' ? (((VALUE) & 0xffff) == 0                     \
-                  && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0)) \
-   : (C) == 'M' ? zap_mask (VALUE)                             \
-   : (C) == 'N' ? (unsigned HOST_WIDE_INT) (~ (VALUE)) < 0x100 \
-   : (C) == 'O' ? (unsigned HOST_WIDE_INT) (- (VALUE)) < 0x100 \
-   : (C) == 'P' ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 3 \
-   : 0)
+#define CONST_OK_FOR_LETTER_P   alpha_const_ok_for_letter_p
 
 /* Similar, but for floating or large integer constants, and defining letters
    G and H.   Here VALUE is the CONST_DOUBLE rtx itself.
@@ -830,13 +820,7 @@ enum reg_class {
    For Alpha, `G' is the floating-point constant zero.  `H' is a CONST_DOUBLE
    that is the operand of a ZAP insn.  */
 
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)                         \
-  ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT       \
-                && (VALUE) == CONST0_RTX (GET_MODE (VALUE)))           \
-   : (C) == 'H' ? (GET_MODE (VALUE) == VOIDmode                                \
-                  && zap_mask (CONST_DOUBLE_LOW (VALUE))               \
-                  && zap_mask (CONST_DOUBLE_HIGH (VALUE)))             \
-   : 0)
+#define CONST_DOUBLE_OK_FOR_LETTER_P  alpha_const_double_ok_for_letter_p
 
 /* Optional extra constraints for this machine.
 
@@ -848,31 +832,18 @@ enum reg_class {
 
    'S' is a 6-bit constant (valid for a shift insn).  
 
+   'T' is a HIGH.
+
    'U' is a symbolic operand.  */
 
-#define EXTRA_CONSTRAINT(OP, C)                                \
-  ((C) == 'Q' ? normal_memory_operand (OP, VOIDmode)                   \
-   : (C) == 'R' ? direct_call_operand (OP, Pmode)              \
-   : (C) == 'S' ? (GET_CODE (OP) == CONST_INT                          \
-                  && (unsigned HOST_WIDE_INT) INTVAL (OP) < 64)        \
-   : (C) == 'T' ? GET_CODE (OP) == HIGH                                        \
-   : (TARGET_ABI_UNICOSMK && (C) == 'U')                               \
-               ? symbolic_operand (OP, VOIDmode)                       \
-   : 0)
+#define EXTRA_CONSTRAINT  alpha_extra_constraint
 
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
    In general this is just CLASS; but on some machines
-   in some cases it is preferable to use a more restrictive class.
-
-   On the Alpha, all constants except zero go into a floating-point
-   register via memory.  */
+   in some cases it is preferable to use a more restrictive class.  */
 
-#define PREFERRED_RELOAD_CLASS(X, CLASS)                               \
-  (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \
-   ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS            \
-      : (CLASS) == ALL_REGS ? GENERAL_REGS : (CLASS))                  \
-   : (CLASS))
+#define PREFERRED_RELOAD_CLASS  alpha_preferred_reload_class
 
 /* Loading and storing HImode or QImode values to and from memory
    usually requires a scratch register.  The exceptions are loading
@@ -1479,14 +1450,14 @@ do {                                            \
    to be legitimate.  If we find one, return the new, valid address.
    This macro is used in only one place: `memory_address' in explow.c.  */
 
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)            \
-do {                                                   \
-  rtx new_x = alpha_legitimize_address (X, OLDX, MODE);        \
-  if (new_x)                                           \
-    {                                                  \
-      X = new_x;                                       \
-      goto WIN;                                                \
-    }                                                  \
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)                    \
+do {                                                           \
+  rtx new_x = alpha_legitimize_address (X, NULL_RTX, MODE);    \
+  if (new_x)                                                   \
+    {                                                          \
+      X = new_x;                                               \
+      goto WIN;                                                        \
+    }                                                          \
 } while (0)
 
 /* Try a machine-dependent way of reloading an illegitimate address
@@ -2117,9 +2088,9 @@ do {                                              \
   {"global_symbolic_operand", {SYMBOL_REF, CONST}},                    \
   {"call_operand", {REG, SYMBOL_REF}},                                 \
   {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,                \
-                    SYMBOL_REF, CONST, LABEL_REF}},                    \
+                    SYMBOL_REF, CONST, LABEL_REF, HIGH}},              \
   {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,         \
-                   SYMBOL_REF, CONST, LABEL_REF}},                     \
+                   SYMBOL_REF, CONST, LABEL_REF, HIGH}},               \
   {"some_ni_operand", {SUBREG, REG, MEM}},                             \
   {"aligned_memory_operand", {MEM}},                                   \
   {"unaligned_memory_operand", {MEM}},                                 \
@@ -2130,7 +2101,9 @@ do {                                              \
   {"reg_not_elim_operand", {SUBREG, REG}},                             \
   {"reg_no_subreg_operand", {REG}},                                    \
   {"addition_operation", {PLUS}},                                      \
-  {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},
+  {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                        \
+  {"some_small_symbolic_mem_operand", {MEM, SIGN_EXTEND, ZERO_EXTEND,  \
+                                     FLOAT_EXTEND}},
 \f
 /* Define the `__builtin_va_list' type for the ABI.  */
 #define BUILD_VA_LIST_TYPE(VALIST) \
index 7ab782a36e7868c343c115ac5640c6b3c9695806..31d03c43ad1647d80b5cae78d4f187af9a77b98f 100644 (file)
@@ -649,6 +649,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   "TARGET_EXPLICIT_RELOCS"
   "ldah %0,%2(%1)\t\t!gprelhigh")
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (high:DI (match_operand:DI 1 "local_symbolic_operand" "")))]
+  "TARGET_EXPLICIT_RELOCS && reload_completed"
+  [(set (match_dup 0)
+       (plus:DI (match_dup 2) (high:DI (match_dup 1))))]
+  "operands[2] = pic_offset_table_rtx;")
+
 ;; We used to expend quite a lot of effort choosing addq/subq/lda.
 ;; With complications like
 ;;
@@ -1225,9 +1233,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
     default:
       abort ();
     }
-  emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx,
-                                 gen_rtx_SYMBOL_REF (DImode, str),
-                                 const0_rtx));
+  emit_move_insn (operands[0], gen_rtx_SYMBOL_REF (DImode, str));
 }
   [(set_attr "type" "jsr")
    (set_attr "length" "8")])
@@ -1290,9 +1296,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
     default:
       abort ();
     }
-  emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx,
-                                 gen_rtx_SYMBOL_REF (DImode, str),
-                                 const0_rtx));
+  emit_move_insn (operands[0], gen_rtx_SYMBOL_REF (DImode, str));
 }
   [(set_attr "type" "jsr")
    (set_attr "length" "8")])
@@ -5459,7 +5463,39 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
     return "lda %0,%2(%1)\t\t!gprellow";
 })
 
-(define_insn "movdi_er_high_g"
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (match_operand:DI 1 "small_symbolic_operand" ""))]
+  "TARGET_EXPLICIT_RELOCS && reload_completed"
+  [(set (match_dup 0)
+       (lo_sum:DI (match_dup 2) (match_dup 1)))]
+  "operands[2] = pic_offset_table_rtx;")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (match_operand:DI 1 "local_symbolic_operand" ""))]
+  "TARGET_EXPLICIT_RELOCS && reload_completed"
+  [(set (match_dup 0)
+       (plus:DI (match_dup 2) (high:DI (match_dup 1))))
+   (set (match_dup 0)
+       (lo_sum:DI (match_dup 0) (match_dup 1)))]
+  "operands[2] = pic_offset_table_rtx;")
+
+(define_split
+  [(set (match_operand 0 "some_small_symbolic_mem_operand" "")
+       (match_operand 1 "" ""))]
+  "TARGET_EXPLICIT_RELOCS && reload_completed"
+  [(set (match_dup 0) (match_dup 1))]
+  "operands[0] = split_small_symbolic_mem_operand (operands[0]);")
+
+(define_split
+  [(set (match_operand 0 "" "")
+       (match_operand 1 "some_small_symbolic_mem_operand" ""))]
+  "TARGET_EXPLICIT_RELOCS && reload_completed"
+  [(set (match_dup 0) (match_dup 1))]
+  "operands[1] = split_small_symbolic_mem_operand (operands[1]);")
+
+(define_insn "*movdi_er_high_g"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unspec:DI [(match_operand:DI 1 "register_operand" "r")
                    (match_operand:DI 2 "global_symbolic_operand" "")
@@ -5469,9 +5505,19 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   "ldq %0,%2(%1)\t\t!literal"
   [(set_attr "type" "ldsym")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (match_operand:DI 1 "global_symbolic_operand" ""))]
+  "TARGET_EXPLICIT_RELOCS && reload_completed"
+  [(set (match_dup 0)
+       (unspec:DI [(match_dup 2)
+                   (match_dup 1)
+                   (const_int 0)] UNSPEC_LITERAL))]
+  "operands[2] = pic_offset_table_rtx;")
+
 (define_insn "*movdi_er_nofix"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q")
-       (match_operand:DI 1 "input_operand" "rJ,K,L,T,m,rJ,*fJ,Q,*f"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
+       (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))]
   "TARGET_EXPLICIT_RELOCS && ! TARGET_FIX
    && (register_operand (operands[0], DImode)
        || reg_or_0_operand (operands[1], DImode))"
@@ -5479,13 +5525,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    mov %r1,%0
    lda %0,%1($31)
    ldah %0,%h1($31)
-   ldah %0,%H1
+   #
+   #
    ldq%A1 %0,%1
    stq%A0 %r1,%0
    fmov %R1,%0
    ldt %0,%1
    stt %R1,%0"
-  [(set_attr "type" "ilog,iadd,iadd,iadd,ild,ist,fcpys,fld,fst")])
+  [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
 
 ;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should
 ;; have been split up by the rules above but we shouldn't reject the
@@ -5512,8 +5559,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    (set_attr "length" "*,*,*,16,*,*,*,*,*,*")])
 
 (define_insn "*movdi_er_fix"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f")
-       (match_operand:DI 1 "input_operand" "rJ,K,L,T,m,rJ,*fJ,Q,*f,*f,r"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand"
+                               "=r,r,r,r,r,r, m, *f,*f, Q, r,*f")
+       (match_operand:DI 1 "input_operand"
+                               "rJ,K,L,T,s,m,rJ,*fJ, Q,*f,*f, r"))]
   "TARGET_EXPLICIT_RELOCS && TARGET_FIX
    && (register_operand (operands[0], DImode)
        || reg_or_0_operand (operands[1], DImode))"
@@ -5521,7 +5570,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    mov %r1,%0
    lda %0,%1($31)
    ldah %0,%h1($31)
-   ldah %0,%H1
+   #
+   #
    ldq%A1 %0,%1
    stq%A0 %r1,%0
    fmov %R1,%0
@@ -5529,7 +5579,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    stt %R1,%0
    ftoit %1,%0
    itoft %1,%0"
-  [(set_attr "type" "ilog,iadd,iadd,iadd,ild,ist,fcpys,fld,fst,ftoi,itof")])
+  [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")])
 
 (define_insn "*movdi_fix"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f")