OSDN Git Service

* config/alpha/alpha.md, config/arm/arm.c, config/arm/arm.h,
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.c
index f6a354d..1cb61c7 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines for insn-output.c for Sun SPARC.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
    64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
    at Cygnus Support.
@@ -31,16 +31,20 @@ Boston, MA 02111-1307, USA.  */
 #include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
-#include "insn-flags.h"
 #include "output.h"
 #include "insn-attr.h"
 #include "flags.h"
 #include "function.h"
 #include "expr.h"
+#include "optabs.h"
+#include "libfuncs.h"
 #include "recog.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "tm_p.h"
+#include "debug.h"
+#include "target.h"
+#include "target-def.h"
 
 /* 1 if the caller has placed an "unimp" insn immediately after the call.
    This is used in v8 code when calling a function that returns a structure.
@@ -83,7 +87,7 @@ static rtx leaf_label;
    registers.  FRAME_POINTER_REGNUM cannot be remapped by
    this function to eliminate it.  You must use -fomit-frame-pointer
    to get that.  */
-char leaf_reg_remap[] =
+const char leaf_reg_remap[] =
 { 0, 1, 2, 3, 4, 5, 6, 7,
   -1, -1, -1, -1, -1, -1, 14, -1,
   -1, -1, -1, -1, -1, -1, -1, -1,
@@ -127,7 +131,6 @@ char sparc_leaf_regs[] =
 static const char *frame_base_name;
 static int frame_base_offset;
 
-static rtx pic_setup_code      PARAMS ((void));
 static void sparc_init_modes   PARAMS ((void));
 static int save_regs           PARAMS ((FILE *, int, int, const char *,
                                       int, int, int));
@@ -154,8 +157,27 @@ static rtx *ultra_find_type PARAMS ((int, rtx *, int));
 static void ultra_build_types_avail PARAMS ((rtx *, int));
 static void ultra_flush_pipeline PARAMS ((void));
 static void ultra_rescan_pipeline_state PARAMS ((rtx *, int));
-static int set_extends PARAMS ((rtx, rtx));
+static int set_extends PARAMS ((rtx));
 static void output_restore_regs PARAMS ((FILE *, int));
+static void sparc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_flat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_flat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void sparc_nonflat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT,
+                                                    int));
+static void sparc_nonflat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT,
+                                                    int));
+static void sparc_elf_asm_named_section PARAMS ((const char *, unsigned int));
+
+static void ultrasparc_sched_reorder PARAMS ((FILE *, int, rtx *, int));
+static int ultrasparc_variable_issue PARAMS ((rtx));
+static void ultrasparc_sched_init PARAMS ((void));
+
+static int sparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static int sparc_issue_rate PARAMS ((void));
+static int sparc_variable_issue PARAMS ((FILE *, int, rtx, int));
+static void sparc_sched_init PARAMS ((FILE *, int, int));
+static int sparc_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
 \f
 /* Option handling.  */
 
@@ -177,7 +199,26 @@ struct sparc_cpu_select sparc_select[] =
 
 /* CPU type.  This is set from TARGET_CPU_DEFAULT and -m{cpu,tune}=xxx.  */
 enum processor_type sparc_cpu;
-
+\f
+/* Initialize the GCC target structure.  */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE sparc_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE sparc_output_function_epilogue
+
+#undef TARGET_SCHED_ADJUST_COST
+#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
+#undef TARGET_SCHED_VARIABLE_ISSUE
+#define TARGET_SCHED_VARIABLE_ISSUE sparc_variable_issue
+#undef TARGET_SCHED_INIT
+#define TARGET_SCHED_INIT sparc_sched_init
+#undef TARGET_SCHED_REORDER
+#define TARGET_SCHED_REORDER sparc_sched_reorder
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+\f
 /* Validate and override various options, and do some machine dependent
    initialization.  */
 
@@ -185,9 +226,9 @@ void
 sparc_override_options ()
 {
   static struct code_model {
-    const char *name;
-    int value;
-  } cmodels[] = {
+    const char *const name;
+    const int value;
+  } const cmodels[] = {
     { "32", CM_32 },
     { "medlow", CM_MEDLOW },
     { "medmid", CM_MEDMID },
@@ -195,12 +236,12 @@ sparc_override_options ()
     { "embmedany", CM_EMBMEDANY },
     { 0, 0 }
   };
-  struct code_model *cmodel;
+  const struct code_model *cmodel;
   /* Map TARGET_CPU_DEFAULT to value for -m{arch,tune}=.  */
   static struct cpu_default {
-    int cpu;
-    const char *name;
-  } cpu_default[] = {
+    const int cpu;
+    const char *const name;
+  } const cpu_default[] = {
     /* There must be one entry here for each TARGET_CPU value.  */
     { TARGET_CPU_sparc, "cypress" },
     { TARGET_CPU_sparclet, "tsc701" },
@@ -213,14 +254,14 @@ sparc_override_options ()
     { TARGET_CPU_ultrasparc, "ultrasparc" },
     { 0, 0 }
   };
-  struct cpu_default *def;
+  const struct cpu_default *def;
   /* Table of values for -m{cpu,tune}=.  */
   static struct cpu_table {
-    const char *name;
-    enum processor_type processor;
-    int disable;
-    int enable;
-  } cpu_table[] = {
+    const char *const name;
+    const enum processor_type processor;
+    const int disable;
+    const int enable;
+  } const cpu_table[] = {
     { "v7",         PROCESSOR_V7, MASK_ISA, 0 },
     { "cypress",    PROCESSOR_CYPRESS, MASK_ISA, 0 },
     { "v8",         PROCESSOR_V8, MASK_ISA, MASK_V8 },
@@ -242,33 +283,20 @@ sparc_override_options ()
     { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9
     /* Although insns using %y are deprecated, it is a clear win on current
        ultrasparcs. */
-                                                   |MASK_DEPRECATED_V8_INSNS },
+                                                   |MASK_DEPRECATED_V8_INSNS},
     { 0, 0, 0, 0 }
   };
-  struct cpu_table *cpu;
-  struct sparc_cpu_select *sel;
+  const struct cpu_table *cpu;
+  const struct sparc_cpu_select *sel;
   int fpu;
   
 #ifndef SPARC_BI_ARCH
   /* Check for unsupported architecture size.  */
   if (! TARGET_64BIT != DEFAULT_ARCH32_P)
-    {
-      error ("%s is not supported by this configuration",
-            DEFAULT_ARCH32_P ? "-m64" : "-m32");
-    }
+    error ("%s is not supported by this configuration",
+          DEFAULT_ARCH32_P ? "-m64" : "-m32");
 #endif
 
