OSDN Git Service

* config/rs6000/rs6000.c (rs6000_override_options): Enable
[pf3gnuchains/gcc-fork.git] / gcc / config / mmix / mmix.c
index 9c7fb62..b57ed7a 100644 (file)
@@ -1,5 +1,6 @@
 /* Definitions of target machine for GNU compiler, for MMIX.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
    Contributed by Hans-Peter Nilsson (hp@bitrange.com)
 
 This file is part of GCC.
@@ -16,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -106,11 +107,6 @@ Boston, MA 02111-1307, USA.  */
 rtx mmix_compare_op0;
 rtx mmix_compare_op1;
 
-/* We ignore some options with arguments.  They are passed to the linker,
-   but also ends up here because they start with "-m".  We tell the driver
-   to store them in a variable we don't inspect.  */
-const char *mmix_cc1_ignored_option;
-
 /* Declarations of locals.  */
 
 /* Intermediate for insn output.  */
@@ -139,8 +135,8 @@ static void mmix_file_start (void);
 static void mmix_file_end (void);
 static bool mmix_rtx_costs (rtx, int, int, int *);
 static rtx mmix_struct_value_rtx (tree, int);
-static tree mmix_gimplify_va_arg_expr (tree, tree, tree *, tree *);
-
+static bool mmix_pass_by_reference (const CUMULATIVE_ARGS *,
+                                   enum machine_mode, tree, bool);
 
 /* Target structure macros.  Listed by node.  See `Using and Porting GCC'
    for a general description.  */
@@ -202,11 +198,14 @@ static tree mmix_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX mmix_struct_value_rtx
-
 #undef TARGET_SETUP_INCOMING_VARARGS
 #define TARGET_SETUP_INCOMING_VARARGS mmix_setup_incoming_varargs
-#undef TARGET_GIMPLIFY_VA_ARG_EXPR
-#define TARGET_GIMPLIFY_VA_ARG_EXPR mmix_gimplify_va_arg_expr
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE mmix_pass_by_reference
+#undef TARGET_CALLEE_COPIES
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -225,7 +224,7 @@ mmix_override_options (void)
      labels.  */
   if (flag_pic)
     {
-      warning ("-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");
+      warning (0, "-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");
       flag_pic = 0;
     }
 }
@@ -578,7 +577,7 @@ mmix_function_arg (const CUMULATIVE_ARGS *argsp,
       : NULL_RTX;
 
   return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
-         && !MUST_PASS_IN_STACK (mode, type)
+         && !targetm.calls.must_pass_in_stack (mode, type)
          && (GET_MODE_BITSIZE (mode) <= 64
              || argsp->lib
              || TARGET_LIBFUNC))
