OSDN Git Service

* config/mmix/mmix.h (FUNCTION_INCOMING_ARG_REGNO_P): Don't define
[pf3gnuchains/gcc-fork.git] / gcc / config / mmix / mmix.c
index 9c7fb62..a55b0dc 100644 (file)
@@ -1,12 +1,13 @@
 /* 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, 2006, 2007
+   Free Software Foundation, Inc.
    Contributed by Hans-Peter Nilsson (hp@bitrange.com)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -55,7 +55,7 @@ Boston, MA 02111-1307, USA.  */
 /* We have no means to tell DWARF 2 about the register stack, so we need
    to store the return address on the stack if an exception can get into
    this function.  FIXME: Narrow condition.  Before any whole-function
-   analysis, regs_ever_live[] isn't initialized.  We know it's up-to-date
+   analysis, df_regs_ever_live_p () isn't initialized.  We know it's up-to-date
    after reload_completed; it may contain incorrect information some time
    before that.  Within a RTL sequence (after a call to start_sequence,
    such as in RTL expanders), leaf_function_p doesn't see all insns
@@ -65,7 +65,7 @@ Boston, MA 02111-1307, USA.  */
    preferable.  */
 #define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS                        \
  (flag_exceptions                                              \
-  && ((reload_completed && regs_ever_live[MMIX_rJ_REGNUM])     \
+  && ((reload_completed && df_regs_ever_live_p (MMIX_rJ_REGNUM))       \
       || !leaf_function_p ()))
 
 #define IS_MMIX_EH_RETURN_DATA_REG(REGNO)      \
@@ -106,11 +106,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 +134,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 (CUMULATIVE_ARGS *,
+                                   enum machine_mode, const_tree, bool);
 
 /* Target structure macros.  Listed by node.  See `Using and Porting GCC'
    for a general description.  */
@@ -192,7 +187,7 @@ static tree mmix_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 #define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg
 
 #undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
 #if 0
 /* Apparently not doing TRT if int < register-size.  FIXME: Perhaps
    FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say.  */
@@ -202,11 +197,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 +223,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;
     }
 }
@@ -321,6 +319,26 @@ mmix_conditional_register_usage (void)
        reg_names[i]++;
 }
 
+/* INCOMING_REGNO and OUTGOING_REGNO worker function.
+   Those two macros must only be applied to function argument
+   registers.  FIXME: for their current use in gcc, it'd be better
+   with an explicit specific additional FUNCTION_INCOMING_ARG_REGNO_P
+   a'la FUNCTION_ARG / FUNCTION_INCOMING_ARG instead of forcing the
+   target to commit to a fixed mapping and for any unspecified
+   register use.  */
+
+int
+mmix_opposite_regno (int regno, int incoming)
+{
+  if (!mmix_function_arg_regno_p (regno, incoming))
+    return regno;
+
+  return
+    regno - (incoming
+            ? MMIX_FIRST_INCOMING_ARG_REGNUM - MMIX_FIRST_ARG_REGNUM
+            : MMIX_FIRST_ARG_REGNUM - MMIX_FIRST_INCOMING_ARG_REGNUM);
+}
+
 /* LOCAL_REGNO.
    All registers that are part of the register stack and that will be
    saved are local.  */
@@ -548,7 +566,7 @@ mmix_initial_elimination_offset (int fromreg, int toreg)
   for (regno = MMIX_FIRST_GLOBAL_REGNUM;
        regno <= 255;
        regno++)
