Now includes reload.h.
authorRichard Kenner <kenner@gcc.gnu.org>
Tue, 13 Oct 1992 23:07:05 +0000 (19:07 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Tue, 13 Oct 1992 23:07:05 +0000 (19:07 -0400)
(spec_reg_operand): Validate mode and know that some regs support
MODE_PARTIAL_INT and some MODE_INT.
(call_operand, reload_memory_operand, a29k_get_reloaded_address)
 New functions.
(in_operand): Allow constants with MODE_PARTIAL_INT.
(out_operand): Allow special registers with any mode.
Any MEM a word or wider is valid.
(extend_operator): Deleted.
(secondary_reload_class): A pseudo is the same as memory; we need
BP_REGS for multi-word memory or for bytes and halfword if -mndw.
(print_operand): Delete %X; add %m.
(print_operand, case 'F'): Check for SYMBOL_REF.

From-SVN: r2443

gcc/config/a29k/a29k.c

index 8f73f4f95299fe32e77c5223544f68a568442d1b..ad1a62035ecf5dedf89fb23333bd4f29c239efa8 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines used for code generation on AMD Am29000.
-   Copyright (C) 1987, 1988, 1990, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1990, 1991, 1992 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@nyu.edu)
 
 This file is part of GNU CC.
@@ -34,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "expr.h"
 #include "obstack.h"
 #include "tree.h"
+#include "reload.h"
 
 #define min(A,B)       ((A) < (B) ? (A) : (B))
 
@@ -99,7 +100,7 @@ cint_16_operand (op, mode)
   return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0;
 }
 
-/* Returns 1 if OP cannot be moved in a single insn.  */
+/* Returns 1 if OP is a constant that cannot be moved in a single insn.  */
 
 int
 long_const_operand (op, mode)
@@ -210,8 +211,18 @@ spec_reg_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  return GET_MODE (op) == SImode && GET_CODE (op) == REG
-        && REGNO (op) >= R_BP && REGNO (op) <= R_EXO;
+  if (GET_CODE (op) != REG || GET_MODE (op) != mode)
+    return 0;
+
+  switch (GET_MODE_CLASS (mode))
+    {
+    case MODE_PARTIAL_INT:
+      return REGNO (op) >= R_BP && REGNO (op) <= R_CR;
+    case MODE_INT:
+      return REGNO (op) >= R_Q && REGNO (op) <= R_EXO;
+    detault:
+      return 0;
+    }
 }
 
 /* Returns 1 if OP is an accumulator register.  */
@@ -307,6 +318,29 @@ add_operand (op, mode)
          || (GET_CODE (op) == CONST_INT
              && ((unsigned) ((- INTVAL (op)) & GET_MODE_MASK (mode)) < 256)));
 }
+
+/* Return 1 if OP is a valid address in a CALL_INSN.  These are a SYMBOL_REF
+   to the current function, all SYMBOL_REFs if TARGET_SMALL_MEMORY, or
+   a sufficiently-small constant.  */
+
+int
+call_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  switch (GET_CODE (op))
+    {
+    case SYMBOL_REF:
+      return (TARGET_SMALL_MEMORY
+             || ! strcmp (XSTR (op, 0), current_function_name));
+
+    case CONST_INT:
+      return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000;
+
+    default:
+      return 0;
+    }
+}
 \f
 /* Return 1 if OP can be used as the input operand for a move insn.  */
 
@@ -332,7 +366,8 @@ in_operand (op, mode)
       return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE);
 
     case CONST_INT:
-      if (GET_MODE_CLASS (mode) != MODE_INT)
+      if (GET_MODE_CLASS (mode) != MODE_INT
+         && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
        return 0;
 
       return 1;
@@ -370,26 +405,51 @@ out_operand (op, mode)
     op = SUBREG_REG (op);
 
   if (GET_CODE (op) == REG)
-    return (mode == SImode || gpc_reg_operand (orig_op, mode)
+    return (gpc_reg_operand (orig_op, mode)
+           || spec_reg_operand (orig_op, mode)
            || (GET_MODE_CLASS (mode) == MODE_FLOAT
                && accum_reg_operand (orig_op, mode)));
 
   else if (GET_CODE (op) == MEM)
-    return mode == SImode || mode == SFmode || TARGET_DW_ENABLE;
-
+    return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE);
   else
     return 0;
 }
 