-  /* At the moment we don't allow different pointer size and architecture */
-  if (! TARGET_64BIT != ! TARGET_PTR64)
-    {
-      error ("-mptr%d not allowed on -m%d",
-            TARGET_PTR64 ? 64 : 32, TARGET_64BIT ? 64 : 32);
-      if (TARGET_64BIT)
-       target_flags |= MASK_PTR64;
-      else
-        target_flags &= ~MASK_PTR64;
-    }
-
   /* We force all 64bit archs to use 128 bit long double */
   if (TARGET_64BIT && ! TARGET_LONG_DOUBLE_128)
     {
@@ -1128,7 +1156,7 @@ uns_small_int (op, mode)
   return (GET_CODE (op) == CONST_INT
          && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
              || (INTVAL (op) >= 0xFFFFF000
-                  && INTVAL (op) < 0x100000000)));
+                  && INTVAL (op) <= 0xFFFFFFFF)));
 #else
   return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
          || (GET_CODE (op) == CONST_DOUBLE
@@ -1194,7 +1222,8 @@ input_operand (op, mode)
                  (SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
                   && (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0
                        && CONST_DOUBLE_HIGH (op) == 0)
-                      || (CONST_DOUBLE_HIGH (op) == -1)))
+                      || (CONST_DOUBLE_HIGH (op) == -1
+                          && CONST_DOUBLE_LOW (op) & 0x80000000) != 0))
 #endif
                  ))))
     return 1;
@@ -1832,12 +1861,17 @@ sparc_emit_set_const64 (op0, op1)
   rtx temp;
 
   /* Sanity check that we know what we are working with.  */
-  if (! TARGET_ARCH64
-      || GET_CODE (op0) != REG
-      || (REGNO (op0) >= SPARC_FIRST_FP_REG
-         && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
+  if (! TARGET_ARCH64)
     abort ();
 
+  if (GET_CODE (op0) != SUBREG)
+    {
+      if (GET_CODE (op0) != REG
+         || (REGNO (op0) >= SPARC_FIRST_FP_REG
+             && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
+       abort ();
+    }
+
   if (reload_in_progress || reload_completed)
     temp = op0;
   else
@@ -2386,6 +2420,11 @@ eligible_for_epilogue_delay (trial, slot)
   if (num_gfregs)
     return 0;
 
+  /* If the function uses __builtin_eh_return, the eh_return machinery
+     occupies the delay slot.  */
+  if (current_function_calls_eh_return)
+    return 0;
+
   /* In the case of a true leaf function, anything can go into the delay slot.
      A delay slot only exists however if the frame size is zero, otherwise
      we will put an insn to adjust the stack after the return.  */
@@ -2422,7 +2461,8 @@ eligible_for_epilogue_delay (trial, slot)
   src = SET_SRC (pat);
 
   /* This matches "*return_[qhs]i" or even "*return_di" on TARGET_ARCH64.  */
-  if (arith_operand (src, GET_MODE (src)))
+  if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+      && arith_operand (src, GET_MODE (src)))
     {
       if (TARGET_ARCH64)
         return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
@@ -2431,7 +2471,8 @@ eligible_for_epilogue_delay (trial, slot)
     }
 
   /* This matches "*return_di".  */
-  else if (arith_double_operand (src, GET_MODE (src)))
+  else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+          && arith_double_operand (src, GET_MODE (src)))
     return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
 
   /* This matches "*return_sf_no_fpu".  */
@@ -2528,7 +2569,8 @@ eligible_for_sibcall_delay (trial)
 
   src = SET_SRC (pat);
 
-  if (arith_operand (src, GET_MODE (src)))
+  if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+      && arith_operand (src, GET_MODE (src)))
     {
       if (TARGET_ARCH64)
         return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
@@ -2536,7 +2578,8 @@ eligible_for_sibcall_delay (trial)
         return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
     }
 
-  else if (arith_double_operand (src, GET_MODE (src)))
+  else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+          && arith_double_operand (src, GET_MODE (src)))
     return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
 
   else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
@@ -2768,8 +2811,8 @@ legitimize_pic_address (orig, mode, reg)
        address = orig;
 
       pic_ref = gen_rtx_MEM (Pmode,
-                        gen_rtx_PLUS (Pmode,
-                                 pic_offset_table_rtx, address));
+                            gen_rtx_PLUS (Pmode,
+                                          pic_offset_table_rtx, address));
       current_function_uses_pic_offset_table = 1;
       RTX_UNCHANGING_P (pic_ref) = 1;
       insn = emit_move_insn (reg, pic_ref);
@@ -2807,7 +2850,7 @@ legitimize_pic_address (orig, mode, reg)
       if (GET_CODE (offset) == CONST_INT)
        {
          if (SMALL_INT (offset))
-           return plus_constant_for_output (base, INTVAL (offset));
+           return plus_constant (base, INTVAL (offset));
          else if (! reload_in_progress && ! reload_completed)
            offset = force_reg (Pmode, offset);
          else
@@ -2825,33 +2868,13 @@ legitimize_pic_address (orig, mode, reg)
   return orig;
 }
 
-/* Return the RTX for insns to set the PIC register.  */
-
-static rtx
-pic_setup_code ()
-{
-  rtx seq;
-
-  start_sequence ();
-  emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
-                        get_pc_symbol));
-  seq = gen_sequence ();
-  end_sequence ();
-
-  return seq;
-}
-
-/* Emit special PIC prologues and epilogues.  */
+/* Emit special PIC prologues.  */
 
 void
-finalize_pic ()
+load_pic_register ()
 {
   /* Labels to get the PC in the prologue of this function.  */
   int orig_flag_pic = flag_pic;
-  rtx insn;
-
-  if (current_function_uses_pic_offset_table == 0)
-    return;
 
   if (! flag_pic)
     abort ();
@@ -2868,7 +2891,7 @@ finalize_pic ()
       if (align > 0)
        ASM_OUTPUT_ALIGN (asm_out_file, align);
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0);
-      fputs ("\tretl\n\tadd %o7,%l7,%l7\n", asm_out_file);
+      fputs ("\tretl\n\tadd\t%o7, %l7, %l7\n", asm_out_file);
     }
 
   /* Initialize every time through, since we can't easily
@@ -2877,16 +2900,8 @@ finalize_pic ()
   get_pc_symbol = gen_rtx_SYMBOL_REF (Pmode, get_pc_symbol_name);
   flag_pic = 0;
 
-  emit_insn_after (pic_setup_code (), get_insns ());
-
-  /* Insert the code in each nonlocal goto receiver.
-     If you make changes here or to the nonlocal_goto_receiver
-     pattern, make sure the unspec_volatile numbers still
-     match.  */
-  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
-       && XINT (PATTERN (insn), 1) == 5)
-      emit_insn_after (pic_setup_code (), insn);
+  emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
+                        get_pc_symbol));
 
   flag_pic = orig_flag_pic;
 
@@ -3277,11 +3292,11 @@ restore_regs (file, low, high, base, offset, n_regs)
                       base, offset + 4 * n_regs, reg_names[i]),
              n_regs += 2;
            else
-             fprintf (file, "\tld\t[%s+%d],%s\n",
+             fprintf (file, "\tld\t[%s+%d], %s\n",
                       base, offset + 4 * n_regs, reg_names[i]),
              n_regs += 2;
          else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
-           fprintf (file, "\tld\t[%s+%d],%s\n",
+           fprintf (file, "\tld\t[%s+%d], %s\n",
                     base, offset + 4 * n_regs + 4, reg_names[i+1]),
            n_regs += 2;
        }
@@ -3410,12 +3425,40 @@ sparc_output_scratch_registers (file)
 #endif
 }
 