-    if ((regs_ever_live[regno] && ! call_used_regs[regno])
+    if ((df_regs_ever_live_p (regno) && ! call_used_regs[regno])
        || IS_MMIX_EH_RETURN_DATA_REG (regno))
       fp_sp_offset += 8;
 
@@ -578,7 +596,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 +611,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 (CUMULATIVE_ARGS *argsp, enum machine_mode mode,
+                       const_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
@@ -624,7 +644,7 @@ mmix_function_arg_regno_p (int regno, int incoming)
 /* FUNCTION_OUTGOING_VALUE.  */
 
 rtx
-mmix_function_outgoing_value (tree valtype, tree func ATTRIBUTE_UNUSED)
+mmix_function_outgoing_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
 {
   enum machine_mode mode = TYPE_MODE (valtype);
   enum machine_mode cmode;
@@ -641,8 +661,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
@@ -750,7 +784,7 @@ mmix_reorg (void)
   for (regno = MMIX_LAST_STACK_REGISTER_REGNUM;
        regno >= 0;
        regno--)
-    if ((regs_ever_live[regno] && !call_used_regs[regno])
+    if ((df_regs_ever_live_p (regno) && !call_used_regs[regno])
        || (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed))
       break;
 
@@ -759,7 +793,7 @@ mmix_reorg (void)
      insns to see whether they're actually used (and indeed do other less
      trivial register usage analysis and transformations), but it seems
      wasteful to optimize for unused parameter registers.  As of
-     2002-04-30, regs_ever_live[n] seems to be set for only-reads too, but
+     2002-04-30, df_regs_ever_live_p (n) seems to be set for only-reads too, but
      that might change.  */
   if (!TARGET_ABI_GNU && regno < current_function_args_info.regs - 1)
     {
@@ -846,21 +880,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;
@@ -1142,7 +1161,7 @@ mmix_encode_section_info (tree decl, rtx rtl, int first)
       char *newstr;
 
       /* Why is the return type of ggc_alloc_string const?  */
-      newstr = (char *) ggc_alloc_string ("", len + 1);
+      newstr = CONST_CAST (char *, ggc_alloc_string ("", len + 1));
 
       strcpy (newstr + 1, str);
       *newstr = '@';
@@ -1182,7 +1201,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 +1210,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 +1267,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 +1319,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 +1369,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 +1385,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 +1624,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))
@@ -1838,7 +1855,7 @@ mmix_use_simple_return (void)
     /* Note that we assume that the frame-pointer-register is one of these
        registers, in which case we don't count it here.  */
     if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
-         && regs_ever_live[regno] && !call_used_regs[regno]))
+         && df_regs_ever_live_p (regno) && !call_used_regs[regno]))
        || IS_MMIX_EH_RETURN_DATA_REG (regno))
       return 0;
 
@@ -1874,7 +1891,7 @@ mmix_expand_prologue (void)
     /* Note that we assume that the frame-pointer-register is one of these
        registers, in which case we don't count it here.  */
     if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
-         && regs_ever_live[regno] && !call_used_regs[regno]))
+         && df_regs_ever_live_p (regno) && !call_used_regs[regno]))
        || IS_MMIX_EH_RETURN_DATA_REG (regno))
       stack_space_to_allocate += 8;
 
@@ -1893,7 +1910,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)
@@ -2059,7 +2076,7 @@ mmix_expand_prologue (void)
        regno >= MMIX_FIRST_GLOBAL_REGNUM;
        regno--)
     if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
-        && regs_ever_live[regno] && ! call_used_regs[regno])
+        && df_regs_ever_live_p (regno) && ! call_used_regs[regno])
        || IS_MMIX_EH_RETURN_DATA_REG (regno))
       {
        rtx insn;
@@ -2101,11 +2118,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
@@ -2114,7 +2128,7 @@ mmix_expand_epilogue (void)
        regno >= MMIX_FIRST_GLOBAL_REGNUM;
        regno--)
     if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
-        && regs_ever_live[regno] && !call_used_regs[regno])
+        && df_regs_ever_live_p (regno) && !call_used_regs[regno])
        || IS_MMIX_EH_RETURN_DATA_REG (regno))
       stack_space_to_deallocate += 8;
 
@@ -2132,7 +2146,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.
@@ -2143,7 +2157,7 @@ mmix_expand_epilogue (void)
        regno <= 255;
        regno++)
     if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
-        && regs_ever_live[regno] && !call_used_regs[regno])
+        && df_regs_ever_live_p (regno) && !call_used_regs[regno])
        || IS_MMIX_EH_RETURN_DATA_REG (regno))
       {
        if (offset > 255)
@@ -2164,7 +2178,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 +2362,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 +2595,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 +2658,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 +2724,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)
        {