-/* Return 1 if OP is some extension operator.  */
+/* Return 1 if OP is an item in memory, given that we are in reload.  */
 
 int
-extend_operator (op, mode)
+reload_memory_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  return ((mode == VOIDmode || GET_MODE (op) == mode)
-         && (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND));
+  int regno = true_regnum (op);
+
+  return (! CONSTANT_P (op)
+         && (regno == -1
+             || (GET_CODE (op) == REG
+                 && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
+}
+
+/* Given an object for which reload_memory_operand is true, return the address
+   of the operand, taking into account anything that reload may do.  */
+
+rtx
+a29k_get_reloaded_address (op)
+     rtx op;
+{
+  if (GET_CODE (op) == SUBREG)
+    {
+      if (SUBREG_WORD (op) != 0)
+       abort ();
+
+      op = SUBREG_REG (op);
+    }
+
+  if (GET_CODE (op) == REG)
+    op = reg_equiv_mem[REGNO (op)];
+
+  return find_replacement (&XEXP (op, 0));
 }
 
 /* Return 1 if OP is a comparison operator that we have in floating-point.  */
@@ -591,19 +651,34 @@ secondary_reload_class (class, mode, in)
      rtx in;
 {
   int regno = -1;
+  enum rtx_code code = GET_CODE (in);
+
+  if (! CONSTANT_P (in))
+    {
+      regno = true_regnum (in);
 
-  if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
-    regno = true_regnum (in);
+      /* A pseudo is the same as memory.  */
+      if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER)
+       code = MEM;
+    }
+
+  /* If we are transferring between memory and a multi-word mode or between
+     memory and a mode smaller than a word without DW being enabled, we need
+     BP.  */
+
+  if (code == MEM
+      && (GET_MODE_SIZE (mode) > UNITS_PER_WORD
+         || (! TARGET_DW_ENABLE && GET_MODE_SIZE (mode) < UNITS_PER_WORD)))
+    return BP_REGS;
 
-  /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
-     into anything.  */
+  /* Otherwise, we can place anything into GENERAL_REGS and can put
+     GENERAL_REGS into anything.  */
   if (class == GENERAL_REGS || (regno != -1 && regno < R_BP))
     return NO_REGS;
 
   /* We can place 16-bit constants into a special register.  */
-  if (GET_CODE (in) == CONST_INT
-      && (GET_MODE_BITSIZE (mode) <= 16
-         || (unsigned) INTVAL (in) <= 65535)
+  if (code == CONST_INT
+      && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535)
       && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS))
     return NO_REGS;
 
@@ -739,8 +814,8 @@ null_epilogue ()
        %N means write the low-order 8 bits of the negative of the constant
        %Q means write a QImode operand (truncate constants to 8 bits)
        %M means write the low-order 16 bits of the constant
+       %m means write the low-order 16 bits shifted left 16 bits
        %C means write the low-order 8 bits of the complement of the constant
-       %X means write the cntl values for LOAD with operand an extension op
        %b means write `f' is this is a reversed condition, `t' otherwise
        %B means write `t' is this is a reversed condition, `f' otherwise
        %J means write the 29k opcode part for a comparison operation
@@ -807,11 +882,12 @@ print_operand (file, x, code)
       fprintf (file, "%d", INT_LOWPART (x) & 0xffff);
       return;
 
-    case 'X':
-      fprintf (file, "%d", ((GET_MODE (XEXP (x, 0)) == QImode ? 1 : 2)
-                           + (GET_CODE (x) == SIGN_EXTEND ? 16 : 0)));
+    case 'm':
+      if (! INT_P (x))
+       output_operand_lossage ("invalid %%m value");
+      fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16);
       return;
-  
+
     case 'b':
       if (GET_CODE (x) == GE)
        fprintf (file, "f");
@@ -878,7 +954,8 @@ print_operand (file, x, code)
       output_addr_const (file, x);
       if (dbr_sequence_length () == 0)
        {
-         if (! strcmp (XSTR (x, 0), current_function_name))
+         if (GET_CODE (x) == SYMBOL_REF
+             && ! strcmp (XSTR (x, 0), current_function_name))
            fprintf (file, "+4\n\t%s,%d",
                     a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1",
                     a29k_regstack_size * 4);