+/* This function generates the assembly code for function entry.
+   FILE is a stdio stream to output the code to.
+   SIZE is an int: how many units of temporary storage to allocate.
+   Refer to the array `regs_ever_live' to determine which registers
+   to save; `regs_ever_live[I]' is nonzero if register number I
+   is ever used in the function.  This macro is responsible for
+   knowing which registers should not be saved even if used.  */
+
+/* On SPARC, move-double insns between fpu and cpu need an 8-byte block
+   of memory.  If any fpu reg is used in the function, we allocate
+   such a block here, at the bottom of the frame, just in case it's needed.
+
+   If this function is a leaf procedure, then we may choose not
+   to do a "save" insn.  The decision about whether or not
+   to do this is made in regclass.c.  */
+
+static void
+sparc_output_function_prologue (file, size)
+     FILE *file;
+     HOST_WIDE_INT size;
+{
+  if (TARGET_FLAT)
+    sparc_flat_function_prologue (file, size);
+  else
+    sparc_nonflat_function_prologue (file, size,
+                                    current_function_uses_only_leaf_regs);
+}
+
 /* Output code for the function prologue.  */
 
-void
-output_function_prologue (file, size, leaf_function)
+static void
+sparc_nonflat_function_prologue (file, size, leaf_function)
      FILE *file;
-     int size;
+     HOST_WIDE_INT size;
      int leaf_function;
 {
   sparc_output_scratch_registers (file);
@@ -3577,12 +3620,32 @@ output_restore_regs (file, leaf_function)
     restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
 }
 
+/* This function generates the assembly code for function exit,
+   on machines that need it.
+
+   The function epilogue should not depend on the current stack pointer!
+   It should use the frame pointer only.  This is mandatory because
+   of alloca; we also take advantage of it to omit stack adjustments
+   before returning.  */
+
+static void
+sparc_output_function_epilogue (file, size)
+     FILE *file;
+     HOST_WIDE_INT size;
+{
+  if (TARGET_FLAT)
+    sparc_flat_function_epilogue (file, size);
+  else
+    sparc_nonflat_function_epilogue (file, size,
+                                    current_function_uses_only_leaf_regs);
+}
+
 /* Output code for the function epilogue.  */
 
-void
-output_function_epilogue (file, size, leaf_function)
+static void
+sparc_nonflat_function_epilogue (file, size, leaf_function)
      FILE *file;
-     int size ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
      int leaf_function;
 {
   const char *ret;
@@ -3627,8 +3690,17 @@ output_function_epilogue (file, size, leaf_function)
 
       if (! leaf_function)
        {
+         if (current_function_calls_eh_return)
+           {
+             if (current_function_epilogue_delay_list)
+               abort ();
+             if (SKIP_CALLERS_UNIMP_P)
+               abort ();
+
+             fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
+           }
          /* If we wound up with things in our delay slot, flush them here.  */
-         if (current_function_epilogue_delay_list)
+         else if (current_function_epilogue_delay_list)
            {
              rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
 
@@ -3668,6 +3740,8 @@ output_function_epilogue (file, size, leaf_function)
          else
            fprintf (file, "\t%s\n\trestore\n", ret);
        }
+      else if (current_function_calls_eh_return)
+       abort ();
       /* All of the following cases are for leaf functions.  */
       else if (current_function_epilogue_delay_list)
        {
@@ -3971,6 +4045,7 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
     case HImode : case CHImode :
     case SImode : case CSImode :
     case DImode : case CDImode :
+    case TImode : case CTImode :
       if (slotno >= SPARC_INT_ARG_MAX)
        return -1;
       regno = regbase + slotno;
@@ -4092,6 +4167,9 @@ static void function_arg_record_value_1
 static rtx function_arg_record_value
        PARAMS ((tree, enum machine_mode, int, int, int));
 
+/* A subroutine of function_arg_record_value.  Traverse the structure
+   recusively and determine how many registers will be required.  */
+
 static void
 function_arg_record_value_1 (type, startbitpos, parms)
      tree type;
@@ -4166,7 +4244,8 @@ function_arg_record_value_1 (type, startbitpos, parms)
     }
 }
 
-/* Handle recursive structure field register assignment.  */
+/* A subroutine of function_arg_record_value.  Assign the bits of the
+   structure between parms->intoffset and bitpos to integer registers.  */
 
 static void 
 function_arg_record_value_3 (bitpos, parms)
@@ -4175,6 +4254,7 @@ function_arg_record_value_3 (bitpos, parms)
 {
   enum machine_mode mode;
   unsigned int regno;
+  unsigned int startbit, endbit;
   int this_slotno, intslots, intoffset;
   rtx reg;
 
@@ -4184,7 +4264,9 @@ function_arg_record_value_3 (bitpos, parms)
   intoffset = parms->intoffset;
   parms->intoffset = -1;
 
-  intslots = (bitpos - intoffset + BITS_PER_WORD - 1) / BITS_PER_WORD;
+  startbit = intoffset & -BITS_PER_WORD;
+  endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
+  intslots = (endbit - startbit) / BITS_PER_WORD;
   this_slotno = parms->slotno + intoffset / BITS_PER_WORD;
 
   intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
@@ -4218,6 +4300,11 @@ function_arg_record_value_3 (bitpos, parms)
   while (intslots > 0);
 }
 
+/* A subroutine of function_arg_record_value.  Traverse the structure
+   recursively and assign bits to floating point registers.  Track which
+   bits in between need integer registers; invoke function_arg_record_value_3
+   to make that happen.  */
+
 static void
 function_arg_record_value_2 (type, startbitpos, parms)
      tree type;
@@ -4278,6 +4365,9 @@ function_arg_record_value_2 (type, startbitpos, parms)
     }
 }
 
+/* Used by function_arg and function_value to implement the complex
+   Sparc64 structure calling conventions.  */
+
 static rtx
 function_arg_record_value (type, mode, slotno, named, regbase)
      tree type;
@@ -4300,10 +4390,12 @@ function_arg_record_value (type, mode, slotno, named, regbase)
 
   if (parms.intoffset != -1)
     {
+      unsigned int startbit, endbit;
       int intslots, this_slotno;
 
-      intslots = (typesize*BITS_PER_UNIT - parms.intoffset + BITS_PER_WORD - 1)
-       / BITS_PER_WORD;
+      startbit = parms.intoffset & -BITS_PER_WORD;
+      endbit = (typesize*BITS_PER_UNIT + BITS_PER_WORD - 1) & -BITS_PER_WORD;
+      intslots = (endbit - startbit) / BITS_PER_WORD;
       this_slotno = slotno + parms.intoffset / BITS_PER_WORD;
 
       intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
@@ -4701,9 +4793,11 @@ function_value (type, mode, incoming_p)
 
          return function_arg_record_value (type, mode, 0, 1, regbase);
        }
-      else if (TREE_CODE (type) == UNION_TYPE)
+      else if (AGGREGATE_TYPE_P (type))
        {
-         int bytes = int_size_in_bytes (type);
+         /* All other aggregate types are passed in an integer register
+            in a mode corresponding to the size of the type.  */
+         HOST_WIDE_INT bytes = int_size_in_bytes (type);
 
          if (bytes > 32)
            abort ();
@@ -4715,7 +4809,7 @@ function_value (type, mode, incoming_p)
   if (TARGET_ARCH64
       && GET_MODE_CLASS (mode) == MODE_INT 
       && GET_MODE_SIZE (mode) < UNITS_PER_WORD
-      && type && TREE_CODE (type) != UNION_TYPE)
+      && type && ! AGGREGATE_TYPE_P (type))
     mode = DImode;
 
   if (incoming_p)