@@ -593,19 +592,21 @@ mmix_function_arg (const CUMULATIVE_ARGS *argsp,
 /* Returns nonzero for everything that goes by reference, 0 for
    everything that goes by value.  */
 
-int
-mmix_function_arg_pass_by_reference (const CUMULATIVE_ARGS *argsp,
-                                    enum machine_mode mode,
-                                    tree type,
-                                    int named ATTRIBUTE_UNUSED)
+static bool
+mmix_pass_by_reference (const CUMULATIVE_ARGS *argsp, enum machine_mode mode,
+                       tree type, bool named ATTRIBUTE_UNUSED)
 {
-  /* FIXME: Check: I'm not sure the MUST_PASS_IN_STACK check is
+  /* FIXME: Check: I'm not sure the must_pass_in_stack check is
      necessary.  */
-  return
-    MUST_PASS_IN_STACK (mode, type)
-    || (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8
-       && !TARGET_LIBFUNC
-       && !argsp->lib);
+  if (targetm.calls.must_pass_in_stack (mode, type))
+    return true;
+
+  if (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8
+      && !TARGET_LIBFUNC
+      && (!argsp || !argsp->lib))
+    return true;
+
+  return false;
 }
 
 /* Return nonzero if regno is a register number where a parameter is
@@ -641,8 +642,22 @@ mmix_function_outgoing_value (tree valtype, tree func ATTRIBUTE_UNUSED)
     return
       gen_rtx_REG (mode, MMIX_OUTGOING_RETURN_VALUE_REGNUM);
 
-  /* A complex type, made up of components.  */
-  cmode = TYPE_MODE (TREE_TYPE (valtype));
+  if (COMPLEX_MODE_P (mode))
+    /* A complex type, made up of components.  */
+    cmode = TYPE_MODE (TREE_TYPE (valtype));
+  else
+    {
+      /* Of the other larger-than-register modes, we only support
+        scalar mode TImode.  (At least, that's the only one that's
+        been rudimentally tested.)  Make sure we're alerted for
+        unexpected cases.  */
+      if (mode != TImode)
+       sorry ("support for mode %qs", GET_MODE_NAME (mode));
+
+      /* In any case, we will fill registers to the natural size.  */
+      cmode = DImode;
+    }
+
   nregs = ((GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD);
 
   /* We need to take care of the effect of the register hole on return
@@ -846,21 +861,6 @@ mmix_setup_incoming_varargs (CUMULATIVE_ARGS *args_so_farp,
     internal_error ("MMIX Internal: Last named vararg would not fit in a register");
 }
 
-/* Gimplify VA_ARG_EXPR.  All we need to do is figure out if TYPE is
-   pass-by-reference and hand off to standard routines.  */
-
-static tree
-mmix_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
-{
-  CUMULATIVE_ARGS cum;
-  cum.lib = 0;
-
-  if (mmix_function_arg_pass_by_reference (&cum, TYPE_MODE (type), type, 0))
-    return ind_gimplify_va_arg_expr (valist, type, pre_p, post_p);
-  else
-    return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
-}
-
 /* TRAMPOLINE_SIZE.  */
 /* Four 4-byte insns plus two 8-byte values.  */
 int mmix_trampoline_size = 32;
@@ -1182,7 +1182,7 @@ mmix_file_start (void)
   fputs ("! mmixal:= 8H LOC Data_Section\n", asm_out_file);
 
   /* Make sure each file starts with the text section.  */
-  text_section ();
+  switch_to_section (text_section);
 }
 
 /* TARGET_ASM_FILE_END.  */
@@ -1191,7 +1191,7 @@ static void
 mmix_file_end (void)
 {
   /* Make sure each file ends with the data section.  */
-  data_section ();
+  switch_to_section (data_section);
 }
 
 /* ASM_OUTPUT_SOURCE_FILENAME.  */
@@ -1248,16 +1248,6 @@ mmix_output_quoted_string (FILE *stream, const char *string, int length)
     }
 }
 
-/* ASM_OUTPUT_SOURCE_LINE.  */
-
-void
-mmix_asm_output_source_line  (FILE *stream, int lineno)
-{
-  fprintf (stream, "# %d ", lineno);
-  OUTPUT_QUOTED_STRING (stream, main_input_filename);
-  fprintf (stream, "\n");
-}
-
 /* Target hook for assembling integer objects.  Use mmix_print_operand
    for WYDE and TETRA.  Use mmix_output_octa to output 8-byte
    CONST_DOUBLEs.  */
@@ -1310,11 +1300,10 @@ mmix_assemble_integer (rtx x, unsigned int size, int aligned_p)
        return true;
 
       case 8:
-       if (GET_CODE (x) == CONST_DOUBLE)
-         /* We don't get here anymore for CONST_DOUBLE, because DImode
-            isn't expressed as CONST_DOUBLE, and DFmode is handled
-            elsewhere.  */
-         abort ();
+       /* We don't get here anymore for CONST_DOUBLE, because DImode
+          isn't expressed as CONST_DOUBLE, and DFmode is handled
+          elsewhere.  */
+       gcc_assert (GET_CODE (x) != CONST_DOUBLE);
        assemble_integer_with_op ("\tOCTA\t", x);
        return true;
       }
@@ -1361,7 +1350,7 @@ mmix_asm_output_aligned_local (FILE *stream,
                               int size,
                               int align)
 {
-  data_section ();
+  switch_to_section (data_section);
 
   ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT));
   assemble_name (stream, name);
@@ -1377,6 +1366,15 @@ mmix_asm_output_label (FILE *stream, const char *name)
   fprintf (stream, "\tIS @\n");
 }
 
+/* ASM_OUTPUT_INTERNAL_LABEL.  */
+
+void
+mmix_asm_output_internal_label (FILE *stream, const char *name)
+{
+  assemble_name_raw (stream, name);
+  fprintf (stream, "\tIS @\n");
+}
+
 /* ASM_DECLARE_REGISTER_GLOBAL.  */
 
 void