@@ -4739,17 +4833,18 @@ sparc_builtin_saveregs ()
 
   for (regno = first_reg; regno < NPARM_REGS (word_mode); regno++)
     emit_move_insn (gen_rtx_MEM (word_mode,
-                            gen_rtx_PLUS (Pmode,
-                                     frame_pointer_rtx,
-                                     GEN_INT (STACK_POINTER_OFFSET
-                                              + UNITS_PER_WORD * regno))),
+                                gen_rtx_PLUS (Pmode,
+                                              frame_pointer_rtx,
+                                              GEN_INT (STACK_POINTER_OFFSET
+                                                       + (UNITS_PER_WORD
+                                                          * regno)))),
                    gen_rtx_REG (word_mode,
-                            BASE_INCOMING_ARG_REG (word_mode) + regno));
+                                BASE_INCOMING_ARG_REG (word_mode) + regno));
 
   address = gen_rtx_PLUS (Pmode,
-                    frame_pointer_rtx,
-                    GEN_INT (STACK_POINTER_OFFSET
-                             + UNITS_PER_WORD * first_reg));
+                         frame_pointer_rtx,
+                         GEN_INT (STACK_POINTER_OFFSET
+                                  + UNITS_PER_WORD * first_reg));
 
   if (current_function_check_memory_usage
       && first_reg < NPARM_REGS (word_mode))
@@ -4816,12 +4911,6 @@ sparc_va_arg (valist, type)
          indirect = 1;
          size = rsize = UNITS_PER_WORD;
        }
-      else
-       {
-         /* ??? The old va-sparc.h implementation, for 8 byte objects
-            copied stuff to a temporary -- I don't see that that 
-            provides any more alignment than the stack slot did.  */
-       }
     }
 
   incr = valist;
@@ -4848,11 +4937,42 @@ sparc_va_arg (valist, type)
 
   addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
 
+  /* If the address isn't aligned properly for the type,
+     we may need to copy to a temporary.  
+     FIXME: This is inefficient.  Usually we can do this
+     in registers.  */
+  if (align == 0
+      && TYPE_ALIGN (type) > BITS_PER_WORD
+      && !indirect)
+    {
+      /* FIXME: We really need to specify that the temporary is live
+        for the whole function because expand_builtin_va_arg wants
+        the alias set to be get_varargs_alias_set (), but in this
+        case the alias set is that for TYPE and if the memory gets
+        reused it will be reused with alias set TYPE.  */
+      rtx tmp = assign_temp (type, 0, 1, 0);
+      rtx dest_addr;
+
+      addr_rtx = force_reg (Pmode, addr_rtx);
+      addr_rtx = gen_rtx_MEM (BLKmode, addr_rtx);
+      set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
+      set_mem_align (addr_rtx, BITS_PER_WORD);
+      tmp = shallow_copy_rtx (tmp);
+      PUT_MODE (tmp, BLKmode);
+      set_mem_alias_set (tmp, 0);
+      
+      dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize));
+      if (dest_addr != NULL_RTX)
+       addr_rtx = dest_addr;
+      else
+       addr_rtx = XCEXP (tmp, 0, MEM);
+    }
+
   if (indirect)
     {
       addr_rtx = force_reg (Pmode, addr_rtx);
       addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
-      MEM_ALIAS_SET (addr_rtx) = get_varargs_alias_set ();
+      set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
     }
 
   return addr_rtx;
@@ -5415,9 +5535,9 @@ output_return (operands)
       else
        {
          if ((actual_fsize & 0x3ff) != 0)
-           return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
+           return "sethi\t%%hi(%a0), %%g1\n\tor\t%%g1, %%lo(%a0), %%g1\n\tretl\n\tadd\t%%sp, %%g1, %%sp";
          else
-           return "sethi %%hi(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
+           return "sethi\t%%hi(%a0), %%g1\n\tretl\n\tadd\t%%sp, %%g1, %%sp";
        }
     }
   else if (TARGET_V9)
@@ -5445,13 +5565,13 @@ output_return (operands)
 \f
 /* Leaf functions and non-leaf functions have different needs.  */
 
-static int
+static const int
 reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
 
-static int
+static const int
 reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
 
-static int *reg_alloc_orders[] = {
+static const int *const reg_alloc_orders[] = {
   reg_leaf_alloc_order,
   reg_nonleaf_alloc_order};
 
@@ -5463,8 +5583,9 @@ order_regs_for_local_alloc ()
   if (regs_ever_live[15] != last_order_nonleaf)
     {
       last_order_nonleaf = !last_order_nonleaf;
-      bcopy ((char *) reg_alloc_orders[last_order_nonleaf],
-            (char *) reg_alloc_order, FIRST_PSEUDO_REGISTER * sizeof (int));
+      memcpy ((char *) reg_alloc_order,
+             (const char *) reg_alloc_orders[last_order_nonleaf],
+             FIRST_PSEUDO_REGISTER * sizeof (int));
     }
 }
 \f
@@ -5556,7 +5677,8 @@ int
 addrs_ok_for_ldd_peep (addr1, addr2)
       rtx addr1, addr2;
 {
-  int reg1, offset1;
+  unsigned int reg1;
+  int offset1;
 
   /* Extract a register number and offset (if used) from the first addr.  */
   if (GET_CODE (addr1) == PLUS)
@@ -6536,10 +6658,10 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
 \f
 /* Set up the stack and frame (if desired) for the function.  */
 
-void
-sparc_flat_output_function_prologue (file, size)
+static void
+sparc_flat_function_prologue (file, size)
      FILE *file;
-     int size;
+     HOST_WIDE_INT size;
 {
   const char *sp_str = reg_names[STACK_POINTER_REGNUM];
   unsigned long gmask = current_frame_info.gmask;
@@ -6580,8 +6702,8 @@ sparc_flat_output_function_prologue (file, size)
   if (size > 0)
     {
       unsigned int reg_offset = current_frame_info.reg_offset;
-      const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
-      const char *t1_str = "%g1";
+      const char *const fp_str = reg_names[FRAME_POINTER_REGNUM];
+      static const char *const t1_str = "%g1";
 
       /* Things get a little tricky if local variables take up more than ~4096
         bytes and outgoing arguments take up more than ~4096 bytes.  When that
@@ -6600,20 +6722,22 @@ sparc_flat_output_function_prologue (file, size)
          if (size <= 4096)
            {
              fprintf (file, "\tadd\t%s, %d, %s\n",
-                      sp_str, -size, sp_str);
+                      sp_str, (int) -size, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
                  fprintf (file, "\tst\t%s, [%s+%d]\n",
                           fp_str, sp_str, reg_offset);
                  fprintf (file, "\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
-                          sp_str, -size, fp_str, ASM_COMMENT_START);
+                          sp_str, (int) -size, fp_str, ASM_COMMENT_START);
                  reg_offset += 4;
                }
            }
          else
            {
-             fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
-                      size, t1_str, sp_str, t1_str, sp_str);
+             fprintf (file, "\tset\t");
+             fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
+             fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
+                      t1_str, sp_str, t1_str, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
                  fprintf (file, "\tst\t%s, [%s+%d]\n",
@@ -6653,31 +6777,33 @@ sparc_flat_output_function_prologue (file, size)
          /* Subtract %sp in two steps, but make sure there is always a
             64 byte register save area, and %sp is properly aligned.  */
          /* Amount to decrement %sp by, the first time.  */
-         unsigned int size1 = ((size - reg_offset + 64) + 15) & -16;
+         unsigned HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16;
          /* Offset to register save area from %sp.  */
-         unsigned int offset = size1 - (size - reg_offset);
+         unsigned HOST_WIDE_INT offset = size1 - (size - reg_offset);
          
          if (size1 <= 4096)
            {
              fprintf (file, "\tadd\t%s, %d, %s\n",
-                      sp_str, -size1, sp_str);
+                      sp_str, (int) -size1, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
                  fprintf (file, "\tst\t%s, [%s+%d]\n\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
-                          fp_str, sp_str, offset, sp_str, -size1, fp_str,
-                          ASM_COMMENT_START);
+                          fp_str, sp_str, (int) offset, sp_str, (int) -size1,
+                          fp_str, ASM_COMMENT_START);
                  offset += 4;
                }
            }
          else
            {
-             fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
-                      size1, t1_str, sp_str, t1_str, sp_str);
+             fprintf (file, "\tset\t");
+             fprintf (file, HOST_WIDE_INT_PRINT_DEC, size1);
+             fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
+                      t1_str, sp_str, t1_str, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
                  fprintf (file, "\tst\t%s, [%s+%d]\n\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
-                          fp_str, sp_str, offset, sp_str, t1_str, fp_str,
-                          ASM_COMMENT_START);
+                          fp_str, sp_str, (int) offset, sp_str, t1_str,
+                          fp_str, ASM_COMMENT_START);
                  offset += 4;
                }
            }
@@ -6696,7 +6822,7 @@ sparc_flat_output_function_prologue (file, size)
          if (gmask & RETURN_ADDR_MASK)
            {
              fprintf (file, "\tst\t%s, [%s+%d]\n",
-                      reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
+                      reg_names[RETURN_ADDR_REGNUM], sp_str, (int) offset);
              if (dwarf2out_do_frame ())
                /* offset - size1 == reg_offset - size
                   if reg_offset were updated above like offset.  */
@@ -6707,8 +6833,10 @@ sparc_flat_output_function_prologue (file, size)
                                   gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
                                   current_frame_info.fmask,
                                   "st", "std", -size1);
-         fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
-                  size - size1, t1_str, sp_str, t1_str, sp_str);
+         fprintf (file, "\tset\t");
+         fprintf (file, HOST_WIDE_INT_PRINT_DEC, size - size1);
+         fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
+                  t1_str, sp_str, t1_str, sp_str);
          if (dwarf2out_do_frame ())
            if (! (gmask & FRAME_POINTER_MASK))
              dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
@@ -6721,10 +6849,10 @@ sparc_flat_output_function_prologue (file, size)
 /* Do any necessary cleanup after a function to restore stack, frame,
    and regs. */
 
-void
-sparc_flat_output_function_epilogue (file, size)
+static void
+sparc_flat_function_epilogue (file, size)
      FILE *file;
-     int size;
+     HOST_WIDE_INT size;
 {
   rtx epilogue_delay = current_function_epilogue_delay_list;
   int noepilogue = FALSE;
@@ -6756,18 +6884,22 @@ sparc_flat_output_function_epilogue (file, size)
 
   if (!noepilogue)
     {
-      unsigned int reg_offset = current_frame_info.reg_offset;
-      unsigned int size1;
-      const char *sp_str = reg_names[STACK_POINTER_REGNUM];
-      const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
-      const char *t1_str = "%g1";
+      unsigned HOST_WIDE_INT reg_offset = current_frame_info.reg_offset;
+      unsigned HOST_WIDE_INT size1;
+      const char *const sp_str = reg_names[STACK_POINTER_REGNUM];
+      const char *const fp_str = reg_names[FRAME_POINTER_REGNUM];
+      static const char *const t1_str = "%g1";
 
       /* In the reload sequence, we don't need to fill the load delay
         slots for most of the loads, also see if we can fill the final
         delay slot if not otherwise filled by the reload sequence.  */
 
       if (size > 4095)
-       fprintf (file, "\tset\t%d, %s\n", size, t1_str);
+        {
+         fprintf (file, "\tset\t");
+         fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
+         fprintf (file, ", %s\n", t1_str);
+       }
 
       if (frame_pointer_needed)
        {
@@ -6776,7 +6908,7 @@ sparc_flat_output_function_epilogue (file, size)
                     fp_str, t1_str, sp_str, ASM_COMMENT_START);
          else
            fprintf (file,"\tsub\t%s, %d, %s\t\t%s# sp not trusted here\n",
-                    fp_str, size, sp_str, ASM_COMMENT_START);
+                    fp_str, (int) size, sp_str, ASM_COMMENT_START);
        }
 
       /* Is the entire register save area offsettable from %sp?  */
@@ -6793,8 +6925,10 @@ sparc_flat_output_function_epilogue (file, size)
          /* Offset to register save area from %sp.  */
          reg_offset = size1 - reg_offset;
 
-         fprintf (file, "\tset\t%d, %s\n\tadd\t%s, %s, %s\n",
-                  size1, t1_str, sp_str, t1_str, sp_str);
+         fprintf (file, "\tset\t");
+         fprintf (file, HOST_WIDE_INT_PRINT_DEC, size1);
+         fprintf (file, ", %s\n\tadd\t%s, %s, %s\n",
+                  t1_str, sp_str, t1_str, sp_str);
        }
 
       /* We must restore the frame pointer and return address reg first
@@ -6802,13 +6936,13 @@ sparc_flat_output_function_epilogue (file, size)
       if (current_frame_info.gmask & FRAME_POINTER_MASK)
        {
          fprintf (file, "\tld\t[%s+%d], %s\n",
-                  sp_str, reg_offset, fp_str);
+                  sp_str, (int) reg_offset, fp_str);
          reg_offset += 4;
        }
       if (current_frame_info.gmask & RETURN_ADDR_MASK)
        {
          fprintf (file, "\tld\t[%s+%d], %s\n",
-                  sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]);
+                  sp_str, (int) reg_offset, reg_names[RETURN_ADDR_REGNUM]);
          reg_offset += 4;
        }
 
@@ -6824,8 +6958,11 @@ sparc_flat_output_function_epilogue (file, size)
        {
          size -= size1;
          if (size > 4095)
-           fprintf (file, "\tset\t%d, %s\n",
-                    size, t1_str);
+           {
+             fprintf (file, "\tset\t");
+             fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
+             fprintf (file, ", %s\n", t1_str);
+           }
        }
 
       if (current_function_returns_struct)
@@ -6849,7 +6986,7 @@ sparc_flat_output_function_epilogue (file, size)
        fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
 
       else if (size > 0)
-       fprintf (file, "\tadd\t%s, %d, %s\n", sp_str, size, sp_str);
+       fprintf (file, "\tadd\t%s, %d, %s\n", sp_str, (int) size, sp_str);
 
       else
        fprintf (file, "\tnop\n");
@@ -6878,7 +7015,7 @@ sparc_flat_epilogue_delay_slots ()
   return 0;
 }
 
-/* Return true is TRIAL is a valid insn for the epilogue delay slot.
+/* Return true if TRIAL is a valid insn for the epilogue delay slot.
    Any single length instruction which doesn't reference the stack or frame
    pointer is OK.  */
 