@@ -1607,7 +1605,7 @@ mmix_print_operand (FILE *stream, rtx x, int code)
 
     default:
       /* Presumably there's a missing case above if we get here.  */
-      internal_error ("MMIX Internal: Missing `%c' case in mmix_print_operand", code);
+      internal_error ("MMIX Internal: Missing %qc case in mmix_print_operand", code);
     }
 
   switch (GET_CODE (modified_x))
@@ -1893,7 +1891,7 @@ mmix_expand_prologue (void)
 
   /* Make sure we don't get an unaligned stack.  */
   if ((stack_space_to_allocate % 8) != 0)
-    internal_error ("stack frame not a multiple of 8 bytes: %d",
+    internal_error ("stack frame not a multiple of 8 bytes: %wd",
                    stack_space_to_allocate);
 
   if (current_function_pretend_args_size)
@@ -2101,11 +2099,8 @@ mmix_expand_epilogue (void)
        + current_function_pretend_args_size
        + locals_size + 7) & ~7;
 
-  /* The assumption that locals_size fits in an int is asserted in
-     mmix_expand_prologue.  */
-
   /* The first address to access is beyond the outgoing_args area.  */
-  int offset = current_function_outgoing_args_size;
+  HOST_WIDE_INT offset = current_function_outgoing_args_size;
 
   /* Add the space for global non-register-stack registers.
      It is assumed that the frame-pointer register can be one of these
@@ -2132,7 +2127,7 @@ mmix_expand_epilogue (void)
 
   /* Make sure we don't get an unaligned stack.  */
   if ((stack_space_to_deallocate % 8) != 0)
-    internal_error ("stack frame not a multiple of octabyte: %d",
+    internal_error ("stack frame not a multiple of octabyte: %wd",
                    stack_space_to_deallocate);
 
   /* We will add back small offsets to the stack pointer as we go.
@@ -2164,7 +2159,6 @@ mmix_expand_epilogue (void)
      might be of an unaligned size.  */
   offset += (locals_size + 7) & ~7;
 
-
   /* The saved register stack pointer is just below the frame-pointer
      register.  We don't need to restore it "manually"; the POP
      instruction does that.  */
@@ -2349,139 +2343,6 @@ mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value)
   return 1;
 }
 