@@ -7150,8 +7287,7 @@ ultrasparc_adjust_cost (insn, link, dep_insn, cost)
             or the cycle after an instruction which writes any
             integer register.  Model this as cost 2 for dependent
             instructions.  */
-         if ((dep_type == TYPE_IALU || dep_type == TYPE_UNARY
-              || dep_type == TYPE_BINARY)
+         if (dep_type == TYPE_IALU
              && cost < 2)
            return 2;
          /* Otherwise check as for integer conditional moves. */
@@ -7200,7 +7336,7 @@ ultrasparc_adjust_cost (insn, link, dep_insn, cost)
 #undef SLOW_FP
 }
 
-int
+static int
 sparc_adjust_cost(insn, link, dep, cost)
      rtx insn;
      rtx link;
@@ -7245,7 +7381,7 @@ enum ultra_code { NONE=0, /* no insn at all                               */
 static enum ultra_code ultra_code_from_mask PARAMS ((int));
 static void ultra_schedule_insn PARAMS ((rtx *, rtx *, int, enum ultra_code));
 
-static const char *ultra_code_names[NUM_ULTRA_CODES] = {
+static const char *const ultra_code_names[NUM_ULTRA_CODES] = {
   "NONE", "IEU0", "IEU1", "IEUN", "LSU", "CTI",
   "FPM", "FPA", "SINGLE" };
 
@@ -7292,8 +7428,7 @@ ultra_code_from_mask (type_mask)
                        TMASK (TYPE_SIBCALL) |
                        TMASK (TYPE_UNCOND_BRANCH)))
     return IEU1;
-  else if (type_mask & (TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
-                       TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY)))
+  else if (type_mask & TMASK (TYPE_IALU))
     return IEUN;
   else if (type_mask & (TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
                        TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
@@ -7374,7 +7509,7 @@ ultra_fpmode_conflict_exists (fpmode)
            continue;
 
          /* If it is not FMOV, FABS, FNEG, FDIV, or FSQRT then
-            we will get a stall.  Loads and stores are independant
+            we will get a stall.  Loads and stores are independent
             of these rules.  */
          if (GET_CODE (SET_SRC (pat)) != ABS
              && GET_CODE (SET_SRC (pat)) != NEG
@@ -7465,8 +7600,8 @@ ultra_find_type (type_mask, list, start)
                                  && GET_CODE (SET_SRC (pat)) == SUBREG
                                  && REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
                                       REGNO (SUBREG_REG (SET_SRC (pat)))
-                                 && SUBREG_WORD (SET_DEST (slot_pat)) ==
-                                      SUBREG_WORD (SET_SRC (pat)))))
+                                 && SUBREG_BYTE (SET_DEST (slot_pat)) ==
+                                      SUBREG_BYTE (SET_SRC (pat)))))
                      || (check_fpmode_conflict == 1
                          && GET_CODE (slot_insn) == INSN
                          && GET_CODE (slot_pat) == SET
@@ -7576,26 +7711,34 @@ ultra_flush_pipeline ()
 {
   ultra_cur_hist = (ultra_cur_hist + 1) & (ULTRA_NUM_HIST - 1);
   ultra_cycles_elapsed += 1;
-  bzero ((char *) &ultra_pipe, sizeof ultra_pipe);
+  memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
   ultra_pipe.free_slot_mask = 0xf;
 }
 
 /* Init our data structures for this current block.  */
-void
-ultrasparc_sched_init (dump, sched_verbose)
-     FILE *dump ATTRIBUTE_UNUSED;
-     int sched_verbose ATTRIBUTE_UNUSED;
+static void
+ultrasparc_sched_init ()
 {
-  bzero ((char *) ultra_pipe_hist, sizeof ultra_pipe_hist);
+  memset ((char *) ultra_pipe_hist, 0, sizeof ultra_pipe_hist);
   ultra_cur_hist = 0;
   ultra_cycles_elapsed = 0;
   ultra_pipe.free_slot_mask = 0xf;
 }
 
+static void
+sparc_sched_init (dump, sched_verbose, max_ready)
+     FILE *dump ATTRIBUTE_UNUSED;
+     int sched_verbose ATTRIBUTE_UNUSED;
+     int max_ready ATTRIBUTE_UNUSED;
+{
+  if (sparc_cpu == PROCESSOR_ULTRASPARC)
+    ultrasparc_sched_init ();
+}
+  
 /* INSN has been scheduled, update pipeline commit state
    and return how many instructions are still to be
    scheduled in this group.  */
-int
+static int
 ultrasparc_variable_issue (insn)
      rtx insn;
 {
@@ -7619,6 +7762,19 @@ ultrasparc_variable_issue (insn)
   return left_to_fire;
 }
 
+static int
+sparc_variable_issue (dump, sched_verbose, insn, cim)
+     FILE *dump ATTRIBUTE_UNUSED;
+     int sched_verbose ATTRIBUTE_UNUSED;
+     rtx insn;
+     int cim;
+{
+  if (sparc_cpu == PROCESSOR_ULTRASPARC)
+    return ultrasparc_variable_issue (insn);
+  else
+    return cim - 1;
+}
+
 /* In actual_hazard_this_instance, we may have yanked some
    instructions from the ready list due to conflict cost
    adjustments.  If so, and such an insn was in our pipeline
@@ -7668,7 +7824,7 @@ ultra_rescan_pipeline_state (ready, n_ready)
     }
 }
 
-void
+static void
 ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
      FILE *dump;
      int sched_verbose;
@@ -7749,7 +7905,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
       {
        /* If the pipeline is (still) empty and we have any single
           group insns, get them out now as this is a good time.  */
-       rtx *ip = ultra_find_type ((TMASK (TYPE_RETURN) | TMASK (TYPE_ADDRESS) |
+       rtx *ip = ultra_find_type ((TMASK (TYPE_RETURN) |
                                    TMASK (TYPE_IMUL) | TMASK (TYPE_CMOVE) |
                                    TMASK (TYPE_MULTI) | TMASK (TYPE_MISC)),
                                   ready, this_insn);
@@ -7803,8 +7959,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
     if ((up->free_slot_mask & 0x7) != 0
        && up->num_ieu_insns < 2)
       {
-       rtx *ip = ultra_find_type ((TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
-                                   TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY) |
+       rtx *ip = ultra_find_type ((TMASK (TYPE_IALU) |
                                    (up->contents[IEU1] == 0 ? TMASK (TYPE_COMPARE) : 0)),
                                   ready, this_insn);
        if (ip)
@@ -7825,8 +7980,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
        && up->num_ieu_insns < 2)
       {
        rtx *ip;
-       int tmask = (TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
-                    TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY));
+       int tmask = TMASK (TYPE_IALU);
 
        if (!up->contents[IEU1])
          tmask |= TMASK (TYPE_COMPARE);
@@ -7922,7 +8076,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
       }
     else
       {
-       bzero ((char *) &ultra_pipe, sizeof ultra_pipe);
+       memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
        ultra_pipe.free_slot_mask = 0xf;
       }
   }
@@ -7954,7 +8108,20 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
     }
 }
 
-int                                                           
+static int
+sparc_sched_reorder (dump, sched_verbose, ready, n_readyp, clock)
+     FILE *dump;
+     int sched_verbose;
+     rtx *ready;
+     int *n_readyp;
+     int clock ATTRIBUTE_UNUSED;
+{
+  if (sparc_cpu == PROCESSOR_ULTRASPARC)
+    ultrasparc_sched_reorder (dump, sched_verbose, ready, *n_readyp);
+  return sparc_issue_rate ();
+}
+
+static int                                                           
 sparc_issue_rate ()
 {
   switch (sparc_cpu)
@@ -7975,8 +8142,8 @@ sparc_issue_rate ()
 }
 
 static int
-set_extends(x, insn)
-     rtx x, insn;
+set_extends (insn)
+     rtx insn;
 {
   register rtx pat = PATTERN (insn);
 
@@ -8000,27 +8167,40 @@ set_extends(x, insn)
       return 1;
     case AND:
       {
+       rtx op0 = XEXP (SET_SRC (pat), 0);
        rtx op1 = XEXP (SET_SRC (pat), 1);
        if (GET_CODE (op1) == CONST_INT)
          return INTVAL (op1) >= 0;
-       if (GET_CODE (XEXP (SET_SRC (pat), 0)) == REG
-           && sparc_check_64 (XEXP (SET_SRC (pat), 0), insn) == 1)
-         return 1;
-       if (GET_CODE (op1) == REG
-           && sparc_check_64 ((op1), insn) == 1)
+       if (GET_CODE (op0) != REG)
+         return 0;
+       if (sparc_check_64 (op0, insn) == 1)
          return 1;
+       return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
+      }
+    case IOR:
+    case XOR:
+      {
+       rtx op0 = XEXP (SET_SRC (pat), 0);
+       rtx op1 = XEXP (SET_SRC (pat), 1);
+       if (GET_CODE (op0) != REG || sparc_check_64 (op0, insn) <= 0)
+         return 0;
+       if (GET_CODE (op1) == CONST_INT)
+         return INTVAL (op1) >= 0;
+       return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
       }
     case ASHIFT:
     case LSHIFTRT:
       return GET_MODE (SET_SRC (pat)) == SImode;
       /* Positive integers leave the high bits zero. */
     case CONST_DOUBLE:
-      return ! (CONST_DOUBLE_LOW (x) & 0x80000000);
+      return ! (CONST_DOUBLE_LOW (SET_SRC (pat)) & 0x80000000);
     case CONST_INT:
-      return ! (INTVAL (x) & 0x80000000);
+      return ! (INTVAL (SET_SRC (pat)) & 0x80000000);
     case ASHIFTRT:
     case SIGN_EXTEND:
       return - (GET_MODE (SET_SRC (pat)) == SImode);
+    case REG:
+      return sparc_check_64 (SET_SRC (pat), insn);
     default:
       return 0;
     }
@@ -8142,10 +8322,16 @@ sparc_check_64 (x, insn)
      the single set and return the correct value or fail to recognize
      it and return 0.  */
   int set_once = 0;
+  rtx y = x;
+
+  if (GET_CODE (x) != REG)
+    abort ();
 
-  if (GET_CODE (x) == REG
-      && flag_expensive_optimizations
-      && REG_N_SETS (REGNO (x)) == 1)
+  if (GET_MODE (x) == DImode)
+    y = gen_rtx_REG (SImode, REGNO (x) + WORDS_BIG_ENDIAN);
+
+  if (flag_expensive_optimizations
+      && REG_N_SETS (REGNO (y)) == 1)
     set_once = 1;
 
   if (insn == 0)
@@ -8175,8 +8361,10 @@ sparc_check_64 (x, insn)
            if (GET_CODE (pat) != SET)
              return 0;
            if (rtx_equal_p (x, SET_DEST (pat)))
-             return set_extends (x, insn);
-           if (reg_overlap_mentioned_p (SET_DEST (pat), x))
+             return set_extends (insn);
+           if (y && rtx_equal_p (y, SET_DEST (pat)))
+             return set_extends (insn);
+           if (reg_overlap_mentioned_p (SET_DEST (pat), y))
              return 0;
          }
        }
@@ -8196,21 +8384,21 @@ sparc_v8plus_shift (operands, insn, opcode)
     operands[3] = operands[0];
   if (GET_CODE (operands[1]) == CONST_INT)
     {
-      output_asm_insn ("mov %1,%3", operands);
+      output_asm_insn ("mov\t%1, %3", operands);
     }
   else
     {
-      output_asm_insn ("sllx %H1,32,%3", operands);
+      output_asm_insn ("sllx\t%H1, 32, %3", operands);
       if (sparc_check_64 (operands[1], insn) <= 0)
-       output_asm_insn ("srl %L1,0,%L1", operands);
-      output_asm_insn ("or %L1,%3,%3", operands);
+       output_asm_insn ("srl\t%L1, 0, %L1", operands);
+      output_asm_insn ("or\t%L1, %3, %3", operands);
     }
 
   strcpy(asm_code, opcode);
   if (which_alternative != 2)
-    return strcat (asm_code, " %0,%2,%L0\n\tsrlx %L0,32,%H0");
+    return strcat (asm_code, "\t%0, %2, %L0\n\tsrlx\t%L0, 32, %H0");
   else
-    return strcat (asm_code, " %3,%2,%3\n\tsrlx %3,32,%H0\n\tmov %3,%L0");
+    return strcat (asm_code, "\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0");
 }
 
 
@@ -8247,22 +8435,22 @@ sparc_function_profiler (file, labelno)
   ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
 
   if (! TARGET_ARCH64)
-    fputs ("\tst\t%g2,[%fp-4]\n", file);
+    fputs ("\tst\t%g2, [%fp-4]\n", file);
 
   fputs ("\tsethi\t%hi(", file);
   assemble_name (file, buf);
-  fputs ("),%o0\n", file);
+  fputs ("), %o0\n", file);
 
   fputs ("\tcall\t", file);
   assemble_name (file, MCOUNT_FUNCTION);
   putc ('\n', file);
 
-  fputs ("\t or\t%o0,%lo(", file);
+  fputs ("\t or\t%o0, %lo(", file);
   assemble_name (file, buf);
-  fputs ("),%o0\n", file);
+  fputs ("), %o0\n", file);
 
   if (! TARGET_ARCH64)
-    fputs ("\tld\t[%fp-4],%g2\n", file);
+    fputs ("\tld\t[%fp-4], %g2\n", file);
 }
 
 