-/* True if this is an address_operand or a symbolic operand.  */
-
-int
-mmix_symbolic_or_address_operand (rtx op, enum machine_mode mode)
-{
-  switch (GET_CODE (op))
-    {
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return 1;
-    case CONST:
-      op = XEXP (op, 0);
-      if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-          || GET_CODE (XEXP (op, 0)) == LABEL_REF)
-         && (GET_CODE (XEXP (op, 1)) == CONST_INT
-             || (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE
-                 && GET_MODE (XEXP (op, 1)) == VOIDmode)))
-       return 1;
-      /* Fall through.  */
-    default:
-      return address_operand (op, mode);
-    }
-}
-
-/* True if this is a register or CONST_INT (or CONST_DOUBLE for DImode).
-   We could narrow the value down with a couple of predicated, but that
-   doesn't seem to be worth it at the moment.  */
-
-int
-mmix_reg_or_constant_operand (rtx op, enum machine_mode mode)
-{
-  return register_operand (op, mode)
-    || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
-    || GET_CODE (op) == CONST_INT;
-}
-
-/* True if this is a register with a condition-code mode.  */
-
-int
-mmix_reg_cc_operand (rtx op, enum machine_mode mode)
-{
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  return register_operand (op, mode)
-    && (mode == CCmode || mode == CC_UNSmode || mode == CC_FPmode
-       || mode == CC_FPEQmode || mode == CC_FUNmode);
-}
-
-/* True if this is a foldable comparison operator
-   - one where a the result of (compare:CC (reg) (const_int 0)) can be
-   replaced by (reg).  */
-
-int
-mmix_foldable_comparison_operator (rtx op, enum machine_mode mode)
-{
-  RTX_CODE code = GET_CODE (op);
-
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  if (mode == VOIDmode && COMPARISON_P (op))
-    mode = GET_MODE (XEXP (op, 0));
-
-  return ((mode == CCmode || mode == DImode)
-         && (code == NE || code == EQ || code == GE || code == GT
-             || code == LE))
-    /* FIXME: This may be a stupid trick.  What happens when GCC wants to
-       reverse the condition?  Can it do that by itself?  Maybe it can
-       even reverse the condition to fit a foldable one in the first
-       place?  */
-    || (mode == CC_UNSmode && (code == GTU || code == LEU));
-}
-
-/* Like comparison_operator, but only true if this comparison operator is
-   applied to a valid mode.  Needed to avoid jump.c generating invalid
-   code with -ffast-math (gcc.dg/20001228-1.c).  */
-
-int
-mmix_comparison_operator (rtx op, enum machine_mode mode)
-{
-  RTX_CODE code = GET_CODE (op);
-
-  /* Comparison operators usually don't have a mode, but let's try and get
-     one anyway for the day that changes.  */
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  /* Get the mode from the first operand if we don't have one.  */
-  if (mode == VOIDmode && COMPARISON_P (op))
-    mode = GET_MODE (XEXP (op, 0));
-
-  /* FIXME: This needs to be kept in sync with the tables in
-     mmix_output_condition.  */
-  return
-    (mode == VOIDmode && COMPARISON_P (op))
-    || (mode == CC_FUNmode
-       && (code == ORDERED || code == UNORDERED))
-    || (mode == CC_FPmode
-       && (code == GT || code == LT))
-    || (mode == CC_FPEQmode
-       && (code == NE || code == EQ))
-    || (mode == CC_UNSmode
-       && (code == GEU || code == GTU || code == LEU || code == LTU))
-    || (mode == CCmode
-       && (code == NE || code == EQ || code == GE || code == GT
-           || code == LE || code == LT))
-    || (mode == DImode
-       && (code == NE || code == EQ || code == GE || code == GT
-           || code == LE || code == LT || code == LEU || code == GTU));
-}
-
-/* True if this is a register or 0 (int or float).  */
-
-int
-mmix_reg_or_0_operand (rtx op, enum machine_mode mode)
-{
-  /* FIXME: Is mode calculation necessary and correct?  */
-  return
-    op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)
-    || register_operand (op, mode);
-}
-
-/* True if this is a register or an int 0..255.  */
-
-int
-mmix_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
-  return register_operand (op, mode)
-    || (GET_CODE (op) == CONST_INT
-       && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
-}
-
 /* Returns zero if code and mode is not a valid condition from a
    compare-type insn.  Nonzero if it is.  The parameter op, if non-NULL,
    is the comparison of mode is CC-somethingmode.  */
@@ -2715,12 +2576,12 @@ mmix_output_condition (FILE *stream, rtx x, int reversed)
   {
     enum machine_mode cc_mode;
 
-    /* Terminated with {NIL, NULL, NULL} */
+    /* Terminated with {UNKNOWN, NULL, NULL} */
     const struct cc_conv *const convs;
   };
 
 #undef CCEND
-#define CCEND {NIL, NULL, NULL}
+#define CCEND {UNKNOWN, NULL, NULL}
 
   static const struct cc_conv cc_fun_convs[]
     = {{ORDERED, "Z", "P"},
@@ -2778,7 +2639,7 @@ mmix_output_condition (FILE *stream, rtx x, int reversed)
     {
       if (mode == cc_convs[i].cc_mode)
        {
-         for (j = 0; cc_convs[i].convs[j].cc != NIL; j++)
+         for (j = 0; cc_convs[i].convs[j].cc != UNKNOWN; j++)
            if (cc == cc_convs[i].convs[j].cc)
              {
                const char *mmix_cc
@@ -2844,19 +2705,13 @@ mmix_intval (rtx x)
 
          REAL_VALUE_TO_TARGET_DOUBLE (value, bits);
 
-         if (sizeof (long) < sizeof (HOST_WIDEST_INT))
-           {
-             retval = (unsigned long) bits[1] / 2;
-             retval *= 2;
-             retval |= (unsigned long) bits[1] & 1;
-             retval
-               |= (unsigned HOST_WIDEST_INT) bits[0]
-                 << (sizeof (bits[0]) * 8);
-           }
-         else
-           retval = (unsigned long) bits[1];
-
-         return retval;
+         /* The double cast is necessary to avoid getting the long
+            sign-extended to unsigned long long(!) when they're of
+            different size (usually 32-bit hosts).  */
+         return
+           ((unsigned HOST_WIDEST_INT) (unsigned long) bits[0]
+            << (unsigned HOST_WIDEST_INT) 32U)
+           | (unsigned HOST_WIDEST_INT) (unsigned long) bits[1];
        }
       else if (GET_MODE (x) == SFmode)
        {