@@ -8334,17 +8522,17 @@ sparc_function_block_profiler(file, block_or_label)
     {
       fputs ("\tsethi\t%hi(", file);
       assemble_name (file, LPBX);
-      fputs ("),%o0\n", file);
+      fputs ("), %o0\n", file);
   
-      fprintf (file, "\tsethi\t%%hi(%d),%%o1\n", block_or_label);
+      fprintf (file, "\tsethi\t%%hi(%d), %%o1\n", block_or_label);
 
-      fputs ("\tor\t%o0,%lo(", file);
+      fputs ("\tor\t%o0, %lo(", file);
       assemble_name (file, LPBX);
-      fputs ("),%o0\n", file);
+      fputs ("), %o0\n", file);
   
       fprintf (file, "\tcall\t%s__bb_init_trace_func\n", user_label_prefix);
 
-      fprintf (file, "\t or\t%%o1,%%lo(%d),%%o1\n", block_or_label);
+      fprintf (file, "\t or\t%%o1, %%lo(%d), %%o1\n", block_or_label);
     }
   else if (profile_block_flag != 0)
     {
@@ -8353,11 +8541,11 @@ sparc_function_block_profiler(file, block_or_label)
 
       fputs ("\tsethi\t%hi(", file);
       assemble_name (file, LPBX);
-      fputs ("),%o0\n", file);
+      fputs ("), %o0\n", file);
       
       fputs ("\tld\t[%lo(", file);
       assemble_name (file, LPBX);
-      fputs (")+%o0],%o1\n", file);
+      fputs (")+%o0], %o1\n", file);
 
       fputs ("\ttst\t%o1\n", file);
 
@@ -8374,9 +8562,9 @@ sparc_function_block_profiler(file, block_or_label)
          putc ('\n', file);
        }
 
-      fputs ("\t or\t%o0,%lo(", file);
+      fputs ("\t or\t%o0, %lo(", file);
       assemble_name (file, LPBX);
-      fputs ("),%o0\n", file);
+      fputs ("), %o0\n", file);
 
       fprintf (file, "\tcall\t%s__bb_init_func\n\t nop\n", user_label_prefix);
 
@@ -8461,27 +8649,27 @@ sparc_block_profiler(file, blockno)
     {
       ASM_GENERATE_INTERNAL_LABEL (LPBX, "LPBX", 0);
 
-      fprintf (file, "\tsethi\t%%hi(%s__bb),%%g1\n", user_label_prefix);
-      fprintf (file, "\tsethi\t%%hi(%d),%%g%d\n", blockno, bbreg);
-      fprintf (file, "\tor\t%%g1,%%lo(%s__bb),%%g1\n", user_label_prefix);
-      fprintf (file, "\tor\t%%g%d,%%lo(%d),%%g%d\n", bbreg, blockno, bbreg);
+      fprintf (file, "\tsethi\t%%hi(%s__bb), %%g1\n", user_label_prefix);
+      fprintf (file, "\tsethi\t%%hi(%d), %%g%d\n", blockno, bbreg);
+      fprintf (file, "\tor\t%%g1, %%lo(%s__bb), %%g1\n", user_label_prefix);
+      fprintf (file, "\tor\t%%g%d, %%lo(%d), %%g%d\n", bbreg, blockno, bbreg);
 
-      fprintf (file, "\tst\t%%g%d,[%%g1]\n", bbreg);
+      fprintf (file, "\tst\t%%g%d, [%%g1]\n", bbreg);
 
       fputs ("\tsethi\t%hi(", file);
       assemble_name (file, LPBX);
-      fprintf (file, "),%%g%d\n", bbreg);
+      fprintf (file, "), %%g%d\n", bbreg);
   
-      fputs ("\tor\t%o2,%lo(", file);
+      fputs ("\tor\t%o2, %lo(", file);
       assemble_name (file, LPBX);
-      fprintf (file, "),%%g%d\n", bbreg);
+      fprintf (file, "), %%g%d\n", bbreg);
   
-      fprintf (file, "\tst\t%%g%d,[%%g1+4]\n", bbreg);
-      fprintf (file, "\tmov\t%%o7,%%g%d\n", bbreg);
+      fprintf (file, "\tst\t%%g%d, [%%g1 + 4]\n", bbreg);
+      fprintf (file, "\tmov\t%%o7, %%g%d\n", bbreg);
 
       fprintf (file, "\tcall\t%s__bb_trace_func\n\t nop\n", user_label_prefix);
 
-      fprintf (file, "\tmov\t%%g%d,%%o7\n", bbreg);
+      fprintf (file, "\tmov\t%%g%d, %%o7\n", bbreg);
     }
   else if (profile_block_flag != 0)
     {
@@ -8489,18 +8677,18 @@ sparc_block_profiler(file, blockno)
 
       fputs ("\tsethi\t%hi(", file);
       assemble_name (file, LPBX);
-      fprintf (file, "+%d),%%g1\n", blockno*4);
+      fprintf (file, "+%d), %%g1\n", blockno*4);
 
       fputs ("\tld\t[%g1+%lo(", file);
       assemble_name (file, LPBX);
       if (TARGET_ARCH64 && USE_AS_OFFSETABLE_LO10)
-       fprintf (file, ")+%d],%%g%d\n", blockno*4, bbreg);
+       fprintf (file, ")+%d], %%g%d\n", blockno*4, bbreg);
       else
-       fprintf (file, "+%d)],%%g%d\n", blockno*4, bbreg);
+       fprintf (file, "+%d)], %%g%d\n", blockno*4, bbreg);
 
-      fprintf (file, "\tadd\t%%g%d,1,%%g%d\n", bbreg, bbreg);
+      fprintf (file, "\tadd\t%%g%d, 1, %%g%d\n", bbreg, bbreg);
 
-      fprintf (file, "\tst\t%%g%d,[%%g1+%%lo(", bbreg);
+      fprintf (file, "\tst\t%%g%d, [%%g1+%%lo(", bbreg);
       assemble_name (file, LPBX);
       if (TARGET_ARCH64 && USE_AS_OFFSETABLE_LO10)
        fprintf (file, ")+%d]\n", blockno*4);
@@ -8569,8 +8757,33 @@ sparc_add_gc_roots ()
   ggc_add_rtx_root (&get_pc_symbol, 1);
   ggc_add_rtx_root (&sparc_addr_diff_list, 1);
   ggc_add_rtx_root (&sparc_addr_list, 1);
-  ggc_add_root (ultra_pipe_hist, 
-               sizeof (ultra_pipe_hist) / sizeof (ultra_pipe_hist[0]),
-               sizeof (ultra_pipe_hist[0]),
-               &mark_ultrasparc_pipeline_state);
+  ggc_add_root (ultra_pipe_hist, ARRAY_SIZE (ultra_pipe_hist),
+               sizeof (ultra_pipe_hist[0]), &mark_ultrasparc_pipeline_state);
+}
+
+static void
+sparc_elf_asm_named_section (name, flags)
+     const char *name;
+     unsigned int flags;
+{
+  if (flags & SECTION_MERGE)
+    {
+      /* entsize cannot be expressed in this section attributes
+        encoding style.  */
+      default_elf_asm_named_section (name, flags);
+      return;
+    }
+
+  fprintf (asm_out_file, "\t.section\t\"%s\"", name);
+
+  if (!(flags & SECTION_DEBUG))
+    fputs (",#alloc", asm_out_file);
+  if (flags & SECTION_WRITE)
+    fputs (",#write", asm_out_file);
+  if (flags & SECTION_CODE)
+    fputs (",#execinstr", asm_out_file);
+
+  /* ??? Handle SECTION_BSS.  */
+
+  fputc ('\n', asm_out_file);
 }