Sparc backend rewrite by rth and myself, please
authorDavid S. Miller <davem@pierdol.cobaltmicro.com>
Mon, 10 Aug 1998 05:34:44 +0000 (05:34 +0000)
committerDavid S. Miller <davem@gcc.gnu.org>
Mon, 10 Aug 1998 05:34:44 +0000 (22:34 -0700)
peruse the lengthy ChangeLog for a blow by blow account.

Co-Authored-By: Richard Henderson <rth@cygnus.com>
From-SVN: r21652

gcc/ChangeLog
gcc/config/sparc/sp64-elf.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md
gcc/config/sparc/sysv4.h
gcc/final.c
gcc/reorg.c

index e1a6e38f24874617a0d7d783df2ad6588df8b0e2..edb3dc6392f149e832efb10f38981c3e6f88d1f2 100644 (file)
@@ -1,3 +1,286 @@
+Mon Aug 10 04:28:13 1998  David S. Miller  <davem@pierdol.cobaltmicro.com>
+                         Richard Henderson  <rth@cygnus.com>
+       
+       Rewrite Sparc backend for better code generation and
+       improved sparc64 support.
+       * config/sparc/sp64-elf.h: Set JUMP_TABLES_IN_TEXT_SECTION to
+       zero.
+       * config/sparc/sysv4.h: Likewise.
+       * config/sparc/sparc.c (v8plus_regcmp_p, sparc_operand,
+       move_operand, v8plus_regcmp_op, emit_move_sequence,
+       singlemove_string, doublemove_string, mem_aligned_8,
+       output_move_double, output_move_quad, output_fp_move_double,
+       move_quad_direction, output_fp_move_quad, output_scc_insn):
+       Remove.
+       (small_int_or_double): New predicate.
+       (gen_compare_reg): Remove TARGET_V8PLUS cmpdi_v8plus emission.
+       (legitimize_pic_address): Emit movsi_{high,lo_sum}_pic instead of
+       old pic_{sethi,lo_sum}_si patterns.
+       (mem_min_alignment): New generic function to replace
+       mem_aligned_8, which uses REGNO_POINTER_ALIGN information when
+       available and can test for arbitrary alignments.  All callers
+       changed.
+       (save_regs, restore_regs, build_big_number,
+       output_function_prologue, output_cbranch, output_return,
+       sparc_flat_save_restore, sparc_flat_output_function_prologue,
+       sparc_flat_output_function_epilogue): Prettify
+       insn output.
+       (output_function_epilogue): Likewise and add code to output
+       deferred case vectors.
+       (output_v9branch): Likewise, add new arg INSN and use it to tack
+       on branch prediction settings.  All callers changed.
+       (print_operand): Likewise and output %l44 for LO_SUMs when
+       TARGET_CM_MEDMID.
+       (sparc_splitdi_legitimate): New function to make sure DImode
+       splits can be run properly when !arch64.
+       (sparc_initialize_trampoline, sparc64_initialize_trampoline):
+       Reformat example code in comments.
+       (set_extends): Remove UNSPEC/v8plus_clear_high case.
+       (sparc_addr_diff_list, sparc_addr_list): New statics to keep track
+       of deferred case vectors we need to output.
+       (sparc_defer_case_vector): Record a case vector.
+       (sparc_output_addr_vec, sparc_output_addr_diff_vec,
+       sparc_output_deferred_case_vectors): New functions to output them.
+       (sparc_emit_set_const32): New function to form 32-bit constants in
+       registers when that requires more than one instruction.
+       (safe_constDI, sparc_emit_set_const64_quick1,
+       sparc_emit_set_const64_quick2, sparc_emit_set_const64_longway,
+       analyze_64bit_constant, const64_is_2insns,
+       create_simple_focus_bits, sparc_emit_set_const64): New functions
+       which do the same for 64-bit constants when arch64.
+       (sparc_emit_set_symbolic_const64): New function to emit address
+       loading for all code models on v9.
+       * config/sparc/sparc.h (CONDITIONAL_REGISTER_USAGE): Do not make
+       %g1 fixed when arch64, unfix %g0 when TARGET_LIVE_G0.
+       (ALTER_HARD_SUBREG): Fix thinko, return REGNO + 1 not 1.
+       (SECONDARY_INPUT_RELOAD_CLASS, SECONDARY_OUTPUT_RELOAD_CLASS): Fix
+       inaccuracies in comments, add symbolic and text_segment operands
+       when TARGET_CM_MEDANY and TARGET_CM_EMBMEDANY respectively.  Use
+       GENERAL_REGS in these cases as a temp REG is needed to load these
+       addresses into a register properly.
+       (EXTRA_CONSTRAINT): Document more accurately, remove Q case as it
+       is no longer used.
+       (GO_IF_LEGITIMATE_ADDRESS): Allow TFmode for LO_SUM on v9 since fp
+       quads are guarenteed to have 16-byte alignment.
+       (LEGITIMIZE_ADDRESS): For SYMBOL_REF, CONST, and LABEL_REF use
+       copy_to_suggested_reg instead of explicit LO_SUM and HIGH.
+       (ASM_OUTPUT_ADDR_VEC, ASM_OUTPUT_ADDR_DIFF_VEC): New macros for
+       deferred case vector implementation.
+       (ASM_OUTPUT_ADDR_VEC_ELT): Use fputc to output newline.
+       (ASM_OUTPUT_ADDR_DIFF_ELT): Parenthesize LABEL in macro calls.
+       Generate "internal label - label" instead of "label - 1b".
+       (PRINT_OPERAND_ADDRESS): For LO_SUM use %l44 on TARGET_CM_MEDMID.
+       (PREDICATE_CODES): Remove sparc_operand, move_operand,
+       v8plus_regcmp_op.  Add small_int_or_double, input_operand, and
+       zero_operand.
+       (doublemove_string, output_block_move, output_fp_move_double,
+       output_fp_move_quad, output_move_double, output_move_quad,
+       output_scc_insn, singlemove_string, mem_aligned_8, move_operand,
+       sparc_operand, v8plus_regcmp_op, v8plus_regcmp_p): Remove externs.
+       (sparc_emit_set_const32, sparc_emit_set_const64,
+       sparc_emit_set_symbolic_const64, input_operand, zero_operand,
+       mem_min_alignment, small_int_or_double): Add externs.
+       * config/sparc/sparc.md: Document the many uses of UNSPEC and
+       UNSPEC_VOLATILE in this backend.
+       (define_function_unit ieu): Rename to ieu_unnamed.  Add move and
+       unary to types which execute in it.
+       (define_function_unit ieu_shift): Rename to ieu0.
+       (define_function_unit ieu1): New, executes compare, call, and
+       uncond_branch type insns.
+       (define_function_units for type fdivs, fdivd, fsqrt): These
+       execute in the fpu multiply unit not the adder on UltraSparc.
+       (define_expand cmpdi): Disallow TARGET_V8PLUS.
+       (define_insn cmpsi_insn): Rename to cmpsi_insn_sp32.
+       (define_insn cmpsi_insn_sp64): New, same as sp32 variant except it
+       allows the arith_double_operand predicate and rHI constraint when
+       TARGET_ARCH64.
+       (define_insn cmpdi_sp64, cmpsf_fpe, cmpdf_fpe, cmptf_fpe,
+       cmpsf_fp, cmpdf_fp, cmptf_fp, sltu_insn, neg_sltu_insn,
+       neg_sltu_minux_x, neg_sltu_plus_x, sgeu_insn, neg_sgeu_insn,
+       sltu_plus_x, sltu_plus_x, sltu_plus_x_plus_y, x_minus_sltu,
+       sgeu_plus_x, x_minus_sgeu, movqi_cc_sp64, movhi_cc_sp64,
+       movsi_cc_sp64, movdi_cc_sp64, movsf_cc_sp64, movdf_cc_sp64,
+       movtf_cc_sp64, movqi_cc_reg_sp64, movhi_cc_reg_sp64,
+       movsi_cc_reg_sp64, movdi_cc_reg_sp64, movsf_cc_reg_sp64,
+       movdf_cc_reg_sp64, movtf_cc_reg_sp64, zero_extendhisi2_insn,
+       cmp_siqi_trunc, cmp_siqi_trunc_set, sign_extendhisi2_insn,
+       sign_extendqihi2_insn, sign_extendqisi2_insn,
+       sign_extendqidi2_insn, sign_extendhidi2_insn,
+       extendsfdf2, extendsftf2, extenddftf2, truncdfsf2, trunctfsf2,
+       trunctfdf2, floatsisf2, floatsidf2, floatsitf2, floatdisf2,
+       floatdidf2, floatditf2, fix_truncsfsi2, fix_truncdfsi2,
+       fix_trunctfsi2, fix_truncsfdi2, fix_truncdfdi2, fix_trunctfdi2,
+       adddi3_sp64, addsi3, cmp_ccx_plus, cmp_cc_plus_set, subdi_sp64,
+       subsi3, cmp_minus_ccx, cmp_minus_ccx_set, mulsi3, muldi3,
+       muldi3_v8plus, cmp_mul_set, mulsidi3, mulsidi3_v8plus,
+       const_mulsidi3_v8plus, mulsidi3_sp32, const_mulsidi3,
+       smulsi3_highpart_v8plus, unnamed subreg mult,
+       const_smulsi3_highpart_v8plus, smulsi3_highpart_sp32,
+       const_smulsi3_highpart, umulsidi3_v8plus, umulsidi3_sp32,
+       const_umulsidi3, const_umulsidi3_v8plus, umulsi3_highpart_v8plus,
+       const_umulsi3_highpart_v8plus, umulsi3_highpart_sp32,
+       const_umulsi3_highpart, divsi3, divdi3, cmp_sdiv_cc_set, udivsi3,
+       udivdi3, cmp_udiv_cc_set, smacsi, smacdi, umacdi, anddi3_sp64,
+       andsi3, and_not_di_sp64, and_not_si, iordi3_sp64, iorsi3,
+       or_not_di_sp64, or_not_si, xordi3_sp64, xorsi3, xor_not_di_sp64,
+       xor_not_si, cmp_cc_arith_op, cmp_ccx_arith_op,
+       cmp_cc_arith_op_set, cmp_ccx_arith_op_set, cmp_ccx_xor_not,
+       cmp_cc_xor_not_set, cmp_ccx_xor_not_set, cmp_cc_arith_op_not,
+       cmp_ccx_arith_op_not, cmp_cc_arith_op_not_set,
+       cmp_ccx_arith_op_not_set, negdi2_sp64, cmp_cc_neg, cmp_ccx_neg,
+       cmp_cc_set_neg, cmp_ccx_set_neg, one_cmpldi2_sp64, cmp_cc_not,
+       cmp_ccx_not, cmp_cc_set_not, cmp_ccx_set_not, addtf3, adddf3,
+       addsf3, subtf3, subdf3, subsf3, multf3, muldf3, mulsf3,
+       muldf3_extend, multf3_extend, divtf3, divdf3, divsf3, negtf2,
+       negdf2, negsf2, abstf2, absdf2, abssf2, sqrttf2, sqrtdf2, sqrtsf2,
+       ashlsi3, ashldi3, unnamed DI ashift, cmp_cc_ashift_1,
+       cmp_cc_set_ashift_1, ashrsi3, ashrdi3, unnamed DI ashiftrt,
+       ashrdi3_v8plus, lshrsi3, lshrdi3, unnamed DI lshiftrt,
+       lshrdi3_v8plus, tablejump_sp32, tablejump_sp64, call_address_sp32,
+       call_symbolic_sp32, call_address_sp64, call_symbolic_sp64,
+       call_address_struct_value_sp32, call_symbolic_struct_value_sp32,
+       call_address_untyped_struct_value_sp32,
+       call_symbolic_untyped_struct_value_sp32, call_value_address_sp32,
+       call_value_symbolic_sp32, call_value_address_sp64,
+       call_value_symbolic_sp64, branch_sp32, branch_sp64,
+       flush_register_windows, goto_handler_and_restore,
+       goto_handler_and_restore_v9, goto_handler_and_restore_v9_sp64,
+       flush, all ldd/std peepholes, return_qi, return_hi, return_si,
+       return_addsi, return_di, return_adddi, return_sf, all call+jump
+       peepholes, trap, unnamed trap insns): Prettify output strings.
+       (define_insn anddi3_sp32, and_not_di_sp32, iordi3_sp32,
+       or_not_di_sp32, xordi3_sp32, xor_not_di_sp32, one_cmpldi2):
+       Likewise and force + implement splits for integer cases.
+       (define_insn return_sf_no_fpu): Likewise and allow to match when
+       no-fpu because of our subreg SFmode splits.
+       (define_insn zero_extendqihi2, zero_extendqisi2_insn,
+       zero_extendqidi2_insn, zero_extendhidi2_insn,
+       zero_extendsidi2_insn, sign_extendsidi2_insn): Likewise and use
+       input_operand for second operand.
+       (cmp_minus_cc, cmp_minus_cc_set): Likewise and use
+       reg_or_0_operand for operand 2 so new splits can use it.
+       (cmp_zero_extendqisi2, cmp_zero_extendqisi2_set, cmp_cc_plus,
+       cmp_cc_xor_not): Likewise and don't forget to check TARGET_LIVE_G0
+       too.
+       (cmp_zero_extract, cmp_zero_extract_sp64): Likewise and allow
+       CONST_DOUBLEs for operand 2.
+       (define_insn move_label_di): Likewise and label distance
+       optimization because it no longer works with new deferred case
+       vector scheme.  To be revisited.
+       (define_insn x_minus_y_minus_sltu, x_minus_sltu_plus_y): Likewise
+       and allow reg_or_0_operand and J constraint for second operand.
+       (define_insn jump): Set branch predict taken on V9.
+       (define_insn tablejump): Emit LABEL_REF + PLUS memory address for
+       new deferred case vector scheme.
+       (define_insn pic_tablejump_32, pic_tablejump_64): Remove.
+       (define_insn negdi2_sp32): Force + implement splits.
+       (define_insn negsi2, one_cmplsi2): Rename to negsi2_not_liveg0 and
+       one_cmplsi2_not_liveg0 respectively, and create expander of original
+       names which emit special rtl for TARGET_LIVE_G0.
+       (define_insn cmpdi_v8plus, scc_si, scc_di): Remove.
+       (define_insn seq, sne, slt, sge, sle, sltu, sgeu): Don't do
+       gen_compare_reg, FAIL instead.
+       (define_insn sgtu, sleu): Likewise and check gen_s*() return
+       values when trying to reverse condition codes, if they FAIL then
+       do likewise.
+       (define_insn snesi_zero, neg_snesi_zero, snesi_zero_extend,
+       snedi_zero, neg_snedi_zero, snedi_zero_trunc, seqsi_zero,
+       neg_seqsi_zero, seqsi_zero_extend, seqdi_zero, neg_seqdi_zero,
+       seqdi_zero_trunc, x_plus_i_ne_0, x_minus_i_ne_0, x_plus_i_eq_0,
+       x_minus_i_eq_0): Add new splits to perform these multi-insn cases,
+       set output string to # to indicate they are mandatory splits.
+       (define_insn pic_lo_sum_si, pic_sethi_si, pic_lo_sum_di,
+       pic_sethi_di, move_pic_label_si): Remove.
+       (define_insn movsi_low_sum, movsi_high, movsi_lo_sum_pic,
+       movsi_high_pic, movsi_pic_label_reg): New patterns to take their
+       place.
+       (define_expand movsi_pic_label_ref, define_insn
+       movsi_high_pic_label_ref, movsi_lo_sum_pic_label_ref): New
+       expander and insns to handle PIC label references and deferred
+       case vectors.
+       (define_insn get_pc_via_rdpc): Comment out as it is no longer
+       used.
+       (define_expand movqi, movhi, movsi, movdi, movsf, movdf, movtf):
+       Rewrite to not use emit_move_sequence, make use of new constant
+       formation code, and new splits for all multi-insn cases.
+       (define_insn movqi_insn): Remove sethi case, it can never happen.
+       Use reg_or_zero_operand instead of const0_rtx explicit test,
+       use input_operand instead of move_operand for source, and use
+       general_operand now for dest.
+       (define_insn movhi_insn): Similar but leave sethi case.
+       (define_insn lo_sum_qi, store_qi, store_hi): Remove.
+       (define_insn sethi_hi lo_sum_hi): Rename to movhi_high and
+       movhi_lo_sum respectively, prettify output string.
+       (define_insn movsi_zero_liveg0): New pattern to put zero into a
+       register when needed on TARGET_LIVE_G0.
+       (define_insn movsi_insn): Use general_operand and input_operand
+       for dest and src respectively.  Simplify applicability test.
+       Prettify output strings, and add clr alternative for J
+       constraint.
+       (define_insn movdi_sp32_v9, movdi_sp32, define_splits for
+       deprecated std and reg-reg DI moves): Remove and...
+       (define_insn movdi_insn_sp32, movdi_insn_sp64): Replace with new
+       implementation which uses forced splits for all non-single insn
+       cases.
+       (define_split DI move cases on !arch64): New splits to handle all
+       situations of 64-bit double register DImode on 32bit, and
+       unaligned registers and memory addresses for all subtargets.
+       (define_insn movsf_const_insn, movdf_const_insn, store_sf):
+       Remove.
+       (define_insn movsf_insn, movsf_no_f_insn): Use general_operand and
+       input_operand for dest and src respectively, prettify output
+       strings.
+       (define_insn movdf_insn, movdf_no_e_insn, store_df,
+       movtf_const_insn, movtf_insn, movtf_no_e_insn, store_tf): Remove
+       and...
+       (define_insn movdf_insn_sp32, movdf_no_e_insn_sp32,
+       movdf_insn_sp64, movdf_no_e_insn_sp64, movtf_insn,
+       movtf_no_e_insn_sp32, movtf_insn_hq_sp64, movtf_insn_sp64,
+       movtf_no_e_insn_sp64) Replace with new
+       implementation which uses forced splits for all non-single insn
+       cases.
+       (define_split DF move cases): New splits in similar vein to DI
+       move counterparts.
+       (define_insn sethi_di_medlow, sethi_di_medium_pic,
+       sethi_di_embmedany_data, sethi_di_embmedany_text, sethi_di_sp64,
+       movdi_sp64_insn): Remove old v9 code model and constant loading
+       support insns and..
+       (define_insn pic_lo_sum_di, pic_sethi_di,
+       sethi_di_medlow_embmedany_pic, sethi_di_medlow, losum_di_medlow,
+       seth44, setm44, setl44, sethh, setlm, sethm, setlo,
+       embmedany_sethi, embmedany_losum, embmedany_brsum,
+       embmedany_textuhi, embmedany_texthi, embmedany_textulo,
+       embmedany_textlo, movdi_lo_sum_sp64_cint, movdi_lo_sum_sp64_dbl,
+       movdi_high_sp64_cint, movdi_high_sp64_dbl): Replace with new
+       scheme, using unspecs, secondary reloads, and one to one sparc
+       insn to rtl insn mapping for better scheduling and code gen.
+       (define_expand reload_indi, reload_outdi): Reload helpers for
+       MEDANY and EMBMEDANY symbol address loading cases which require a
+       temporary register.
+       (define_expand movsicc): Remove v8plus_regcmp cases.
+       (define_insn movdi_cc_sp64_trunc, movdi_cc_reg_sp64_trunc,
+       cmp_zero_extendqidi2, cmp_zero_extendqidi2_set, cmp_qidi_trunc,
+       cmp_diqi_trunc_set): New patterns used by some of the new scc
+       splits on arch64.
+       (define_insn xordi3_sp64_dbl): New pattern used for constant
+       formation when crossing from 32-bit targets.
+       (define_insn movsi_cc_reg_v8plus, v8plus_clear_high, and helper
+       split): Remove.
+       (define_insn addx, subx): Make visible and prettify.
+       (define_insn adddi3_insn_sp32): Likewise and force split.
+       (define_insn addx_extend, subx_extend, unnamed): New patterns for
+       64bit scc split usage.
+       (define_insn unnamed plusDI zero_extend, unnamed minusDI
+       zero_extend, subdi3): Force and implement splits.
+       
+       * final.c (final_scan_insn): Don't output labels if target
+       specifies ASM_OUTPUT_ADDR_{DIFF}_VEC.  Do these macro operations
+       instead.
+       
+       * reorg.c (dbr_schedule): When taking on BR_PRED notes at the end,
+       don't forget to walk inside SEQUENCESs too as these are what the
+       delay slot scheduler will create.
+       
 Mon Aug 10 01:21:01 1998  Richard Henderson  <rth@cygnus.com>
 
        * alpha.md (extxl+1,+2): New patterns to work around
index 24828664496c8d5c98a7a01be772f90aa71ca015..a1e4ef0c252ab500db1b01865a4d8e0cfdcc1f69 100644 (file)
@@ -102,9 +102,10 @@ crtbegin.o%s \
 /* The medium/anywhere code model practically requires us to put jump tables
    in the text section as gcc is unable to distinguish LABEL_REF's of jump
    tables from other label refs (when we need to).  */
-/* ??? Revisit this.  */
+/* But we now defer the tables to the end of the function, so we make
+   this 0 to not confuse the branch shortening code.  */
 #undef JUMP_TABLES_IN_TEXT_SECTION
-#define JUMP_TABLES_IN_TEXT_SECTION 1
+#define JUMP_TABLES_IN_TEXT_SECTION 0
 
 /* System V Release 4 uses DWARF debugging info.
    GDB doesn't support 64 bit stabs yet and the desired debug format is DWARF
index da7c257ba94186f547a97afbf0f03b32a292f304..c4411fae5fd3cdb58eb5777f19f44b5560859d73 100644 (file)
@@ -111,6 +111,9 @@ static void build_big_number        PROTO((FILE *, int, char *));
 static int function_arg_slotno PROTO((const CUMULATIVE_ARGS *,
                                       enum machine_mode, tree, int, int,
                                       int *, int *));
+static void sparc_output_addr_vec PROTO((rtx));
+static void sparc_output_addr_diff_vec PROTO((rtx));
+static void sparc_output_deferred_case_vectors PROTO((void));
 
 #ifdef DWARF2_DEBUGGING_INFO
 extern char *dwarf2out_cfi_label ();
@@ -347,14 +350,6 @@ v9_regcmp_p (code)
          || code == LE || code == GT);
 }
 
-/* 32 bit registers are zero extended so only zero/non-zero comparisons
-   work.  */
-int
-v8plus_regcmp_p (code)
-     enum rtx_code code;
-{
-  return (code == EQ || code == NE);
-}
 \f
 /* Operand constraints.  */
 
@@ -636,56 +631,6 @@ reg_or_nonsymb_mem_operand (op, mode)
   return 0;
 }
 
-int
-sparc_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode)
-      || GET_CODE (op) == CONSTANT_P_RTX)
-    return 1;
-  if (GET_CODE (op) == CONST_INT)
-    return SMALL_INT (op);
-  if (GET_MODE (op) != mode)
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) != MEM)
-    return 0;
-
-  op = XEXP (op, 0);
-  if (GET_CODE (op) == LO_SUM)
-    return (GET_CODE (XEXP (op, 0)) == REG
-           && symbolic_operand (XEXP (op, 1), Pmode));
-  return memory_address_p (mode, op);
-}
-
-int
-move_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (mode == DImode && arith_double_operand (op, mode))
-    return 1;
-  if (register_operand (op, mode)
-      || GET_CODE (op) == CONSTANT_P_RTX)
-    return 1;
-  if (GET_CODE (op) == CONST_INT)
-    return SMALL_INT (op) || SPARC_SETHI_P (INTVAL (op));
-
-  if (GET_MODE (op) != mode)
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) != MEM)
-    return 0;
-  op = XEXP (op, 0);
-  if (GET_CODE (op) == LO_SUM)
-    return (register_operand (XEXP (op, 0), Pmode)
-           && CONSTANT_P (XEXP (op, 1)));
-  return memory_address_p (mode, op);
-}
-
 int
 splittable_symbolic_memory_operand (op, mode)
      rtx op;
@@ -775,17 +720,6 @@ v9_regcmp_op (op, mode)
   return v9_regcmp_p (code);
 }
 
-/* ??? Same as eq_or_neq.  */
-int
-v8plus_regcmp_op (op, mode)
-     register rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  enum rtx_code code = GET_CODE (op);
-
-  return (code == EQ || code == NE);
-}
-
 /* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation.  */
 
 int
@@ -963,6 +897,18 @@ small_int (op, mode)
          || GET_CODE (op) == CONSTANT_P_RTX);
 }
 
+int
+small_int_or_double (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))
+         || (GET_CODE (op) == CONST_DOUBLE
+             && CONST_DOUBLE_HIGH (op) == 0
+             && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)))
+         || GET_CODE (op) == CONSTANT_P_RTX);
+}
+
 /* Recognize operand values for the umul instruction.  That instruction sign
    extends immediate values just like all other sparc instructions, but
    interprets the extended result as an unsigned number.  */
@@ -976,7 +922,8 @@ uns_small_int (op, mode)
   /* All allowed constants will fit a CONST_INT.  */
   return ((GET_CODE (op) == CONST_INT
           && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
-              || (INTVAL (op) >= 0xFFFFF000 && INTVAL (op) < 0x100000000L)))
+              || (INTVAL (op) >= 0xFFFFF000
+                   && INTVAL (op) < 0x100000000)))
          || GET_CODE (op) == CONSTANT_P_RTX);
 #else
   return (((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
@@ -1003,1670 +950,1467 @@ clobbered_register (op, mode)
 {
   return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
 }
-\f
-/* X and Y are two things to compare using CODE.  Emit the compare insn and
-   return the rtx for the cc reg in the proper mode.  */
 
-rtx
-gen_compare_reg (code, x, y)
-     enum rtx_code code;
-     rtx x, y;
+/* Return 1 if OP is const0_rtx, used for TARGET_LIVE_G0 insns.  */
+
+int
+zero_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  enum machine_mode mode = SELECT_CC_MODE (code, x, y);
-  rtx cc_reg;
+  return (op == const0_rtx || GET_CODE (op) == CONSTANT_P_RTX);
+}
 
-  /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
-     fcc regs (cse can't tell they're really call clobbered regs and will
-     remove a duplicate comparison even if there is an intervening function
-     call - it will then try to reload the cc reg via an int reg which is why
-     we need the movcc patterns).  It is possible to provide the movcc
-     patterns by using the ldxfsr/stxfsr v9 insns.  I tried it: you need two
-     registers (say %g1,%g5) and it takes about 6 insns.  A better fix would be
-     to tell cse that CCFPE mode registers (even pseudos) are call
-     clobbered.  */
+/* Return 1 if OP is a valid operand for the source of a move insn.  */
 
-  /* ??? This is an experiment.  Rather than making changes to cse which may
-     or may not be easy/clean, we do our own cse.  This is possible because
-     we will generate hard registers.  Cse knows they're call clobbered (it
-     doesn't know the same thing about pseudos). If we guess wrong, no big
-     deal, but if we win, great!  */
+int
+input_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  /* If both modes are non-void they must be the same.  */
+  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+    return 0;
 
-  if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-#if 1 /* experiment */
+  /* Allow any one instruction integer constant, and all CONST_INT
+     variants when we are working in DImode and !arch64.  */
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && GET_CODE (op) == CONST_INT
+      && ((SPARC_SETHI_P (INTVAL (op))
+          && (! TARGET_ARCH64
+              || (INTVAL (op) >= 0)
+              || mode == SImode))
+         || SPARC_SIMM13_P (INTVAL (op))
+         || (mode == DImode
+             && ! TARGET_ARCH64)))
+    return 1;
+
+  /* Always match this.  */
+  if (GET_CODE (op) == CONSTANT_P_RTX)
+    return 1;
+
+  /* If !arch64 and this is a DImode const, allow it so that
+     the splits can be generated.  */
+  if (! TARGET_ARCH64
+      && mode == DImode
+      && GET_CODE (op) == CONST_DOUBLE)
+    return 1;
+
+  if (register_operand (op, mode))
+    return 1;
+
+  /* If this is a SUBREG, look inside so that we handle
+     paradoxical ones.  */
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  /* Check for valid MEM forms.  */
+  if (GET_CODE (op) == MEM)
     {
-      int reg;
-      /* We cycle through the registers to ensure they're all exercised.  */
-      static int next_fcc_reg = 0;
-      /* Previous x,y for each fcc reg.  */
-      static rtx prev_args[4][2];
+      rtx inside = XEXP (op, 0);
 
-      /* Scan prev_args for x,y.  */
-      for (reg = 0; reg < 4; reg++)
-       if (prev_args[reg][0] == x && prev_args[reg][1] == y)
-         break;
-      if (reg == 4)
-       {
-         reg = next_fcc_reg;
-         prev_args[reg][0] = x;
-         prev_args[reg][1] = y;
-         next_fcc_reg = (next_fcc_reg + 1) & 3;
-       }
-      cc_reg = gen_rtx_REG (mode, reg + SPARC_FIRST_V9_FCC_REG);
+      if (GET_CODE (inside) == LO_SUM)
+       return (register_operand (XEXP (inside, 0), Pmode)
+               && CONSTANT_P (XEXP (inside, 1)));
+      return memory_address_p (mode, inside);
     }
-#else
-    cc_reg = gen_reg_rtx (mode);
-#endif /* ! experiment */
-  else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-    cc_reg = gen_rtx_REG (mode, SPARC_FCC_REG);
-  else
-    cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG);
 
-  if (TARGET_V8PLUS && mode == CCXmode)
+  return 0;
+}
+
+\f
+/* We know it can't be done in one insn when we get here,
+   the movsi expander guarentees this.  */
+void
+sparc_emit_set_const32 (op0, op1)
+     rtx op0;
+     rtx op1;
+{
+  enum machine_mode mode = GET_MODE (op0);
+  rtx temp;
+
+  if (GET_CODE (op1) == CONST_INT)
     {
-      emit_insn (gen_cmpdi_v8plus (x, y));
+      int value = INTVAL (op1);
+
+      if (SPARC_SETHI_P (value)
+         || SPARC_SIMM13_P (value))
+       abort ();
     }
+
+  /* Full 2-insn decomposition is needed.  */
+  if (reload_in_progress || reload_completed)
+    temp = op0;
   else
+    temp = gen_reg_rtx (mode);
+
+  emit_insn (gen_rtx_SET (mode,
+                         temp,
+                         gen_rtx_HIGH (mode,
+                                       op1)));
+  emit_insn (gen_rtx_SET (mode,
+                         op0,
+                         gen_rtx_LO_SUM (mode,
+                                         temp,
+                                         op1)));
+}
+
+\f
+/* Sparc-v9 code-model support. */
+void
+sparc_emit_set_symbolic_const64 (op0, op1, temp1)
+     rtx op0;
+     rtx op1;
+     rtx temp1;
+{
+  switch (sparc_cmodel)
     {
-      emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
-                         gen_rtx_COMPARE (mode, x, y)));
-    }
+    case CM_MEDLOW:
+      /* The range spanned by all instructions in the object is less
+        than 2^31 bytes (2GB) and the distance from any instruction
+        to the location of the label _GLOBAL_OFFSET_TABLE_ is less
+        than 2^31 bytes (2GB).
 
-  return cc_reg;
-}
+        The executable must be in the low 4TB of the virtual address
+        space.
 
-/* This function is used for v9 only.
-   CODE is the code for an Scc's comparison.
-   OPERANDS[0] is the target of the Scc insn.
-   OPERANDS[1] is the value we compare against const0_rtx (which hasn't
-   been generated yet).
+        sethi  %hi(symbol), %temp
+        or     %temp, %lo(symbol), %reg  */
+      emit_insn (gen_rtx_SET (DImode, temp1, gen_rtx_HIGH (DImode, op1)));
+      emit_insn (gen_rtx_SET (DImode, op0, gen_rtx_LO_SUM (DImode, temp1, op1)));
+      break;
 
-   This function is needed to turn
+    case CM_MEDMID:
+      /* The range spanned by all instructions in the object is less
+        than 2^31 bytes (2GB) and the distance from any instruction
+        to the location of the label _GLOBAL_OFFSET_TABLE_ is less
+        than 2^31 bytes (2GB).
+
+        The executable must be in the low 16TB of the virtual address
+        space.
+
+        sethi  %h44(symbol), %temp1
+        or     %temp1, %m44(symbol), %temp2
+        sllx   %temp2, 12, %temp3
+        or     %temp3, %l44(symbol), %reg  */
+      emit_insn (gen_seth44 (op0, op1));
+      emit_insn (gen_setm44 (op0, op0, op1));
+      emit_insn (gen_rtx_SET (DImode, temp1,
+                             gen_rtx_ASHIFT (DImode, op0, GEN_INT (12))));
+      emit_insn (gen_setl44 (op0, temp1, op1));
+      break;
 
-          (set (reg:SI 110)
-              (gt (reg:CCX 100 %icc)
-                  (const_int 0)))
-   into
-          (set (reg:SI 110)
-              (gt:DI (reg:CCX 100 %icc)
-                  (const_int 0)))
+    case CM_MEDANY:
+      /* The range spanned by all instructions in the object is less
+        than 2^31 bytes (2GB) and the distance from any instruction
+        to the location of the label _GLOBAL_OFFSET_TABLE_ is less
+        than 2^31 bytes (2GB).
+
+        The executable can be placed anywhere in the virtual address
+        space.
+
+        sethi  %hh(symbol), %temp1
+        sethi  %lm(symbol), %temp2
+        or     %temp1, %hm(symbol), %temp3
+        or     %temp2, %lo(symbol), %temp4
+        sllx   %temp3, 32, %temp5
+        or     %temp4, %temp5, %reg  */
+
+      /* Getting this right wrt. reloading is really tricky.
+        We _MUST_ have a seperate temporary at this point,
+        if we don't barf immediately instead of generating
+        incorrect code.  */
+      if (temp1 == op0)
+       abort ();
 
-   IE: The instruction recognizer needs to see the mode of the comparison to
-   find the right instruction. We could use "gt:DI" right in the
-   define_expand, but leaving it out allows us to handle DI, SI, etc.
+      emit_insn (gen_sethh (op0, op1));
+      emit_insn (gen_setlm (temp1, op1));
+      emit_insn (gen_sethm (op0, op0, op1));
+      emit_insn (gen_rtx_SET (DImode, op0,
+                             gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
+      emit_insn (gen_rtx_SET (DImode, op0,
+                             gen_rtx_PLUS (DImode, op0, temp1)));
+      emit_insn (gen_setlo (op0, op0, op1));
+      break;
 
-   We refer to the global sparc compare operands sparc_compare_op0 and
-   sparc_compare_op1.  */
+    case CM_EMBMEDANY:
+      /* Old old old backwards compatibility kruft here.
+        Essentially it is MEDLOW with a fixed 64-bit
+        virtual base added to all data segment addresses.
+        Text-segment stuff is computed like MEDANY, we can't
+        reuse the code above because the relocation knobs
+        look different.
+
+        Data segment:  sethi   %hi(symbol), %temp1
+                       or      %temp1, %lo(symbol), %temp2
+                       add     %temp2, EMBMEDANY_BASE_REG, %reg
+
+        Text segment:  sethi   %uhi(symbol), %temp1
+                       sethi   %hi(symbol), %temp2
+                       or      %temp1, %ulo(symbol), %temp3
+                       or      %temp2, %lo(symbol), %temp4
+                       sllx    %temp3, 32, %temp5
+                       or      %temp4, %temp5, %reg  */
+      if (data_segment_operand (op1, GET_MODE (op1)))
+       {
+         emit_insn (gen_embmedany_sethi (temp1, op1));
+         emit_insn (gen_embmedany_brsum (op0, temp1));
+         emit_insn (gen_embmedany_losum (op0, op0, op1));
+       }
+      else
+       {
+         /* Getting this right wrt. reloading is really tricky.
+            We _MUST_ have a seperate temporary at this point,
+            if we don't barf immediately instead of generating
+            incorrect code.  */
+         if (temp1 == op0)
+           abort ();
 
-int
-gen_v9_scc (compare_code, operands)
-     enum rtx_code compare_code;
-     register rtx *operands;
+         emit_insn (gen_embmedany_textuhi (op0, op1));
+         emit_insn (gen_embmedany_texthi  (temp1, op1));
+         emit_insn (gen_embmedany_textulo (op0, op0, op1));
+         emit_insn (gen_rtx_SET (DImode, op0,
+                                 gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
+         emit_insn (gen_rtx_SET (DImode, op0,
+                                 gen_rtx_PLUS (DImode, op0, temp1)));
+         emit_insn (gen_embmedany_textlo  (op0, op0, op1));
+       }
+      break;
+
+    default:
+      abort();
+    }
+}
+
+/* This avoids problems when cross compiling. */
+static rtx
+safe_constDI(val)
+     HOST_WIDE_INT val;
 {
-  rtx temp, op0, op1;
+#if HOST_BITS_PER_WIDE_INT != 64
+  if (val & 0x80000000)
+    return immed_double_const (val, 0, DImode);
+  else
+#endif
+    return GEN_INT (val);
+}
 
-  if (! TARGET_ARCH64
-      && (GET_MODE (sparc_compare_op0) == DImode
-         || GET_MODE (operands[0]) == DImode))
-    return 0;
+/* Worker routines for 64-bit constant formation on arch64.
+   One of the key things to be doing in these emissions is
+   to create as many temp REGs as possible.  This makes it
+   possible for half-built constants to be used later when
+   such values are similar to something required later on.
+   Without doing this, the optimizer cannot see such
+   opportunities.  */
+static void
+sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
+  rtx op0;
+  rtx temp;
+  unsigned int low_bits;
+  int is_neg;
+{
+  unsigned int high_bits;
 
-  /* Handle the case where operands[0] == sparc_compare_op0.
-     We "early clobber" the result.  */
-  if (REGNO (operands[0]) == REGNO (sparc_compare_op0))
-    {
-      op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
-      emit_move_insn (op0, sparc_compare_op0);
-    }
+  if (is_neg)
+    high_bits = ~low_bits;
   else
-    op0 = sparc_compare_op0;
-  /* For consistency in the following.  */
-  op1 = sparc_compare_op1;
+    high_bits = low_bits;
 
-  /* Try to use the movrCC insns.  */
-  if (TARGET_ARCH64
-      && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-      && op1 == const0_rtx
-      && v9_regcmp_p (compare_code))
+  emit_insn (gen_rtx_SET (DImode, temp,
+                         gen_rtx_HIGH (DImode,
+                                       safe_constDI (high_bits))));
+  if (!is_neg)
     {
-      /* Special case for op0 != 0.  This can be done with one instruction if
-        operands[0] == sparc_compare_op0.  We don't assume they are equal
-        now though.  */
+      emit_insn (gen_rtx_SET (DImode, op0,
+                             gen_rtx_LO_SUM (DImode, temp,
+                                             safe_constDI (high_bits))));
+    }
+  else
+    { /* as opposed to, say, tricky dick... */
+      rtx tricky_bits = safe_constDI (-0x400 | (low_bits & 0x3ff));
+      emit_insn (gen_rtx_SET (DImode, op0,
+                             gen_rtx_XOR (DImode, temp, tricky_bits)));
+    }
+}
 
-      if (compare_code == NE
-         && GET_MODE (operands[0]) == DImode
-         && GET_MODE (op0) == DImode)
-       {
-         emit_insn (gen_rtx_SET (VOIDmode, operands[0], op0));
-         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                             gen_rtx_IF_THEN_ELSE (DImode,
-                                      gen_rtx_fmt_ee (compare_code, DImode,
-                                                      op0, const0_rtx),
-                                      const1_rtx,
-                                      operands[0])));
-         return 1;
-       }
+static void
+sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count)
+  rtx op0;
+  rtx temp;
+  unsigned int high_bits;
+  unsigned int low_immediate;
+  int shift_count;
+{
+  rtx temp2 = op0;
 
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
-      if (GET_MODE (op0) != DImode)
-       {
-         temp = gen_reg_rtx (DImode);
-         convert_move (temp, op0, 0);
-       }
+  if ((high_bits & 0xfffffc00) != 0)
+    {
+      emit_insn (gen_rtx_SET (DImode, temp,
+                             gen_rtx_HIGH (DImode,
+                                           safe_constDI (high_bits))));
+      if ((high_bits & ~0xfffffc00) != 0)
+       emit_insn (gen_rtx_SET (DImode, op0,
+                               gen_rtx_LO_SUM (DImode, temp,
+                                               safe_constDI (high_bits))));
       else
-       temp = op0;
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                         gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
-                                  gen_rtx_fmt_ee (compare_code, DImode,
-                                                  temp, const0_rtx),
-                                  const1_rtx,
-                                  operands[0])));
-      return 1;
+       temp2 = temp;
     }
   else
     {
-      operands[1] = gen_compare_reg (compare_code, op0, op1);
+      emit_insn (gen_rtx_SET (DImode, temp, safe_constDI (high_bits)));
+      temp2 = temp;
+    }
 
-      switch (GET_MODE (operands[1]))
-       {
-         case CCmode :
-         case CCXmode :
-         case CCFPEmode :
-         case CCFPmode :
-           break;
-         default :
-           abort ();
-       }
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                         gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
-                                  gen_rtx_fmt_ee (compare_code,
-                                                  GET_MODE (operands[1]),
-                                                  operands[1], const0_rtx),
-                                   const1_rtx, operands[0])));
-      return 1;
-    }
-}
-
-/* Emit a conditional jump insn for the v9 architecture using comparison code
-   CODE and jump target LABEL.
-   This function exists to take advantage of the v9 brxx insns.  */
+  /* Now shift it up into place. */
+  emit_insn (gen_rtx_SET (DImode, op0,
+                         gen_rtx_ASHIFT (DImode, temp2,
+                                         GEN_INT (shift_count))));
 
-void
-emit_v9_brxx_insn (code, op0, label)
-     enum rtx_code code;
-     rtx op0, label;
-{
-  emit_jump_insn (gen_rtx_SET (VOIDmode,
-                          pc_rtx,
-                          gen_rtx_IF_THEN_ELSE (VOIDmode,
-                                   gen_rtx_fmt_ee (code, GET_MODE (op0),
-                                                   op0, const0_rtx),
-                                   gen_rtx_LABEL_REF (VOIDmode, label),
-                                   pc_rtx)));
-}
-\f
-/* Return nonzero if a return peephole merging return with
-   setting of output register is ok.  */
-int
-leaf_return_peephole_ok ()
-{
-  return (actual_fsize == 0);
+  /* If there is a low immediate part piece, finish up by
+     putting that in as well.  */
+  if (low_immediate != 0)
+    emit_insn (gen_rtx_SET (DImode, op0,
+                           gen_rtx_IOR (DImode, op0,
+                                        safe_constDI (low_immediate & 0x3ff))));
 }
 
-/* Return nonzero if TRIAL can go into the function epilogue's
-   delay slot.  SLOT is the slot we are trying to fill.  */
-
-int
-eligible_for_epilogue_delay (trial, slot)
-     rtx trial;
-     int slot;
+/* Full 64-bit constant decomposition.  Even though this is the
+   'worst' case, we still optimize a few things away.  */
+static void
+sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits)
+     rtx op0;
+     rtx temp;
+     unsigned int high_bits;
+     unsigned int low_bits;
 {
-  rtx pat, src;
-
-  if (slot >= 1)
-    return 0;
-
-  if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
-    return 0;
+  rtx sub_temp;
 
-  if (get_attr_length (trial) != 1)
-    return 0;
-
-  /* If %g0 is live, there are lots of things we can't handle.
-     Rather than trying to find them all now, let's punt and only
-     optimize things as necessary.  */
-  if (TARGET_LIVE_G0)
-    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.  */
-  if (leaf_function)
+  if (reload_in_progress || reload_completed)
+    sub_temp = op0;
+  else
+    sub_temp = gen_reg_rtx (DImode);
+
+  if ((high_bits & 0xfffffc00) != 0)
+    {
+      emit_insn (gen_rtx_SET (DImode,
+                             temp,
+                             gen_rtx_HIGH (DImode,
+                                           safe_constDI (high_bits))));
+      if ((high_bits & ~0xfffffc00) != 0)
+       emit_insn (gen_rtx_SET (DImode,
+                               sub_temp,
+                               gen_rtx_LO_SUM (DImode, temp,
+                                               safe_constDI (high_bits))));
+      else
+       sub_temp = temp;
+    }
+  else
     {
-      if (leaf_return_peephole_ok ())
-       return ((get_attr_in_uncond_branch_delay (trial)
-                == IN_BRANCH_DELAY_TRUE));
-      return 0;
+      emit_insn (gen_rtx_SET (DImode, temp, safe_constDI (high_bits)));
+      sub_temp = temp;
     }
 
-  /* If only trivial `restore' insns work, nothing can go in the
-     delay slot.  */
-  else if (TARGET_BROKEN_SAVERESTORE)
-    return 0;
-
-  pat = PATTERN (trial);
-
-  /* Otherwise, only operations which can be done in tandem with
-     a `restore' insn can go into the delay slot.  */
-  if (GET_CODE (SET_DEST (pat)) != REG
-      || REGNO (SET_DEST (pat)) >= 32
-      || REGNO (SET_DEST (pat)) < 24)
-    return 0;
-
-  /* The set of insns matched here must agree precisely with the set of
-     patterns paired with a RETURN in sparc.md.  */
-
-  src = SET_SRC (pat);
-
-  /* This matches "*return_[qhs]i".  */
-  if (arith_operand (src, GET_MODE (src)))
-    return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
-    
-  /* This matches "*return_di".  */
-  else if (arith_double_operand (src, GET_MODE (src)))
-    return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
-
-  /* This matches "*return_sf_no_fpu".  */
-  else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
-          && register_operand (src, SFmode))
-    return 1;
-
-  /* This matches "*return_addsi".  */
-  else if (GET_CODE (src) == PLUS
-          && arith_operand (XEXP (src, 0), SImode)
-          && arith_operand (XEXP (src, 1), SImode)
-          && (register_operand (XEXP (src, 0), SImode)
-              || register_operand (XEXP (src, 1), SImode)))
-    return 1;
-
-  /* This matches "*return_adddi".  */
-  else if (GET_CODE (src) == PLUS
-          && arith_double_operand (XEXP (src, 0), DImode)
-          && arith_double_operand (XEXP (src, 1), DImode)
-          && (register_operand (XEXP (src, 0), DImode)
-              || register_operand (XEXP (src, 1), DImode)))
-    return 1;
-
-  return 0;
-}
-
-static int
-check_return_regs (x)
-     rtx x;
-{
-  switch (GET_CODE (x))
+  if (!reload_in_progress && !reload_completed)
     {
-    case REG:
-      return IN_OR_GLOBAL_P (x);
+      rtx temp2 = gen_reg_rtx (DImode);
+      rtx temp3 = gen_reg_rtx (DImode);
+      rtx temp4 = gen_reg_rtx (DImode);
 
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST:
-    case SYMBOL_REF:
-    case LABEL_REF:
-    return 1;
+      emit_insn (gen_rtx_SET (DImode, temp4,
+                             gen_rtx_ASHIFT (DImode, sub_temp,
+                                             GEN_INT (32))));
 
-    case SET:
-    case IOR:
-    case AND:
-    case XOR:
-    case PLUS:
-    case MINUS:
-      if (check_return_regs (XEXP (x, 1)) == 0)
-  return 0;
-    case NOT:
-    case NEG:
-    case MEM:
-      return check_return_regs (XEXP (x, 0));
-      
-    default:
-      return 0;
+      /* Be careful, we must mask the bits here because otherwise
+        on a 32-bit host the optimizer will think we're putting
+        something like "-1" here and optimize it away.  */
+      emit_insn (gen_rtx_SET (DImode, temp2,
+                             gen_rtx_HIGH (DImode,
+                                           safe_constDI (low_bits))));
+      if ((low_bits & ~0xfffffc00) != 0)
+       emit_insn (gen_rtx_SET (DImode, temp3,
+                               gen_rtx_LO_SUM (DImode, temp2,
+                                               safe_constDI (low_bits))));
+      emit_insn (gen_rtx_SET (DImode, op0,
+                             gen_rtx_PLUS (DImode, temp4, temp3)));
     }
+  else
+    {
+      rtx low1 = safe_constDI ((low_bits >> (32 - 12))          & 0xfff);
+      rtx low2 = safe_constDI ((low_bits >> (32 - 12 - 12))     & 0xfff);
+      rtx low3 = safe_constDI ((low_bits >> (32 - 12 - 12 - 8)) & 0x0ff);
+      int to_shift = 12;
 
+      /* We are in the middle of reload, so this is really
+        painful.  However we do still make an attempt to
+        avoid emmitting truly stupid code.  */
+      if (low1 != const0_rtx)
+       {
+         emit_insn (gen_rtx_SET (DImode, op0,
+                                 gen_rtx_ASHIFT (DImode, sub_temp,
+                                                 GEN_INT(to_shift))));
+         emit_insn (gen_rtx_SET (DImode, op0,
+                                 gen_rtx_IOR (DImode, op0, low1)));
+         sub_temp = op0;
+         to_shift = 12;
+       }
+      else
+       {
+         to_shift += 12;
+       }
+      if (low2 != const0_rtx)
+       {
+         emit_insn (gen_rtx_SET (DImode, op0,
+                                 gen_rtx_ASHIFT (DImode, sub_temp,
+                                                 GEN_INT (to_shift))));
+         emit_insn (gen_rtx_SET (DImode, op0,
+                                 gen_rtx_IOR (DImode, op0, low2)));
+         sub_temp = op0;
+         to_shift = 8;
+       }
+      else
+       {
+         to_shift += 8;
+       }
+      emit_insn (gen_rtx_SET (DImode, op0,
+                             gen_rtx_ASHIFT (DImode, sub_temp,
+                                             GEN_INT (to_shift))));
+      if (low3 != const0_rtx)
+       emit_insn (gen_rtx_SET (DImode, op0,
+                               gen_rtx_IOR (DImode, op0, low3)));
+      /* phew... */
+    }
 }
 
-/* Return 1 if TRIAL references only in and global registers.  */
-int
-eligible_for_return_delay (trial)
-     rtx trial;
-{
-  if (GET_CODE (PATTERN (trial)) != SET)
-    return 0;
-
-  return check_return_regs (PATTERN (trial));
-}
-
-int
-short_branch (uid1, uid2)
-     int uid1, uid2;
-{
-  unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];
-  if (delta + 1024 < 2048)
-    return 1;
-  /* warning ("long branch, distance %d", delta); */
-  return 0;
-}
-
-/* Return non-zero if REG is not used after INSN.
-   We assume REG is a reload reg, and therefore does
-   not live past labels or calls or jumps.  */
-int
-reg_unused_after (reg, insn)
-     rtx reg;
-     rtx insn;
+/* Analyze a 64-bit constant for certain properties. */
+static void
+analyze_64bit_constant (high_bits, low_bits, hbsp, lbsp, abbasp)
+     unsigned int high_bits, low_bits;
+     int *hbsp, *lbsp, *abbasp;
 {
-  enum rtx_code code, prev_code = UNKNOWN;
+  int lowest_bit_set, highest_bit_set, all_bits_between_are_set;
+  int i;
 
-  while ((insn = NEXT_INSN (insn)))
+  lowest_bit_set = highest_bit_set = -1;
+  i = 0;
+  do
     {
-      if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
-       return 1;
-
-      code = GET_CODE (insn);
-      if (GET_CODE (insn) == CODE_LABEL)
-       return 1;
-
-      if (GET_RTX_CLASS (code) == 'i')
+      if ((lowest_bit_set == -1)
+         && ((low_bits >> i) & 1))
+       lowest_bit_set = i;
+      if ((highest_bit_set == -1)
+         && ((high_bits >> (32 - i - 1)) & 1))
+       highest_bit_set = (64 - i - 1);
+    }
+  while (++i < 32
+        && ((highest_bit_set == -1)
+            || (lowest_bit_set == -1)));
+  if (i == 32)
+    {
+      i = 0;
+      do
        {
-         rtx set = single_set (insn);
-         int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
-         if (set && in_src)
-           return 0;
-         if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
-           return 1;
-         if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
-           return 0;
+         if ((lowest_bit_set == -1)
+             && ((high_bits >> i) & 1))
+           lowest_bit_set = i + 32;
+         if ((highest_bit_set == -1)
+             && ((low_bits >> (32 - i - 1)) & 1))
+           highest_bit_set = 32 - i - 1;
        }
-      prev_code = code;
+      while (++i < 32
+            && ((highest_bit_set == -1)
+                || (lowest_bit_set == -1)));
+    }
+  /* If there are no bits set this should have gone out
+     as one instruction!  */
+  if (lowest_bit_set == -1
+      || highest_bit_set == -1)
+    abort();
+  all_bits_between_are_set = 1;
+  for (i = lowest_bit_set; i <= highest_bit_set; i++)
+    {
+      if (i < 32)
+       {
+         if ((low_bits & (1 << i)) != 0)
+           continue;
+       }
+      else
+       {
+         if ((high_bits & (1 << (i - 32))) != 0)
+           continue;
+       }
+      all_bits_between_are_set = 0;
+      break;
     }
-  return 1;
+  *hbsp = highest_bit_set;
+  *lbsp = lowest_bit_set;
+  *abbasp = all_bits_between_are_set;
 }
-\f
-/* The table we use to reference PIC data.  */
-static rtx global_offset_table;
 
-/* The function we use to get at it.  */
-static rtx get_pc_symbol;
-static char get_pc_symbol_name[256];
+static int
+const64_is_2insns (high_bits, low_bits)
+     unsigned int high_bits, low_bits;
+{
+  int highest_bit_set, lowest_bit_set, all_bits_between_are_set;
 
-/* Ensure that we are not using patterns that are not OK with PIC.  */
+  if (high_bits == 0
+      || high_bits == -1)
+    return 1;
 
-int
-check_pic (i)
-     int i;
-{
-  switch (flag_pic)
-    {
-    case 1:
-      if (GET_CODE (recog_operand[i]) == SYMBOL_REF
-         || (GET_CODE (recog_operand[i]) == CONST
-             && ! (GET_CODE (XEXP (recog_operand[i], 0)) == MINUS
-                   && (XEXP (XEXP (recog_operand[i], 0), 0)
-                       == global_offset_table)
-                   && (GET_CODE (XEXP (XEXP (recog_operand[i], 0), 1))
-                       == CONST))))
-       abort ();
-    case 2:
-    default:
-      return 1;
-    }
-}
+  analyze_64bit_constant (high_bits, low_bits,
+                         &highest_bit_set, &lowest_bit_set,
+                         &all_bits_between_are_set);
 
-/* Return true if X is an address which needs a temporary register when 
-   reloaded while generating PIC code.  */
+  if (highest_bit_set == 63
+      && all_bits_between_are_set != 0)
+    return 1;
 
-int
-pic_address_needs_scratch (x)
-     rtx x;
-{
-  /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
-  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
-      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-      && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
+  if ((highest_bit_set - lowest_bit_set) < 22)
     return 1;
 
   return 0;
 }
 
-/* Legitimize PIC addresses.  If the address is already position-independent,
-   we return ORIG.  Newly generated position-independent addresses go into a
-   reg.  This is REG if non zero, otherwise we allocate register(s) as
-   necessary.  */
-
-rtx
-legitimize_pic_address (orig, mode, reg)
-     rtx orig;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     rtx reg;
+static unsigned int
+create_simple_focus_bits (high_bits, low_bits, highest_bit_set, lowest_bit_set, shift)
+     unsigned int high_bits, low_bits;
+     int highest_bit_set, lowest_bit_set, shift;
 {
-  if (GET_CODE (orig) == SYMBOL_REF)
-    {
-      rtx pic_ref, address;
-      rtx insn;
+  unsigned int hi, lo;
 
-      if (reg == 0)
-       {
-         if (reload_in_progress || reload_completed)
-           abort ();
-         else
-           reg = gen_reg_rtx (Pmode);
-       }
+  if (lowest_bit_set < 32)
+    {
+      lo = (low_bits >> lowest_bit_set) << shift;
+      hi = ((high_bits << (32 - lowest_bit_set)) << shift);
+    }
+  else
+    {
+      lo = 0;
+      hi = ((high_bits >> (lowest_bit_set - 32)) << shift);
+    }
+  if (hi & lo)
+    abort();
+  return (hi | lo);
+}
 
-      if (flag_pic == 2)
-       {
-         /* If not during reload, allocate another temp reg here for loading
-            in the address, so that these instructions can be optimized
-            properly.  */
-         rtx temp_reg = ((reload_in_progress || reload_completed)
-                         ? reg : gen_reg_rtx (Pmode));
+/* Here we are sure to be arch64 and this is an integer constant
+   being loaded into a register.  Emit the most efficient
+   insn sequence possible.  Detection of all the 1-insn cases
+   has been done already.  */
+void
+sparc_emit_set_const64 (op0, op1)
+     rtx op0;
+     rtx op1;
+{
+  unsigned int high_bits, low_bits;
+  int lowest_bit_set, highest_bit_set;
+  int all_bits_between_are_set;
+  int i;
+  rtx temp;
 
-         /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
-            won't get confused into thinking that these two instructions
-            are loading in the true address of the symbol.  If in the
-            future a PIC rtx exists, that should be used instead.  */
-         emit_insn (gen_pic_sethi_si (temp_reg, orig));
-         emit_insn (gen_pic_lo_sum_si (temp_reg, temp_reg, orig));
+  /* 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))
+    abort();
 
-         address = temp_reg;
-       }
+  if (GET_CODE (op1) != CONST_DOUBLE
+      && GET_CODE (op1) != CONST_INT)
+    {
+      if (reload_in_progress || reload_completed)
+       temp = op0;
       else
-       address = orig;
+       temp = gen_reg_rtx (DImode);
+      return sparc_emit_set_symbolic_const64 (op0, op1, temp);
+    }
 
-      pic_ref = gen_rtx_MEM (Pmode,
-                        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);
-      /* Put a REG_EQUAL note on this insn, so that it can be optimized
-        by loop.  */
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
-                                 REG_NOTES (insn));
-      return reg;
+  if (GET_CODE (op1) == CONST_DOUBLE)
+    {
+#if HOST_BITS_PER_WIDE_INT == 64
+      high_bits = CONST_DOUBLE_LOW (op1) >> 32;
+      low_bits  = CONST_DOUBLE_LOW (op1) & 0xffffffff;
+#else
+      high_bits = CONST_DOUBLE_HIGH (op1);
+      low_bits = CONST_DOUBLE_LOW (op1);
+#endif
     }
-  else if (GET_CODE (orig) == CONST)
+  else
     {
-      rtx base, offset;
+#if HOST_BITS_PER_WIDE_INT == 64
+      high_bits = (INTVAL (op1) >> 32);
+      low_bits = (INTVAL (op1) & 0xffffffff);
+#else
+      high_bits = ((INTVAL (op1) < 0) ?
+                  0xffffffff :
+                  0x00000000);
+      low_bits = INTVAL (op1);
+#endif
+    }
 
-      if (GET_CODE (XEXP (orig, 0)) == PLUS
-         && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
-       return orig;
+  /* low_bits  bits 0  --> 31
+     high_bits bits 32 --> 63  */
 
-      if (reg == 0)
+  if (reload_in_progress || reload_completed)
+    temp = op0;
+  else
+    temp = gen_reg_rtx (DImode);
+
+  analyze_64bit_constant (high_bits, low_bits,
+                         &highest_bit_set, &lowest_bit_set,
+                         &all_bits_between_are_set);
+
+  /* First try for a 2-insn sequence.  */
+
+  /* These situations are preferred because the optimizer can
+   * do more things with them:
+   * 1) mov    -1, %reg
+   *    sllx   %reg, shift, %reg
+   * 2) mov    -1, %reg
+   *    srlx   %reg, shift, %reg
+   * 3) mov    some_small_const, %reg
+   *    sllx   %reg, shift, %reg
+   */
+  if (((highest_bit_set == 63
+       || lowest_bit_set == 0)
+       && all_bits_between_are_set != 0)
+      || ((highest_bit_set - lowest_bit_set) < 13))
+    {
+      rtx the_const = constm1_rtx;
+      int shift = lowest_bit_set;
+
+      if (highest_bit_set == lowest_bit_set)
        {
-         if (reload_in_progress || reload_completed)
+         /* There is no way to get here like this, because this case
+            can be done in one instruction.  */
+         if (lowest_bit_set < 32)
            abort ();
-         else
-           reg = gen_reg_rtx (Pmode);
+         the_const = const1_rtx;
        }
-
-      if (GET_CODE (XEXP (orig, 0)) == PLUS)
+      else if (all_bits_between_are_set == 0)
        {
-         base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
-         offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
-                                        base == reg ? 0 : reg);
+         the_const =
+           safe_constDI (create_simple_focus_bits (high_bits, low_bits,
+                                                   highest_bit_set,
+                                                   lowest_bit_set, 0));
        }
+      else if (lowest_bit_set == 0)
+       shift = -(64 - highest_bit_set);
+      emit_insn (gen_rtx_SET (DImode, temp, the_const));
+
+      if (shift > 0)
+       emit_insn (gen_rtx_SET (DImode,
+                               op0,
+                               gen_rtx_ASHIFT (DImode,
+                                               temp,
+                                               GEN_INT (shift))));
+      else if (shift < 0)
+       emit_insn (gen_rtx_SET (DImode,
+                               op0,
+                               gen_rtx_ASHIFTRT (DImode,
+                                                 temp,
+                                                 GEN_INT (-shift))));
       else
        abort ();
+      return;
+    }
 
-      if (GET_CODE (offset) == CONST_INT)
+  /* Now a range of 22 or less bits set somewhere.
+   * 1) sethi  %hi(focus_bits), %reg
+   *    sllx   %reg, shift, %reg
+   * 2) sethi  %hi(focus_bits), %reg
+   *    srlx   %reg, shift, %reg
+   */
+  if ((highest_bit_set - lowest_bit_set) < 22)
+    {
+      unsigned int focus_bits =
+       create_simple_focus_bits (high_bits, low_bits,
+                                 highest_bit_set, lowest_bit_set, 10);
+      emit_insn (gen_rtx_SET (DImode,
+                             temp,
+                             gen_rtx_HIGH (DImode, safe_constDI (focus_bits))));
+
+      if (lowest_bit_set < 10)
+       emit_insn (gen_rtx_SET (DImode,
+                               op0,
+                               gen_rtx_ASHIFTRT (DImode, temp,
+                                                 GEN_INT (10 - lowest_bit_set))));
+      else if (lowest_bit_set >= 10)
+       emit_insn (gen_rtx_SET (DImode,
+                               op0,
+                               gen_rtx_ASHIFT (DImode, temp,
+                                               GEN_INT (lowest_bit_set - 10))));
+      else
+       abort();
+      return;
+    }
+
+  /* 1) sethi  %hi(low_bits), %reg
+   *    or     %reg, %lo(low_bits), %reg
+   * 2) sethi  %hi(~low_bits), %reg
+   *   xor     %reg, %lo(-0x400 | (low_bits & 0x3ff)), %reg
+   */
+  if (high_bits == 0
+      || high_bits == -1)
+    return sparc_emit_set_const64_quick1 (op0, temp, low_bits,
+                                         (high_bits == -1));
+
+  /* 1) sethi  %hi(high_bits), %reg
+   *    or     %reg, %lo(high_bits), %reg
+   *    sllx   %reg, 32, %reg
+   */
+  if (low_bits == 0
+      || (SPARC_SIMM13_P(low_bits)
+         && ((int)low_bits > 0)))
+    return sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_bits, 32);
+
+  /* Now, try 3-insn sequences.  But first we may be able to do something
+     quick when the constant is negated, so try that.  */
+  if (const64_is_2insns ((~high_bits) & 0xffffffff,
+                        (~low_bits) & 0xfffffc00))
+    {
+      unsigned int trailing_bits = (~low_bits) & 0x3ff;
+
+      if ((((~high_bits) & 0xffffffff) == 0
+          && ((~low_bits) & 0x80000000) == 0)
+         || (((~high_bits) & 0xffffffff) == 0xffffffff
+             && ((~low_bits) & 0x80000000) != 0))
        {
-         if (SMALL_INT (offset))
-           return plus_constant_for_output (base, INTVAL (offset));
-         else if (! reload_in_progress && ! reload_completed)
-           offset = force_reg (Pmode, offset);
+         rtx fast_int = GEN_INT (~low_bits & 0xffffffff);
+
+         if (input_operand (fast_int, DImode))
+           emit_insn (gen_rtx_SET (DImode, temp,
+                                   safe_constDI (~low_bits & 0xffffffff)));
          else
-           /* If we reach here, then something is seriously wrong.  */
-           abort ();
+           sparc_emit_set_const64 (temp, fast_int);
        }
-      return gen_rtx_PLUS (Pmode, base, offset);
+      else
+       {
+         rtx negated_const;
+#if HOST_BITS_PER_WIDE_INT == 64
+         negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
+                                  (((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
+#else
+         negated_const = gen_rtx_CONST_DOUBLE (DImode, NULL_RTX,
+                                               (~low_bits) & 0xfffffc00,
+                                               (~high_bits) & 0xffffffff);
+#endif
+         sparc_emit_set_const64 (temp, negated_const);
+       }
+      emit_insn (gen_rtx_SET (DImode,
+                             op0,
+                             gen_rtx_XOR (DImode, temp,
+                                          safe_constDI (-0x400 | trailing_bits))));
+      return;
     }
-  else if (GET_CODE (orig) == LABEL_REF)
-    /* ??? Why do we do this?  */
-    current_function_uses_pic_offset_table = 1;
-
-  return orig;
-}
-
-/* Set up PIC-specific rtl.  This should not cause any insns
-   to be emitted.  */
-
-void
-initialize_pic ()
-{
-}
 
-/* Return the RTX for insns to set the PIC register.  */
+  /* 1) sethi  %hi(xxx), %reg
+   *    or     %reg, %lo(xxx), %reg
+   *   sllx    %reg, yyy, %reg
+   */
+  if ((highest_bit_set - lowest_bit_set) < 32)
+    {
+      unsigned int hi, lo, focus_bits;
 
-static rtx
-pic_setup_code ()
-{
-  rtx seq;
+      /* We can't get here in this state.  */
+      if (highest_bit_set < 32
+         || lowest_bit_set >= 32)
+       abort();
 
-  start_sequence ();
-  emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
-                        get_pc_symbol));
-  seq = gen_sequence ();
-  end_sequence ();
+      /* So what we know is that the set bits straddle the
+        middle of the 64-bit word.  */
+      hi = (low_bits >> lowest_bit_set);
+      lo = (high_bits << (32 - lowest_bit_set));
+      if (hi & lo)
+       abort();
+      focus_bits = (hi | lo);
+      return sparc_emit_set_const64_quick2 (op0, temp,
+                                           focus_bits, 0,
+                                           lowest_bit_set);
+    }
 
-  return seq;
+  /* The easiest way when all else fails, is full decomposition. */
+#if 0
+  printf ("sparc_emit_set_const64: Hard constant [%08lx%08lx] neg[%08lx%08lx]\n",
+         high_bits, low_bits, ~high_bits, ~low_bits);
+#endif
+  sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
 }
 
-/* Emit special PIC prologues and epilogues.  */
+/* X and Y are two things to compare using CODE.  Emit the compare insn and
+   return the rtx for the cc reg in the proper mode.  */
 
-void
-finalize_pic ()
+rtx
+gen_compare_reg (code, x, y)
+     enum rtx_code code;
+     rtx x, y;
 {
-  /* Labels to get the PC in the prologue of this function.  */
-  int orig_flag_pic = flag_pic;
-  rtx insn;
+  enum machine_mode mode = SELECT_CC_MODE (code, x, y);
+  rtx cc_reg;
 
-  if (current_function_uses_pic_offset_table == 0)
-    return;
+  /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
+     fcc regs (cse can't tell they're really call clobbered regs and will
+     remove a duplicate comparison even if there is an intervening function
+     call - it will then try to reload the cc reg via an int reg which is why
+     we need the movcc patterns).  It is possible to provide the movcc
+     patterns by using the ldxfsr/stxfsr v9 insns.  I tried it: you need two
+     registers (say %g1,%g5) and it takes about 6 insns.  A better fix would be
+     to tell cse that CCFPE mode registers (even pseudos) are call
+     clobbered.  */
 
-  if (! flag_pic)
-    abort ();
+  /* ??? This is an experiment.  Rather than making changes to cse which may
+     or may not be easy/clean, we do our own cse.  This is possible because
+     we will generate hard registers.  Cse knows they're call clobbered (it
+     doesn't know the same thing about pseudos). If we guess wrong, no big
+     deal, but if we win, great!  */
 
-  /* If we havn't emitted the special get_pc helper function, do so now.  */
-  if (get_pc_symbol_name[0] == 0)
+  if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+#if 1 /* experiment */
     {
-      ASM_GENERATE_INTERNAL_LABEL (get_pc_symbol_name, "LGETPC", 0);
+      int reg;
+      /* We cycle through the registers to ensure they're all exercised.  */
+      static int next_fcc_reg = 0;
+      /* Previous x,y for each fcc reg.  */
+      static rtx prev_args[4][2];
 
-      text_section ();
-      ASM_OUTPUT_ALIGN (asm_out_file, 3);
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0);
-      fputs ("\tretl\n\tadd %o7,%l7,%l7\n", asm_out_file);
+      /* Scan prev_args for x,y.  */
+      for (reg = 0; reg < 4; reg++)
+       if (prev_args[reg][0] == x && prev_args[reg][1] == y)
+         break;
+      if (reg == 4)
+       {
+         reg = next_fcc_reg;
+         prev_args[reg][0] = x;
+         prev_args[reg][1] = y;
+         next_fcc_reg = (next_fcc_reg + 1) & 3;
+       }
+      cc_reg = gen_rtx_REG (mode, reg + SPARC_FIRST_V9_FCC_REG);
     }
+#else
+    cc_reg = gen_reg_rtx (mode);
+#endif /* ! experiment */
+  else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+    cc_reg = gen_rtx_REG (mode, SPARC_FCC_REG);
+  else
+    cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG);
 
-  /* Initialize every time through, since we can't easily
-     know this to be permanent.  */
-  global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
-  get_pc_symbol = gen_rtx_SYMBOL_REF (Pmode, get_pc_symbol_name);
-  flag_pic = 0;
+  emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
+                         gen_rtx_COMPARE (mode, x, y)));
 
-  emit_insn_after (pic_setup_code (), get_insns ());
+  return cc_reg;
+}
 
-  /* Insert the code in each nonlocal goto receiver.  */
-  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
-       && XINT (PATTERN (insn), 1) == 4)
-      emit_insn_after (pic_setup_code (), insn);
+/* This function is used for v9 only.
+   CODE is the code for an Scc's comparison.
+   OPERANDS[0] is the target of the Scc insn.
+   OPERANDS[1] is the value we compare against const0_rtx (which hasn't
+   been generated yet).
 
-  flag_pic = orig_flag_pic;
+   This function is needed to turn
 
-  /* Need to emit this whether or not we obey regdecls,
-     since setjmp/longjmp can cause life info to screw up.
-     ??? In the case where we don't obey regdecls, this is not sufficient
-     since we may not fall out the bottom.  */
-  emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
-}
-\f
-/* Emit insns to move operands[1] into operands[0].
+          (set (reg:SI 110)
+              (gt (reg:CCX 100 %icc)
+                  (const_int 0)))
+   into
+          (set (reg:SI 110)
+              (gt:DI (reg:CCX 100 %icc)
+                  (const_int 0)))
+
+   IE: The instruction recognizer needs to see the mode of the comparison to
+   find the right instruction. We could use "gt:DI" right in the
+   define_expand, but leaving it out allows us to handle DI, SI, etc.
 
-   Return 1 if we have written out everything that needs to be done to
-   do the move.  Otherwise, return 0 and the caller will emit the move
-   normally.  */
+   We refer to the global sparc compare operands sparc_compare_op0 and
+   sparc_compare_op1.  */
 
 int
-emit_move_sequence (operands, mode)
-     rtx *operands;
-     enum machine_mode mode;
+gen_v9_scc (compare_code, operands)
+     enum rtx_code compare_code;
+     register rtx *operands;
 {
-  register rtx operand0 = operands[0];
-  register rtx operand1 = operands[1];
+  rtx temp, op0, op1;
 
-  if (CONSTANT_P (operand1) && flag_pic
-      && pic_address_needs_scratch (operand1))
-    operands[1] = operand1 = legitimize_pic_address (operand1, mode, 0);
+  if (! TARGET_ARCH64
+      && (GET_MODE (sparc_compare_op0) == DImode
+         || GET_MODE (operands[0]) == DImode))
+    return 0;
 
-  /* Handle most common case first: storing into a register.  */
-  if (register_operand (operand0, mode))
+  /* Handle the case where operands[0] == sparc_compare_op0.
+     We "early clobber" the result.  */
+  if (REGNO (operands[0]) == REGNO (sparc_compare_op0))
     {
-      /* Integer constant to FP register. */
-      if (GET_CODE (operand0) == REG
-         && REGNO (operand0) >= 32
-         && REGNO (operand0) < FIRST_PSEUDO_REGISTER
-         && CONSTANT_P (operand1))
-       {
-         operand1 = validize_mem (force_const_mem (GET_MODE (operand0), operand1));
-       }
-
-      if (register_operand (operand1, mode)
-         || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
-         || (GET_CODE (operand1) == CONST_DOUBLE
-             && arith_double_operand (operand1, DImode))
-         || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) != DImode)
-         /* Only `general_operands' can come here, so MEM is ok.  */
-         || GET_CODE (operand1) == MEM)
-       {
-         /* Run this case quickly.  */
-         emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
-         return 1;
-       }
+      op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
+      emit_move_insn (op0, sparc_compare_op0);
     }
-  else if (GET_CODE (operand0) == MEM)
+  else
+    op0 = sparc_compare_op0;
+  /* For consistency in the following.  */
+  op1 = sparc_compare_op1;
+
+  /* Try to use the movrCC insns.  */
+  if (TARGET_ARCH64
+      && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
+      && op1 == const0_rtx
+      && v9_regcmp_p (compare_code))
     {
-      if (register_operand (operand1, mode)
-         || (operand1 == const0_rtx && ! TARGET_LIVE_G0))
+      /* Special case for op0 != 0.  This can be done with one instruction if
+        operands[0] == sparc_compare_op0.  We don't assume they are equal
+        now though.  */
+
+      if (compare_code == NE
+         && GET_MODE (operands[0]) == DImode
+         && GET_MODE (op0) == DImode)
        {
-         /* Run this case quickly.  */
-         emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
+         emit_insn (gen_rtx_SET (VOIDmode, operands[0], op0));
+         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                             gen_rtx_IF_THEN_ELSE (DImode,
+                                      gen_rtx_fmt_ee (compare_code, DImode,
+                                                      op0, const0_rtx),
+                                      const1_rtx,
+                                      operands[0])));
          return 1;
        }
-      if (! reload_in_progress)
+
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
+      if (GET_MODE (op0) != DImode)
        {
-         operands[0] = validize_mem (operand0);
-         operands[1] = operand1 = force_reg (mode, operand1);
+         temp = gen_reg_rtx (DImode);
+         convert_move (temp, op0, 0);
        }
-    }
-
-  if (GET_CODE (operand1) == LABEL_REF
-      && mode == SImode && flag_pic)
-    {
-      if (TARGET_ARCH64)
-       abort ();
-      emit_insn (gen_move_pic_label_si (operand0, operand1));
-      return 1;
-    }
-  /* Non-pic LABEL_REF's in sparc64 are expensive to do the normal way,
-     so always use special code.  */
-  else if (GET_CODE (operand1) == LABEL_REF
-          && mode == DImode)
-    {
-      if (! TARGET_ARCH64)
-       abort ();
-      emit_insn (gen_move_label_di (operand0, operand1));
-      return 1;
-    }
-  /* DImode HIGH values in sparc64 need a clobber added.  */
-  else if (TARGET_ARCH64
-      && GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode)
-    {
-      emit_insn (gen_sethi_di_sp64 (operand0, XEXP (operand1, 0)));
+      else
+       temp = op0;
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                         gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                                  gen_rtx_fmt_ee (compare_code, DImode,
+                                                  temp, const0_rtx),
+                                  const1_rtx,
+                                  operands[0])));
       return 1;
     }
-  /* Simplify the source if we need to.  */
-  else if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
+  else
     {
-      if (flag_pic && symbolic_operand (operand1, mode))
-       {
-         rtx temp_reg = reload_in_progress ? operand0 : 0;
+      operands[1] = gen_compare_reg (compare_code, op0, op1);
 
-         operands[1] = legitimize_pic_address (operand1, mode, temp_reg);
-       }
-      else if (GET_CODE (operand1) == CONST_INT
-              ? (! SMALL_INT (operand1)
-                 && INTVAL (operand1) != -4096
-                 && ! SPARC_SETHI_P (INTVAL (operand1)))
-              : GET_CODE (operand1) == CONST_DOUBLE
-              ? ! arith_double_operand (operand1, DImode)
-              : 1)
+      switch (GET_MODE (operands[1]))
        {
-         /* For DImode values, temp must be operand0 because of the way
-            HI and LO_SUM work.  The LO_SUM operator only copies half of
-            the LSW from the dest of the HI operator.  If the LO_SUM dest is
-            not the same as the HI dest, then the MSW of the LO_SUM dest will
-            never be set.
-
-            ??? The real problem here is that the ...(HI:DImode pattern emits
-            multiple instructions, and the ...(LO_SUM:DImode pattern emits
-            one instruction.  This fails, because the compiler assumes that
-            LO_SUM copies all bits of the first operand to its dest.  Better
-            would be to have the HI pattern emit one instruction and the
-            LO_SUM pattern multiple instructions.  Even better would be
-            to use four rtl insns.  */
-         rtx temp = ((reload_in_progress || mode == DImode)
-                     ? operand0 : gen_reg_rtx (mode));
-
-         if (mode == SImode)
-           {
-             if (GET_CODE (operand1) == CONST_INT)
-               operand1 = GEN_INT (INTVAL (operand1) & 0xffffffff);
-             else if (GET_CODE (operand1) == CONST_DOUBLE)
-               operand1 = GEN_INT (CONST_DOUBLE_LOW (operand1) & 0xffffffff);
-           }
-
-         if (TARGET_ARCH64 && mode == DImode)
-           emit_insn (gen_sethi_di_sp64 (temp, operand1));
-         else
-           emit_insn (gen_rtx_SET (VOIDmode, temp,
-                               gen_rtx_HIGH (mode, operand1)));
-
-         operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
+         case CCmode :
+         case CCXmode :
+         case CCFPEmode :
+         case CCFPmode :
+           break;
+         default :
+           abort ();
        }
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                         gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                                  gen_rtx_fmt_ee (compare_code,
+                                                  GET_MODE (operands[1]),
+                                                  operands[1], const0_rtx),
+                                   const1_rtx, operands[0])));
+      return 1;
     }
-
-  /* Now have insn-emit do whatever it normally does.  */
-  return 0;
 }
-\f
-/* Return the best assembler insn template
-   for moving operands[1] into operands[0] as a 4 byte quantity.
-
-   This isn't intended to be very smart.  It is up to the caller to
-   choose the best way to do things.
 
-   Note that OPERANDS may be modified to suit the returned string.  */
+/* Emit a conditional jump insn for the v9 architecture using comparison code
+   CODE and jump target LABEL.
+   This function exists to take advantage of the v9 brxx insns.  */
 
-char *
-singlemove_string (operands)
-     rtx *operands;
+void
+emit_v9_brxx_insn (code, op0, label)
+     enum rtx_code code;
+     rtx op0, label;
 {
-  if (GET_CODE (operands[0]) == MEM)
-    {
-      if (GET_CODE (operands[1]) != MEM)
-       return "st %r1,%0";
-      else
-       abort ();
-    }
-  else if (GET_CODE (operands[1]) == MEM)
-    return "ld %1,%0";
-  else if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    {
-      REAL_VALUE_TYPE r;
-      long i;
-
-      /* Must be SFmode, otherwise this doesn't make sense.  */
-      if (GET_MODE (operands[1]) != SFmode)
-       abort ();
-
-      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-      REAL_VALUE_TO_TARGET_SINGLE (r, i);
-      operands[1] = GEN_INT (i);
-
-      if (CONST_OK_FOR_LETTER_P (i, 'I'))
-       return "mov %1,%0";
-      else if ((i & 0x000003FF) != 0)
-       return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
-      else
-       return "sethi %%hi(%a1),%0";
-    }
-  else if (GET_CODE (operands[1]) == CONST_INT)
-    {
-      /* Only consider the low 32 bits of the constant. */
-      int i = INTVAL (operands[1]) & 0xffffffff;
-
-      if (SPARC_SIMM13_P (i))
-       return "mov %1,%0";
+  emit_jump_insn (gen_rtx_SET (VOIDmode,
+                          pc_rtx,
+                          gen_rtx_IF_THEN_ELSE (VOIDmode,
+                                   gen_rtx_fmt_ee (code, GET_MODE (op0),
+                                                   op0, const0_rtx),
+                                   gen_rtx_LABEL_REF (VOIDmode, label),
+                                   pc_rtx)));
+}
+\f
+/* Return nonzero if a return peephole merging return with
+   setting of output register is ok.  */
+int
+leaf_return_peephole_ok ()
+{
+  return (actual_fsize == 0);
+}
 
-      if (i == 4096)
-       return "sub %%g0,-4096,%0";
+/* Return nonzero if TRIAL can go into the function epilogue's
+   delay slot.  SLOT is the slot we are trying to fill.  */
 
-      /* If all low order 10 bits are clear, then we only need a single
-        sethi insn to load the constant.  */
-      /* FIXME: Use SETHI_P.  */
-      if ((i & 0x000003FF) != 0)
-       return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
-      else
-       return "sethi %%hi(%a1),%0";
-    }
-  /* Operand 1 must be a register, or a 'I' type CONST_INT.  */
-  return "mov %1,%0";
-}
+int
+eligible_for_epilogue_delay (trial, slot)
+     rtx trial;
+     int slot;
+{
+  rtx pat, src;
 
-/* Return the best assembler insn template
-   for moving operands[1] into operands[0] as an 8 byte quantity.
+  if (slot >= 1)
+    return 0;
 
-   This isn't intended to be very smart.  It is up to the caller to
-   choose the best way to do things.
+  if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
+    return 0;
 
-   Note that OPERANDS may be modified to suit the returned string.  */
+  if (get_attr_length (trial) != 1)
+    return 0;
 
-char *
-doublemove_string (operands)
-     rtx *operands;
-{
-  rtx op0 = operands[0], op1 = operands[1];
+  /* If %g0 is live, there are lots of things we can't handle.
+     Rather than trying to find them all now, let's punt and only
+     optimize things as necessary.  */
+  if (TARGET_LIVE_G0)
+    return 0;
 
-  if (GET_CODE (op0) == MEM)
-    {
-      if (GET_CODE (op1) == REG)
-       {
-         if (FP_REG_P (op1))
-           return "std %1,%0";
-         return TARGET_ARCH64 ? "stx %1,%0" : "std %1,%0";
-       }
-      if (TARGET_ARCH64
-         && (op1 == const0_rtx
-             || (GET_MODE (op1) != VOIDmode
-                 && op1 == CONST0_RTX (GET_MODE (op1)))))
-       return "stx %r1,%0";
-      abort ();
-    }
-  else if (GET_CODE (op1) == MEM)
-    {
-      if (GET_CODE (op0) != REG)
-       abort ();
-      if (FP_REG_P (op0))
-       return "ldd %1,%0";
-      return TARGET_ARCH64 ? "ldx %1,%0" : "ldd %1,%0";
-    }
-  else if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    {
-      /* ??? Unfinished, and maybe not needed.  */
-      abort ();
-    }
-  else if (GET_CODE (operands[1]) == CONST_INT
-          && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
+  /* 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.  */
+  if (leaf_function)
     {
-      /* ??? Unfinished, and maybe not needed.  */
-      abort ();
+      if (leaf_return_peephole_ok ())
+       return ((get_attr_in_uncond_branch_delay (trial)
+                == IN_BRANCH_DELAY_TRUE));
+      return 0;
     }
-  /* Operand 1 must be a register, or a 'I' type CONST_INT.  */
-  return "mov %1,%0";
-}
 
-/* Return non-zero if it is OK to assume that the given memory operand is
-   aligned at least to a 8-byte boundary.  This should only be called
-   for memory accesses whose size is 8 bytes or larger.  */
+  /* If only trivial `restore' insns work, nothing can go in the
+     delay slot.  */
+  else if (TARGET_BROKEN_SAVERESTORE)
+    return 0;
 
-int
-mem_aligned_8 (mem)
-     register rtx mem;
-{
-  register rtx addr;
-  register rtx base;
-  register rtx offset;
+  pat = PATTERN (trial);
 
-  if (GET_CODE (mem) != MEM)
-    return 0;  /* It's gotta be a MEM! */
+  /* Otherwise, only operations which can be done in tandem with
+     a `restore' insn can go into the delay slot.  */
+  if (GET_CODE (SET_DEST (pat)) != REG
+      || REGNO (SET_DEST (pat)) >= 32
+      || REGNO (SET_DEST (pat)) < 24)
+    return 0;
 
-  addr = XEXP (mem, 0);
+  /* The set of insns matched here must agree precisely with the set of
+     patterns paired with a RETURN in sparc.md.  */
 
-  /* Now that all misaligned double parms are copied on function entry,
-     we can assume any 64-bit object is 64-bit aligned except those which
-     are at unaligned offsets from the stack or frame pointer.  If the
-     TARGET_UNALIGNED_DOUBLES switch is given, we do not make this
-     assumption.  */
+  src = SET_SRC (pat);
 
-  /* See what register we use in the address.  */
-  base = offset = 0;
-  if (GET_CODE (addr) == PLUS)
-    {
-      if (GET_CODE (XEXP (addr, 0)) == REG
-         && GET_CODE (XEXP (addr, 1)) == CONST_INT)
-       {
-         base = XEXP (addr, 0);
-         offset = XEXP (addr, 1);
-       }
-    }
-  else if (GET_CODE (addr) == REG)
-    {
-      base = addr;
-      offset = const0_rtx;
-    }
+  /* This matches "*return_[qhs]i".  */
+  if (arith_operand (src, GET_MODE (src)))
+    return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
+    
+  /* This matches "*return_di".  */
+  else if (arith_double_operand (src, GET_MODE (src)))
+    return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
 
-  /* If it's the stack or frame pointer, check offset alignment.
-     We can have improper alignment in the function entry code.  */
-  if (base
-      && (REGNO (base) == FRAME_POINTER_REGNUM
-         || REGNO (base) == STACK_POINTER_REGNUM))
-    {
-      if (((INTVAL (offset) - SPARC_STACK_BIAS) & 0x7) == 0)
-       return 1;
-    }
-  /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES
-     is true, in which case we can only assume that an access is aligned if
-     it is to a constant address, or the address involves a LO_SUM.
+  /* This matches "*return_sf_no_fpu".  */
+  else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
+          && register_operand (src, SFmode))
+    return 1;
 
-     We used to assume an address was aligned if MEM_IN_STRUCT_P was true.
-     That assumption was deleted so that gcc generated code can be used with
-     memory allocators that only guarantee 4 byte alignment.  */
-  else if (! TARGET_UNALIGNED_DOUBLES || CONSTANT_P (addr)
-          || GET_CODE (addr) == LO_SUM)
+  /* This matches "*return_addsi".  */
+  else if (GET_CODE (src) == PLUS
+          && arith_operand (XEXP (src, 0), SImode)
+          && arith_operand (XEXP (src, 1), SImode)
+          && (register_operand (XEXP (src, 0), SImode)
+              || register_operand (XEXP (src, 1), SImode)))
+    return 1;
+
+  /* This matches "*return_adddi".  */
+  else if (GET_CODE (src) == PLUS
+          && arith_double_operand (XEXP (src, 0), DImode)
+          && arith_double_operand (XEXP (src, 1), DImode)
+          && (register_operand (XEXP (src, 0), DImode)
+              || register_operand (XEXP (src, 1), DImode)))
     return 1;
 
-  /* An obviously unaligned address.  */
   return 0;
 }
 
-enum optype { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP };
-
-/* Output assembler code to perform a doubleword move insn
-   with operands OPERANDS.  This is very similar to the following
-   output_move_quad function.  */
-
-char *
-output_move_double (operands)
-     rtx *operands;
+static int
+check_return_regs (x)
+     rtx x;
 {
-  register rtx op0 = operands[0];
-  register rtx op1 = operands[1];
-  register enum optype optype0;
-  register enum optype optype1;
-  rtx latehalf[2];
-  rtx addreg0 = 0;
-  rtx addreg1 = 0;
-  int highest_first = 0;
-  int no_addreg1_decrement = 0;
-
-  /* First classify both operands.  */
-
-  if (REG_P (op0))
-    optype0 = REGOP;
-  else if (offsettable_memref_p (op0))
-    optype0 = OFFSOP;
-  else if (GET_CODE (op0) == MEM)
-    optype0 = MEMOP;
-  else
-    optype0 = RNDOP;
-
-  if (REG_P (op1))
-    optype1 = REGOP;
-  else if (CONSTANT_P (op1))
-    optype1 = CNSTOP;
-  else if (offsettable_memref_p (op1))
-    optype1 = OFFSOP;
-  else if (GET_CODE (op1) == MEM)
-    optype1 = MEMOP;
-  else
-    optype1 = RNDOP;
+  switch (GET_CODE (x))
+    {
+    case REG:
+      return IN_OR_GLOBAL_P (x);
 
-  /* Check for the cases that the operand constraints are not
-     supposed to allow to happen.  Abort if we get one,
-     because generating code for these cases is painful.  */
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+    return 1;
 
-  if (optype0 == RNDOP || optype1 == RNDOP
-      || (optype0 == MEM && optype1 == MEM))
-    abort ();
+    case SET:
+    case IOR:
+    case AND:
+    case XOR:
+    case PLUS:
+    case MINUS:
+      if (check_return_regs (XEXP (x, 1)) == 0)
+  return 0;
+    case NOT:
+    case NEG:
+    case MEM:
+      return check_return_regs (XEXP (x, 0));
+      
+    default:
+      return 0;
+    }
 
-  /* If an operand is an unoffsettable memory ref, find a register
-     we can increment temporarily to make it refer to the second word.  */
+}
 
-  if (optype0 == MEMOP)
-    addreg0 = find_addr_reg (XEXP (op0, 0));
+/* Return 1 if TRIAL references only in and global registers.  */
+int
+eligible_for_return_delay (trial)
+     rtx trial;
+{
+  if (GET_CODE (PATTERN (trial)) != SET)
+    return 0;
 
-  if (optype1 == MEMOP)
-    addreg1 = find_addr_reg (XEXP (op1, 0));
+  return check_return_regs (PATTERN (trial));
+}
 
-  /* Ok, we can do one word at a time.
-     Set up in LATEHALF the operands to use for the
-     high-numbered (least significant) word and in some cases alter the
-     operands in OPERANDS to be suitable for the low-numbered word.  */
+int
+short_branch (uid1, uid2)
+     int uid1, uid2;
+{
+  unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];
+  if (delta + 1024 < 2048)
+    return 1;
+  /* warning ("long branch, distance %d", delta); */
+  return 0;
+}
 
-  if (optype0 == REGOP)
-    latehalf[0] = gen_rtx_REG (SImode, REGNO (op0) + 1);
-  else if (optype0 == OFFSOP)
-    latehalf[0] = adj_offsettable_operand (op0, 4);
-  else
-    latehalf[0] = op0;
+/* Return non-zero if REG is not used after INSN.
+   We assume REG is a reload reg, and therefore does
+   not live past labels or calls or jumps.  */
+int
+reg_unused_after (reg, insn)
+     rtx reg;
+     rtx insn;
+{
+  enum rtx_code code, prev_code = UNKNOWN;
 
-  if (optype1 == REGOP)
-    latehalf[1] = gen_rtx_REG (SImode, REGNO (op1) + 1);
-  else if (optype1 == OFFSOP)
-    latehalf[1] = adj_offsettable_operand (op1, 4);
-  else if (optype1 == CNSTOP)
+  while ((insn = NEXT_INSN (insn)))
     {
-      if (TARGET_ARCH64)
-       {
-         if (arith_double_operand (op1, DImode))
-           {
-             operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
-             return "mov %1,%0";
-           }
-         else
-           {
-             /* The only way to handle CONST_DOUBLEs or other 64 bit
-                constants here is to use a temporary, such as is done
-                for the V9 DImode sethi insn pattern.  This is not
-                a practical solution, so abort if we reach here.
-                The md file should always force such constants to
-                memory.  */
-             abort ();
-           }
-       }
-      else
-       split_double (op1, &operands[1], &latehalf[1]);
-    }
-  else
-    latehalf[1] = op1;
+      if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
+       return 1;
 
-  /* Easy case: try moving both words at once.  Check for moving between
-     an even/odd register pair and a memory location.  */
-  if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
-       && (TARGET_ARCH64 || (REGNO (op0) & 1) == 0))
-      || (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
-         && (TARGET_ARCH64 || (REGNO (op1) & 1) == 0)))
-    {
-      register rtx mem,reg;
+      code = GET_CODE (insn);
+      if (GET_CODE (insn) == CODE_LABEL)
+       return 1;
 
-      if (optype0 == REGOP)
-       mem = op1, reg = op0;
-      else
-       mem = op0, reg = op1;
-
-      /* In v9, ldd can be used for word aligned addresses, so technically
-        some of this logic is unneeded.  We still avoid ldd if the address
-        is obviously unaligned though.
-
-        Integer ldd/std are deprecated in V9 and are slow on UltraSPARC.
-        Use them only if the access is volatile or not offsettable.  */
-
-      if ((mem_aligned_8 (mem)
-          && (REGNO (reg) >= 32
-              || MEM_VOLATILE_P (mem)
-              || ! ((optype0 == OFFSOP || optype1 == OFFSOP)
-                    && (sparc_cpu == PROCESSOR_ULTRASPARC
-                        || sparc_cpu == PROCESSOR_V9))))
-         /* If this is a floating point register higher than %f31,
-            then we *must* use an aligned load, since `ld' will not accept
-            the register number.  */
-         || (TARGET_V9 && REGNO (reg) >= 64)
-         /* Even if two instructions would otherwise be better than ldd/std,
-            if this insn was put in a delay slot because reorg thought it
-            was only one machine instruction, make sure it is only one
-            instruction.  */
-         || dbr_sequence_length () != 0)
+      if (GET_RTX_CLASS (code) == 'i')
        {
-         if (FP_REG_P (reg) || ! TARGET_ARCH64)
-           return (mem == op1 ? "ldd %1,%0" : "std %1,%0");
-         else
-           return (mem == op1 ? "ldx %1,%0" : "stx %1,%0");
+         rtx set = single_set (insn);
+         int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
+         if (set && in_src)
+           return 0;
+         if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
+           return 1;
+         if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
+           return 0;
        }
+      prev_code = code;
     }
+  return 1;
+}
+\f
+/* The table we use to reference PIC data.  */
+static rtx global_offset_table;
 
-  if (TARGET_ARCH64)
-    {
-      if (optype0 == REGOP && optype1 == REGOP)
-       {
-         if (FP_REG_P (op0))
-           return "fmovd %1,%0";
-         else
-           return "mov %1,%0";
-       }
-    }
+/* The function we use to get at it.  */
+static rtx get_pc_symbol;
+static char get_pc_symbol_name[256];
 
-  /* If the first move would clobber the source of the second one,
-     do them in the other order.  */
+/* Ensure that we are not using patterns that are not OK with PIC.  */
 
-  /* Overlapping registers.  */
-  if (optype0 == REGOP && optype1 == REGOP
-      && REGNO (op0) == REGNO (latehalf[1]))
+int
+check_pic (i)
+     int i;
+{
+  switch (flag_pic)
     {
-      /* Do that word.  */
-      output_asm_insn (singlemove_string (latehalf), latehalf);
-      /* Do low-numbered word.  */
-      return singlemove_string (operands);
+    case 1:
+      if (GET_CODE (recog_operand[i]) == SYMBOL_REF
+         || (GET_CODE (recog_operand[i]) == CONST
+             && ! (GET_CODE (XEXP (recog_operand[i], 0)) == MINUS
+                   && (XEXP (XEXP (recog_operand[i], 0), 0)
+                       == global_offset_table)
+                   && (GET_CODE (XEXP (XEXP (recog_operand[i], 0), 1))
+                       == CONST))))
+       abort ();
+    case 2:
+    default:
+      return 1;
     }
-  /* Loading into a register which overlaps a register used in the address.  */
-  else if (optype0 == REGOP && optype1 != REGOP
-          && reg_overlap_mentioned_p (op0, op1))
-    {
-      /* If both halves of dest are used in the src memory address,
-        add the two regs and put them in the low reg (op0).
-        Then it works to load latehalf first.  */
-      if (reg_mentioned_p (op0, XEXP (op1, 0))
-         && reg_mentioned_p (latehalf[0], XEXP (op1, 0)))
-       {
-         rtx xops[2];
-         xops[0] = latehalf[0];
-         xops[1] = op0;
-         output_asm_insn ("add %1,%0,%1", xops);
-         operands[1] = gen_rtx_MEM (DImode, op0);
-         latehalf[1] = adj_offsettable_operand (operands[1], 4);
-         addreg1 = 0;
-         highest_first = 1;
-       }
-      /* Only one register in the dest is used in the src memory address,
-        and this is the first register of the dest, so we want to do
-        the late half first here also.  */
-      else if (! reg_mentioned_p (latehalf[0], XEXP (op1, 0)))
-       highest_first = 1;
-      /* Only one register in the dest is used in the src memory address,
-        and this is the second register of the dest, so we want to do
-        the late half last.  If addreg1 is set, and addreg1 is the same
-        register as latehalf, then we must suppress the trailing decrement,
-        because it would clobber the value just loaded.  */
-      else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0]))
-       no_addreg1_decrement = 1;
-    }
-
-  /* Normal case: do the two words, low-numbered first.
-     Overlap case (highest_first set): do high-numbered word first.  */
-
-  if (! highest_first)
-    output_asm_insn (singlemove_string (operands), operands);
-
-  /* Make any unoffsettable addresses point at high-numbered word.  */
-  if (addreg0)
-    output_asm_insn ("add %0,0x4,%0", &addreg0);
-  if (addreg1)
-    output_asm_insn ("add %0,0x4,%0", &addreg1);
-
-  /* Do that word.  */
-  output_asm_insn (singlemove_string (latehalf), latehalf);
-
-  /* Undo the adds we just did.  */
-  if (addreg0)
-    output_asm_insn ("add %0,-0x4,%0", &addreg0);
-  if (addreg1 && ! no_addreg1_decrement)
-    output_asm_insn ("add %0,-0x4,%0", &addreg1);
-
-  if (highest_first)
-    output_asm_insn (singlemove_string (operands), operands);
-
-  return "";
 }
 
-/* Output assembler code to perform a quadword move insn
-   with operands OPERANDS.  This is very similar to the preceding
-   output_move_double function.  */
+/* Return true if X is an address which needs a temporary register when 
+   reloaded while generating PIC code.  */
 
-char *
-output_move_quad (operands)
-     rtx *operands;
+int
+pic_address_needs_scratch (x)
+     rtx x;
 {
-  register rtx op0 = operands[0];
-  register rtx op1 = operands[1];
-  register enum optype optype0;
-  register enum optype optype1;
-  rtx wordpart[4][2];
-  rtx load_late[4];
-  int load_late_half[2];
-  rtx addreg0 = 0;
-  rtx addreg1 = 0;
-
-  load_late_half[0] = 0; load_late_half[1] = 0;
-  load_late[0] = 0; load_late[1] = 0; load_late[2] = 0; 
-  load_late[3] = 0;
-
-  wordpart[0][0] = NULL;  wordpart[1][0] = NULL;  wordpart[2][0] = NULL;
-  wordpart[3][0] = NULL;
-
-  /* First classify both operands.  */
-
-  if (REG_P (op0))
-    optype0 = REGOP;
-  else if (offsettable_memref_p (op0))
-    optype0 = OFFSOP;
-  else if (GET_CODE (op0) == MEM)
-    optype0 = MEMOP;
-  else
-    optype0 = RNDOP;
-
-  if (REG_P (op1))
-    optype1 = REGOP;
-  else if (CONSTANT_P (op1))
-    optype1 = CNSTOP;
-  else if (offsettable_memref_p (op1))
-    optype1 = OFFSOP;
-  else if (GET_CODE (op1) == MEM)
-    optype1 = MEMOP;
-  else
-    optype1 = RNDOP;
+  /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
+  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+      && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
+    return 1;
 
-  /* Check for the cases that the operand constraints are not
-     supposed to allow to happen.  Abort if we get one,
-     because generating code for these cases is painful.  */
+  return 0;
+}
 
-  if (optype0 == RNDOP || optype1 == RNDOP
-      || (optype0 == MEM && optype1 == MEM))
-    abort ();
+/* Legitimize PIC addresses.  If the address is already position-independent,
+   we return ORIG.  Newly generated position-independent addresses go into a
+   reg.  This is REG if non zero, otherwise we allocate register(s) as
+   necessary.  */
 
-  if (optype0 == REGOP)
+rtx
+legitimize_pic_address (orig, mode, reg)
+     rtx orig;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+     rtx reg;
+{
+  if (GET_CODE (orig) == SYMBOL_REF)
     {
-      wordpart[0][0] = gen_rtx_REG (word_mode, REGNO (op0) + 0);
-      if (TARGET_ARCH64 && FP_REG_P (op0) 
-         && REGNO (op0) < SPARC_FIRST_V9_FP_REG)
-       wordpart[1][0] = gen_rtx_REG (word_mode, REGNO (op0) + 2);
-      else
-       wordpart[1][0] = gen_rtx_REG (word_mode, REGNO (op0) + 1);
+      rtx pic_ref, address;
+      rtx insn;
 
-      if (TARGET_ARCH32)
-       {
-         wordpart[2][0] = gen_rtx_REG (word_mode, REGNO (op0) + 2);
-         wordpart[3][0] = gen_rtx_REG (word_mode, REGNO (op0) + 3);
-       }
-  
-      /* Loading into a register which overlaps a register used in the
-        address.  */
-      if (optype1 != REGOP && reg_overlap_mentioned_p (op0, op1))
+      if (reg == 0)
        {
-         int i;
-         int count;
-
-         count = 0;
-
-         for (i = 0; i < 4 && wordpart[i][0] != NULL; i++)
-           {
-             if (reg_mentioned_p (wordpart[i][0], op1))
-               {
-                 load_late[i] = wordpart[i][0];
-                 load_late_half[TARGET_ARCH64 ? i : i/2] = 1;
-                 count++;
-               }
-           }
-         if (count > 2)
-           {
-             /* Not sure what to do here. Multiple adds? Can't happen. */
-             abort ();
-           }
-         else if (count == 2)
-           {
-             /* We have a two-address source operand, and both registers
-                overlap with the dest quad. Add them together and
-                store the result into the last register of the quad being
-                loaded, then generate an appropriate MEM insn. */
-             rtx temp[3];
-             int place = 0;
-
-             for (i = 0; i < 4; i++)
-               {
-                 if (load_late[i])
-                   {
-                     temp[place++] = load_late[i];
-                     load_late[i] = 0;
-                   }
-               }
-             temp[2] = wordpart[3][0];
-             output_asm_insn ("add %0, %1, %2", temp);
-             load_late_half[0] = 0;
-             load_late_half[1] = 1;
-             op1 = gen_rtx_MEM (TFmode, wordpart[3][0]);
-             operands[1] = op1;
-             optype1 = OFFSOP;
-           }
+         if (reload_in_progress || reload_completed)
+           abort ();
+         else
+           reg = gen_reg_rtx (Pmode);
        }
-    }
-
-  /* If an operand is an unoffsettable memory ref, find a register
-     we can increment temporarily to make it refer to the later words.  */
-
-  if (optype0 == MEMOP)
-    addreg0 = find_addr_reg (XEXP (op0, 0));
-
-  if (optype1 == MEMOP)
-    addreg1 = find_addr_reg (XEXP (op1, 0));
 
-  /* Ok, we can do one word at a time.
-     Set up in wordpart the operands to use for each word of the arguments.  */
-
-  if (optype0 == OFFSOP)
-    {
-      wordpart[0][0] = adj_offsettable_operand (op0, 0);
-      if (TARGET_ARCH32)
+      if (flag_pic == 2)
        {
-         wordpart[1][0] = adj_offsettable_operand (op0, 4);
-         wordpart[2][0] = adj_offsettable_operand (op0, 8);
-         wordpart[3][0] = adj_offsettable_operand (op0, 12);
+         /* If not during reload, allocate another temp reg here for loading
+            in the address, so that these instructions can be optimized
+            properly.  */
+         rtx temp_reg = ((reload_in_progress || reload_completed)
+                         ? reg : gen_reg_rtx (Pmode));
+
+         /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
+            won't get confused into thinking that these two instructions
+            are loading in the true address of the symbol.  If in the
+            future a PIC rtx exists, that should be used instead.  */
+         emit_insn (gen_movsi_high_pic (temp_reg, orig));
+         emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
+         address = temp_reg;
        }
       else
-       wordpart[1][0] = adj_offsettable_operand (op0, 8);
+       address = orig;
+
+      pic_ref = gen_rtx_MEM (Pmode,
+                        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);
+      /* Put a REG_EQUAL note on this insn, so that it can be optimized
+        by loop.  */
+      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
+                                 REG_NOTES (insn));
+      return reg;
     }
-  else if (optype0 != REGOP)
+  else if (GET_CODE (orig) == CONST)
     {
-      wordpart[0][0] = op0;
-      wordpart[1][0] = op0;
-      wordpart[2][0] = op0;
-      wordpart[3][0] = op0;
-    }
+      rtx base, offset;
 
-  if (optype1 == REGOP)
-    {
-      wordpart[0][1] = gen_rtx_REG (word_mode, REGNO (op1) + 0);
-      if (TARGET_ARCH64 && FP_REG_P (op1)
-         && REGNO (op1) < SPARC_FIRST_V9_FP_REG)
-       wordpart[1][1] = gen_rtx_REG (word_mode, REGNO (op1) + 2);
-      else
-       wordpart[1][1] = gen_rtx_REG (word_mode, REGNO (op1) + 1);
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+         && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+       return orig;
 
-      if (TARGET_ARCH32)
+      if (reg == 0)
        {
-         wordpart[2][1] = gen_rtx_REG (word_mode, REGNO (op1) + 2);
-         wordpart[3][1] = gen_rtx_REG (word_mode, REGNO (op1) + 3);
+         if (reload_in_progress || reload_completed)
+           abort ();
+         else
+           reg = gen_reg_rtx (Pmode);
        }
-    }
-  else if (optype1 == OFFSOP)
-    {
-      wordpart[0][1] = adj_offsettable_operand (op1, 0);
-      if (TARGET_ARCH32)
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS)
        {
-         wordpart[1][1] = adj_offsettable_operand (op1, 4);
-         wordpart[2][1] = adj_offsettable_operand (op1, 8);
-         wordpart[3][1] = adj_offsettable_operand (op1, 12);
+         base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+         offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+                                        base == reg ? 0 : reg);
        }
       else
-       wordpart[1][1] = adj_offsettable_operand (op1, 8);
-    }
-  else if (optype1 == CNSTOP)
-    {
-      REAL_VALUE_TYPE r;
-      long l[4];
-
-      /* This only works for TFmode floating point constants.  */
-      if (GET_CODE (op1) != CONST_DOUBLE || GET_MODE (op1) != TFmode)
        abort ();
 
-      REAL_VALUE_FROM_CONST_DOUBLE (r, op1);
-      REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
-      
-      wordpart[0][1] = GEN_INT (l[0]);
-      wordpart[1][1] = GEN_INT (l[1]);
-      wordpart[2][1] = GEN_INT (l[2]);
-      wordpart[3][1] = GEN_INT (l[3]);
-    }
-  else
-    {
-      wordpart[0][1] = op1;
-      wordpart[1][1] = op1;
-      wordpart[2][1] = op1;
-      wordpart[3][1] = op1;
+      if (GET_CODE (offset) == CONST_INT)
+       {
+         if (SMALL_INT (offset))
+           return plus_constant_for_output (base, INTVAL (offset));
+         else if (! reload_in_progress && ! reload_completed)
+           offset = force_reg (Pmode, offset);
+         else
+           /* If we reach here, then something is seriously wrong.  */
+           abort ();
+       }
+      return gen_rtx_PLUS (Pmode, base, offset);
     }
+  else if (GET_CODE (orig) == LABEL_REF)
+    /* ??? Why do we do this?  */
+    /* Now movsi_pic_label_ref uses it, but we ought to be checking that
+       the register is live instead, in case it is eliminated.  */
+    current_function_uses_pic_offset_table = 1;
 
-  /* Easy case: try moving the quad as two pairs.  Check for moving between
-     an even/odd register pair and a memory location.
-     Also handle new v9 fp regs here.  */
-  /* ??? Should also handle the case of non-offsettable addresses here.
-     We can at least do the first pair as a ldd/std, and then do the third
-     and fourth words individually.  */
-  if ((optype0 == REGOP && optype1 == OFFSOP && (REGNO (op0) & 1) == 0)
-      || (optype0 == OFFSOP && optype1 == REGOP && (REGNO (op1) & 1) == 0))
-    {
-      rtx mem, reg;
-      int use_ldx;
+  return orig;
+}
 
-      if (optype0 == REGOP)
-       mem = op1, reg = op0;
-      else
-       mem = op0, reg = op1;
+/* Set up PIC-specific rtl.  This should not cause any insns
+   to be emitted.  */
 
-      if (mem_aligned_8 (mem)
-         /* If this is a floating point register higher than %f31,
-            then we *must* use an aligned load, since `ld' will not accept
-            the register number.  */
-         || (TARGET_V9 && REGNO (reg) >= SPARC_FIRST_V9_FP_REG))
-       {
-         static char * const mov_by_64[2][2][2] = {
-           { { "std %S1,%2;std %1,%0", "stx %R1,%2;stx %1,%0" },
-             { "ldd %2,%S0;ldd %1,%0", "ldx %2,%R0;ldx %1,%0" } },
-           { { "std %1,%0;std %S1,%2", "stx %1,%0;stx %R1,%2" },
-             { "ldd %1,%0;ldd %2,%S0", "ldx %1,%0;ldx %2,%R0" } }
-         };
-
-         if (TARGET_V9 && FP_REG_P (reg) && TARGET_HARD_QUAD)
-           {
-             /* Only abort if the register # requires that we use ldq. */
-             if ((REGNO (reg) & 3) == 0)
-               {
-                 /* ??? Can `mem' have an inappropriate alignment here?  */
-                 return (mem == op1 ? "ldq %1,%0" : "stq %1,%0");
-               }
-             else 
-               {
-                 if (REGNO (reg) >= SPARC_FIRST_V9_FP_REG)
-                   abort();
-               }
-           }
-         operands[2] = adj_offsettable_operand (mem, 8);
+void
+initialize_pic ()
+{
+}
+
+/* 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 ();
 
-         /* Do the loads in the right order; can't overwrite our address
-            register. */
-         use_ldx = TARGET_ARCH64 && !FP_REG_P (reg);
-         return mov_by_64[!load_late_half[0]][mem == op1][use_ldx];
-       }
-    }
+  return seq;
+}
 
-  /* If the first move would clobber the source of the second one,
-     do them in the other order.  */
+/* Emit special PIC prologues and epilogues.  */
 
-  /* Overlapping registers?  */
-  if (TARGET_ARCH32)
-    {
-      if (optype0 == REGOP && optype1 == REGOP
-         && (REGNO (op0) == REGNO (wordpart[1][3])
-             || REGNO (op0) == REGNO (wordpart[1][2])
-             || REGNO (op0) == REGNO (wordpart[1][1])))
-       {
-         /* Do fourth word.  */
-         output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
-         /* Do the third word.  */
-         output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
-         /* Do the second word.  */
-         output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
-         /* Do lowest-numbered word.  */
-         output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]);
-         return "";
-       }
-    }
-  else /* TARGET_ARCH64 */
-    {
-      if (optype0 == REGOP && optype1 == REGOP
-         && REGNO (op0) == REGNO (wordpart[1][1]))
-       {
-         output_asm_insn ("mov %1,%0", wordpart[1]);
-         output_asm_insn ("mov %1,%0", wordpart[0]);
-         return "";
-       }
-    }
+void
+finalize_pic ()
+{
+  /* Labels to get the PC in the prologue of this function.  */
+  int orig_flag_pic = flag_pic;
+  rtx insn;
 
-  /* Normal case: move the words in lowest to highest address order.
-     There may have an overlapping register; in that case, skip and go
-     back. */
+  if (current_function_uses_pic_offset_table == 0)
+    return;
 
-  if (TARGET_ARCH32)
+  if (! flag_pic)
+    abort ();
+
+  /* If we havn't emitted the special get_pc helper function, do so now.  */
+  if (get_pc_symbol_name[0] == 0)
     {
-      int i;
-      int offset = 0xc;
-      rtx temp[2];
+      ASM_GENERATE_INTERNAL_LABEL (get_pc_symbol_name, "LGETPC", 0);
 
-      for (i = 0; i < 4; i++)
-       {
-         if (! load_late[i])
-           output_asm_insn (singlemove_string (wordpart[i]), wordpart[i]);
+      text_section ();
+      ASM_OUTPUT_ALIGN (asm_out_file, 3);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0);
+      fputs ("\tretl\n\tadd %o7,%l7,%l7\n", asm_out_file);
+    }
 
-         if (i != 3)
-           {
-             /* Make any unoffsettable addresses point at the next word.  */
-             if (addreg0)
-               output_asm_insn ("add %0,0x4,%0", &addreg0);
-             if (addreg1)
-               output_asm_insn ("add %0,0x4,%0", &addreg1);
-           }
-       }
-      for (i = 0; i < 4; i++)
-       {
-         if (load_late[i])
-           {
-             int fix = offset - i * 4;
+  /* Initialize every time through, since we can't easily
+     know this to be permanent.  */
+  global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+  get_pc_symbol = gen_rtx_SYMBOL_REF (Pmode, get_pc_symbol_name);
+  flag_pic = 0;
 
-             /* Back up to the appropriate place. */
-             temp[1] = GEN_INT (-fix);
-             if (addreg0)
-               {
-                 temp[0] = addreg0;
-                 output_asm_insn ("add %0,%1,%0", temp);
-               }
-             if (addreg1)
-               {
-                 temp[0] = addreg1;
-                 output_asm_insn ("add %0,%1,%0", temp);
-               }
-             output_asm_insn (singlemove_string (wordpart[i]),
-                              wordpart[i]);
-             /* Don't modify the register that's the destination of the
-                move. */
-             temp[0] = GEN_INT (-(offset - fix));
-             if (addreg0 && REGNO (addreg0) != REGNO (wordpart[i][0]))
-               {
-                 temp[1] = addreg0;
-                 output_asm_insn("add %0,%1,%0", temp);
-               }
-             if (addreg1 && REGNO (addreg1) != REGNO (wordpart[i][0]))
-               {
-                 temp[1] = addreg1;
-                 output_asm_insn("add %0,%1,%0",temp);
-               }
-             offset = 0;
-             break;
-           }
-       }
-      if (offset)
-       {
-         temp[1] = GEN_INT (-offset);
-         /* Undo the adds we just did.  */
-         if (addreg0)
-           {
-             temp[0] = addreg0;
-             output_asm_insn ("add %0,%1,%0", temp);
-           }
-         if (addreg1)
-           {
-             temp[0] = addreg1;
-             output_asm_insn ("add %0,%1,%0", temp);
-           }
-       }
-    }
-  else /* TARGET_ARCH64 */
-    {
-      if (load_late_half[0]) 
-       {
-         /* Load the second half first. */
-         if (addreg0)
-           output_asm_insn ("add %0,0x8,%0", &addreg0);
-         if (addreg1)
-           output_asm_insn ("add %0,0x8,%0", &addreg1);
+  emit_insn_after (pic_setup_code (), get_insns ());
 
-         output_asm_insn (doublemove_string (wordpart[1]), wordpart[1]);
+  /* Insert the code in each nonlocal goto receiver.  */
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+       && XINT (PATTERN (insn), 1) == 4)
+      emit_insn_after (pic_setup_code (), insn);
 
-         /* Undo the adds we just did.  */
-         if (addreg0)
-           output_asm_insn ("add %0,-0x8,%0", &addreg0);
-         if (addreg1)
-           output_asm_insn ("add %0,-0x8,%0", &addreg1);
+  flag_pic = orig_flag_pic;
 
-         output_asm_insn (doublemove_string (wordpart[0]), wordpart[0]);
-       }
-      else
-       {
-         output_asm_insn (doublemove_string (wordpart[0]), wordpart[0]);
-
-         if (addreg0)
-           output_asm_insn ("add %0,0x8,%0", &addreg0);
-         if (addreg1)
-           output_asm_insn ("add %0,0x8,%0", &addreg1);
-
-         /* Do the second word.  */
-         output_asm_insn (doublemove_string (wordpart[1]), wordpart[1]);
-
-         /* Undo the adds we just did.  But don't modify the dest of
-            the move. */
-         if (addreg0 && REGNO (addreg0) != REGNO (wordpart[1][0]))
-           output_asm_insn ("add %0,-0x8,%0", &addreg0);
-         if (addreg1 && REGNO (addreg1) != REGNO (wordpart[1][0]))
-           output_asm_insn ("add %0,-0x8,%0", &addreg1);
-       }
-    }
-  
-  return "";
+  /* Need to emit this whether or not we obey regdecls,
+     since setjmp/longjmp can cause life info to screw up.
+     ??? In the case where we don't obey regdecls, this is not sufficient
+     since we may not fall out the bottom.  */
+  emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
 }
 \f
-/* Output assembler code to perform a doubleword move insn with operands
-   OPERANDS, one of which must be a floating point register.  */
+/* Return 1 if RTX is a MEM which is known to be aligned to at
+   least an 8 byte boundary.  */
 
-char *
-output_fp_move_double (operands)
-     rtx *operands;
+int
+mem_min_alignment (mem, desired)
+     rtx mem;
+     int desired;
 {
-  if (FP_REG_P (operands[0]))
+  rtx addr, base, offset;
+
+  /* If it's not a MEM we can't accept it.  */
+  if (GET_CODE (mem) != MEM)
+    return 0;
+
+  addr = XEXP (mem, 0);
+  base = offset = NULL_RTX;
+  if (GET_CODE (addr) == PLUS)
     {
-      if (FP_REG_P (operands[1]))
+      if (GET_CODE (XEXP (addr, 0)) == REG)
        {
-         if (TARGET_V9)
-           return "fmovd %1,%0";
+         base = XEXP (addr, 0);
+
+         /* What we are saying here is that if the base
+            REG is aligned properly, the compiler will make
+            sure any REG based index upon it will be so
+            as well.  */
+         if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+           offset = XEXP (addr, 1);
          else
-           return "fmovs %1,%0\n\tfmovs %R1,%R0";
+           offset = const0_rtx;
        }
-      else if (GET_CODE (operands[1]) == REG)
-       abort ();
-      else
-       return output_move_double (operands);
     }
-  else if (FP_REG_P (operands[1]))
+  else if (GET_CODE (addr) == REG)
     {
-      if (GET_CODE (operands[0]) == REG)
-       abort ();
-      else
-       return output_move_double (operands);
+      base = addr;
+      offset = const0_rtx;
     }
-  else abort ();
-}
-
-/* When doing a quad-register move, determine the drection in which
-   the move needs to be performed. SRC and DST are the source and
-   destination registers.
-
-   A value of -1 indicates that the move needs to be done from the
-   highest register to the lowest. */
-
-static int
-move_quad_direction (src, dst)
-     rtx src, dst;
-{
-  if ((REGNO (dst) > REGNO (src))
-      && (REGNO (dst) < (REGNO (src) + 4)))
-    return -1;
-  else
-    return 1;
-}
 
-/* Output assembler code to perform a quadword move insn with operands
-   OPERANDS, one of which must be a floating point register.  */
-
-char *
-output_fp_move_quad (operands)
-     rtx *operands;
-{
-  register rtx op0 = operands[0];
-  register rtx op1 = operands[1];
-
-  if (FP_REG_P (op0))
+  if (base != NULL_RTX)
     {
-      if (FP_REG_P (op1))
+      int regno = REGNO (base);
+
+      if (regno != FRAME_POINTER_REGNUM
+         && regno != STACK_POINTER_REGNUM)
        {
-         if (TARGET_V9 && TARGET_HARD_QUAD)
-           return "fmovq %1,%0";
-         else if (TARGET_V9)
-           {
-             int dir = move_quad_direction (op1, op0);
-             if (dir > 0)
-               return "fmovd %1,%0\n\tfmovd %S1,%S0";
-             else 
-               return "fmovd %S1,%S0\n\tfmovd %1,%0";
-           }
-         else
-           {
-             int dir = move_quad_direction (op0, op1);
-             if (dir > 0)
-               return "fmovs %1,%0\n\tfmovs %R1,%R0\n\tfmovs %S1,%S0\n\tfmovs %T1,%T0";
-             else
-               return "fmovs %T1,%T0\n\tfmovs %S1,%S0\n\tfmovs %R1,%R0\n\tfmovs %1,%0";
-           }
+         /* Check if the compiler has recorded some information
+            about the alignment of the base REG.  If reload has
+            completed, we already matched with proper alignments.  */
+         if (((regno_pointer_align != NULL
+               && REGNO_POINTER_ALIGN (regno) >= desired)
+              || reload_completed)
+             && ((INTVAL (offset) & (desired - 1)) == 0))
+           return 1;
        }
-      else if (GET_CODE (op1) == REG)
-       abort ();
       else
-       return output_move_quad (operands);
+       {
+         if (((INTVAL (offset) - SPARC_STACK_BIAS) & (desired - 1)) == 0)
+           return 1;
+       }
     }
-  else if (FP_REG_P (op1))
+  else if (! TARGET_UNALIGNED_DOUBLES
+          || CONSTANT_P (addr)
+          || GET_CODE (addr) == LO_SUM)
     {
-      if (GET_CODE (op0) == REG)
-       abort ();
-      else
-       return output_move_quad (operands);
+      /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES
+        is true, in which case we can only assume that an access is aligned if
+        it is to a constant address, or the address involves a LO_SUM.  */
+      return 1;
     }
-  else
-    abort ();
+  
+  /* An obviously unaligned address.  */
+  return 0;
 }
+
 \f
 /* Return a REG that occurs in ADDR with coefficient 1.
    ADDR can be effectively incremented by incrementing REG.  */
@@ -2698,71 +2442,6 @@ find_addr_reg (addr)
   abort ();
 }
 \f
-/* Output reasonable peephole for set-on-condition-code insns.
-   Note that these insns assume a particular way of defining
-   labels.  Therefore, *both* sparc.h and this function must
-   be changed if a new syntax is needed.    */
-
-char *
-output_scc_insn (operands, insn)
-     rtx operands[];
-     rtx insn;
-{
-  static char string[100];
-  rtx label = 0, next = insn;
-  int need_label = 0;
-
-  /* This code used to be called with final_sequence nonzero (for fpcc
-     delay slots), but that is no longer allowed.  */
-  if (final_sequence)
-    abort ();
-
-  /* On UltraSPARC a conditional moves blocks until 3 cycles after prior loads
-     complete.  It might be beneficial here to use branches if any recent
-     instructions were loads.  */
-  if (TARGET_V9 && REGNO (operands[1]) == SPARC_ICC_REG)
-    return "mov 0,%0\n\tmov%C2 %x1,1,%0";
-
-  /* Try doing a jump optimization which jump.c can't do for us
-     because we did not expose that setcc works by using branches.
-
-     If this scc insn is followed by an unconditional branch, then have
-     the jump insn emitted here jump to that location, instead of to
-     the end of the scc sequence as usual.  */
-
-  do
-    {
-      if (GET_CODE (next) == CODE_LABEL)
-       label = next;
-      next = NEXT_INSN (next);
-    }
-  while (next && (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL));
-
-  if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next))
-    label = JUMP_LABEL (next);
-
-  /* If not optimizing, jump label fields are not set.  To be safe, always
-     check here to whether label is still zero.  */
-  if (label == 0)
-    {
-      label = gen_label_rtx ();
-      need_label = 1;
-    }
-
-  LABEL_NUSES (label) += 1;
-
-  /* operands[3] is an unused slot.  */
-  operands[3] = label;
-
-  strcpy (string, output_cbranch (operands[2], 3, 0, 1, 0));
-  strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
-
-  if (need_label)
-    strcat (string, "\n%l3:");
-
-  return string;
-}
-\f
 /* Vectors to keep interesting information about registers where it can easily
    be got.  We use to use the actual mode value as the bit number, but there
    are more than 32 modes now.  Instead we use two tables: one indexed by
@@ -2973,7 +2652,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
        {
          if (regs_ever_live[i] && ! call_used_regs[i])
            {
-             fprintf (file, "\tstx %s,[%s+%d]\n",
+             fprintf (file, "\tstx\t%s, [%s+%d]\n",
                       reg_names[i], base, offset + 4 * n_regs);
              if (dwarf2out_do_frame ())
                dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
@@ -2989,7 +2668,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
            {
              if (regs_ever_live[i+1] && ! call_used_regs[i+1])
                {
-                 fprintf (file, "\tstd %s,[%s+%d]\n",
+                 fprintf (file, "\tstd\t%s, [%s+%d]\n",
                           reg_names[i], base, offset + 4 * n_regs);
                  if (dwarf2out_do_frame ())
                    {
@@ -3001,7 +2680,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
                }
              else
                {
-                 fprintf (file, "\tst %s,[%s+%d]\n",
+                 fprintf (file, "\tst\t%s, [%s+%d]\n",
                           reg_names[i], base, offset + 4 * n_regs);
                  if (dwarf2out_do_frame ())
                    dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
@@ -3012,7 +2691,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
            {
              if (regs_ever_live[i+1] && ! call_used_regs[i+1])
                {
-                 fprintf (file, "\tst %s,[%s+%d]\n",
+                 fprintf (file, "\tst\t%s, [%s+%d]\n",
                           reg_names[i+1], base, offset + 4 * n_regs + 4);
                  if (dwarf2out_do_frame ())
                    dwarf2out_reg_save ("", i + 1, real_offset + 4 * n_regs + 4);
@@ -3044,7 +2723,7 @@ restore_regs (file, low, high, base, offset, n_regs)
       for (i = low; i < high; i++)
        {
          if (regs_ever_live[i] && ! call_used_regs[i])
-           fprintf (file, "\tldx [%s+%d], %s\n",
+           fprintf (file, "\tldx\t[%s+%d], %s\n",
              base, offset + 4 * n_regs, reg_names[i]),
            n_regs += 2;
        }
@@ -3055,15 +2734,15 @@ restore_regs (file, low, high, base, offset, n_regs)
        {
          if (regs_ever_live[i] && ! call_used_regs[i])
            if (regs_ever_live[i+1] && ! call_used_regs[i+1])
-             fprintf (file, "\tldd [%s+%d], %s\n",
+             fprintf (file, "\tldd\t[%s+%d], %s\n",
                       base, offset + 4 * n_regs, reg_names[i]),
              n_regs += 2;
            else
-             fprintf (file, "\tld [%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 [%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;
        }
@@ -3152,9 +2831,9 @@ build_big_number (file, num, reg)
 {
   if (num >= 0 || ! TARGET_ARCH64)
     {
-      fprintf (file, "\tsethi %%hi(%d),%s\n", num, reg);
+      fprintf (file, "\tsethi\t%%hi(%d), %s\n", num, reg);
       if ((num & 0x3ff) != 0)
-       fprintf (file, "\tor %s,%%lo(%d),%s\n", reg, num, reg);
+       fprintf (file, "\tor\t%s, %%lo(%d), %s\n", reg, num, reg);
     }
   else /* num < 0 && TARGET_ARCH64 */
     {
@@ -3167,7 +2846,7 @@ build_big_number (file, num, reg)
       int inv = ~asize;
       int low = -0x400 + (asize & 0x3FF);
          
-      fprintf (file, "\tsethi %%hi(%d),%s\n\txor %s,%d,%s\n",
+      fprintf (file, "\tsethi\t%%hi(%d), %s\n\txor\t%s, %d, %s\n",
               inv, reg, reg, low, reg);
     }
 }
@@ -3203,16 +2882,16 @@ output_function_prologue (file, size, leaf_function)
   else if (! leaf_function && ! TARGET_BROKEN_SAVERESTORE)
     {
       if (actual_fsize <= 4096)
-       fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);
+       fprintf (file, "\tsave\t%%sp, -%d, %%sp\n", actual_fsize);
       else if (actual_fsize <= 8192)
        {
-         fprintf (file, "\tsave %%sp,-4096,%%sp\n");
-         fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
+         fprintf (file, "\tsave\t%%sp, -4096, %%sp\n");
+         fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
        }
       else
        {
          build_big_number (file, -actual_fsize, "%g1");
-         fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
+         fprintf (file, "\tsave\t%%sp, %%g1, %%sp\n");
        }
     }
   else if (! leaf_function && TARGET_BROKEN_SAVERESTORE)
@@ -3223,31 +2902,31 @@ output_function_prologue (file, size, leaf_function)
       fprintf (file, "\tsave\n");
 
       if (actual_fsize <= 4096)
-       fprintf (file, "\tadd %%fp,-%d,%%sp\n", actual_fsize);
+       fprintf (file, "\tadd\t%%fp, -%d, %%sp\n", actual_fsize);
       else if (actual_fsize <= 8192)
        {
-         fprintf (file, "\tadd %%fp,-4096,%%sp\n");
-         fprintf (file, "\tadd %%fp,-%d,%%sp\n", actual_fsize - 4096);
+         fprintf (file, "\tadd\t%%fp, -4096, %%sp\n");
+         fprintf (file, "\tadd\t%%fp, -%d, %%sp\n", actual_fsize - 4096);
        }
       else
        {
          build_big_number (file, -actual_fsize, "%g1");
-         fprintf (file, "\tadd %%fp,%%g1,%%sp\n");
+         fprintf (file, "\tadd\t%%fp, %%g1, %%sp\n");
        }
     }
   else /* leaf function */
     {
       if (actual_fsize <= 4096)
-       fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
+       fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize);
       else if (actual_fsize <= 8192)
        {
-         fprintf (file, "\tadd %%sp,-4096,%%sp\n");
-         fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
+         fprintf (file, "\tadd\t%%sp, -4096, %%sp\n");
+         fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
        }
       else
        {
          build_big_number (file, -actual_fsize, "%g1");
-         fprintf (file, "\tadd %%sp,%%g1,%%sp\n");
+         fprintf (file, "\tadd\t%%sp, %%g1, %%sp\n");
        }
     }
 
@@ -3293,7 +2972,7 @@ output_function_prologue (file, size, leaf_function)
             output_function_epilogue will lose (the result will get
             clobbered).  */
          build_big_number (file, offset, "%g1");
-         fprintf (file, "\tadd %s,%%g1,%%g1\n", frame_base_name);
+         fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
          base = "%g1";
          offset = 0;
        }
@@ -3348,12 +3027,13 @@ output_function_epilogue (file, size, leaf_function)
 
   else if (current_function_epilogue_delay_list == 0)
     {                                                
-      /* If code does not drop into the epilogue, do nothing.  */
+      /* If code does not drop into the epilogue, we need
+        do nothing except output pending case vectors.  */
       rtx insn = get_last_insn ();                               
       if (GET_CODE (insn) == NOTE)                               
       insn = prev_nonnote_insn (insn);                           
       if (insn && GET_CODE (insn) == BARRIER)                    
-      return;                                                    
+      goto output_vectors;                                                    
     }
 
   /* Restore any call saved registers.  */
@@ -3366,7 +3046,7 @@ output_function_epilogue (file, size, leaf_function)
       if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 /*double*/)
        {
          build_big_number (file, offset, "%g1");
-         fprintf (file, "\tadd %s,%%g1,%%g1\n", frame_base_name);
+         fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
          base = "%g1";
          offset = 0;
        }
@@ -3388,9 +3068,9 @@ output_function_epilogue (file, size, leaf_function)
 
   /* Work out how to skip the caller's unimp instruction if required.  */
   if (leaf_function)
-    ret = (SKIP_CALLERS_UNIMP_P ? "jmp %o7+12" : "retl");
+    ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%o7+12" : "retl");
   else
-    ret = (SKIP_CALLERS_UNIMP_P ? "jmp %i7+12" : "ret");
+    ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
 
   if (TARGET_EPILOGUE || leaf_label)
     {
@@ -3411,7 +3091,7 @@ output_function_epilogue (file, size, leaf_function)
              final_scan_insn (insn, file, 1, 0, 1);
            }
          else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
-           fputs ("\treturn %i7+8\n\tnop\n", file);
+           fputs ("\treturn\t%i7+8\n\tnop\n", file);
          else
            fprintf (file, "\t%s\n\trestore\n", ret);
        }
@@ -3433,18 +3113,21 @@ output_function_epilogue (file, size, leaf_function)
       else if (actual_fsize == 0)
        fprintf (file, "\t%s\n\tnop\n", ret);
       else if (actual_fsize <= 4096)
-       fprintf (file, "\t%s\n\tsub %%sp,-%d,%%sp\n", ret, actual_fsize);
+       fprintf (file, "\t%s\n\tsub\t%%sp, -%d, %%sp\n", ret, actual_fsize);
       else if (actual_fsize <= 8192)
-       fprintf (file, "\tsub %%sp,-4096,%%sp\n\t%s\n\tsub %%sp,-%d,%%sp\n",
+       fprintf (file, "\tsub\t%%sp, -4096, %%sp\n\t%s\n\tsub\t%%sp, -%d, %%sp\n",
                 ret, actual_fsize - 4096);
       else if ((actual_fsize & 0x3ff) == 0)
-       fprintf (file, "\tsethi %%hi(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
+       fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
                 actual_fsize, ret);
       else              
-       fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
+       fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\tor\t%%g1, %%lo(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
                 actual_fsize, actual_fsize, ret);
       target_flags |= old_target_epilogue;
     }
+
+ output_vectors:
+  sparc_output_deferred_case_vectors ();
 }
 \f
 /* Functions for handling argument passing.
@@ -4366,16 +4049,16 @@ output_cbranch (op, label, reversed, annul, noop, insn)
      int reversed, annul, noop;
      rtx insn;
 {
-  static char string[20];
+  static char string[32];
   enum rtx_code code = GET_CODE (op);
   rtx cc_reg = XEXP (op, 0);
   enum machine_mode mode = GET_MODE (cc_reg);
-  static char v8_labelno[] = " %lX";
-  static char v9_icc_labelno[] = " %%icc,%lX";
-  static char v9_xcc_labelno[] = " %%xcc,%lX";
-  static char v9_fcc_labelno[] = " %%fccX,%lY";
+  static char v8_labelno[] = "%lX";
+  static char v9_icc_labelno[] = "%%icc, %lX";
+  static char v9_xcc_labelno[] = "%%xcc, %lX";
+  static char v9_fcc_labelno[] = "%%fccX, %lY";
   char *labelno;
-  int labeloff;
+  int labeloff, spaces = 8;
 
   /* ??? !v9: FP branches cannot be preceded by another floating point insn.
      Because there is currently no concept of pre-delay slots, we can fix
@@ -4396,16 +4079,28 @@ output_cbranch (op, label, reversed, annul, noop, insn)
     {
     case NE:
       if (mode == CCFPmode || mode == CCFPEmode)
-       strcat (string, "fbne");
+       {
+         strcat (string, "fbne");
+         spaces -= 4;
+       }
       else
-       strcpy (string, "bne");
+       {
+         strcpy (string, "bne");
+         spaces -= 3;
+       }
       break;
 
     case EQ:
       if (mode == CCFPmode || mode == CCFPEmode)
-       strcat (string, "fbe");
+       {
+         strcat (string, "fbe");
+         spaces -= 3;
+       }
       else
-       strcpy (string, "be");
+       {
+         strcpy (string, "be");
+         spaces -= 2;
+       }
       break;
 
     case GE:
@@ -4415,23 +4110,39 @@ output_cbranch (op, label, reversed, annul, noop, insn)
            strcat (string, "fbul");
          else
            strcat (string, "fbge");
+         spaces -= 4;
        }
       else if (mode == CC_NOOVmode)
-       strcpy (string, "bpos");
+       {
+         strcpy (string, "bpos");
+         spaces -= 4;
+       }
       else
-       strcpy (string, "bge");
+       {
+         strcpy (string, "bge");
+         spaces -= 3;
+       }
       break;
 
     case GT:
       if (mode == CCFPmode || mode == CCFPEmode)
        {
          if (reversed)
-           strcat (string, "fbule");
+           {
+             strcat (string, "fbule");
+             spaces -= 5;
+           }
          else
-           strcat (string, "fbg");
+           {
+             strcat (string, "fbg");
+             spaces -= 3;
+           }
        }
       else
-       strcpy (string, "bg");
+       {
+         strcpy (string, "bg");
+         spaces -= 2;
+       }
       break;
 
     case LE:
@@ -4441,52 +4152,75 @@ output_cbranch (op, label, reversed, annul, noop, insn)
            strcat (string, "fbug");
          else
            strcat (string, "fble");
+         spaces -= 4;
        }
       else
-       strcpy (string, "ble");
+       {
+         strcpy (string, "ble");
+         spaces -= 3;
+       }
       break;
 
     case LT:
       if (mode == CCFPmode || mode == CCFPEmode)
        {
          if (reversed)
-           strcat (string, "fbuge");
+           {
+             strcat (string, "fbuge");
+             spaces -= 5;
+           }
          else
-           strcat (string, "fbl");
+           {
+             strcat (string, "fbl");
+             spaces -= 3;
+           }
        }
       else if (mode == CC_NOOVmode)
-       strcpy (string, "bneg");
+       {
+         strcpy (string, "bneg");
+         spaces -= 4;
+       }
       else
-       strcpy (string, "bl");
+       {
+         strcpy (string, "bl");
+         spaces -= 2;
+       }
       break;
 
     case GEU:
       strcpy (string, "bgeu");
+      spaces -= 4;
       break;
 
     case GTU:
       strcpy (string, "bgu");
+      spaces -= 3;
       break;
 
     case LEU:
       strcpy (string, "bleu");
+      spaces -= 4;
       break;
 
     case LTU:
       strcpy (string, "blu");
+      spaces -= 3;
       break;
 
     default:
-      break;
+      abort ();
     }
 
   /* Now add the annulling, the label, and a possible noop.  */
   if (annul)
-    strcat (string, ",a");
+    {
+      strcat (string, ",a");
+      spaces -= 2;
+    }
 
   if (! TARGET_V9)
     {
-      labeloff = 3;
+      labeloff = 2;
       labelno = v8_labelno;
     }
   else
@@ -4494,7 +4228,11 @@ output_cbranch (op, label, reversed, annul, noop, insn)
       rtx note;
 
       if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
-       strcat (string, INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
+       {
+         strcat (string,
+                 INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
+         spaces -= 3;
+       }
 
       labeloff = 9;
       if (mode == CCFPmode || mode == CCFPEmode)
@@ -4502,7 +4240,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
          labeloff = 10;
          labelno = v9_fcc_labelno;
          /* Set the char indicating the number of the fcc reg to use.  */
-         labelno[6] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
+         labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
        }
       else if (mode == CCXmode || mode == CCX_NOOVmode)
        labelno = v9_xcc_labelno;
@@ -4512,6 +4250,10 @@ output_cbranch (op, label, reversed, annul, noop, insn)
   /* Set the char indicating the number of the operand containing the
      label_ref.  */
   labelno[labeloff] = label + '0';
+  if (spaces > 0)
+    strcat (string, "\t");
+  else
+    strcat (string, " ");
   strcat (string, labelno);
 
   if (noop)
@@ -4532,15 +4274,18 @@ output_cbranch (op, label, reversed, annul, noop, insn)
    NOOP is non-zero if we have to follow this branch by a noop.  */
 
 char *
-output_v9branch (op, reg, label, reversed, annul, noop)
+output_v9branch (op, reg, label, reversed, annul, noop, insn)
      rtx op;
      int reg, label;
      int reversed, annul, noop;
+     rtx insn;
 {
   static char string[20];
   enum rtx_code code = GET_CODE (op);
   enum machine_mode mode = GET_MODE (XEXP (op, 0));
-  static char labelno[] = " %X,%lX";
+  static char labelno[] = "%X, %lX";
+  rtx note;
+  int spaces = 8;
 
   /* If not floating-point or if EQ or NE, we can just reverse the code.  */
   if (reversed)
@@ -4556,26 +4301,32 @@ output_v9branch (op, reg, label, reversed, annul, noop)
     {
     case NE:
       strcpy (string, "brnz");
+      spaces -= 4;
       break;
 
     case EQ:
       strcpy (string, "brz");
+      spaces -= 3;
       break;
 
     case GE:
       strcpy (string, "brgez");
+      spaces -= 5;
       break;
 
     case LT:
       strcpy (string, "brlz");
+      spaces -= 4;
       break;
 
     case LE:
       strcpy (string, "brlez");
+      spaces -= 5;
       break;
 
     case GT:
       strcpy (string, "brgz");
+      spaces -= 4;
       break;
 
     default:
@@ -4584,12 +4335,24 @@ output_v9branch (op, reg, label, reversed, annul, noop)
 
   /* Now add the annulling, reg, label, and nop.  */
   if (annul)
-    strcat (string, ",a");
+    {
+      strcat (string, ",a");
+      spaces -= 2;
+    }
 
-  /* ??? Optional prediction bit ",pt" or ",pf" goes here.  */
+  if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
+    {
+      strcat (string,
+             INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
+      spaces -= 3;
+    }
 
-  labelno[2] = reg + '0';
+  labelno[1] = reg + '0';
   labelno[6] = label + '0';
+  if (spaces > 0)
+    strcat (string, "\t");
+  else
+    strcat (string, " ");
   strcat (string, labelno);
 
   if (noop)
@@ -4681,24 +4444,24 @@ output_return (operands)
       if (actual_fsize <= 4096)
        {
          if (SKIP_CALLERS_UNIMP_P)
-           return "jmp %%o7+12\n\tsub %%sp,-%0,%%sp";
+           return "jmp\t%%o7+12\n\tsub\t%%sp, -%0, %%sp";
          else
-           return "retl\n\tsub %%sp,-%0,%%sp";
+           return "retl\n\tsub\t%%sp, -%0, %%sp";
        }
       else if (actual_fsize <= 8192)
        {
          operands[0] = GEN_INT (actual_fsize - 4096);
          if (SKIP_CALLERS_UNIMP_P)
-           return "sub %%sp,-4096,%%sp\n\tjmp %%o7+12\n\tsub %%sp,-%0,%%sp";
+           return "sub\t%%sp, -4096, %%sp\n\tjmp\t%%o7+12\n\tsub\t%%sp, -%0, %%sp";
          else
-           return "sub %%sp,-4096,%%sp\n\tretl\n\tsub %%sp,-%0,%%sp";
+           return "sub\t%%sp, -4096, %%sp\n\tretl\n\tsub\t%%sp, -%0, %%sp";
        }
       else if (SKIP_CALLERS_UNIMP_P)
        {
          if ((actual_fsize & 0x3ff) != 0)
-           return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
+           return "sethi\t%%hi(%a0), %%g1\n\tor\t%%g1, %%lo(%a0), %%g1\n\tjmp\t%%o7+12\n\tadd\t%%sp, %%g1, %%sp";
          else
-           return "sethi %%hi(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
+           return "sethi\t%%hi(%a0), %%g1\n\tjmp\t%%o7+12\n\tadd\t%%sp, %%g1, %%sp";
        }
       else
        {
@@ -4716,16 +4479,16 @@ output_return (operands)
          epilogue_renumber (&SET_SRC (PATTERN (delay)));
        }
       if (SKIP_CALLERS_UNIMP_P)
-       return "return %%i7+12%#";
+       return "return\t%%i7+12%#";
       else
-       return "return %%i7+8%#";
+       return "return\t%%i7+8%#";
     }
   else
     {
       if (delay)
        abort ();
       if (SKIP_CALLERS_UNIMP_P)
-       return "jmp %%i7+12\n\trestore";
+       return "jmp\t%%i7+12\n\trestore";
       else
        return "ret\n\trestore";
     }
@@ -4756,6 +4519,34 @@ order_regs_for_local_alloc ()
     }
 }
 \f
+/* Return 1 if REG and MEM are legitimate enough to allow the various
+   mem<-->reg splits to be run.  */
+
+int
+sparc_splitdi_legitimate(reg, mem)
+     rtx reg;
+     rtx mem;
+{
+  rtx addr_part = XEXP (mem, 0);
+
+  /* Punt if we are here by mistake.  */
+  if (! reload_completed)
+    abort();
+
+  /* We must have an offsettable memory reference.  */
+  if (! offsettable_memref_p (mem))
+    return 0;
+
+  /* If we have legitimate args for ldd/std, we do not want
+     the split to happen.  */
+  if ((REGNO (reg) % 2) == 0
+      && mem_min_alignment (mem, 8))
+    return 0;
+
+  /* Success.  */
+  return 1;
+}
+
 /* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
    This makes them candidates for using ldd and std insns. 
 
@@ -4886,7 +4677,7 @@ print_operand (file, x, code)
     case '#':
       /* Output a 'nop' if there's nothing for the delay slot.  */
       if (dbr_sequence_length () == 0)
-       fputs ("\n\tnop", file);
+       fputs ("\n\t nop", file);
       return;
     case '*':
       /* Output an annul flag if there's nothing for the delay slot and we
@@ -4904,7 +4695,7 @@ print_operand (file, x, code)
         not optimizing.  This is always used with '*' above.  */
       if (dbr_sequence_length () == 0
          && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
-       fputs ("\n\tnop", file);
+       fputs ("\n\t nop", file);
       return;
     case '_':
       /* Output the Embedded Medium/Anywhere code model base register.  */
@@ -5106,7 +4897,10 @@ print_operand (file, x, code)
   else if (GET_CODE (x) == LO_SUM)
     {
       print_operand (file, XEXP (x, 0), 0);
-      fputs ("+%lo(", file);
+      if (TARGET_CM_MEDMID)
+       fputs ("+%l44(", file);
+      else
+       fputs ("+%lo(", file);
       output_addr_const (file, XEXP (x, 1));
       fputc (')', file);
     }
@@ -5355,10 +5149,10 @@ sparc_initialize_trampoline (tramp, fnaddr, cxt)
 {
   /* SPARC 32 bit trampoline:
 
-       sethi %hi(fn),%g1
-       sethi %hi(static),%g2
-       jmp %g1+%lo(fn)
-       or %g2,%lo(static),%g2
+       sethi   %hi(fn), %g1
+       sethi   %hi(static), %g2
+       jmp     %g1+%lo(fn)
+       or      %g2, %lo(static), %g2
 
     SETHI i,r  = 00rr rrr1 00ii iiii iiii iiii iiii iiii
     JMPL r+i,d = 10dd ddd1 1100 0rrr rr1i iiii iiii iiii
@@ -5407,10 +5201,10 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
      rtx tramp, fnaddr, cxt;
 {
   /*
-       rd %pc,%g1
-       ldx [%g1+24],%g5
-       jmp %g5
-       ldx [%g1+16],%g5
+       rd      %pc, %g1
+       ldx     [%g1+24], %g5
+       jmp     %g5
+       ldx     [%g1+16], %g5
        +16 bytes data
    */
 
@@ -5676,7 +5470,7 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
 
                  if (word_op[0] == 's')
                    {
-                     fprintf (file, "\t%s %s,[%s+%d]\n",
+                     fprintf (file, "\t%s\t%s, [%s+%d]\n",
                               doubleword_op, reg_names[regno],
                               base_reg, offset);
                      if (dwarf2out_do_frame ())
@@ -5688,7 +5482,7 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
                        }
                    }
                  else
-                   fprintf (file, "\t%s [%s+%d],%s\n",
+                   fprintf (file, "\t%s\t[%s+%d], %s\n",
                             doubleword_op, base_reg, offset,
                             reg_names[regno]);
 
@@ -5699,14 +5493,14 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
                {
                  if (word_op[0] == 's')
                    {
-                     fprintf (file, "\t%s %s,[%s+%d]\n",
+                     fprintf (file, "\t%s\t%s, [%s+%d]\n",
                               word_op, reg_names[regno],
                               base_reg, offset);
                      if (dwarf2out_do_frame ())
                        dwarf2out_reg_save ("", regno, offset + base_offset);
                    }
                  else
-                   fprintf (file, "\t%s [%s+%d],%s\n",
+                   fprintf (file, "\t%s\t[%s+%d], %s\n",
                             word_op, base_reg, offset, reg_names[regno]);
 
                  offset += UNITS_PER_WORD;
@@ -5723,14 +5517,14 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
            {
              if (word_op[0] == 's')
                {
-                 fprintf (file, "\t%s %s,[%s+%d]\n",
+                 fprintf (file, "\t%s\t%s, [%s+%d]\n",
                           word_op, reg_names[regno],
                           base_reg, offset);
                  if (dwarf2out_do_frame ())
                    dwarf2out_reg_save ("", regno, offset + base_offset);
                }
              else
-               fprintf (file, "\t%s [%s+%d],%s\n",
+               fprintf (file, "\t%s\t[%s+%d], %s\n",
                         word_op, base_reg, offset, reg_names[regno]);
 
              offset += UNITS_PER_WORD;
@@ -5802,26 +5596,26 @@ sparc_flat_output_function_prologue (file, size)
        {
          if (size <= 4096)
            {
-             fprintf (file, "\tadd %s,%d,%s\n",
+             fprintf (file, "\tadd\t%s, %d, %s\n",
                       sp_str, -size, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
-                 fprintf (file, "\tst %s,[%s+%d]\n",
+                 fprintf (file, "\tst\t%s, [%s+%d]\n",
                           fp_str, sp_str, reg_offset);
-                 fprintf (file, "\tsub %s,%d,%s\t%s# set up frame pointer\n",
+                 fprintf (file, "\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
                           sp_str, -size, fp_str, ASM_COMMENT_START);
                  reg_offset += 4;
                }
            }
          else
            {
-             fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
+             fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
                       size, t1_str, sp_str, t1_str, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
-                 fprintf (file, "\tst %s,[%s+%d]\n",
+                 fprintf (file, "\tst\t%s, [%s+%d]\n",
                           fp_str, sp_str, reg_offset);
-                 fprintf (file, "\tadd %s,%s,%s\t%s# set up frame pointer\n",
+                 fprintf (file, "\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
                           sp_str, t1_str, fp_str, ASM_COMMENT_START);
                  reg_offset += 4;
                }
@@ -5840,7 +5634,7 @@ sparc_flat_output_function_prologue (file, size)
            }
          if (gmask & RETURN_ADDR_MASK)
            {
-             fprintf (file, "\tst %s,[%s+%d]\n",
+             fprintf (file, "\tst\t%s, [%s+%d]\n",
                       reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset);
              if (dwarf2out_do_frame ())
                dwarf2out_return_save ("", reg_offset - size);
@@ -5862,11 +5656,11 @@ sparc_flat_output_function_prologue (file, size)
          
          if (size1 <= 4096)
            {
-             fprintf (file, "\tadd %s,%d,%s\n",
+             fprintf (file, "\tadd\t%s, %d, %s\n",
                       sp_str, -size1, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
-                 fprintf (file, "\tst %s,[%s+%d]\n\tsub %s,%d,%s\t%s# set up frame pointer\n",
+                 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);
                  offset += 4;
@@ -5874,11 +5668,11 @@ sparc_flat_output_function_prologue (file, size)
            }
          else
            {
-             fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
+             fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
                       size1, t1_str, sp_str, t1_str, sp_str);
              if (gmask & FRAME_POINTER_MASK)
                {
-                 fprintf (file, "\tst %s,[%s+%d]\n\tadd %s,%s,%s\t%s# set up frame pointer\n",
+                 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);
                  offset += 4;
@@ -5898,7 +5692,7 @@ sparc_flat_output_function_prologue (file, size)
            }
          if (gmask & RETURN_ADDR_MASK)
            {
-             fprintf (file, "\tst %s,[%s+%d]\n",
+             fprintf (file, "\tst\t%s, [%s+%d]\n",
                       reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
              if (dwarf2out_do_frame ())
                /* offset - size1 == reg_offset - size
@@ -5910,7 +5704,7 @@ sparc_flat_output_function_prologue (file, size)
                                   gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
                                   current_frame_info.fmask,
                                   "st", "std", -size1);
-         fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
+         fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
                   size - size1, t1_str, sp_str, t1_str, sp_str);
          if (dwarf2out_do_frame ())
            if (! (gmask & FRAME_POINTER_MASK))
@@ -5970,15 +5764,15 @@ sparc_flat_output_function_epilogue (file, size)
         delay slot if not otherwise filled by the reload sequence.  */
 
       if (size > 4095)
-       fprintf (file, "\tset %d,%s\n", size, t1_str);
+       fprintf (file, "\tset\t%d, %s\n", size, t1_str);
 
       if (frame_pointer_needed)
        {
          if (size > 4095)
-           fprintf (file,"\tsub %s,%s,%s\t\t%s# sp not trusted here\n",
+           fprintf (file,"\tsub\t%s, %s, %s\t\t%s# sp not trusted here\n",
                     fp_str, t1_str, sp_str, ASM_COMMENT_START);
          else
-           fprintf (file,"\tsub %s,%d,%s\t\t%s# sp not trusted here\n",
+           fprintf (file,"\tsub\t%s, %d, %s\t\t%s# sp not trusted here\n",
                     fp_str, size, sp_str, ASM_COMMENT_START);
        }
 
@@ -5996,7 +5790,7 @@ sparc_flat_output_function_epilogue (file, size)
          /* Offset to register save area from %sp.  */
          reg_offset = size1 - reg_offset;
 
-         fprintf (file, "\tset %d,%s\n\tadd %s,%s,%s\n",
+         fprintf (file, "\tset\t%d, %s\n\tadd\t%s, %s, %s\n",
                   size1, t1_str, sp_str, t1_str, sp_str);
        }
 
@@ -6004,13 +5798,13 @@ sparc_flat_output_function_epilogue (file, size)
         because they are treated specially by the prologue output code.  */
       if (current_frame_info.gmask & FRAME_POINTER_MASK)
        {
-         fprintf (file, "\tld [%s+%d],%s\n",
+         fprintf (file, "\tld\t[%s+%d], %s\n",
                   sp_str, reg_offset, fp_str);
          reg_offset += 4;
        }
       if (current_frame_info.gmask & RETURN_ADDR_MASK)
        {
-         fprintf (file, "\tld [%s+%d],%s\n",
+         fprintf (file, "\tld\t[%s+%d], %s\n",
                   sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]);
          reg_offset += 4;
        }
@@ -6027,12 +5821,12 @@ sparc_flat_output_function_epilogue (file, size)
        {
          size -= size1;
          if (size > 4095)
-           fprintf (file, "\tset %d,%s\n",
+           fprintf (file, "\tset\t%d, %s\n",
                     size, t1_str);
        }
 
       if (current_function_returns_struct)
-       fprintf (file, "\tjmp %%o7+12\n");
+       fprintf (file, "\tjmp\t%%o7+12\n");
       else
        fprintf (file, "\tretl\n");
 
@@ -6049,10 +5843,10 @@ sparc_flat_output_function_epilogue (file, size)
        }
 
       else if (size > 4095)
-       fprintf (file, "\tadd %s,%s,%s\n", sp_str, t1_str, sp_str);
+       fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
 
       else if (size > 0)
-       fprintf (file, "\tadd %s,%d,%s\n", sp_str, size, sp_str);
+       fprintf (file, "\tadd\t%s, %d, %s\n", sp_str, size, sp_str);
 
       else
        fprintf (file, "\tnop\n");
@@ -6060,6 +5854,8 @@ sparc_flat_output_function_epilogue (file, size)
 
   /* Reset state info for each function.  */
   current_frame_info = zero_frame_info;
+
+  sparc_output_deferred_case_vectors ();
 }
 \f
 /* Define the number of delay slots needed for the function epilogue.
@@ -6342,8 +6138,6 @@ set_extends(x, insn)
       /* LO_SUM is used with sethi.  sethi cleared the high
         bits and the values used with lo_sum are positive */
     case LO_SUM:
-      /* UNSPEC is v8plus_clear_high */
-    case UNSPEC:
       /* Store flag stores 0 or 1 */
     case LT: case LTU:
     case GT: case GTU:
@@ -6380,6 +6174,86 @@ set_extends(x, insn)
     }
 }
 
+/* We _ought_ to have only one kind per function, but... */
+static rtx sparc_addr_diff_list;
+static rtx sparc_addr_list;
+
+void
+sparc_defer_case_vector (lab, vec, diff)
+     rtx lab, vec;
+     int diff;
+{
+  vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
+  if (diff)
+    sparc_addr_diff_list
+      = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_diff_list);
+  else
+    sparc_addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_list);
+}
+
+static void 
+sparc_output_addr_vec (vec)
+     rtx vec;
+{
+  rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
+  int idx, vlen = XVECLEN (body, 0);
+
+#ifdef ASM_OUTPUT_CASE_LABEL
+  ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
+                        NEXT_INSN (lab));
+#else
+  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
+#endif
+
+  for (idx = 0; idx < vlen; idx++)
+    {
+      ASM_OUTPUT_ADDR_VEC_ELT
+       (asm_out_file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
+    }
+}
+
+static void 
+sparc_output_addr_diff_vec (vec)
+     rtx vec;
+{
+  rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
+  rtx base = XEXP (XEXP (body, 0), 0);
+  int idx, vlen = XVECLEN (body, 1);
+
+#ifdef ASM_OUTPUT_CASE_LABEL
+  ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
+                        NEXT_INSN (lab));
+#else
+  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
+#endif
+
+  for (idx = 0; idx < vlen; idx++)
+    {
+      ASM_OUTPUT_ADDR_DIFF_ELT
+        (asm_out_file,
+         body,
+         CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
+         CODE_LABEL_NUMBER (base));
+    }
+}
+
+static void
+sparc_output_deferred_case_vectors ()
+{
+  rtx t;
+
+  /* Align to cache line in the function's code section.  */
+  function_section (current_function_decl);
+  ASM_OUTPUT_ALIGN (asm_out_file, 5);
+  
+  for (t = sparc_addr_list; t ; t = XEXP (t, 1))
+    sparc_output_addr_vec (XEXP (t, 0));
+  for (t = sparc_addr_diff_list; t ; t = XEXP (t, 1))
+    sparc_output_addr_diff_vec (XEXP (t, 0));
+
+  sparc_addr_list = sparc_addr_diff_list = NULL_RTX;
+}
+
 /* Return 0 if the high 32 bits of X (the low word of X, if DImode) are
    unknown.  Return 1 if the high bits are zero, -1 if the register is
    sign extended.  */
index 1f21659178a421d7f676aac682803c862798ca96..9749bd1a3b607d4d2764bef77eee7ed8aa78de58 100644 (file)
@@ -916,10 +916,8 @@ do                                                         \
       {                                                                \
        fixed_regs[5] = 1;                                      \
       }                                                                \
-    else                                                       \
-      {                                                                \
-       fixed_regs[1] = 1;                                      \
-      }                                                                \
+    if (TARGET_LIVE_G0)                                                \
+      fixed_regs[0] = 0;                                       \
     if (! TARGET_V9)                                           \
       {                                                                \
        int regno;                                              \
@@ -982,9 +980,15 @@ while (0)
 
 /* A subreg in 64 bit mode will have the wrong offset for a floating point
    register.  The least significant part is at offset 1, compared to 0 for
-   integer registers.  */
+   integer registers.  This only applies when FMODE is a larger mode.  */
 #define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO)                   \
-     (TARGET_ARCH64 && (REGNO) >= 32 && (REGNO) < 96 && (TMODE) == SImode ? 1 : ((REGNO) + (WORD)))
+     (TARGET_ARCH64                                                    \
+      && (REGNO) >= SPARC_FIRST_FP_REG                                 \
+      && (REGNO) <= SPARC_LAST_V9_FP_REG                               \
+      && (TMODE) == SImode                                             \
+      && !((FMODE) == QImode || (FMODE) == HImode)                     \
+      ? ((REGNO) + 1)                                                  \
+      : ((REGNO) + (WORD)))
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    See sparc.c for how we initialize this.  */
@@ -1356,24 +1360,39 @@ extern char leaf_reg_remap[];
 /* Return the register class of a scratch register needed to load IN into
    a register of class CLASS in MODE.
 
-   On the SPARC, when PIC, we need a temporary when loading some addresses
-   into a register.
-
-   Also, we need a temporary when loading/storing a HImode/QImode value
+   We need a temporary when loading/storing a HImode/QImode value
    between memory and the FPU registers.  This can happen when combine puts
    a paradoxical subreg in a float/fix conversion insn.  */
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN)          \
-  ((FP_REG_CLASS_P (CLASS) && ((MODE) == HImode || (MODE) == QImode) \
+  ((FP_REG_CLASS_P (CLASS)                                     \
+    && ((MODE) == HImode || (MODE) == QImode)                  \
     && (GET_CODE (IN) == MEM                                   \
-       || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG)   \
-           && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS)
+        || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG)  \
+            && true_regnum (IN) == -1)))                       \
+   ? GENERAL_REGS                                              \
+   : (((TARGET_CM_MEDANY                                       \
+        && symbolic_operand ((IN), (MODE)))                    \
+       || (TARGET_CM_EMBMEDANY                                 \
+           && text_segment_operand ((IN), (MODE))))            \
+      && !flag_pic)                                            \
+     ? GENERAL_REGS                                            \
+     : NO_REGS)
 
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, IN)         \
-  ((FP_REG_CLASS_P (CLASS) && ((MODE) == HImode || (MODE) == QImode) \
-    && (GET_CODE (IN) == MEM                                   \
-       || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG)   \
-           && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS)
+   ((FP_REG_CLASS_P (CLASS)                                    \
+     && ((MODE) == HImode || (MODE) == QImode)                 \
+     && (GET_CODE (IN) == MEM                                  \
+         || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
+             && true_regnum (IN) == -1)))                      \
+    ? GENERAL_REGS                                             \
+   : (((TARGET_CM_MEDANY                                       \
+        && symbolic_operand ((IN), (MODE)))                    \
+       || (TARGET_CM_EMBMEDANY                                 \
+           && text_segment_operand ((IN), (MODE))))            \
+      && !flag_pic)                                            \
+     ? GENERAL_REGS                                            \
+     : NO_REGS)
 
 /* On SPARC it is not possible to directly move data between 
    GENERAL_REGS and FP_REGS.  */
@@ -2263,15 +2282,13 @@ extern struct rtx_def *sparc_builtin_saveregs ();
    After reload, it makes no difference, since pseudo regs have
    been eliminated by then.  */
 
-/* Optional extra constraints for this machine.  Borrowed from romp.h.
+/* Optional extra constraints for this machine.
 
-   For the SPARC, `Q' means that this is a memory operand but not a
-   symbolic memory operand.  Note that an unassigned pseudo register
-   is such a memory operand.  Needed because reload will generate
-   these things in insns and then not re-recognize the insns, causing
-   constrain_operands to fail.
+   'T' handles memory addresses where the alignment is known to
+       be at least 8 bytes.
 
-   `S' handles constraints for calls.  ??? So where is it?  */
+   `U' handles all pseudo registers or a hard even numbered
+       integer register, needed for ldd/std instructions.  */
 
 #ifndef REG_OK_STRICT
 
@@ -2287,17 +2304,11 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 /* 'T', 'U' are for aligned memory loads which aren't needed for v9.  */
 
 #define EXTRA_CONSTRAINT(OP, C)                                \
-  ((C) == 'Q'                                          \
-   ? ((GET_CODE (OP) == MEM                            \
-       && memory_address_p (GET_MODE (OP), XEXP (OP, 0)) \
-       && ! symbolic_memory_operand (OP, VOIDmode))    \
-      || (reload_in_progress && GET_CODE (OP) == REG   \
-         && REGNO (OP) >= FIRST_PSEUDO_REGISTER))      \
-   : (! TARGET_ARCH64 && (C) == 'T')                   \
-   ? (mem_aligned_8 (OP))                              \
-   : (! TARGET_ARCH64 && (C) == 'U')                   \
-   ? (register_ok_for_ldd (OP))                                \
-   : 0)
+   ((! TARGET_ARCH64 && (C) == 'T')                    \
+    ? (mem_min_alignment (OP, 8))                      \
+    : ((! TARGET_ARCH64 && (C) == 'U')                 \
+       ? (register_ok_for_ldd (OP))                    \
+       : 0))
  
 #else
 
@@ -2307,19 +2318,14 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
 #define EXTRA_CONSTRAINT(OP, C)                                \
-  ((C) == 'Q'                                          \
-   ? (GET_CODE (OP) == REG                             \
-      ? (REGNO (OP) >= FIRST_PSEUDO_REGISTER           \
-        && reg_renumber[REGNO (OP)] < 0)               \
-      : GET_CODE (OP) == MEM)                          \
-   : (! TARGET_ARCH64 && (C) == 'T')                   \
-   ? mem_aligned_8 (OP) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
-   : (! TARGET_ARCH64 && (C) == 'U')                   \
-   ? (GET_CODE (OP) == REG                             \
-      && (REGNO (OP) < FIRST_PSEUDO_REGISTER           \
-         || reg_renumber[REGNO (OP)] >= 0)             \
-      && register_ok_for_ldd (OP))                     \
-   : 0)
+   ((! TARGET_ARCH64 && (C) == 'T')                    \
+    ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
+    : ((! TARGET_ARCH64 && (C) == 'U')                 \
+       ? (GET_CODE (OP) == REG                         \
+          && (REGNO (OP) < FIRST_PSEUDO_REGISTER       \
+             || reg_renumber[REGNO (OP)] >= 0)         \
+          && register_ok_for_ldd (OP))                 \
+       : 0))
 #endif
 \f
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -2387,8 +2393,8 @@ extern struct rtx_def *sparc_builtin_saveregs ();
          && CONSTANT_P (op1)                           \
          /* We can't allow TFmode, because an offset   \
             greater than or equal to the alignment (8) \
-            may cause the LO_SUM to overflow.  */      \
-         && MODE != TFmode)                            \
+            may cause the LO_SUM to overflow if !v9. */\
+         && (MODE != TFmode || TARGET_V9))             \
        goto ADDR;                                      \
     }                                                  \
   else if (GET_CODE (X) == CONST_INT && SMALL_INT (X)) \
@@ -2435,8 +2441,7 @@ extern struct rtx_def *legitimize_pic_address ();
                   copy_to_mode_reg (Pmode, XEXP (X, 0)));      \
   else if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
           || GET_CODE (X) == LABEL_REF)                        \
-    (X) = gen_rtx_LO_SUM (Pmode,                               \
-                         copy_to_mode_reg (Pmode, gen_rtx_HIGH (Pmode, X)), X); \
+    (X) = copy_to_suggested_reg (X, NULL_RTX, Pmode);          \
   if (memory_address_p (MODE, X))                              \
     goto WIN; }
 
@@ -2676,9 +2681,6 @@ extern struct rtx_def *legitimize_pic_address ();
        return 0;                                               \
     return 8;
 
-/* Compute the cost of an address.  For the sparc, all valid addresses are
-   the same cost.  */
-
 #define ADDRESS_COST(RTX)  1
 
 /* Compute extra cost of moving data between one register class
@@ -2920,6 +2922,15 @@ extern struct rtx_def *legitimize_pic_address ();
 #define ASM_OUTPUT_BYTE(FILE,VALUE)  \
   fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE))
 
+/* This is how we hook in and defer the case-vector until the end of
+   the function.  */
+
+#define ASM_OUTPUT_ADDR_VEC(LAB,VEC) \
+  sparc_defer_case_vector ((LAB),(VEC), 0)
+
+#define ASM_OUTPUT_ADDR_DIFF_VEC(LAB,VEC) \
+  sparc_defer_case_vector ((LAB),(VEC), 1)
+
 /* This is how to output an element of a case-vector that is absolute.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
@@ -2933,7 +2944,7 @@ do {                                                                      \
   else                                                                 \
     fprintf (FILE, "\t.xword\t");                                      \
   assemble_name (FILE, label);                                         \
-  fprintf (FILE, "\n");                                                        \
+  fputc ('\n', FILE);                                                  \
 } while (0)
 
 /* This is how to output an element of a case-vector that is relative.
@@ -2942,7 +2953,7 @@ do {                                                                      \
 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)               \
 do {                                                                   \
   char label[30];                                                      \
-  ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);                     \
+  ASM_GENERATE_INTERNAL_LABEL (label, "L", (VALUE));                   \
   if (Pmode == SImode)                                                 \
     fprintf (FILE, "\t.word\t");                                       \
   else if (TARGET_CM_MEDLOW)                                           \
@@ -2950,7 +2961,10 @@ do {                                                                     \
   else                                                                 \
     fprintf (FILE, "\t.xword\t");                                      \
   assemble_name (FILE, label);                                         \
-  fprintf (FILE, "-1b\n");                                             \
+  ASM_GENERATE_INTERNAL_LABEL (label, "L", (REL));                     \
+  fputc ('-', FILE);                                                   \
+  assemble_name (FILE, label);                                         \
+  fputc ('\n', FILE);                                                  \
 } while (0)
 
 /* This is how to output an assembler line
@@ -3116,7 +3130,10 @@ do {                                                                     \
   else if (GET_CODE (addr) == LO_SUM)                          \
     {                                                          \
       output_operand (XEXP (addr, 0), 0);                      \
-      fputs ("+%lo(", FILE);                                   \
+      if (TARGET_CM_MEDMID)                                    \
+        fputs ("+%l44(", FILE);                                        \
+      else                                                     \
+        fputs ("+%lo(", FILE);                                 \
       output_address (XEXP (addr, 1));                         \
       fputc (')', FILE);                                       \
     }                                                          \
@@ -3160,15 +3177,12 @@ do {                                                                    \
 {"data_segment_operand", {SYMBOL_REF, PLUS, CONST}},                               \
 {"text_segment_operand", {LABEL_REF, SYMBOL_REF, PLUS, CONST}},                            \
 {"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}},                                \
-{"sparc_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, MEM}},                  \
-{"move_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE, MEM}},     \
 {"splittable_symbolic_memory_operand", {MEM}},                                     \
 {"splittable_immediate_memory_operand", {MEM}},                                            \
 {"eq_or_neq", {EQ, NE}},                                                           \
 {"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}},                              \
 {"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}},                 \
 {"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}},                                        \
-{"v8plus_regcmp_op", {EQ, NE}},                                                            \
 {"extend_op", {SIGN_EXTEND, ZERO_EXTEND}},                                         \
 {"cc_arithop", {AND, IOR, XOR}},                                                   \
 {"cc_arithopn", {AND, IOR}},                                                       \
@@ -3179,9 +3193,12 @@ do {                                                                     \
 {"arith11_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
 {"arith10_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
 {"small_int", {CONST_INT, CONSTANT_P_RTX}},                                        \
+{"small_int_or_double", {CONST_INT, CONST_DOUBLE, CONSTANT_P_RTX}},                \
 {"uns_small_int", {CONST_INT, CONSTANT_P_RTX}},                                            \
 {"uns_arith_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},                   \
-{"clobbered_register", {REG}},
+{"clobbered_register", {REG}},                                                     \
+{"input_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, MEM}},                  \
+{"zero_operand", {CONST_INT, CONSTANT_P_RTX}},
 
 
 /* The number of Pmode words for the setjmp buffer.  */
@@ -3191,17 +3208,14 @@ do {                                                                    \
 
 /* Declare functions defined in sparc.c and used in templates.  */
 
-extern char *doublemove_string ();
-extern char *output_block_move ();
+extern void sparc_emit_set_const32 ();
+extern void sparc_emit_set_const64 ();
+extern void sparc_emit_set_symbolic_const64 ();
+extern int sparc_splitdi_legitimate ();
+
 extern char *output_cbranch ();
-extern char *output_fp_move_double ();
-extern char *output_fp_move_quad ();
-extern char *output_move_double ();
-extern char *output_move_quad ();
 extern char *output_return ();
-extern char *output_scc_insn ();
 extern char *output_v9branch ();
-extern char *singlemove_string ();
 
 extern void emit_v9_brxx_insn ();
 extern void finalize_pic ();
@@ -3221,6 +3235,8 @@ extern int arith11_operand ();
 extern int arith_double_operand ();
 extern int arith_operand ();
 extern int call_operand_address ();
+extern int input_operand ();
+extern int zero_operand ();
 extern int cc_arithop ();
 extern int cc_arithopn ();
 extern int check_pic ();
@@ -3234,8 +3250,7 @@ extern int fcc_reg_operand ();
 extern int fp_zero_operand ();
 extern int icc_or_fcc_reg_operand ();
 extern int label_ref_operand ();
-extern int mem_aligned_8 ();
-extern int move_operand ();
+extern int mem_min_alignment ();
 extern int noov_compare_op ();
 extern int pic_address_needs_scratch ();
 extern int reg_or_0_operand ();
@@ -3246,11 +3261,11 @@ extern int registers_ok_for_ldd_peep ();
 extern int restore_operand ();
 extern int short_branch ();
 extern int small_int ();
+extern int small_int_or_double ();
 extern int sp64_medium_pic_operand ();
 extern int sparc_flat_eligible_for_epilogue_delay ();
 extern int sparc_flat_epilogue_delay_slots ();
 extern int sparc_issue_rate ();
-extern int sparc_operand ();
 extern int splittable_immediate_memory_operand ();
 extern int splittable_symbolic_memory_operand ();
 extern int supersparc_adjust_cost ();
@@ -3259,8 +3274,6 @@ extern int symbolic_operand ();
 extern int text_segment_operand ();
 extern int ultrasparc_adjust_cost ();
 extern int uns_small_int ();
-extern int v8plus_regcmp_op ();
-extern int v8plus_regcmp_p ();
 extern int v9_regcmp_op ();
 extern int v9_regcmp_p ();
 
index 47d2d3de7ad3c22a104d356f7f9fad21c776b0b0..5cf7e807db4f4854920fb2ab34fab44e307adb77 100644 (file)
 
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
 
+;; Uses of UNSPEC and UNSPEC_VOLATILE in this file:
+;;
+;; UNSPEC:             0       movsi_{lo_sum,high}_pic
+;;                             pic_lo_sum_di
+;;                             pic_sethi_di
+;;                     1       update_return
+;;                     2       get_pc
+;;                     5       movsi_{,lo_sum_,high_}pic_label_ref
+;;                     6       seth44
+;;                     7       setm44
+;;                     8       setl44
+;;                     9       sethh
+;;                     10      setlm
+;;                     11      embmedany_sethi, embmedany_brsum
+;;                     13      embmedany_textuhi
+;;                     14      embmedany_texthi
+;;                     15      embmedany_textulo
+;;                     16      embmedany_textlo
+;;                     18      sethm
+;;                     19      setlo
+;;
+;; UNSPEC_VOLATILE:    0       blockage
+;;                     1       flush_register_windows
+;;                     2       goto_handler_and_restore
+;;                     3       goto_handler_and_restore_v9*
+;;                     4       flush
+;;                     5       nonlocal_goto_receiver
+;;
+
 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
 ;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
 (define_attr "leaf_function" "false,true"
   (const (symbol_ref "leaf_function")))
 
-
 (define_attr "in_return_delay" "false,true"
   (if_then_else (and (and (and (eq_attr "type" "move,load,sload,store,binary,ialu")
                               (eq_attr "length" "1"))
     (eq_attr "type" "store,fpstore"))
   1 1)
 
-(define_function_unit "ieu" 1 0
+(define_function_unit "ieu_unnamed" 2 0
   (and (eq_attr "cpu" "ultrasparc")
-    (eq_attr "type" "ialu,binary,shift,compare,cmove,call"))
+    (eq_attr "type" "ialu,binary,move,unary,shift,cmove,compare,call"))
   1 1)
 
-(define_function_unit "ieu_shift" 1 0
+(define_function_unit "ieu0" 1 0
   (and (eq_attr "cpu" "ultrasparc")
     (eq_attr "type" "shift"))
   1 1)
 
-(define_function_unit "ieu_shift" 1 0
+(define_function_unit "ieu0" 1 0
   (and (eq_attr "cpu" "ultrasparc")
     (eq_attr "type" "cmove"))
   2 1)
 
+(define_function_unit "ieu1" 1 0
+  (and (eq_attr "cpu" "ultrasparc")
+    (eq_attr "type" "compare,call,uncond_branch"))
+  1 1)
+
 ;; Timings; throughput/latency
 ;; FMOV     1/1    fmov, fabs, fneg
 ;; FMOVcc   1/2
 ;; FSQRTs   12/12
 ;; FSQRTd   22/22
 ;; FCMP takes 1 cycle to branch, 2 cycles to conditional move.
+;;
+;; ??? This is really bogus because the timings really depend upon
+;; who uses the result.  We should record who the user is with
+;; more descriptive 'type' attribute names and account for these
+;; issues in ultrasparc_adjust_cost. 
 
 (define_function_unit "fadd" 1 0
   (and (eq_attr "cpu" "ultrasparc")
     (eq_attr "type" "fpcmove"))
   2 1)
 
-(define_function_unit "fadd" 1 0
+(define_function_unit "fmul" 1 0
   (and (eq_attr "cpu" "ultrasparc")
     (eq_attr "type" "fpdivs"))
   12 12)
 
-(define_function_unit "fadd" 1 0
+(define_function_unit "fmul" 1 0
   (and (eq_attr "cpu" "ultrasparc")
     (eq_attr "type" "fpdivd"))
   22 22)
 
-(define_function_unit "fadd" 1 0
+(define_function_unit "fmul" 1 0
   (and (eq_attr "cpu" "ultrasparc")
     (eq_attr "type" "fpsqrt"))
   12 12)
   [(set (reg:CCX 100)
        (compare:CCX (match_operand:DI 0 "register_operand" "")
                     (match_operand:DI 1 "arith_double_operand" "")))]
-  "TARGET_ARCH64 || TARGET_V8PLUS"
+  "TARGET_ARCH64"
   "
 {
   sparc_compare_op0 = operands[0];
 
 ;; Now the compare DEFINE_INSNs.
 
-(define_insn "*cmpsi_insn"
+(define_insn "*cmpsi_insn_sp32"
   [(set (reg:CC 100)
        (compare:CC (match_operand:SI 0 "register_operand" "r")
                    (match_operand:SI 1 "arith_operand" "rI")))]
-  ""
-  "cmp %0,%1"
+  "TARGET_ARCH32"
+  "cmp\\t%0, %1"
+  [(set_attr "type" "compare")])
+
+(define_insn "*cmpsi_insn_sp64"
+  [(set (reg:CC 100)
+       (compare:CC (match_operand:SI 0 "register_operand" "r")
+                   (match_operand:SI 1 "arith_double_operand" "rHI")))]
+  "TARGET_ARCH64"
+  "cmp\\t%0, %1"
   [(set_attr "type" "compare")])
 
 (define_insn "*cmpdi_sp64"
        (compare:CCX (match_operand:DI 0 "register_operand" "r")
                     (match_operand:DI 1 "arith_double_operand" "rHI")))]
   "TARGET_ARCH64"
-  "cmp %0,%1"
+  "cmp\\t%0, %1"
   [(set_attr "type" "compare")])
 
-(define_insn "cmpdi_v8plus"
-  [(set (reg:CCX 100)
-       (compare:CCX (match_operand:DI 0 "register_operand" "r,r,r")
-                    (match_operand:DI 1 "arith_double_operand" "J,I,r")))
-   (clobber (match_scratch:SI 2 "=&h,&h,&h"))
-   (clobber (match_scratch:SI 3 "=X,X,&h"))]
-  "TARGET_V8PLUS"
-  "*
-{
-  /* The srl can be omitted if the value in the %L0 or %L1 is already
-     zero extended.  */
-
-  output_asm_insn (\"sllx %H0,32,%2\", operands);
-
-  if (sparc_check_64 (operands[0], insn) <= 0)
-    output_asm_insn (\"srl %L0,0,%L0\", operands);
-
-  switch (which_alternative)
-    {
-    case 0:
-      return \"orcc %L0,%2,%%g0\";
-    case 1:
-      return \"or %L0,%2,%2\;cmp %2,%1\";
-    case 2:
-      if (sparc_check_64 (operands[1], insn) <= 0)
-       output_asm_insn (\"srl %L1,0,%L1\", operands);
-      return \"sllx %H1,32,%3\;or %L0,%2,%2\;or %L1,%3,%3\;cmp %2,%3\";
-    default:
-      abort();
-    }
-}"
-  [(set_attr "length" "3,4,7")])
-
 (define_insn "*cmpsf_fpe"
   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
        (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
   "*
 {
   if (TARGET_V9)
-    return \"fcmpes %0,%1,%2\";
-  return \"fcmpes %1,%2\";
+    return \"fcmpes\\t%0, %1, %2\";
+  return \"fcmpes\\t%1, %2\";
 }"
   [(set_attr "type" "fpcmp")])
 
   "*
 {
   if (TARGET_V9)
-    return \"fcmped %0,%1,%2\";
-  return \"fcmped %1,%2\";
+    return \"fcmped\\t%0, %1, %2\";
+  return \"fcmped\\t%1, %2\";
 }"
   [(set_attr "type" "fpcmp")])
 
   "*
 {
   if (TARGET_V9)
-    return \"fcmpeq %0,%1,%2\";
-  return \"fcmpeq %1,%2\";
+    return \"fcmpeq\\t%0, %1, %2\";
+  return \"fcmpeq\\t%1, %2\";
 }"
   [(set_attr "type" "fpcmp")])
 
   "*
 {
   if (TARGET_V9)
-    return \"fcmps %0,%1,%2\";
-  return \"fcmps %1,%2\";
+    return \"fcmps\\t%0, %1, %2\";
+  return \"fcmps\\t%1, %2\";
 }"
   [(set_attr "type" "fpcmp")])
 
   "*
 {
   if (TARGET_V9)
-    return \"fcmpd %0,%1,%2\";
-  return \"fcmpd %1,%2\";
+    return \"fcmpd\\t%0, %1, %2\";
+  return \"fcmpd\\t%1, %2\";
 }"
   [(set_attr "type" "fpcmp")])
 
   "*
 {
   if (TARGET_V9)
-    return \"fcmpq %0,%1,%2\";
-  return \"fcmpq %1,%2\";
+    return \"fcmpq\\t%0, %1, %2\";
+  return \"fcmpq\\t%1, %2\";
 }"
   [(set_attr "type" "fpcmp")])
 \f
        DONE;
       /* fall through */
     }
-  operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
        DONE;
       /* fall through */
     }
-  operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 (define_expand "sgt"
        DONE;
       /* fall through */
     }
-  operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 (define_expand "slt"
        DONE;
       /* fall through */
     }
-  operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 (define_expand "sge"
        DONE;
       /* fall through */
     }
-  operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 (define_expand "sle"
        DONE;
       /* fall through */
     }
-  operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 (define_expand "sgtu"
 {
   if (! TARGET_V9)
     {
-      rtx tem;
+      rtx tem, pat;
 
       /* We can do ltu easily, so if both operands are registers, swap them and
         do a LTU.  */
          tem = sparc_compare_op0;
          sparc_compare_op0 = sparc_compare_op1;
          sparc_compare_op1 = tem;
-         emit_insn (gen_sltu (operands[0]));
+         pat = gen_sltu (operands[0]);
+          if (pat == NULL_RTX)
+            FAIL;
+          emit_insn (pat);
          DONE;
        }
     }
       if (gen_v9_scc (GTU, operands))
        DONE;
     }
-  operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 (define_expand "sltu"
       if (gen_v9_scc (LTU, operands))
        DONE;
     }
-  operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
+  /* XXX less than unsigned == Carry */
+  FAIL;
 }")
 
 (define_expand "sgeu"
       if (gen_v9_scc (GEU, operands))
        DONE;
     }
-  operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 (define_expand "sleu"
 {
   if (! TARGET_V9)
     {
-      rtx tem;
+      rtx tem, pat;
 
       /* We can do geu easily, so if both operands are registers, swap them and
         do a GEU.  */
          tem = sparc_compare_op0;
          sparc_compare_op0 = sparc_compare_op1;
          sparc_compare_op1 = tem;
-         emit_insn (gen_sgeu (operands[0]));
+         pat = gen_sgeu (operands[0]);
+          if (pat == NULL_RTX)
+            FAIL;
+          emit_insn (pat);
          DONE;
        }
     }
       if (gen_v9_scc (LEU, operands))
        DONE;
     }
-  operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
+  FAIL;
 }")
 
 ;; Now the DEFINE_INSNs for the scc cases.
 
 ;; The SEQ and SNE patterns are special because they can be done
-;; without any branching and do not involve a COMPARE.
+;; without any branching and do not involve a COMPARE.  We want
+;; them to always use the splitz below so the results can be
+;; scheduled.
 
 (define_insn "*snesi_zero"
   [(set (match_operand:SI 0 "register_operand" "=r")
               (const_int 0)))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
-  [(set_attr "type" "unary")
-   (set_attr "length" "2")])
+  "#"
+  [(set_attr "length" "2")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (ne:SI (match_operand:SI 1 "register_operand" "")
+              (const_int 0)))
+   (clobber (reg:CC 100))]
+  ""
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
+  "")
 
 (define_insn "*neg_snesi_zero"
   [(set (match_operand:SI 0 "register_operand" "=r")
                       (const_int 0))))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
-  [(set_attr "type" "unary")
-   (set_attr "length" "2")])
+  "#"
+  [(set_attr "length" "2")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
+                      (const_int 0))))
+   (clobber (reg:CC 100))]
+  ""
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
+  "")
 
 (define_insn "*snesi_zero_extend"
   [(set (match_operand:DI 0 "register_operand" "=r")
               (const_int 0)))
    (clobber (reg:CC 100))]
   "TARGET_ARCH64"
-  "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
+  "#"
   [(set_attr "type" "unary")
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (ne:SI (match_operand:SI 1 "register_operand" "")
+               (const_int 0)))
+   (clobber (reg:CC 100))]
+  "TARGET_ARCH64
+   && reload_completed"
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus (const_int 0) (match_dup 1))
+                                           (const_int 0)))
+   (set (match_dup 0) (minus:SI (minus:SI (const_int 0) (const_int 0))
+                                (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+  "")
+
 (define_insn "*snedi_zero"
   [(set (match_operand:DI 0 "register_operand" "=&r")
        (ne:DI (match_operand:DI 1 "register_operand" "r")
               (const_int 0)))]
   "TARGET_ARCH64"
-  "mov 0,%0\;movrnz %1,1,%0"
+  "#"
   [(set_attr "type" "cmove")
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (ne:DI (match_operand:DI 1 "register_operand" "")
+               (const_int 0)))]
+  "TARGET_ARCH64"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
+                                              (const_int 0))
+                                       (const_int 1)
+                                       (match_dup 0)))]
+  "")
+
 (define_insn "*neg_snedi_zero"
   [(set (match_operand:DI 0 "register_operand" "=&r")
        (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
                       (const_int 0))))]
   "TARGET_ARCH64"
-  "mov 0,%0\;movrnz %1,-1,%0"
+  "#"
   [(set_attr "type" "cmove")
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "")
+                       (const_int 0))))]
+  "TARGET_ARCH64"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
+                                              (const_int 0))
+                                       (const_int -1)
+                                       (match_dup 0)))]
+  "")
+
 (define_insn "*snedi_zero_trunc"
   [(set (match_operand:SI 0 "register_operand" "=&r")
        (ne:DI (match_operand:DI 1 "register_operand" "r")
               (const_int 0)))]
   "TARGET_ARCH64"
-  "mov 0,%0\;movrnz %1,1,%0"
+  "#"
   [(set_attr "type" "cmove")
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (ne:DI (match_operand:DI 1 "register_operand" "")
+               (const_int 0)))]
+  "TARGET_ARCH64"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
+                                              (const_int 0))
+                                       (const_int 1)
+                                       (match_dup 0)))]
+  "")
+
 (define_insn "*seqsi_zero"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (eq:SI (match_operand:SI 1 "register_operand" "r")
               (const_int 0)))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
-  [(set_attr "type" "unary")
-   (set_attr "length" "2")])
+  "#"
+  [(set_attr "length" "2")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (eq:SI (match_operand:SI 1 "register_operand" "")
+              (const_int 0)))
+   (clobber (reg:CC 100))]
+  ""
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
+  "")
 
 (define_insn "*neg_seqsi_zero"
   [(set (match_operand:SI 0 "register_operand" "=r")
                       (const_int 0))))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
-  [(set_attr "type" "unary")
-   (set_attr "length" "2")])
+  "#"
+  [(set_attr "length" "2")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
+                      (const_int 0))))
+   (clobber (reg:CC 100))]
+  ""
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
+  "")
 
 (define_insn "*seqsi_zero_extend"
   [(set (match_operand:DI 0 "register_operand" "=r")
               (const_int 0)))
    (clobber (reg:CC 100))]
   "TARGET_ARCH64"
-  "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
+  "#"
   [(set_attr "type" "unary")
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (eq:SI (match_operand:SI 1 "register_operand" "")
+               (const_int 0)))
+   (clobber (reg:CC 100))]
+  "TARGET_ARCH64"
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 1))
+                                           (const_int 0)))
+   (set (match_dup 0) (minus:SI (minus:SI (const_int 0) (const_int -1))
+                                (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+  "")
+
 (define_insn "*seqdi_zero"
   [(set (match_operand:DI 0 "register_operand" "=&r")
        (eq:DI (match_operand:DI 1 "register_operand" "r")
               (const_int 0)))]
   "TARGET_ARCH64"
-  "mov 0,%0\;movrz %1,1,%0"
+  "#"
   [(set_attr "type" "cmove")
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (eq:DI (match_operand:DI 1 "register_operand" "")
+               (const_int 0)))]
+  "TARGET_ARCH64"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
+                                              (const_int 0))
+                                       (const_int 1)
+                                       (match_dup 0)))]
+  "")
+
 (define_insn "*neg_seqdi_zero"
   [(set (match_operand:DI 0 "register_operand" "=&r")
        (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
                       (const_int 0))))]
   "TARGET_ARCH64"
-  "mov 0,%0\;movrz %1,-1,%0"
+  "#"
   [(set_attr "type" "cmove")
    (set_attr "length" "2")]) 
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "")
+                       (const_int 0))))]
+  "TARGET_ARCH64"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
+                                              (const_int 0))
+                                       (const_int -1)
+                                       (match_dup 0)))]
+  "")
+
 (define_insn "*seqdi_zero_trunc"
   [(set (match_operand:SI 0 "register_operand" "=&r")
        (eq:DI (match_operand:DI 1 "register_operand" "r")
               (const_int 0)))]
   "TARGET_ARCH64"
-  "mov 0,%0\;movrz %1,1,%0"
+  "#"
   [(set_attr "type" "cmove")
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (eq:DI (match_operand:DI 1 "register_operand" "")
+               (const_int 0)))]
+  "TARGET_ARCH64"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
+                                              (const_int 0))
+                                       (const_int 1)
+                                       (match_dup 0)))]
+  "")
+
 ;; We can also do (x + (i == 0)) and related, so put them in.
 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
 ;; versions for v9.
                 (match_operand:SI 2 "register_operand" "r")))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;addx %2,0,%0"
+  "#"
   [(set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
+                       (const_int 0))
+                (match_operand:SI 2 "register_operand" "")))
+   (clobber (reg:CC 100))]
+  "! TARGET_LIVE_G0"
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
+                              (match_dup 2)))]
+  "")
+
 (define_insn "*x_minus_i_ne_0"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (minus:SI (match_operand:SI 2 "register_operand" "r")
                         (const_int 0))))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;subx %2,0,%0"
+  "#"
   [(set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (minus:SI (match_operand:SI 2 "register_operand" "")
+                 (ne:SI (match_operand:SI 1 "register_operand" "")
+                        (const_int 0))))
+   (clobber (reg:CC 100))]
+  "! TARGET_LIVE_G0"
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (minus:SI (match_dup 2)
+                               (ltu:SI (reg:CC 100) (const_int 0))))]
+  "")
+
 (define_insn "*x_plus_i_eq_0"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
                 (match_operand:SI 2 "register_operand" "r")))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
+  "#"
   [(set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
+                       (const_int 0))
+                (match_operand:SI 2 "register_operand" "")))
+   (clobber (reg:CC 100))]
+  "! TARGET_LIVE_G0"
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
+                              (match_dup 2)))]
+  "")
+
 (define_insn "*x_minus_i_eq_0"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (minus:SI (match_operand:SI 2 "register_operand" "r")
                         (const_int 0))))
    (clobber (reg:CC 100))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
+  "#"
   [(set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (minus:SI (match_operand:SI 2 "register_operand" "")
+                 (eq:SI (match_operand:SI 1 "register_operand" "")
+                        (const_int 0))))
+   (clobber (reg:CC 100))]
+  "! TARGET_LIVE_G0"
+  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
+   (set (match_dup 0) (minus:SI (match_dup 2)
+                               (geu:SI (reg:CC 100) (const_int 0))))]
+  "")
+
 ;; We can also do GEU and LTU directly, but these operate after a compare.
 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
 ;; versions for v9.
   [(set (match_operand:SI 0 "register_operand" "=r")
        (ltu:SI (reg:CC 100) (const_int 0)))]
   "! TARGET_LIVE_G0"
-  "addx %%g0,0,%0"
-  [(set_attr "type" "misc")])
+  "addx\\t%%g0, 0, %0"
+  [(set_attr "type" "misc")
+   (set_attr "length" "1")])
 
 (define_insn "*neg_sltu_insn"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
   "! TARGET_LIVE_G0"
-  "subx %%g0,0,%0"
-  [(set_attr "type" "misc")])
+  "subx\\t%%g0, 0, %0"
+  [(set_attr "type" "misc")
+   (set_attr "length" "1")])
 
 ;; ??? Combine should canonicalize these next two to the same pattern.
 (define_insn "*neg_sltu_minus_x"
        (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
                  (match_operand:SI 1 "arith_operand" "rI")))]
   "! TARGET_LIVE_G0"
-  "subx %%g0,%1,%0"
-  [(set_attr "type" "unary")])
+  "subx\\t%%g0, %1, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
 (define_insn "*neg_sltu_plus_x"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
                         (match_operand:SI 1 "arith_operand" "rI"))))]
   "! TARGET_LIVE_G0"
-  "subx %%g0,%1,%0"
-  [(set_attr "type" "unary")])
+  "subx\\t%%g0, %1, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
 (define_insn "*sgeu_insn"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (geu:SI (reg:CC 100) (const_int 0)))]
   "! TARGET_LIVE_G0"
-  "subx %%g0,-1,%0"
-  [(set_attr "type" "misc")])
+  "subx\\t%%g0, -1, %0"
+  [(set_attr "type" "misc")
+   (set_attr "length" "1")])
 
 (define_insn "*neg_sgeu_insn"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
   "! TARGET_LIVE_G0"
-  "addx %%g0,-1,%0"
-  [(set_attr "type" "misc")])
+  "addx\\t%%g0, -1, %0"
+  [(set_attr "type" "misc")
+   (set_attr "length" "1")])
 
 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
        (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
                 (match_operand:SI 1 "arith_operand" "rI")))]
   "! TARGET_LIVE_G0"
-  "addx %%g0,%1,%0"
-  [(set_attr "type" "unary")])
+  "addx\\t%%g0, %1, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
 (define_insn "*sltu_plus_x_plus_y"
   [(set (match_operand:SI 0 "register_operand" "=r")
                 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
                          (match_operand:SI 2 "arith_operand" "rI"))))]
   ""
-  "addx %1,%2,%0")
+  "addx\\t%1, %2, %0"
+  [(set_attr "type" "binary")
+   (set_attr "length" "1")])
 
 (define_insn "*x_minus_sltu"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (minus:SI (match_operand:SI 1 "register_operand" "r")
                  (ltu:SI (reg:CC 100) (const_int 0))))]
   ""
-  "subx %1,0,%0"
-  [(set_attr "type" "unary")])
+  "subx\\t%1, 0, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
 ;; ??? Combine should canonicalize these next two to the same pattern.
 (define_insn "*x_minus_y_minus_sltu"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
+       (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
                            (match_operand:SI 2 "arith_operand" "rI"))
                  (ltu:SI (reg:CC 100) (const_int 0))))]
   ""
-  "subx %1,%2,%0")
+  "subx\\t%r1, %2, %0"
+  [(set_attr "type" "binary")
+   (set_attr "length" "1")])
 
 (define_insn "*x_minus_sltu_plus_y"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (minus:SI (match_operand:SI 1 "register_operand" "r")
+       (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
                  (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
                           (match_operand:SI 2 "arith_operand" "rI"))))]
   ""
-  "subx %1,%2,%0")
+  "subx\\t%r1, %2, %0"
+  [(set_attr "type" "binary")
+   (set_attr "length" "1")])
 
 (define_insn "*sgeu_plus_x"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (geu:SI (reg:CC 100) (const_int 0))
                 (match_operand:SI 1 "register_operand" "r")))]
   ""
-  "subx %1,-1,%0"
-  [(set_attr "type" "unary")])
+  "subx\\t%1, -1, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
 (define_insn "*x_minus_sgeu"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (minus:SI (match_operand:SI 1 "register_operand" "r")
                  (geu:SI (reg:CC 100) (const_int 0))))]
   ""
-  "addx %1,-1,%0"
-  [(set_attr "type" "unary")])
-
-;; Now we have the generic scc insns.
-;; !v9: These will be done using a jump.
-;; v9: Use conditional moves which are defined elsewhere.
-;; We have to exclude the cases above, since we will not want combine to
-;; turn something that does not require a jump into something that does.
-
-(define_insn "*scc_si"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (match_operator:SI 2 "noov_compare_op"
-                          [(match_operand 1 "icc_or_fcc_reg_operand" "")
-                           (const_int 0)]))]
-  ""
-  "* return output_scc_insn (operands, insn); "
-  [(set_attr "type" "multi")
-   (set_attr "length" "3")])
+  "addx\\t%1, -1, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "=r")
                         (match_dup 0)))]
   "")
 
-(define_insn "*scc_di"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (match_operator:DI 2 "noov_compare_op"
-                          [(match_operand 1 "icc_or_fcc_reg_operand" "")
-                           (const_int 0)]))]
-  "TARGET_ARCH64"
-  "* return output_scc_insn (operands, insn); "
-  [(set_attr "type" "multi")
-   (set_attr "length" "3")])
 \f
 ;; These control RTL generation for conditional jump insns
 
 \f
 ;; Now match both normal and inverted jump.
 
+;; XXX fpcmp nop braindamage
 (define_insn "*normal_branch"
   [(set (pc)
        (if_then_else (match_operator 0 "noov_compare_op"
 }"
   [(set_attr "type" "branch")])
 
+;; XXX fpcmp nop braindamage
 (define_insn "*inverted_branch"
   [(set (pc)
        (if_then_else (match_operator 0 "noov_compare_op"
 }"
   [(set_attr "type" "branch")])
 
+;; XXX fpcmp nop braindamage
 (define_insn "*normal_fp_branch"
   [(set (pc)
        (if_then_else (match_operator 1 "comparison_operator"
 }"
   [(set_attr "type" "branch")])
 
+;; XXX fpcmp nop braindamage
 (define_insn "*inverted_fp_branch"
   [(set (pc)
        (if_then_else (match_operator 1 "comparison_operator"
 }"
   [(set_attr "type" "branch")])
 
+;; XXX fpcmp nop braindamage
 (define_insn "*normal_fpe_branch"
   [(set (pc)
        (if_then_else (match_operator 1 "comparison_operator"
 }"
   [(set_attr "type" "branch")])
 
+;; XXX fpcmp nop braindamage
 (define_insn "*inverted_fpe_branch"
   [(set (pc)
        (if_then_else (match_operator 1 "comparison_operator"
 
 ;; There are no 32 bit brreg insns.
 
+;; XXX
 (define_insn "*normal_int_branch_sp64"
   [(set (pc)
        (if_then_else (match_operator 0 "v9_regcmp_op"
 {
   return output_v9branch (operands[0], 1, 2, 0,
                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-                         ! final_sequence);
+                         ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")])
 
+;; XXX
 (define_insn "*inverted_int_branch_sp64"
   [(set (pc)
        (if_then_else (match_operator 0 "v9_regcmp_op"
 {
   return output_v9branch (operands[0], 1, 2, 1,
                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-                         ! final_sequence);
+                         ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")])
 \f
-;; Esoteric move insns (lo_sum, high, pic).
+;; Load program counter insns.
 
-(define_insn "*lo_sum_si"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
-                  (match_operand:SI 2 "immediate_operand" "in")))]
-  ""
-  ;; V9 needs "add" because of the code models.  We still use "or" for v8
-  ;; so we can compare the old compiler with the new.
-  "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
-  ;; Need to set length for this arith insn because operand2
-  ;; is not an "arith_operand".
-  [(set_attr "length" "1")])
+(define_insn "get_pc"
+  [(clobber (reg:SI 15))
+   (set (match_operand 0 "register_operand" "=r")
+       (unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
+  "flag_pic && REGNO (operands[0]) == 23"
+  "sethi\\t%%hi(%a1-4), %0\\n\\tcall\\t%a2\\n\\tadd\\t%0, %%lo(%a1+4), %0"
+  [(set_attr "length" "3")])
 
-;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
-;; confuse them with real addresses.
-(define_insn "pic_lo_sum_si"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
-                  (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
-  "flag_pic"
-  ;; V9 needs "add" because of the code models.  We still use "or" for v8
-  ;; so we can compare the old compiler with the new.
-  "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
-  ;; Need to set length for this arith insn because operand2
-  ;; is not an "arith_operand".
-  [(set_attr "length" "1")])
+;; Currently unused...
+;; (define_insn "get_pc_via_rdpc"
+;;   [(set (match_operand 0 "register_operand" "=r") (pc))]
+;;   "TARGET_V9"
+;;   "rd\\t%%pc, %0"
+;;   [(set_attr "type" "move")])
 
-;; The PIC version of sethi must appear before the non-pic case so that
-;; the unspec will not be matched as part of the operand.
-;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
-;; confuse them with real addresses.
-(define_insn "pic_sethi_si"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
-  "flag_pic && check_pic (1)"
-  "sethi %%hi(%a1),%0"
-  [(set_attr "type" "move")
-   (set_attr "length" "1")])
+\f
+;; Move instructions
 
-(define_insn "pic_lo_sum_di"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (lo_sum:SI (match_operand:DI 1 "register_operand" "r")
-                   (unspec:SI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
-  "TARGET_ARCH64 && flag_pic"
-  "add %1,%%lo(%a2),%0"
-  [(set_attr "length" "1")])
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "general_operand" "")
+       (match_operand:QI 1 "general_operand" ""))]
+  ""
+  "
+{
+  /* Working with CONST_INTs is easier, so convert
+     a double if needed.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    {
+      operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xff);
+    }
+  else if (GET_CODE (operands[1]) == CONST_INT)
+    {
+      /* And further, we know for all QI cases that only the
+        low byte is significant, which we can always process
+        in a single insn.  So mask it now.  */
+      operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
+    }
 
-(define_insn "pic_sethi_di"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
-  "TARGET_ARCH64 && flag_pic && check_pic (1)"
-  "sethi %%hi(%a1),%0"
-  [(set_attr "type" "move")
-   (set_attr "length" "1")])
+  /* Handle sets of MEM first.  */
+  if (GET_CODE (operands[0]) == MEM)
+    {
+      /* This checks TARGET_LIVE_G0 for us.  */
+      if (reg_or_0_operand (operands[1], QImode))
+       goto movqi_is_ok;
 
-(define_insn "get_pc"
-  [(clobber (reg:SI 15))
-   (set (match_operand 0 "register_operand" "=r")
-       (unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
-  "flag_pic && REGNO (operands[0]) == 23"
-  "sethi %%hi(%a1-4),%0\;call %a2\;add %0,%%lo(%a1+4),%0"
-  [(set_attr "length" "3")])
+      if (! reload_in_progress)
+       {
+         operands[0] = validize_mem (operands[0]);
+         operands[1] = force_reg (QImode, operands[1]);
+       }
+    }
 
-(define_insn "get_pc_via_rdpc"
-  [(set (match_operand 0 "register_operand" "=r") (pc))]
-  "TARGET_V9"
-  "rd %%pc,%0"
-  [(set_attr "type" "move")])
+  /* Fixup PIC cases.  */
+  if (flag_pic)
+    {
+      if (CONSTANT_P (operands[1])
+         && pic_address_needs_scratch (operands[1]))
+       operands[1] = legitimize_pic_address (operands[1], QImode, 0);
 
-;; Special pic pattern, for loading the address of a label into a register.
-;; It clobbers o7 because the call puts the return address (i.e. pc value)
-;; there.  The pic tablejump pattern also uses this.
+      if (symbolic_operand (operands[1], QImode))
+       {
+         operands[1] = legitimize_pic_address (operands[1],
+                                               QImode,
+                                               (reload_in_progress ?
+                                                operands[0] :
+                                                NULL_RTX));
+         goto movqi_is_ok;
+       }
+    }
 
-(define_insn "move_pic_label_si"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       ; This was previously (label_ref:SI (match_operand 1 "" "")) but that
-       ; loses the volatil and other flags of the original label_ref.
-       (match_operand:SI 1 "label_ref_operand" ""))
-   (set (reg:SI 15) (pc))]
-  "flag_pic"
-  "*
-{
-  if (get_attr_length (insn) == 2)
-    return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\";
-  else
-    return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\";
-}"
-  [(set_attr "type" "multi")
-   ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
-   (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
-                                          (const_int 960))
-                                     (const_int 2)
-                                     (const_int 4)))])
-
-;; Special sparc64 pattern for loading the address of a label into a register.
-;; The pic and non-pic cases are the same since it's the most efficient way.
-;;
-;; ??? The non-pic case doesn't need to use %o7, we could use a scratch
-;; instead.  But the pic case doesn't need to use %o7 either.  We handle them
-;; both here so that when this is fixed, they can both be fixed together.
-;; Don't forget that the pic jump table stuff uses %o7 (that will need to be
-;; changed too).
+  /* All QI constants require only one insn, so proceed.  */
 
-(define_insn "move_label_di"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       ; This was previously (label_ref:DI (match_operand 1 "" "")) but that
-       ; loses the volatil and other flags of the original label_ref.
-       (match_operand:DI 1 "label_ref_operand" ""))
-   (set (reg:DI 15) (pc))]
-  "TARGET_ARCH64"
-  "*
+ movqi_is_ok:
+}")
+
+(define_insn "*movqi_insn"
+  [(set (match_operand:QI 0 "general_operand" "=r,r,m")
+       (match_operand:QI 1 "input_operand"   "rI,m,rJ"))]
+  "(register_operand (operands[0], QImode)
+    || reg_or_0_operand (operands[1], QImode))"
+  "@
+   mov\\t%1, %0
+   ldub\\t%1, %0
+   stb\\t%r1, %0"
+  [(set_attr "type" "move,load,store")
+   (set_attr "length" "1")])
+
+(define_expand "movhi"
+  [(set (match_operand:HI 0 "general_operand" "")
+       (match_operand:HI 1 "general_operand" ""))]
+  ""
+  "
 {
-  if (get_attr_length (insn) == 2)
-    return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\";
-  else
-    return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\";
-}"
-  [(set_attr "type" "multi")
-   ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
-   (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
-                                          (const_int 960))
-                                     (const_int 2)
-                                     (const_int 5)))])
+  /* Working with CONST_INTs is easier, so convert
+     a double if needed.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+
+  /* Handle sets of MEM first.  */
+  if (GET_CODE (operands[0]) == MEM)
+    {
+      /* This checks TARGET_LIVE_G0 for us.  */
+      if (reg_or_0_operand (operands[1], HImode))
+       goto movhi_is_ok;
+
+      if (! reload_in_progress)
+       {
+         operands[0] = validize_mem (operands[0]);
+         operands[1] = force_reg (HImode, operands[1]);
+       }
+    }
+
+  /* Fixup PIC cases.  */
+  if (flag_pic)
+    {
+      if (CONSTANT_P (operands[1])
+         && pic_address_needs_scratch (operands[1]))
+       operands[1] = legitimize_pic_address (operands[1], HImode, 0);
+
+      if (symbolic_operand (operands[1], HImode))
+       {
+         operands[1] = legitimize_pic_address (operands[1],
+                                               HImode,
+                                               (reload_in_progress ?
+                                                operands[0] :
+                                                NULL_RTX));
+         goto movhi_is_ok;
+       }
+    }
+
+  /* This makes sure we will not get rematched due to splittage. */
+  if (! CONSTANT_P (operands[1]) || input_operand (operands[1], HImode))
+    ;
+  else if (CONSTANT_P (operands[1])
+          && GET_CODE (operands[1]) != HIGH
+          && GET_CODE (operands[1]) != LO_SUM)
+    {
+      sparc_emit_set_const32 (operands[0], operands[1]);
+      DONE;
+    }
+ movhi_is_ok:
+}")
 
-(define_insn "*sethi_hi"
+(define_insn "*movhi_insn"
+  [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
+       (match_operand:HI 1 "input_operand"   "rI,K,m,rJ"))]
+  "(register_operand (operands[0], HImode)
+    || reg_or_0_operand (operands[1], HImode))"
+  "@
+   mov\\t%1, %0
+   sethi\\t%%hi(%a1), %0
+   lduh\\t%1, %0
+   sth\\t%r1, %0"
+  [(set_attr "type" "move,move,load,store")
+   (set_attr "length" "1")])
+
+;; We always work with constants here, never symbols, so no need
+;; for the funny PIC versions.
+(define_insn "*movhi_lo_sum"
   [(set (match_operand:HI 0 "register_operand" "=r")
-       (high:HI (match_operand 1 "" "")))]
-  "check_pic (1)"
-  "sethi %%hi(%a1),%0"
-  [(set_attr "type" "move")
+       (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
+                   (match_operand:HI 2 "immediate_operand" "in")))]
+  ""
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "type" "ialu")
    (set_attr "length" "1")])
 
-;; This must appear after the PIC sethi so that the PIC unspec will not
-;; be matched as part of the operand.
-(define_insn "*sethi_si"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (high:SI (match_operand 1 "" "")))]
-  "check_pic (1)"
-  "sethi %%hi(%a1),%0"
+(define_insn "*movhi_high"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (high:HI (match_operand:SI 1 "" "")))]
+  ""
+  "sethi\\t%%hi(%a1), %0"
   [(set_attr "type" "move")
    (set_attr "length" "1")])
 
-(define_insn "*lo_sum_di_sp32"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
-                  (match_operand:DI 2 "immediate_operand" "in")))]
-  "! TARGET_ARCH64"
-  "*
+(define_expand "movsi"
+  [(set (match_operand:SI 0 "general_operand" "")
+       (match_operand:SI 1 "general_operand" ""))]
+  ""
+  "
 {
-  /* Don't output a 64 bit constant, since we can't trust the assembler to
-     handle it correctly.  */
-  if (GET_CODE (operands[2]) == CONST_DOUBLE)
-    operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
-  else if (GET_CODE (operands[2]) == CONST_INT
-          && HOST_BITS_PER_WIDE_INT > 32
-          && INTVAL (operands[2]) > 0xffffffff)
-    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
-
-  return \"or %L1,%%lo(%a2),%L0\";
-}"
-  ;; Need to set length for this arith insn because operand2
-  ;; is not an "arith_operand".
-  [(set_attr "length" "1")])
-
-;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add?
+  /* Working with CONST_INTs is easier, so convert
+     a double if needed.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
 
-(define_insn "*lo_sum_di_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
-                  (match_operand:DI 2 "immediate_operand" "in")))]
-  "TARGET_ARCH64"
-  "*
-{
-  /* Don't output a 64 bit constant, since we can't trust the assembler to
-     handle it correctly.  */
-  if (GET_CODE (operands[2]) == CONST_DOUBLE)
-    operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
-  else if (GET_CODE (operands[2]) == CONST_INT
-          && HOST_BITS_PER_WIDE_INT > 32
-          && INTVAL (operands[2]) > 0xffffffff)
-    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
-
-  /* Note that we use add here.  This is important because Medium/Anywhere
-     code model support depends on it.  */
-  return \"add %1,%%lo(%a2),%0\";
-}"
-  ;; Need to set length for this arith insn because operand2
-  ;; is not an "arith_operand".
-  [(set_attr "length" "1")])
+  /* Handle sets of MEM first.  */
+  if (GET_CODE (operands[0]) == MEM)
+    {
+      /* This checks TARGET_LIVE_G0 for us.  */
+      if (reg_or_0_operand (operands[1], SImode))
+       goto movsi_is_ok;
 
-(define_insn "*sethi_di_sp32"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (high:DI (match_operand 1 "" "")))]
-  "! TARGET_ARCH64 && check_pic (1)"
-  "*
-{
-  rtx op0 = operands[0];
-  rtx op1 = operands[1];
+      if (! reload_in_progress)
+       {
+         operands[0] = validize_mem (operands[0]);
+         operands[1] = force_reg (SImode, operands[1]);
+       }
+    }
 
-  if (GET_CODE (op1) == CONST_INT)
+  /* Fixup PIC cases.  */
+  if (flag_pic)
     {
-      operands[0] = operand_subword (op0, 1, 0, DImode);
-      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
+      if (CONSTANT_P (operands[1])
+         && pic_address_needs_scratch (operands[1]))
+       operands[1] = legitimize_pic_address (operands[1], SImode, 0);
 
-      operands[0] = operand_subword (op0, 0, 0, DImode);
-      if (INTVAL (op1) < 0)
-       return \"mov -1,%0\";
-      else
-       return \"mov 0,%0\";
+      if (GET_CODE (operands[1]) == LABEL_REF)
+       {
+         /* shit */
+         emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
+         DONE;
+       }
+
+      if (symbolic_operand (operands[1], SImode))
+       {
+         operands[1] = legitimize_pic_address (operands[1],
+                                               SImode,
+                                               (reload_in_progress ?
+                                                operands[0] :
+                                                NULL_RTX));
+         goto movsi_is_ok;
+       }
     }
-  else if (GET_CODE (op1) == CONST_DOUBLE)
-    {
-      operands[0] = operand_subword (op0, 1, 0, DImode);
-      operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
-      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
 
-      operands[0] = operand_subword (op0, 0, 0, DImode);
-      operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
-      return singlemove_string (operands);
+  /* If we are trying to toss an integer constant into the
+     FPU registers, force it into memory.  */
+  if (GET_CODE (operands[0]) == REG
+      && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
+      && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
+      && CONSTANT_P (operands[1]))
+    operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+                                                operands[1]));
+
+  /* This makes sure we will not get rematched due to splittage. */
+  if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
+    ;
+  else if (CONSTANT_P (operands[1])
+          && GET_CODE (operands[1]) != HIGH
+          && GET_CODE (operands[1]) != LO_SUM)
+    {
+      sparc_emit_set_const32 (operands[0], operands[1]);
+      DONE;
     }
-  else
-    abort ();
-  return \"\";
-}"
+ movsi_is_ok:
+}")
+
+;; Special LIVE_G0 pattern to obtain zero in a register.
+(define_insn "*movsi_zero_liveg0"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (match_operand:SI 1 "zero_operand" "J"))]
+  "TARGET_LIVE_G0"
+  "and\\t%0, 0, %0"
+  [(set_attr "type" "binary")
+   (set_attr "length" "1")])
+
+(define_insn "*movsi_insn"
+  [(set (match_operand:SI 0 "general_operand" "=r,f,r,r,r,f,m,m,d")
+       (match_operand:SI 1 "input_operand"   "rI,!f,K,J,m,!m,rJ,!f,J"))]
+  "(register_operand (operands[0], SImode)
+    || reg_or_0_operand (operands[1], SImode))"
+  "@
+   mov\\t%1, %0
+   fmovs\\t%1, %0
+   sethi\\t%%hi(%a1), %0
+   clr\\t%0
+   ld\\t%1, %0
+   ld\\t%1, %0
+   st\\t%r1, %0
+   st\\t%1, %0
+   fzero\\t%0"
+  [(set_attr "type" "move,fpmove,move,move,load,fpload,store,fpstore,fpmove")
+   (set_attr "length" "1")])
+
+(define_insn "*movsi_lo_sum"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+                   (match_operand:SI 2 "immediate_operand" "in")))]
+  ""
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "type" "ialu")
+   (set_attr "length" "1")])
+
+(define_insn "*movsi_high"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (high:SI (match_operand:SI 1 "immediate_operand" "in")))]
+  ""
+  "sethi\\t%%hi(%a1), %0"
   [(set_attr "type" "move")
-   (set_attr "length" "2")])
+   (set_attr "length" "1")])
 
-;;; ??? This pattern originally clobbered a scratch register.  However, this
-;;; is invalid, the movdi pattern may not use a temp register because it
-;;; may be called from reload to reload a DImode value.  In that case, we
-;;; end up with a scratch register that never gets allocated.  To avoid this,
-;;; we use global register 1 which is never otherwise used by gcc as a temp.
-;;; The correct solution here might be to force DImode constants to memory,
-;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg
-;;; 1 will then no longer need to be considered a fixed reg.
-
-(define_expand "sethi_di_sp64"
-  [(parallel
-     [(set (match_operand:DI 0 "register_operand" "")
-          (high:DI (match_operand 1 "general_operand" "")))
-      (clobber (reg:DI 1))])]
-  "TARGET_ARCH64"
-  "")
+;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
+;; so that CSE won't optimize the address computation away.
+(define_insn "movsi_lo_sum_pic"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+                   (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
+  "flag_pic"
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "length" "1")])
 
-(define_insn "*sethi_di_sp64_const"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (high:DI (match_operand 1 "const_double_operand" "")))
-   (clobber (reg:DI 1))]
-  "TARGET_ARCH64 && check_pic (1)"
-  "*
+(define_insn "movsi_high_pic"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
+  "flag_pic && check_pic (1)"
+  "sethi\\t%%hi(%a1), %0"
+  [(set_attr "type" "move")
+   (set_attr "length" "1")])
+
+(define_expand "movsi_pic_label_ref"
+  [(set (match_dup 3) (high:SI
+     (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+                (match_dup 2)] 5)))
+   (set (match_dup 4) (lo_sum:SI (match_dup 3)
+     (unspec:SI [(match_dup 1) (match_dup 2)] 5)))
+   (set (match_operand:SI 0 "register_operand" "=r")
+       (minus:SI (match_dup 5) (match_dup 4)))]
+  "flag_pic"
+  "
 {
-#if HOST_BITS_PER_WIDE_INT == 32
-  rtx high, low;
-  
-  split_double (operands[1], &high, &low);
+  current_function_uses_pic_offset_table = 1;
+  operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
+  operands[3] = gen_reg_rtx (SImode);
+  operands[4] = gen_reg_rtx (SImode);
+  operands[5] = pic_offset_table_rtx;
+}")
 
-  if (high == const0_rtx)
+(define_insn "*movsi_high_pic_label_ref"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+      (high:SI
+        (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+                   (match_operand:SI 2 "" "")] 5)))]
+  "flag_pic"
+  "sethi\\t%%hi(%a2-(%a1-.)), %0"
+  [(set_attr "type" "move")
+   (set_attr "length" "1")])
+
+(define_insn "*movsi_lo_sum_pic_label_ref"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+      (lo_sum:SI (match_operand:SI 1 "register_operand" "=r")
+        (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
+                   (match_operand:SI 3 "" "")] 5)))]
+  "flag_pic"
+  "or\\t%1, %%lo(%a3-(%a2-.)), %0"
+  [(set_attr "length" "1")])
+
+(define_expand "movdi"
+  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
+       (match_operand:DI 1 "general_operand" ""))]
+  ""
+  "
+{
+  /* Where possible, convert CONST_DOUBLE into a CONST_INT.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+#if HOST_BITS_PER_WIDE_INT != 64
+      && ((CONST_DOUBLE_HIGH (operands[1]) == 0
+          && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
+         || (CONST_DOUBLE_HIGH (operands[1]) == 0xffffffff
+             && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
+#endif
+      )
+    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+
+  /* Handle MEM cases first.  */
+  if (GET_CODE (operands[0]) == MEM)
     {
-      operands[1] = low;
-      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
+      /* If it's a REG, we can always do it.
+        The const zero case is more complex, on v9
+        we can always perform it.  */
+      if (register_operand (operands[1], DImode)
+         || (TARGET_ARCH64
+              && (operands[1] == const0_rtx)))
+        goto movdi_is_ok;
+
+      if (! reload_in_progress)
+       {
+         operands[0] = validize_mem (operands[0]);
+         operands[1] = force_reg (DImode, operands[1]);
+       }
     }
-  else
-    {
-      operands[1] = high;
-      output_asm_insn (singlemove_string (operands), operands);
 
-      operands[1] = low;
-      output_asm_insn (\"sllx %0,32,%0\", operands);
-      if (low != const0_rtx)
-       output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
+  if (GET_CODE (operands[1]) == LABEL_REF)
+    {
+      if (! TARGET_ARCH64)
+        abort ();
+      /* ??? revisit this... */
+      emit_insn (gen_move_label_di (operands[0], operands[1]));
+      DONE;
     }
-#else
-  rtx op = operands[1];
 
-  if (! SPARC_SETHI_P (INTVAL(op)))
+  if (flag_pic)
     {
-      operands[1] = GEN_INT (INTVAL (op) >> 32);
-      output_asm_insn (singlemove_string (operands), operands);
+      if (CONSTANT_P (operands[1])
+         && pic_address_needs_scratch (operands[1]))
+       operands[1] = legitimize_pic_address (operands[1], DImode, 0);
 
-      output_asm_insn (\"sllx %0,32,%0\", operands);
-      if (INTVAL (op) & 0xffffffff)
+      if (symbolic_operand (operands[1], DImode))
        {
-         operands[1] = GEN_INT (INTVAL (op) & 0xffffffff);
-         output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
+         operands[1] = legitimize_pic_address (operands[1],
+                                               DImode,
+                                               (reload_in_progress ?
+                                                operands[0] :
+                                                NULL_RTX));
+         goto movdi_is_ok;
        }
     }
-  else
+
+  /* If we are trying to toss an integer constant into the
+     FPU registers, force it into memory.  */
+  if (GET_CODE (operands[0]) == REG
+      && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
+      && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
+      && CONSTANT_P (operands[1]))
+    operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+                                                operands[1]));
+
+  /* This makes sure we will not get rematched due to splittage. */
+  if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
+    ;
+  else if (TARGET_ARCH64
+          && CONSTANT_P (operands[1])
+           && GET_CODE (operands[1]) != HIGH
+           && GET_CODE (operands[1]) != LO_SUM)
     {
-      output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
+      sparc_emit_set_const64 (operands[0], operands[1]);
+      DONE;
     }
-#endif
 
-  return \"\";
+ movdi_is_ok:
+}")
+
+;; Be careful, fmovd does not exist when !arch64.
+;; We match MEM moves directly when we have correct even
+;; numbered registers, but fall into splits otherwise.
+;; The constraint ordering here is really important to
+;; avoid insane problems in reload, especially for patterns
+;; of the form:
+;;
+;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
+;;                       (const_int -5016)))
+;;      (reg:DI 2 %g2))
+;;
+(define_insn "*movdi_insn_sp32"
+  [(set (match_operand:DI 0 "general_operand" "=T,U,o,r,r,r,?T,?f,?f,?o,?f")
+        (match_operand:DI 1 "input_operand"    "U,T,r,o,i,r,f,T,o,f,f"))]
+  "! TARGET_ARCH64 &&
+   (register_operand (operands[0], DImode)
+    || register_operand (operands[1], DImode))"
+  "@
+   std\\t%1, %0
+   ldd\\t%1, %0
+   #
+   #
+   #
+   #
+   std\\t%1, %0
+   ldd\\t%1, %0
+   #
+   #
+   #"
+  [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,*,*,*")
+   (set_attr "length" "1,1,2,2,2,2,1,1,2,2,2")])
+
+(define_insn "*movdi_insn_sp64"
+  [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,m,?e,?e,?m")
+        (match_operand:DI 1 "input_operand"   "rI,K,J,m,rJ,e,m,e"))]
+  "TARGET_ARCH64 &&
+   (register_operand (operands[0], DImode)
+    || reg_or_0_operand (operands[1], DImode))"
+  "@
+   mov\\t%1, %0
+   sethi\\t%%hi(%a1), %0
+   clr\\t%0
+   ldx\\t%1, %0
+   stx\\t%r1, %0
+   fmovd\\t%1, %0
+   ldd\\t%1, %0
+   std\\t%1, %0"
+  [(set_attr "type" "move,move,move,load,store,fpmove,fpload,fpstore")
+   (set_attr "length" "1")])
+
+;; The following two are generated by sparc_emit_set_const64
+(define_insn "*movdi_lo_sum_sp64_cint"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "const_int_operand" "in")))]
+  "TARGET_ARCH64"
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "type" "ialu")
+   (set_attr "length" "1")])
+
+(define_insn "*movdi_lo_sum_sp64_dbl"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "const_double_operand" "")))]
+  "TARGET_ARCH64
+   && CONST_DOUBLE_HIGH (operands[2]) == 0"
+  "*
+{
+  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+  return \"or\\t%1, %%lo(%a2), %0\";
+}"
+  [(set_attr "type" "ialu")
+   (set_attr "length" "1")])
+
+(define_insn "*movdi_high_sp64_cint"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (high:DI (match_operand:DI 1 "const_int_operand" "in")))]
+  "TARGET_ARCH64"
+  "sethi\\t%%hi(%a1), %0"
+  [(set_attr "type" "move")
+   (set_attr "length" "1")])
+
+(define_insn "*movdi_high_sp64_dbl"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (high:DI (match_operand:DI 1 "const_double_operand" "")))]
+  "TARGET_ARCH64
+   && CONST_DOUBLE_HIGH (operands[1]) == 0"
+  "*
+{
+  operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+  return \"sethi\\t%%hi(%a1), %0\";
 }"
   [(set_attr "type" "move")
+   (set_attr "length" "1")])
+
+;; ??? revisit this...
+(define_insn "move_label_di"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       ; This was previously (label_ref:DI (match_operand 1 "" "")) but that
+       ; loses the volatil and other flags of the original label_ref.
+       (match_operand:DI 1 "label_ref_operand" ""))
+   (set (reg:DI 15) (pc))]
+  "TARGET_ARCH64"
+  "*
+{
+  return \"\\n1:\\trd\\t%%pc, %%o7\\n\\tsethi\\t%%hi(%l1-1b), %0\\n\\tadd\\t%0, %%lo(%l1-1b), %0\\n\\tsra\\t%0, 0, %0\\n\\tadd\\t%0, %%o7, %0\";
+}"
+  [(set_attr "type" "multi")
    (set_attr "length" "5")])
 
-;; Most of the required support for the various code models is here.
-;; We can do this because sparcs need the high insn to load the address.  We
-;; just need to get high to do the right thing for each code model.  Then each
-;; uses the same "%X+%lo(...)" in the load/store insn, though in the case of
-;; the medium/middle code model "%lo" is written "%l44".
-
-;; When TARGET_CM_MEDLOW, assume that the upper 32 bits of symbol addresses are
-;; always 0.
-;; When TARGET_CM_MEDMID, the executable must be in the low 16 TB of memory.
-;; This corresponds to the low 44 bits, and the %[hml]44 relocs are used.
-;; ??? Not implemented yet.
-;; When TARGET_CM_EMBMEDANY, the text and data segments have a maximum size of
-;; 31 bits and may be located anywhere.  EMBMEDANY_BASE_REG contains the start
-;; address of the data segment, currently %g4.
-;; When TARGET_CM_MEDANY, the text and data segments have a maximum size of 31
-;; bits and may be located anywhere.  The maximum offset from any instruction
-;; to the label _GLOBAL_OFFSET_TABLE_ is 31 bits.
+;; Sparc-v9 code model support insns.  See sparc_emit_set_symbolic_const64
+;; in sparc.c to see what is going on here... PIC stuff comes first.
+
+(define_insn "*pic_lo_sum_di"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:SI (match_operand:DI 1 "register_operand" "r")
+                   (unspec:SI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
+  "TARGET_ARCH64 && flag_pic"
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "length" "1")])
+
+(define_insn "*pic_sethi_di"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
+  "TARGET_ARCH64 && flag_pic && check_pic (1)"
+  "sethi\\t%%hi(%a1), %0"
+  [(set_attr "type" "move")
+   (set_attr "length" "1")])
+
+(define_insn "*sethi_di_medlow_embmedany_pic"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
+  "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
+  "sethi\\t%%lo(%a1), %0"
+  [(set_attr "type" "move")
+   (set_attr "length" "1")])
 
 (define_insn "*sethi_di_medlow"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (high:DI (match_operand 1 "" "")))
-  ;; The clobber is here because emit_move_sequence assumes the worst case.
-   (clobber (reg:DI 1))]
+        (high:DI (match_operand:DI 1 "" "")))]
   "TARGET_CM_MEDLOW && check_pic (1)"
-  "sethi %%hi(%a1),%0"
+  "sethi\\t%%hi(%a1), %0"
   [(set_attr "type" "move")
    (set_attr "length" "1")])
 
-(define_insn "*sethi_di_medium_pic"
+(define_insn "*losum_di_medlow"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (high:DI (match_operand 1 "sp64_medium_pic_operand" "")))]
-  "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
-  "sethi %%hi(%a1),%0"
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "" "")))]
+  "TARGET_CM_MEDLOW"
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "length" "1")])
+
+(define_insn "seth44"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (high:DI (unspec:DI [(match_operand:DI 1 "" "")] 6)))]
+  "TARGET_CM_MEDMID"
+  "sethi\\t%%h44(%a1), %0"
   [(set_attr "type" "move")
    (set_attr "length" "1")])
 
-;; WARNING: %0 gets %hi(%1)+%g4.
-;;          You cannot OR in %lo(%1), it must be added in.
+(define_insn "setm44"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (unspec:DI [(match_operand:DI 2 "" "")] 7)))]
+  "TARGET_CM_MEDMID"
+  "or\\t%1, %%m44(%a2), %0"
+  [(set_attr "type" "move")
+   (set_attr "length" "1")])
 
-(define_insn "*sethi_di_embmedany_data"
+(define_insn "setl44"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (high:DI (match_operand 1 "data_segment_operand" "")))
-  ;; The clobber is here because emit_move_sequence assumes the worst case.
-   (clobber (reg:DI 1))]
-  "TARGET_CM_EMBMEDANY && check_pic (1)"
-  "sethi %%hi(%a1),%0; add %0,%_,%0"
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "symbolic_operand" "")))]
+  "TARGET_CM_MEDMID"
+  "or\\t%1, %%l44(%a2), %0"
+  [(set_attr "length" "1")])
+
+(define_insn "sethh"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (high:DI (unspec:DI [(match_operand:DI 1 "" "")] 9)))]
+  "TARGET_CM_MEDANY"
+  "sethi\\t%%hh(%a1), %0"
   [(set_attr "type" "move")
-   (set_attr "length" "2")])
+   (set_attr "length" "1")])
 
-(define_insn "*sethi_di_embmedany_text"
+(define_insn "setlm"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (high:DI (match_operand 1 "text_segment_operand" "")))
-  ;; The clobber is here because emit_move_sequence assumes the worst case.
-   (clobber (reg:DI 1))]
-  "TARGET_CM_EMBMEDANY && check_pic (1)"
-  "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
+        (high:DI (unspec:DI [(match_operand:DI 1 "" "")] 10)))]
+  "TARGET_CM_MEDANY"
+  "sethi\\t%%lm(%a1), %0"
   [(set_attr "type" "move")
-   (set_attr "length" "5")])
-\f
-;; Move instructions
+   (set_attr "length" "1")])
 
-(define_expand "movqi"
-  [(set (match_operand:QI 0 "general_operand" "")
-       (match_operand:QI 1 "general_operand" ""))]
-  ""
-  "
-{
-  if (emit_move_sequence (operands, QImode))
-    DONE;
-}")
+(define_insn "sethm"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (unspec:DI [(match_operand:DI 2 "" "")] 18)))]
+  "TARGET_CM_MEDANY"
+  "or\\t%1, %%hm(%a2), %0"
+  [(set_attr "length" "1")])
 
-(define_insn "*movqi_insn"
-  [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
-       (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
-  "! TARGET_LIVE_G0
-   && (register_operand (operands[0], QImode)
-       || register_operand (operands[1], QImode)
-       || operands[1] == const0_rtx)"
-  "@
-   mov %1,%0
-   sethi %%hi(%a1),%0
-   ldub %1,%0
-   stb %r1,%0"
-  [(set_attr "type" "move,move,load,store")
+(define_insn "setlo"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "" "")))]
+  "TARGET_CM_MEDANY"
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "length" "1")])
+
+(define_insn "embmedany_sethi"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] 11)))]
+  "TARGET_CM_EMBMEDANY && check_pic (1)"
+  "sethi\\t%%hi(%a1), %0"
+  [(set_attr "type" "move")
    (set_attr "length" "1")])
 
-(define_insn "*movqi_insn_liveg0"
-  [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
-       (match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))]
-  "TARGET_LIVE_G0
-   && (register_operand (operands[0], QImode)
-       || register_operand (operands[1], QImode))"
-  "@
-   mov %1,%0
-   and %0,0,%0
-   and %0,0,%0\;or %0,%1,%0
-   sethi %%hi(%a1),%0
-   ldub %1,%0
-   stb %1,%0"
-  [(set_attr "type" "move,move,move,move,load,store")
-   (set_attr "length" "1,1,2,1,1,1")])
-
-(define_insn "*lo_sum_qi"
-  [(set (match_operand:QI 0 "register_operand" "=r")
-       (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
-                             (match_operand 2 "immediate_operand" "in")) 0))]
-  ""
-  "or %1,%%lo(%a2),%0"
+(define_insn "embmedany_losum"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "data_segment_operand" "")))]
+  "TARGET_CM_EMBMEDANY"
+  "add\\t%1, %%lo(%a2), %0"
   [(set_attr "length" "1")])
 
-(define_insn "*store_qi"
-  [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
-       (match_operand:QI 1 "reg_or_0_operand" "rJ"))
-   (clobber (match_scratch:SI 2 "=&r"))]
-  "(reload_completed || reload_in_progress)
-   && ! TARGET_PTR64"
-  "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
-  [(set_attr "type" "store")
-   (set_attr "length" "2")])
+(define_insn "embmedany_brsum"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (unspec:DI [(match_operand:DI 1 "register_operand" "r")] 11))]
+  "TARGET_CM_EMBMEDANY"
+  "add\\t%1, %_, %0"
+  [(set_attr "length" "1")])
 
-(define_expand "movhi"
-  [(set (match_operand:HI 0 "general_operand" "")
-       (match_operand:HI 1 "general_operand" ""))]
-  ""
-  "
-{
-  if (emit_move_sequence (operands, HImode))
-    DONE;
-}")
+(define_insn "embmedany_textuhi"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 13)))]
+  "TARGET_CM_EMBMEDANY && check_pic (1)"
+  "sethi\\t%%uhi(%a1), %0"
+  [(set_attr "type" "move")
+   (set_attr "length" "1")])
 
-(define_insn "*movhi_insn"
-  [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
-       (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
-  "! TARGET_LIVE_G0
-   && (register_operand (operands[0], HImode)
-       || register_operand (operands[1], HImode)
-       || operands[1] == const0_rtx)"
-  "@
-   mov %1,%0
-   sethi %%hi(%a1),%0
-   lduh %1,%0
-   sth %r1,%0"
-  [(set_attr "type" "move,move,load,store")
+(define_insn "embmedany_texthi"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 14)))]
+  "TARGET_CM_EMBMEDANY && check_pic (1)"
+  "sethi\\t%%hi(%a1), %0"
+  [(set_attr "type" "move")
    (set_attr "length" "1")])
 
-(define_insn "*movhi_insn_liveg0"
-  [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
-       (match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))]
-  "TARGET_LIVE_G0
-   && (register_operand (operands[0], HImode)
-       || register_operand (operands[1], HImode))"
-  "@
-   mov %1,%0
-   and %0,0,%0
-   and %0,0,%0\;or %0,%1,%0
-   sethi %%hi(%a1),%0
-   lduh %1,%0
-   sth %1,%0"
-  [(set_attr "type" "move,move,move,move,load,store")
-   (set_attr "length" "1,1,2,1,1,1")])
-
-(define_insn "*lo_sum_hi"
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
-                  (match_operand 2 "immediate_operand" "in")))]
-  ""
-  "or %1,%%lo(%a2),%0"
+(define_insn "embmedany_textulo"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] 15)))]
+  "TARGET_CM_EMBMEDANY"
+  "or\\t%1, %%ulo(%a2), %0"
   [(set_attr "length" "1")])
 
-(define_insn "*store_hi"
-  [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
-       (match_operand:HI 1 "reg_or_0_operand" "rJ"))
-   (clobber (match_scratch:SI 2 "=&r"))]
-  "(reload_completed || reload_in_progress)
-   && ! TARGET_PTR64"
-  "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
-  [(set_attr "type" "store")
-   (set_attr "length" "2")])
+(define_insn "embmedany_textlo"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "text_segment_operand" "")))]
+  "TARGET_CM_EMBMEDANY"
+  "or\\t%1, %%lo(%a2), %0"
+  [(set_attr "length" "1")])
 
-(define_expand "movsi"
-  [(set (match_operand:SI 0 "general_operand" "")
-       (match_operand:SI 1 "general_operand" ""))]
-  ""
+;; Now some patterns to help reload out a bit.
+(define_expand "reload_indi"
+  [(parallel [(match_operand:DI 0 "register_operand" "=r")
+              (match_operand:DI 1 "immediate_operand" "")
+              (match_operand:TI 2 "register_operand" "=&r")])]
+  "(TARGET_CM_MEDANY
+    || TARGET_CM_EMBMEDANY)
+   && ! flag_pic"
   "
 {
-  if (emit_move_sequence (operands, SImode))
-    DONE;
+  sparc_emit_set_symbolic_const64 (operands[0], operands[1],
+                                   gen_rtx_REG (DImode, REGNO (operands[2])));
+  DONE;
 }")
 
-;; We must support both 'r' and 'f' registers here, because combine may
-;; convert SFmode hard registers to SImode hard registers when simplifying
-;; subreg sets.
-
-;; We cannot combine the similar 'r' and 'f' constraints, because it causes
-;; problems with register allocation.  Reload might try to put an integer
-;; in an fp register, or an fp number is an integer register.
-
-(define_insn "*movsi_insn"
-  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q,d")
-       (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f,J"))]
-  "! TARGET_LIVE_G0
-   && (register_operand (operands[0], SImode)
-       || register_operand (operands[1], SImode)
-       || operands[1] == const0_rtx)
-   && (GET_CODE (operands[0]) != REG || ! CONSTANT_P (operands[1])
-       || REGNO (operands[0]) < 32
-       || REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)"
-  "@
-   mov %1,%0
-   fmovs %1,%0
-   sethi %%hi(%a1),%0
-   ld %1,%0
-   ld %1,%0
-   st %r1,%0
-   st %1,%0
-   fzeros %0"
-  [(set_attr "type" "move,fpmove,move,load,fpload,store,fpstore,fpmove")
-   (set_attr "length" "1")])
-
-(define_insn "*movsi_insn_liveg0"
-  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q")
-       (match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))]
-  "TARGET_LIVE_G0
-   && (register_operand (operands[0], SImode)
-       || register_operand (operands[1], SImode))"
-  "@
-   mov %1,%0
-   and %0,0,%0
-   and %0,0,%0\;or %0,%1,%0
-   fmovs %1,%0
-   sethi %%hi(%a1),%0
-   ld %1,%0
-   ld %1,%0
-   st %1,%0
-   st %1,%0"
-  [(set_attr "type" "move,move,move,fpmove,move,load,fpload,store,fpstore")
-   (set_attr "length" "1,1,2,1,1,1,1,1,1")])
-
-(define_insn "*store_si"
-  [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
-       (match_operand:SI 1 "reg_or_0_operand" "rJ"))
-   (clobber (match_scratch:SI 2 "=&r"))]
-  "(reload_completed || reload_in_progress)
-   && ! TARGET_PTR64"
-  "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
-  [(set_attr "type" "store")
-   (set_attr "length" "2")])
-
-(define_expand "movdi"
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
-       (match_operand:DI 1 "general_operand" ""))]
-  ""
+(define_expand "reload_outdi"
+  [(parallel [(match_operand:DI 0 "register_operand" "=r")
+              (match_operand:DI 1 "immediate_operand" "")
+              (match_operand:TI 2 "register_operand" "=&r")])]
+  "(TARGET_CM_MEDANY
+    || TARGET_CM_EMBMEDANY)
+   && ! flag_pic"
   "
 {
-  if (emit_move_sequence (operands, DImode))
-    DONE;
+  sparc_emit_set_symbolic_const64 (operands[0], operands[1],
+                                   gen_rtx_REG (DImode, REGNO (operands[2])));
+  DONE;
 }")
 
-;; 32 bit V9 movdi is like regular 32 bit except: a 64 bit zero can be stored
-;; to aligned memory with a single instruction, the ldd/std instructions
-;; are not used, and constants can not be moved to floating point registers.
-
-(define_insn "*movdi_sp32_v9"
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,Q,r,r,?e,?e,?Q,?b")
-       (match_operand:DI 1 "general_operand" "r,J,r,Q,i,e,Q,e,J"))]
-  "TARGET_V9 && ! TARGET_ARCH64
-   && (register_operand (operands[0], DImode)
-       || register_operand (operands[1], DImode)
-       || operands[1] == const0_rtx)
-   && (GET_CODE (operands[0]) != REG || ! CONSTANT_P (operands[1])
-       || REGNO (operands[0]) < 32
-       || REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)"
-  "*
+;; Split up putting CONSTs and REGs into DI regs when !arch64
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (match_operand:DI 1 "const_int_operand" ""))]
+  "! TARGET_ARCH64 && reload_completed"
+  [(clobber (const_int 0))]
+  "
 {
-  if (which_alternative == 1)
-    return \"stx %%g0,%0\";
-  if (which_alternative == 8)
-    return \"fzero %0\";
-  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
-    return output_fp_move_double (operands);
-  return output_move_double (operands);
-}"
-  [(set_attr "type" "move,store,store,load,multi,fp,fpload,fpstore,fpmove")
-   (set_attr "length" "2,1,3,3,3,2,3,3,1")])
+  emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
+                       (INTVAL (operands[1]) < 0) ?
+                       constm1_rtx :
+                       const0_rtx));
+  emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+                       operands[1]));
+  DONE;
+}")
 
-;; SPARC V9 deprecates std.  Split it here.
 (define_split
-  [(set (match_operand:DI 0 "memory_operand" "=m")
-      (match_operand:DI 1 "register_operand" "r"))]
-  "TARGET_V9 && ! TARGET_ARCH64 && reload_completed
-   && REGNO (operands[1]) < 32 && ! MEM_VOLATILE_P (operands[0])
-   && offsettable_memref_p (operands[0])"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 4) (match_dup 5))]
-  "operands[3] = gen_highpart (SImode, operands[1]);
-   operands[5] = gen_lowpart (SImode, operands[1]);
-   operands[4] = adj_offsettable_operand (operands[0], 4);
-   PUT_MODE (operands[4], SImode);
-   operands[2] = copy_rtx (operands[0]);
-   PUT_MODE (operands[2], SImode);")
-
-;; Split register to register moves.
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (match_operand:DI 1 "arith_double_operand" "rIN"))]
-  "! TARGET_ARCH64
-   && REGNO (operands[0]) < 32
-   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 32
-   && ! reg_overlap_mentioned_p (operands[0], operands[1])"
-  [(set (match_dup 2) (match_dup 4))
-   (set (match_dup 3) (match_dup 5))]
-  "operands[2] = gen_highpart (SImode, operands[0]);
-   operands[3] = gen_lowpart (SImode, operands[0]);
-   operands[4] = gen_highpart (SImode, operands[1]);
-   operands[5] = gen_lowpart (SImode, operands[1]);")
-
-(define_insn "*movdi_sp32"
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")
-       (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]
-  "! TARGET_V9
-   && (register_operand (operands[0], DImode)
-       || register_operand (operands[1], DImode)
-       || operands[1] == const0_rtx)"
-  "*
-{
-  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
-    return output_fp_move_double (operands);
-  return output_move_double (operands);
-}"
-  [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")
-   (set_attr "length" "2,1,1,3,3,3,2,3,3")])
-
-;;; ??? The trick used below can be extended to load any negative 32 bit
-;;; constant in two instructions.  Currently the compiler will use HIGH/LO_SUM
-;;; for anything not matching the HIK constraints, which results in 5
-;;; instructions.  Positive 32 bit constants can be loaded in the obvious way
-;;; with sethi/ori.  To extend the trick, in the xor instruction, use 
-;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0
-;;; This needs the original value of operands[1], not the inverted value.
-
-(define_insn "*movdi_sp64_insn"
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?e,?e,?Q")
-       (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,e,Q,e"))]
-  "TARGET_ARCH64
-   && (register_operand (operands[0], DImode)
-       || register_operand (operands[1], DImode)
-       || operands[1] == const0_rtx)"
-  "*
+  [(set (match_operand:DI 0 "register_operand" "")
+        (match_operand:DI 1 "const_double_operand" ""))]
+  "! TARGET_ARCH64 && reload_completed"
+  [(clobber (const_int 0))]
+  "
 {
-  switch (which_alternative)
+  emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
+                       GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
+
+  /* Slick... but this trick loses if this subreg constant part
+     can be done in one insn.  */
+  if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
+      && !(SPARC_SETHI_P (CONST_DOUBLE_HIGH (operands[1]))
+          || SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
     {
-    case 0:
-      return \"mov %1,%0\";
-    case 1:
-      /* Sethi does not sign extend, so we must use a little trickery
-        to use it for negative numbers.  Invert the constant before
-        loading it in, then use a xor immediate to invert the loaded bits
-        (along with the upper 32 bits) to the desired constant.  This
-        works because the sethi and immediate fields overlap.  */
-
-      if ((INTVAL (operands[1]) & 0x80000000) == 0)
-       return \"sethi %%hi(%a1),%0\";
-      else
-       {
-         operands[1] = GEN_INT (~INTVAL (operands[1]));
-         output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
-         /* The low 10 bits are already zero, but invert the rest.
-            Assemblers don't accept 0x1c00, so use -0x400 instead.  */
-         return \"xor %0,-0x400,%0\";
-       }
-    case 2:
-      return \"ldx %1,%0\";
-    case 3:
-      return \"stx %r1,%0\";
-    case 4:
-      return \"fmovd %1,%0\";
-    case 5:
-      return \"ldd %1,%0\";
-    case 6:
-      return \"std %1,%0\";
-    default:
-      abort ();
+      emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+                           gen_highpart (SImode, operands[0])));
     }
-}"
-  [(set_attr "type" "move,move,load,store,fp,fpload,fpstore")
-   (set_attr "length" "1,2,1,1,1,1,1")])
+  else
+    {
+      emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+                           GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
+    }
+  DONE;
+}")
 
-;; ??? There's no symbolic (set (mem:DI ...) ...).
-;; Experimentation with v9 suggested one isn't needed.
-\f
-;; Floating point move insns
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (match_operand:DI 1 "register_operand" ""))]
+  "! TARGET_ARCH64 && reload_completed"
+  [(clobber (const_int 0))]
+  "
+{
+  rtx set_dest = operands[0];
+  rtx set_src = operands[1];
+  rtx dest1, dest2;
+  rtx src1, src2;
 
-;; This pattern forces (set (reg:SF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory.
-;; It must come before the more general movsf pattern.
-(define_insn "*movsf_const_insn"
-  [(set (match_operand:SF 0 "general_operand" "=f,d,m,?r")
-       (match_operand:SF 1 "" "m,G,G,?F"))]
-  "TARGET_FPU
-   && GET_CODE (operands[1]) == CONST_DOUBLE
-   && (GET_CODE (operands[0]) == REG
-       || fp_zero_operand (operands[1]))"
-  "*
+  if (GET_CODE (set_dest) == SUBREG)
+    set_dest = alter_subreg (set_dest);
+  if (GET_CODE (set_src) == SUBREG)
+    set_src = alter_subreg (set_src);
+
+  dest1 = gen_highpart (SImode, set_dest);
+  dest2 = gen_lowpart (SImode, set_dest);
+  src1 = gen_highpart (SImode, set_src);
+  src2 = gen_lowpart (SImode, set_src);
+
+  /* Now emit using the real source and destination we found, swapping
+     the order if we detect overlap.  */
+  if (REGNO(dest1) == REGNO(src2))
+    {
+      emit_insn (gen_movsi (dest2, src2));
+      emit_insn (gen_movsi (dest1, src1));
+    }
+  else
+    {
+      emit_insn (gen_movsi (dest1, src1));
+      emit_insn (gen_movsi (dest2, src2));
+    }
+  DONE;
+}")
+
+;; Now handle the cases of memory moves from/to non-even
+;; DI mode register pairs.
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (match_operand:DI 1 "memory_operand" ""))]
+  "(! TARGET_ARCH64
+    && reload_completed
+    && sparc_splitdi_legitimate (operands[0], operands[1]))"
+  [(clobber (const_int 0))]
+  "
 {
-  switch (which_alternative)
+  rtx word0 = change_address (operands[1], SImode, NULL_RTX);
+  rtx word1 = change_address (operands[1], SImode,
+                             plus_constant_for_output (XEXP (word0, 0), 4));
+  rtx high_part = gen_highpart (SImode, operands[0]);
+  rtx low_part = gen_lowpart (SImode, operands[0]);
+  int self_reference;
+
+  self_reference = reg_mentioned_p (operands[0],
+                                    XEXP (XEXP (word1, 0), 0));
+  if (self_reference != 0
+      && WORDS_BIG_ENDIAN)
     {
-    case 0:
-      return \"ld %1,%0\";
-    case 1:
-      return \"fzeros %0\";
-    case 2:
-      return \"st %%g0,%0\";
-    case 3:
-      return singlemove_string (operands);
-    default:
-      abort ();
+      emit_insn (gen_movsi (low_part, word1));
+      emit_insn (gen_movsi (high_part, word0));
     }
-}"
-  [(set_attr "type" "fpload,fpmove,store,load")
-   (set_attr "length" "1,1,1,2")])
+  else
+    {
+      emit_insn (gen_movsi (high_part, word0));
+      emit_insn (gen_movsi (low_part, word1));
+    }
+  DONE;
+}")
+
+(define_split
+  [(set (match_operand:DI 0 "memory_operand" "")
+        (match_operand:DI 1 "register_operand" ""))]
+  "(! TARGET_ARCH64
+    && reload_completed
+    && sparc_splitdi_legitimate (operands[1], operands[0]))"
+  [(clobber (const_int 0))]
+  "
+{
+  rtx word0 = change_address (operands[0], SImode, NULL_RTX);
+  rtx word1 = change_address (operands[0], SImode,
+                             plus_constant_for_output (XEXP (word0, 0), 4));
+  rtx high_part = gen_highpart (SImode, operands[1]);
+  rtx low_part = gen_lowpart (SImode, operands[1]);
+
+  emit_insn (gen_movsi (word0, high_part));
+  emit_insn (gen_movsi (word1, low_part));
+  DONE;
+}")
+
+\f
+;; Floating point move insns
 
 (define_expand "movsf"
   [(set (match_operand:SF 0 "general_operand" "")
   ""
   "
 {
-  if (emit_move_sequence (operands, SFmode))
-    DONE;
+  /* Force SFmode constants into memory.  */
+  if (GET_CODE (operands[0]) == REG
+      && CONSTANT_P (operands[1]))
+    {
+      /* emit_group_store will send such bogosity to us when it is
+         not storing directly into memory.  So fix this up to avoid
+         crashes in output_constant_pool.  */
+      if (operands [1] == const0_rtx)
+        operands[1] = CONST0_RTX (SFmode);
+      operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+                                                   operands[1]));
+    }
+
+  /* Handle sets of MEM first.  */
+  if (GET_CODE (operands[0]) == MEM)
+    {
+      if (register_operand (operands[1], SFmode))
+       goto movsf_is_ok;
+
+      if (! reload_in_progress)
+       {
+         operands[0] = validize_mem (operands[0]);
+         operands[1] = force_reg (SFmode, operands[1]);
+       }
+    }
+
+  /* Fixup PIC cases.  */
+  if (flag_pic)
+    {
+      if (CONSTANT_P (operands[1])
+         && pic_address_needs_scratch (operands[1]))
+       operands[1] = legitimize_pic_address (operands[1], SFmode, 0);
+
+      if (symbolic_operand (operands[1], SFmode))
+       {
+         operands[1] = legitimize_pic_address (operands[1],
+                                               SFmode,
+                                               (reload_in_progress ?
+                                                operands[0] :
+                                                NULL_RTX));
+       }
+    }
+
+ movsf_is_ok:
 }")
 
 (define_insn "*movsf_insn"
-  [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,f,Q,r,r,Q")
-       (match_operand:SF 1 "reg_or_nonsymb_mem_operand"  "f,Q,f,r,Q,r"))]
+  [(set (match_operand:SF 0 "general_operand" "=f,f,m,r,r,m")
+       (match_operand:SF 1 "input_operand"    "f,m,f,r,m,r"))]
   "TARGET_FPU
    && (register_operand (operands[0], SFmode)
        || register_operand (operands[1], SFmode))"
   "@
-   fmovs %1,%0
-   ld %1,%0
-   st %1,%0
-   mov %1,%0
-   ld %1,%0
-   st %1,%0"
-  [(set_attr "type" "fpmove,fpload,fpstore,move,load,store")])
+   fmovs\\t%1, %0
+   ld\\t%1, %0
+   st\\t%1, %0
+   mov\\t%1, %0
+   ld\\t%1, %0
+   st\\t%1, %0"
+  [(set_attr "type" "fpmove,fpload,fpstore,move,load,store")
+   (set_attr "length" "1")])
 
 ;; Exactly the same as above, except that all `f' cases are deleted.
 ;; This is necessary to prevent reload from ever trying to use a `f' reg
 ;; when -mno-fpu.
 
 (define_insn "*movsf_no_f_insn"
-  [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
-       (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
+  [(set (match_operand:SF 0 "general_operand" "=r,r,m")
+       (match_operand:SF 1 "input_operand"    "r,m,r"))]
   "! TARGET_FPU
    && (register_operand (operands[0], SFmode)
        || register_operand (operands[1], SFmode))"
   "@
-   mov %1,%0
-   ld %1,%0
-   st %1,%0"
-  [(set_attr "type" "move,load,store")])
-
-(define_insn "*store_sf"
-  [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
-       (match_operand:SF 1 "reg_or_0_operand" "rfG"))
-   (clobber (match_scratch:SI 2 "=&r"))]
-  "(reload_completed || reload_in_progress)
-   && ! TARGET_PTR64"
-  "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
-  [(set_attr "type" "store")
-   (set_attr "length" "2")])
-
-;; This pattern forces (set (reg:DF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory.
-;; It must come before the more general movdf pattern.
-
-(define_insn "*movdf_const_insn"
-  [(set (match_operand:DF 0 "general_operand" "=?r,e,o,d")
-       (match_operand:DF 1 "" "?F,m,G,G"))]
-  "TARGET_FPU
-   && GET_CODE (operands[1]) == CONST_DOUBLE
-   && (GET_CODE (operands[0]) == REG
-       || fp_zero_operand (operands[1]))"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-      return output_move_double (operands);
-    case 1:
-      return output_fp_move_double (operands);
-    case 2:
-      if (TARGET_ARCH64 || (TARGET_V9 && mem_aligned_8 (operands[0])))
-       {
-         return \"stx %%g0,%0\";
-       }
-      else
-       {
-         operands[1] = adj_offsettable_operand (operands[0], 4);
-         return \"st %%g0,%0\;st %%g0,%1\";
-       }
-    case 3:
-      return \"fzero %0\";
-    default:
-      abort ();
-    }
-}"
-  [(set_attr "type" "load,fpload,store,fpmove")
-   (set_attr "length" "3,3,3,1")])
+   mov\\t%1, %0
+   ld\\t%1, %0
+   st\\t%1, %0"
+  [(set_attr "type" "move,load,store")
+   (set_attr "length" "1")])
 
 (define_expand "movdf"
   [(set (match_operand:DF 0 "general_operand" "")
   ""
   "
 {
-  if (emit_move_sequence (operands, DFmode))
-    DONE;
+  /* Force DFmode constants into memory.  */
+  if (GET_CODE (operands[0]) == REG
+      && CONSTANT_P (operands[1]))
+    {
+      /* emit_group_store will send such bogosity to us when it is
+         not storing directly into memory.  So fix this up to avoid
+         crashes in output_constant_pool.  */
+      if (operands [1] == const0_rtx)
+        operands[1] = CONST0_RTX (DFmode);
+      operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+                                                   operands[1]));
+    }
+
+  /* Handle MEM cases first.  */
+  if (GET_CODE (operands[0]) == MEM)
+    {
+      if (register_operand (operands[1], DFmode))
+       goto movdf_is_ok;
+
+      if (! reload_in_progress)
+       {
+         operands[0] = validize_mem (operands[0]);
+         operands[1] = force_reg (DFmode, operands[1]);
+       }
+    }
+
+  /* Fixup PIC cases.  */
+  if (flag_pic)
+    {
+      if (CONSTANT_P (operands[1])
+         && pic_address_needs_scratch (operands[1]))
+       operands[1] = legitimize_pic_address (operands[1], DFmode, 0);
+
+      if (symbolic_operand (operands[1], DFmode))
+       {
+         operands[1] = legitimize_pic_address (operands[1],
+                                               DFmode,
+                                               (reload_in_progress ?
+                                                operands[0] :
+                                                NULL_RTX));
+       }
+    }
+
+ movdf_is_ok:
 }")
 
-(define_insn "*movdf_insn"
-  [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=e,Q,e,T,U,r,Q,r")
-       (match_operand:DF 1 "reg_or_nonsymb_mem_operand"  "e,e,Q,U,T,r,r,Q"))]
+;; Be careful, fmovd does not exist when !arch64.
+(define_insn "*movdf_insn_sp32"
+  [(set (match_operand:DF 0 "general_operand" "=e,T,U,T,e,r,r,o,e,o")
+       (match_operand:DF 1 "input_operand"    "T,e,T,U,e,r,o,r,o,e"))]
   "TARGET_FPU
+   && ! TARGET_ARCH64
    && (register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
-  "*
-{
-  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
-    return output_fp_move_double (operands);
-  return output_move_double (operands);
-}"
-  [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load")
-   (set_attr "length" "1,1,2,2,3,3,3,3")])
-
-;; Exactly the same as above, except that all `e' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `e' reg
-;; when -mno-fpu.
-
-(define_insn "*movdf_no_e_insn"
-  [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
-       (match_operand:DF 1 "reg_or_nonsymb_mem_operand"  "U,T,r,r,Q"))]
+  "@
+  ldd\\t%1, %0
+  std\\t%1, %0
+  ldd\\t%1, %0
+  std\\t%1, %0
+  #
+  #
+  #
+  #
+  #
+  #"
+ [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
+  (set_attr "length" "1,1,1,1,2,2,2,2,2,2")])
+
+(define_insn "*movdf_no_e_insn_sp32"
+  [(set (match_operand:DF 0 "general_operand" "=U,T,r,r,o")
+       (match_operand:DF 1 "input_operand"    "T,U,r,o,r"))]
   "! TARGET_FPU
+   && ! TARGET_ARCH64
+   && (register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode))"
+  "@
+  ldd\\t%1, %0
+  std\\t%1, %0
+  #
+  #
+  #"
+  [(set_attr "type" "load,store,*,*,*")
+   (set_attr "length" "1,1,2,2,2")])
+
+(define_insn "*movdf_insn_sp64"
+  [(set (match_operand:DF 0 "general_operand" "=e,e,m,r,r,m")
+        (match_operand:DF 1 "input_operand"    "e,m,e,r,m,r"))]
+  "TARGET_FPU
+   && TARGET_ARCH64
    && (register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
-  "* return output_move_double (operands);"
-  [(set_attr "type" "store,load,move,store,load")
-   (set_attr "length" "1,1,2,3,3")])
+  "@
+  fmovd\\t%1, %0
+  ldd\\t%1, %0
+  std\\t%1, %0
+  mov\\t%1, %0
+  ldx\\t%1, %0
+  stx\\t%1, %0"
+  [(set_attr "type" "fpmove,load,store,move,load,store")
+   (set_attr "length" "1")])
 
-;; Must handle overlapping registers here, since parameters can be unaligned
-;; in registers.
+(define_insn "*movdf_no_e_insn_sp64"
+  [(set (match_operand:DF 0 "general_operand" "=r,r,m")
+        (match_operand:DF 1 "input_operand"    "r,m,r"))]
+  "! TARGET_FPU
+   && TARGET_ARCH64
+   && (register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode))"
+  "@
+  mov\\t%1, %0
+  ldx\\t%1, %0
+  stx\\t%1, %0"
+  [(set_attr "type" "move,load,store")
+   (set_attr "length" "1")])
 
+;; Ok, now the splits to handle all the multi insn and
+;; mis-aligned memory address cases.
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
-       (match_operand:DF 1 "register_operand" ""))]
-  "! TARGET_ARCH64 && reload_completed
-   && REGNO (operands[0]) < SPARC_FIRST_V9_FP_REG
-   && REGNO (operands[1]) < SPARC_FIRST_V9_FP_REG"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 4) (match_dup 5))]
+        (match_operand:DF 1 "register_operand" ""))]
+  "! TARGET_ARCH64 && reload_completed"
+  [(clobber (const_int 0))]
   "
 {
-  rtx first_set = operand_subword (operands[0], 0, 0, DFmode);
-  rtx second_use = operand_subword (operands[1], 1, 0, DFmode);
+  rtx set_dest = operands[0];
+  rtx set_src = operands[1];
+  rtx dest1, dest2;
+  rtx src1, src2;
+
+  if (GET_CODE (set_dest) == SUBREG)
+    set_dest = alter_subreg (set_dest);
+  if (GET_CODE (set_src) == SUBREG)
+    set_src = alter_subreg (set_src);
 
-  if (REGNO (first_set) == REGNO (second_use))
+  dest1 = gen_highpart (SFmode, set_dest);
+  dest2 = gen_lowpart (SFmode, set_dest);
+  src1 = gen_highpart (SFmode, set_src);
+  src2 = gen_lowpart (SFmode, set_src);
+
+  /* Now emit using the real source and destination we found, swapping
+     the order if we detect overlap.  */
+  if (REGNO(dest1) == REGNO(src2))
     {
-      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
-      operands[3] = second_use;
-      operands[4] = first_set;
-      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
+      emit_insn (gen_movsf (dest2, src2));
+      emit_insn (gen_movsf (dest1, src1));
     }
   else
     {
-      operands[2] = first_set;
-      operands[3] = operand_subword (operands[1], 0, 0, DFmode);
-      operands[4] = operand_subword (operands[0], 1, 0, DFmode);
-      operands[5] = second_use;
+      emit_insn (gen_movsf (dest1, src1));
+      emit_insn (gen_movsf (dest2, src2));
     }
+  DONE;
 }")
 
-(define_insn "*store_df"
-  [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
-       (match_operand:DF 1 "reg_or_0_operand" "re,G"))
-   (clobber (match_scratch:SI 2 "=&r,&r"))]
-  "(reload_completed || reload_in_progress)
-   && ! TARGET_PTR64"
-  "*
+(define_split
+  [(set (match_operand:DF 0 "register_operand" "")
+       (match_operand:DF 1 "memory_operand" ""))]
+  "(! TARGET_ARCH64
+    && (reload_completed
+        && (((REGNO (operands[0])) % 2) != 0
+             || ! mem_min_alignment (operands[1], 8))
+        && offsettable_memref_p (operands[1])))"
+  [(clobber (const_int 0))]
+  "
 {
-  output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
-  if (which_alternative == 0)
-    return \"std %1,[%2+%%lo(%a0)]\";
+  rtx word0 = change_address (operands[1], SFmode, NULL_RTX);
+  rtx word1 = change_address (operands[1], SFmode,
+                             plus_constant_for_output (XEXP (word0, 0), 4));
+  int self_reference;
+
+  self_reference = reg_mentioned_p (operands[0],
+                                    XEXP (XEXP (word1, 0), 0));
+  if (self_reference != 0
+      && WORDS_BIG_ENDIAN)
+    {
+      emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
+                           word1));
+      emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
+                           word0));
+    }
   else
-    return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
-}"
-  [(set_attr "type" "store")
-   (set_attr "length" "3")])
-
-;; This pattern forces (set (reg:TF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory.
-;; It must come before the more general movtf pattern.
-(define_insn "*movtf_const_insn"
-  [(set (match_operand:TF 0 "general_operand" "=?r,e,o")
-       (match_operand:TF 1 "" "?F,m,G"))]
-  "TARGET_FPU
-   && GET_CODE (operands[1]) == CONST_DOUBLE
-   && (GET_CODE (operands[0]) == REG
-       || fp_zero_operand (operands[1]))"
-  "*
-{
-  switch (which_alternative)
     {
-    case 0:
-      return output_move_quad (operands);
-    case 1:
-      return output_fp_move_quad (operands);
-    case 2:
-      if (TARGET_ARCH64 || (TARGET_V9 && mem_aligned_8 (operands[0])))
-       {
-         operands[1] = adj_offsettable_operand (operands[0], 8);
-         return \"stx %%g0,%0\;stx %%g0,%1\";
-       }
-      else
-       {
-         /* ??? Do we run off the end of the array here? */
-         operands[1] = adj_offsettable_operand (operands[0], 4);
-         operands[2] = adj_offsettable_operand (operands[0], 8);
-         operands[3] = adj_offsettable_operand (operands[0], 12);
-         return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
-       }
-    default:
-      abort ();
+      emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
+                           word0));
+      emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
+                           word1));
     }
-}"
-  [(set_attr "type" "load,fpload,store")
-   (set_attr "length" "5,5,5")])
+  DONE;
+}")
+
+(define_split
+  [(set (match_operand:DF 0 "memory_operand" "")
+       (match_operand:DF 1 "register_operand" ""))]
+  "(! TARGET_ARCH64
+    && (reload_completed
+        && (((REGNO (operands[1])) % 2) != 0
+             || ! mem_min_alignment (operands[0], 8))
+        && offsettable_memref_p (operands[0])))"
+  [(clobber (const_int 0))]
+  "
+{
+  rtx word0 = change_address (operands[0], SFmode, NULL_RTX);
+  rtx word1 = change_address (operands[0], SFmode,
+                             plus_constant_for_output (XEXP (word0, 0), 4));
+
+  emit_insn (gen_movsf (word0,
+                       gen_highpart (SFmode, operands[1])));
+  emit_insn (gen_movsf (word1,
+                       gen_lowpart (SFmode, operands[1])));
+  DONE;
+}")
 
 (define_expand "movtf"
   [(set (match_operand:TF 0 "general_operand" "")
   ""
   "
 {
-  if (emit_move_sequence (operands, TFmode))
-    DONE;
+  /* Force TFmode constants into memory. */
+  if (GET_CODE (operands[0]) == REG
+      && CONSTANT_P (operands[1]))
+    {
+      /* emit_group_store will send such bogosity to us when it is
+         not storing directly into memory.  So fix this up to avoid
+         crashes in output_constant_pool.  */
+      if (operands [1] == const0_rtx)
+        operands[1] = CONST0_RTX (TFmode);
+      operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+                                                   operands[1]));
+    }
+
+  /* Handle MEM cases first, note that even v9 only guarentees
+     8-byte alignment for quads so... */
+  if (GET_CODE (operands[0]) == MEM)
+    {
+      if (register_operand (operands[1], TFmode))
+        goto movtf_is_ok;
+
+      if (! reload_in_progress)
+       {
+         operands[0] = validize_mem (operands[0]);
+         operands[1] = force_reg (TFmode, operands[1]);
+       }
+    }
+
+  /* Fixup PIC cases.  */
+  if (flag_pic)
+    {
+      if (CONSTANT_P (operands[1])
+         && pic_address_needs_scratch (operands[1]))
+       operands[1] = legitimize_pic_address (operands[1], TFmode, 0);
+
+      if (symbolic_operand (operands[1], TFmode))
+       {
+         operands[1] = legitimize_pic_address (operands[1],
+                                               TFmode,
+                                               (reload_in_progress ?
+                                                operands[0] :
+                                                NULL_RTX));
+       }
+    }
+
+movtf_is_ok:
 }")
 
-(define_insn "*movtf_insn"
-  [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,Q,e,r,Q,r")
-       (match_operand:TF 1 "reg_or_nonsymb_mem_operand"  "e,e,Q,r,r,Q"))]
+;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
+;; we must split them all.  :-(
+(define_insn "*movtf_insn_sp32"
+  [(set (match_operand:TF 0 "general_operand" "=e,m,U,o,e,r,r,o")
+       (match_operand:TF 1 "input_operand"    "m,e,o,U,e,r,o,r"))]
   "TARGET_FPU
+   && ! TARGET_ARCH64
    && (register_operand (operands[0], TFmode)
        || register_operand (operands[1], TFmode))"
-  "*
-{
-  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
-    return output_fp_move_quad (operands);
-  return output_move_quad (operands);
-}"
-  [(set_attr "type" "fp,move,fpstore,store,fpload,load")
-   (set_attr "length" "4,4,5,5,5,5")])
+  "#"
+  [(set_attr "length" "4")])
 
 ;; Exactly the same as above, except that all `e' cases are deleted.
 ;; This is necessary to prevent reload from ever trying to use a `e' reg
 ;; when -mno-fpu.
 
-(define_insn "*movtf_no_e_insn"
-  [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
-       (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
+(define_insn "*movtf_no_e_insn_sp32"
+  [(set (match_operand:TF 0 "general_operand" "=U,o,r,r,o")
+       (match_operand:TF 1 "input_operand"    "o,U,r,o,r"))]
   "! TARGET_FPU
+   && ! TARGET_ARCH64
    && (register_operand (operands[0], TFmode)
        || register_operand (operands[1], TFmode))"
-  "*
-{
-  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
-    return output_fp_move_quad (operands);
-  return output_move_quad (operands);
-}"
-  [(set_attr "type" "move,store,load")
-   (set_attr "length" "4,5,5")])
-
-;; This is disabled because it does not work.  Long doubles have only 8
-;; byte alignment.  Adding an offset of 8 or 12 to an 8 byte aligned %lo may 
-;; cause it to overflow.  See also GO_IF_LEGITIMATE_ADDRESS.
-(define_insn "*store_tf"
-  [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
-       (match_operand:TF 1 "reg_or_0_operand" "re,G"))
-   (clobber (match_scratch:SI 2 "=&r,&r"))]
-  "0 && (reload_completed || reload_in_progress)
-   && ! TARGET_PTR64"
-  "*
+  "#"
+  [(set_attr "length" "4")])
+
+;; Now handle the float reg cases directly when arch64,
+;; hard_quad, and proper reg number alignment are all true.
+(define_insn "*movtf_insn_hq_sp64"
+  [(set (match_operand:TF 0 "general_operand" "=e,e,m,r,r,o")
+        (match_operand:TF 1 "input_operand"    "e,m,e,r,o,r"))]
+  "TARGET_FPU
+   && TARGET_ARCH64
+   && TARGET_V9
+   && TARGET_HARD_QUAD
+   && (register_operand (operands[0], TFmode)
+       || register_operand (operands[1], TFmode))"
+  "@
+  fmovq\\t%1, %0
+  ldq\\t%1, %0
+  stq\\t%1, %0
+  #
+  #
+  #"
+  [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
+   (set_attr "length" "1,1,1,2,2,2")])
+
+;; Now we allow the integer register cases even when
+;; only arch64 is true.
+(define_insn "*movtf_insn_sp64"
+  [(set (match_operand:TF 0 "general_operand" "=e,e,o,r,r,o")
+        (match_operand:TF 1 "input_operand"    "e,o,e,r,o,r"))]
+  "TARGET_FPU
+   && TARGET_ARCH64
+   && ! TARGET_HARD_QUAD
+   && (register_operand (operands[0], TFmode)
+       || register_operand (operands[1], TFmode))"
+  "#"
+  [(set_attr "length" "2")])
+
+(define_insn "*movtf_no_e_insn_sp64"
+  [(set (match_operand:TF 0 "general_operand" "=r,r,o")
+        (match_operand:TF 1 "input_operand"    "r,o,r"))]
+  "! TARGET_FPU
+   && TARGET_ARCH64
+   && (register_operand (operands[0], TFmode)
+       || register_operand (operands[1], TFmode))"
+  "#"
+  [(set_attr "length" "2")])
+
+;; Now all the splits to handle multi-insn TF mode moves.
+(define_split
+  [(set (match_operand:TF 0 "register_operand" "")
+        (match_operand:TF 1 "register_operand" ""))]
+  "reload_completed
+   && (! TARGET_ARCH64
+       || (TARGET_FPU
+           && ! TARGET_HARD_QUAD))"
+  [(clobber (const_int 0))]
+  "
 {
-  output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
-  if (which_alternative == 0)
-    return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
+  rtx set_dest = operands[0];
+  rtx set_src = operands[1];
+  rtx dest1, dest2;
+  rtx src1, src2;
+
+  if (GET_CODE (set_dest) == SUBREG)
+    set_dest = alter_subreg (set_dest);
+  if (GET_CODE (set_src) == SUBREG)
+    set_src = alter_subreg (set_src);
+
+  dest1 = gen_highpart (DFmode, set_dest);
+  dest2 = gen_lowpart (DFmode, set_dest);
+  src1 = gen_highpart (DFmode, set_src);
+  src2 = gen_lowpart (DFmode, set_src);
+
+  /* Now emit using the real source and destination we found, swapping
+     the order if we detect overlap.  */
+  if (REGNO(dest1) == REGNO(src2))
+    {
+      emit_insn (gen_movdf (dest2, src2));
+      emit_insn (gen_movdf (dest1, src1));
+    }
   else
-    return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
-}"
-  [(set_attr "type" "store")
-   (set_attr "length" "5")])
+    {
+      emit_insn (gen_movdf (dest1, src1));
+      emit_insn (gen_movdf (dest2, src2));
+    }
+  DONE;
+}")
+
+(define_split
+  [(set (match_operand:TF 0 "register_operand" "")
+        (match_operand:TF 1 "memory_operand" ""))]
+  "(reload_completed
+    && offsettable_memref_p (operands[1]))"
+  [(clobber (const_int 0))]
+  "
+{
+  rtx word0 = change_address (operands[1], DFmode, NULL_RTX);
+  rtx word1 = change_address (operands[1], DFmode,
+                             plus_constant_for_output (XEXP (word0, 0), 8));
+
+  emit_insn (gen_movdf (gen_highpart (DFmode, operands[0]),
+                       word0));
+  emit_insn (gen_movdf (gen_lowpart (DFmode, operands[0]),
+                       word1));
+  DONE;
+}")
+
+(define_split
+  [(set (match_operand:TF 0 "memory_operand" "")
+       (match_operand:TF 1 "register_operand" ""))]
+  "(reload_completed
+    && offsettable_memref_p (operands[0]))"
+  [(clobber (const_int 0))]
+  "
+{
+  rtx word0 = change_address (operands[0], DFmode, NULL_RTX);
+  rtx word1 = change_address (operands[0], DFmode,
+                             plus_constant_for_output (XEXP (word0, 0), 8));
+
+  emit_insn (gen_movdf (word0,
+                       gen_highpart (DFmode, operands[1])));
+  emit_insn (gen_movdf (word1,
+                       gen_lowpart (DFmode, operands[1])));
+  DONE;
+}")
 \f
 ;; Sparc V9 conditional move instructions.
 
 
   if (sparc_compare_op1 == const0_rtx
       && GET_CODE (sparc_compare_op0) == REG
-      && ((TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code))
-         || (op0_mode == SImode && v8plus_regcmp_p (code))))
+      && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
     {
       operands[1] = gen_rtx_fmt_ee (code, op0_mode,
                             sparc_compare_op0, sparc_compare_op1);
                      (match_operand:QI 4 "arith11_operand" "0,rL")))]
   "TARGET_V9"
   "@
-   mov%C1 %x2,%3,%0
-   mov%c1 %x2,%4,%0"
-  [(set_attr "type" "cmove")])
+   mov%C1\\t%x2, %3, %0
+   mov%c1\\t%x2, %4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movhi_cc_sp64"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
                      (match_operand:HI 4 "arith11_operand" "0,rL")))]
   "TARGET_V9"
   "@
-   mov%C1 %x2,%3,%0
-   mov%c1 %x2,%4,%0"
-  [(set_attr "type" "cmove")])
+   mov%C1\\t%x2, %3, %0
+   mov%c1\\t%x2, %4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movsi_cc_sp64"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
                      (match_operand:SI 4 "arith11_operand" "0,rL")))]
   "TARGET_V9"
   "@
-   mov%C1 %x2,%3,%0
-   mov%c1 %x2,%4,%0"
-  [(set_attr "type" "cmove")])
+   mov%C1\\t%x2, %3, %0
+   mov%c1\\t%x2, %4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
 
 ;; ??? The constraints of operands 3,4 need work.
 (define_insn "*movdi_cc_sp64"
                      (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
   "TARGET_ARCH64"
   "@
-   mov%C1 %x2,%3,%0
-   mov%c1 %x2,%4,%0"
-  [(set_attr "type" "cmove")])
+   mov%C1\\t%x2, %3, %0
+   mov%c1\\t%x2, %4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
+
+(define_insn "*movdi_cc_sp64_trunc"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (if_then_else:DI (match_operator 1 "comparison_operator"
+                               [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+                                (const_int 0)])
+                     (match_operand:SI 3 "arith11_double_operand" "rLH,0")
+                     (match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
+  "TARGET_ARCH64"
+  "@
+   mov%C1\\t%x2, %3, %0
+   mov%c1\\t%x2, %4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movsf_cc_sp64"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
                      (match_operand:SF 4 "register_operand" "0,f")))]
   "TARGET_V9 && TARGET_FPU"
   "@
-   fmovs%C1 %x2,%3,%0
-   fmovs%c1 %x2,%4,%0"
-  [(set_attr "type" "fpcmove")])
+   fmovs%C1\\t%x2, %3, %0
+   fmovs%c1\\t%x2, %4, %0"
+  [(set_attr "type" "fpcmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movdf_cc_sp64"
   [(set (match_operand:DF 0 "register_operand" "=e,e")
                      (match_operand:DF 4 "register_operand" "0,e")))]
   "TARGET_V9 && TARGET_FPU"
   "@
-   fmovd%C1 %x2,%3,%0
-   fmovd%c1 %x2,%4,%0"
-  [(set_attr "type" "fpcmove")])
+   fmovd%C1\\t%x2, %3, %0
+   fmovd%c1\\t%x2, %4, %0"
+  [(set_attr "type" "fpcmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movtf_cc_sp64"
   [(set (match_operand:TF 0 "register_operand" "=e,e")
                      (match_operand:TF 4 "register_operand" "0,e")))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
   "@
-   fmovq%C1 %x2,%3,%0
-   fmovq%c1 %x2,%4,%0"
-  [(set_attr "type" "fpcmove")])
+   fmovq%C1\\t%x2, %3, %0
+   fmovq%c1\\t%x2, %4, %0"
+  [(set_attr "type" "fpcmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movqi_cc_reg_sp64"
   [(set (match_operand:QI 0 "register_operand" "=r,r")
                      (match_operand:QI 4 "arith10_operand" "0,rM")))]
   "TARGET_ARCH64"
   "@
-   movr%D1 %2,%r3,%0
-   movr%d1 %2,%r4,%0"
-  [(set_attr "type" "cmove")])
+   movr%D1\\t%2, %r3, %0
+   movr%d1\\t%2, %r4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movhi_cc_reg_sp64"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
                      (match_operand:HI 4 "arith10_operand" "0,rM")))]
   "TARGET_ARCH64"
   "@
-   movr%D1 %2,%r3,%0
-   movr%d1 %2,%r4,%0"
-  [(set_attr "type" "cmove")])
+   movr%D1\\t%2, %r3, %0
+   movr%d1\\t%2, %r4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movsi_cc_reg_sp64"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
                      (match_operand:SI 4 "arith10_operand" "0,rM")))]
   "TARGET_ARCH64"
   "@
-   movr%D1 %2,%r3,%0
-   movr%d1 %2,%r4,%0"
-  [(set_attr "type" "cmove")])
-
-;; On UltraSPARC this is slightly worse than cmp/mov %icc if the register
-;; needs to be zero extended but better on average.
-(define_insn "*movsi_cc_reg_v8plus"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (if_then_else:SI (match_operator 1 "v8plus_regcmp_op"
-                               [(match_operand:SI 2 "register_operand" "r,r")
-                                (const_int 0)])
-                     (match_operand:SI 3 "arith10_operand" "rM,0")
-                     (match_operand:SI 4 "arith10_operand" "0,rM")))]
-  "TARGET_V9"
-  "*
-{
-  if (! sparc_check_64 (operands[2], insn))
-    output_asm_insn (\"srl %2,0,%2\", operands);
-  if (which_alternative == 0)
-    return \"movr%D1 %2,%r3,%0\";
-  return \"movr%d1 %2,%r4,%0\";
-}"
+   movr%D1\\t%2, %r3, %0
+   movr%d1\\t%2, %r4, %0"
   [(set_attr "type" "cmove")
-   (set_attr "length" "2")])
-
-;; To work well this needs to know the current insn, but that is not an
-;; argument to gen_split_*.
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (if_then_else:SI (match_operator 1 "v8plus_regcmp_op"
-                               [(match_operand:SI 2 "register_operand" "r,r")
-                                (const_int 0)])
-                     (match_operand:SI 3 "arith10_operand" "rM,0")
-                     (match_operand:SI 4 "arith10_operand" "0,rM")))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 4)] 9))]
-  "if (! sparc_check_64 (operands[2], NULL_RTX))
-     emit_insn (gen_v8plus_clear_high (operands[2], operands[2]));")
-
-;; A conditional move with the condition argument known to be zero extended
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (unspec:SI [(match_operator 1 "v8plus_regcmp_op"
-                                   [(match_operand:SI 2 "register_operand" "r,r")
-                                    (const_int 0)])
-                   (match_operand:SI 3 "arith10_operand" "rM,0")
-                   (match_operand:SI 4 "arith10_operand" "0,rM")] 9))]
-  "TARGET_V9"
-  "@
-   movr%D1 %2,%r3,%0
-   movr%d1 %2,%r4,%0"
-  [(set_attr "type" "cmove")])
+   (set_attr "length" "1")])
 
 ;; ??? The constraints of operands 3,4 need work.
 (define_insn "*movdi_cc_reg_sp64"
                      (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
   "TARGET_ARCH64"
   "@
-   movr%D1 %2,%r3,%0
-   movr%d1 %2,%r4,%0"
-  [(set_attr "type" "cmove")])
+   movr%D1\\t%2, %r3, %0
+   movr%d1\\t%2, %r4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
+
+(define_insn "*movdi_cc_reg_sp64_trunc"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (if_then_else:DI (match_operator 1 "v9_regcmp_op"
+                               [(match_operand:DI 2 "register_operand" "r,r")
+                                (const_int 0)])
+                     (match_operand:SI 3 "arith10_double_operand" "rMH,0")
+                     (match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
+  "TARGET_ARCH64"
+  "@
+   movr%D1\\t%2, %r3, %0
+   movr%d1\\t%2, %r4, %0"
+  [(set_attr "type" "cmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movsf_cc_reg_sp64"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
                      (match_operand:SF 4 "register_operand" "0,f")))]
   "TARGET_ARCH64 && TARGET_FPU"
   "@
-   fmovrs%D1 %2,%3,%0
-   fmovrs%d1 %2,%4,%0"
-  [(set_attr "type" "fpcmove")])
+   fmovrs%D1\\t%2, %3, %0
+   fmovrs%d1\\t%2, %4, %0"
+  [(set_attr "type" "fpcmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movdf_cc_reg_sp64"
   [(set (match_operand:DF 0 "register_operand" "=e,e")
                      (match_operand:DF 4 "register_operand" "0,e")))]
   "TARGET_ARCH64 && TARGET_FPU"
   "@
-   fmovrd%D1 %2,%3,%0
-   fmovrd%d1 %2,%4,%0"
-  [(set_attr "type" "fpcmove")])
+   fmovrd%D1\\t%2, %3, %0
+   fmovrd%d1\\t%2, %4, %0"
+  [(set_attr "type" "fpcmove")
+   (set_attr "length" "1")])
 
 (define_insn "*movtf_cc_reg_sp64"
   [(set (match_operand:TF 0 "register_operand" "=e,e")
                      (match_operand:TF 4 "register_operand" "0,e")))]
   "TARGET_ARCH64 && TARGET_FPU"
   "@
-   fmovrq%D1 %2,%3,%0
-   fmovrq%d1 %2,%4,%0"
-  [(set_attr "type" "fpcmove")])
+   fmovrq%D1\\t%2, %3, %0
+   fmovrq%d1\\t%2, %4, %0"
+  [(set_attr "type" "fpcmove")
+   (set_attr "length" "1")])
 \f
 ;;- zero extension instructions
 
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
   ""
-  "lduh %1,%0"
-  [(set_attr "type" "load")])
+  "lduh\\t%1, %0"
+  [(set_attr "type" "load")
+   (set_attr "length" "1")])
 
 (define_expand "zero_extendqihi2"
   [(set (match_operand:HI 0 "register_operand" "")
 
 (define_insn "*zero_extendqihi2_insn"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
-       (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
+       (zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
   "GET_CODE (operands[1]) != CONST_INT"
   "@
-   and %1,0xff,%0
-   ldub %1,%0"
+   and\\t%1, 0xff, %0
+   ldub\\t%1, %0"
   [(set_attr "type" "unary,load")
    (set_attr "length" "1")])
 
 
 (define_insn "*zero_extendqisi2_insn"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
+       (zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
   "GET_CODE (operands[1]) != CONST_INT"
   "@
-   and %1,0xff,%0
-   ldub %1,%0"
+   and\\t%1, 0xff, %0
+   ldub\\t%1, %0"
   [(set_attr "type" "unary,load")
    (set_attr "length" "1")])
 
 
 (define_insn "*zero_extendqidi2_insn"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-       (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))]
+       (zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
   "@
-   and %1,0xff,%0
-   ldub %1,%0"
+   and\\t%1, 0xff, %0
+   ldub\\t%1, %0"
   [(set_attr "type" "unary,load")
    (set_attr "length" "1")])
 
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
   "TARGET_ARCH64"
-  "lduh %1,%0"
-  [(set_attr "type" "load")])
+  "lduh\\t%1, %0"
+  [(set_attr "type" "load")
+   (set_attr "length" "1")])
 
 
 ;; ??? Write truncdisi pattern using sra?
 
 (define_insn "*zero_extendsidi2_insn"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-       (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
+       (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
   "@
-   srl %1,0,%0
-   lduw %1,%0"
+   srl\\t%1, 0, %0
+   lduw\\t%1, %0"
   [(set_attr "type" "unary,load")
    (set_attr "length" "1")])
 
-;; Zero extend a 32 bit value in a 64 bit register.
-(define_insn "v8plus_clear_high"
-  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,Q")
-       (unspec:SI [(match_operand:SI 1 "register_operand" "r,r")] 10))]
-  "TARGET_V9"
-  "*
-if (which_alternative == 1)
-  return \"st %1,%0\";
-if (sparc_check_64 (operands[1], insn) > 0)
-  return final_sequence ? \"nop\" : \"\";
-return \"srl %1,0,%0\";
-"
-  [(set_attr "type" "shift,store")])
-
 ;; Simplify comparisons of extended values.
 
 (define_insn "*cmp_zero_extendqisi2"
   [(set (reg:CC 100)
        (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
                    (const_int 0)))]
-  ""
-  "andcc %0,0xff,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "andcc\\t%0, 0xff, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_zero_extendqisi2_set"
   [(set (reg:CC 100)
@@ -3270,18 +3830,40 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_dup 1)))]
   ""
-  "andcc %1,0xff,%0"
-  [(set_attr "type" "unary")])
+  "andcc\\t%1, 0xff, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
+
+(define_insn "*cmp_zero_extendqidi2"
+  [(set (reg:CCX 100)
+       (compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
+                    (const_int 0)))]
+  "TARGET_ARCH64"
+  "andcc\\t%0, 0xff, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
+
+(define_insn "*cmp_zero_extendqidi2_set"
+  [(set (reg:CCX 100)
+       (compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
+                    (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (match_dup 1)))]
+  "TARGET_ARCH64"
+  "andcc\\t%1, 0xff, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
-;; Similarly, handle SI->QI mode truncation followed by a compare.
+;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
 
 (define_insn "*cmp_siqi_trunc"
   [(set (reg:CC 100)
        (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
                    (const_int 0)))]
-  ""
-  "andcc %0,0xff,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "andcc\\t%0, 0xff, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_siqi_trunc_set"
   [(set (reg:CC 100)
@@ -3290,8 +3872,29 @@ return \"srl %1,0,%0\";
    (set (match_operand:QI 0 "register_operand" "=r")
        (match_dup 1))]
   ""
-  "andcc %1,0xff,%0"
-  [(set_attr "type" "unary")])
+  "andcc\\t%1, 0xff, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
+
+(define_insn "*cmp_diqi_trunc"
+  [(set (reg:CC 100)
+       (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 0)
+                   (const_int 0)))]
+  "TARGET_ARCH64"
+  "andcc\\t%0, 0xff, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
+
+(define_insn "*cmp_diqi_trunc_set"
+  [(set (reg:CC 100)
+       (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 0)
+                   (const_int 0)))
+   (set (match_operand:QI 0 "register_operand" "=r")
+       (match_dup 1))]
+  "TARGET_ARCH64"
+  "andcc\\t%1, 0xff, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 \f
 ;;- sign extension instructions
 
@@ -3326,8 +3929,9 @@ return \"srl %1,0,%0\";
   [(set (match_operand:SI 0 "register_operand" "=r")
        (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
   ""
-  "ldsh %1,%0"
-  [(set_attr "type" "sload")])
+  "ldsh\\t%1, %0"
+  [(set_attr "type" "sload")
+   (set_attr "length" "1")])
 
 (define_expand "extendqihi2"
   [(set (match_operand:HI 0 "register_operand" "")
@@ -3363,8 +3967,9 @@ return \"srl %1,0,%0\";
   [(set (match_operand:HI 0 "register_operand" "=r")
        (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
   ""
-  "ldsb %1,%0"
-  [(set_attr "type" "sload")])
+  "ldsb\\t%1, %0"
+  [(set_attr "type" "sload")
+   (set_attr "length" "1")])
 
 (define_expand "extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "")
@@ -3393,8 +3998,9 @@ return \"srl %1,0,%0\";
   [(set (match_operand:SI 0 "register_operand" "=r")
        (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
   ""
-  "ldsb %1,%0"
-  [(set_attr "type" "sload")])
+  "ldsb\\t%1, %0"
+  [(set_attr "type" "sload")
+   (set_attr "length" "1")])
 
 (define_expand "extendqidi2"
   [(set (match_operand:DI 0 "register_operand" "")
@@ -3423,8 +4029,9 @@ return \"srl %1,0,%0\";
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
   "TARGET_ARCH64"
-  "ldsb %1,%0"
-  [(set_attr "type" "sload")])
+  "ldsb\\t%1, %0"
+  [(set_attr "type" "sload")
+   (set_attr "length" "1")])
 
 (define_expand "extendhidi2"
   [(set (match_operand:DI 0 "register_operand" "")
@@ -3453,8 +4060,9 @@ return \"srl %1,0,%0\";
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
   "TARGET_ARCH64"
-  "ldsh %1,%0"
-  [(set_attr "type" "load")])
+  "ldsh\\t%1, %0"
+  [(set_attr "type" "load")
+   (set_attr "length" "1")])
 
 (define_expand "extendsidi2"
   [(set (match_operand:DI 0 "register_operand" "")
@@ -3464,11 +4072,11 @@ return \"srl %1,0,%0\";
 
 (define_insn "*sign_extendsidi2_insn"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-       (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
+       (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
   "TARGET_ARCH64"
   "@
-  sra %1,0,%0
-  ldsw %1,%0"
+  sra\\t%1, 0, %0
+  ldsw\\t%1, %0"
   [(set_attr "type" "unary,sload")
    (set_attr "length" "1")])
 \f
@@ -3479,37 +4087,59 @@ return \"srl %1,0,%0\";
   [(set (reg:CC 100)
        (compare:CC
         (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
-                         (match_operand:SI 1 "small_int" "n")
-                         (match_operand:SI 2 "small_int" "n"))
+                         (match_operand:SI 1 "small_int_or_double" "n")
+                         (match_operand:SI 2 "small_int_or_double" "n"))
         (const_int 0)))]
-  "INTVAL (operands[2]) > 19"
+  "! TARGET_LIVE_G0
+   && ((GET_CODE (operands[2]) == CONST_INT
+        && INTVAL (operands[2]) > 19)
+       || (GET_CODE (operands[2]) == CONST_DOUBLE
+           && CONST_DOUBLE_LOW (operands[2]) > 19))"
   "*
 {
-  int len = INTVAL (operands[1]);
-  int pos = 32 - INTVAL (operands[2]) - len;
+  int len = (GET_CODE (operands[1]) == CONST_INT
+             ? INTVAL (operands[1])
+             : CONST_DOUBLE_LOW (operands[1]));
+  int pos = 32 -
+            (GET_CODE (operands[2]) == CONST_INT
+             ? INTVAL (operands[2])
+             : CONST_DOUBLE_LOW (operands[2])) - len;
   unsigned mask = ((1 << len) - 1) << pos;
 
   operands[1] = GEN_INT (mask);
-  return \"andcc %0,%1,%%g0\";
-}")
+  return \"andcc\\t%0, %1, %%g0\";
+}"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_zero_extract_sp64"
   [(set (reg:CCX 100)
        (compare:CCX
         (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
-                         (match_operand:SI 1 "small_int" "n")
-                         (match_operand:SI 2 "small_int" "n"))
+                         (match_operand:SI 1 "small_int_or_double" "n")
+                         (match_operand:SI 2 "small_int_or_double" "n"))
         (const_int 0)))]
-  "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
+  "TARGET_ARCH64
+   && ((GET_CODE (operands[2]) == CONST_INT
+        && INTVAL (operands[2]) > 51)
+       || (GET_CODE (operands[2]) == CONST_DOUBLE
+           && CONST_DOUBLE_LOW (operands[2]) > 51))"
   "*
 {
-  int len = INTVAL (operands[1]);
-  int pos = 64 - INTVAL (operands[2]) - len;
+  int len = (GET_CODE (operands[1]) == CONST_INT
+             ? INTVAL (operands[1])
+             : CONST_DOUBLE_LOW (operands[1]));
+  int pos = 64 -
+            (GET_CODE (operands[2]) == CONST_INT
+             ? INTVAL (operands[2])
+             : CONST_DOUBLE_LOW (operands[2])) - len;
   unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
 
   operands[1] = GEN_INT (mask);
-  return \"andcc %0,%1,%%g0\";
-}")
+  return \"andcc\\t%0, %1, %%g0\";
+}"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 \f
 ;; Conversions between float, double and long double.
 
@@ -3518,48 +4148,54 @@ return \"srl %1,0,%0\";
        (float_extend:DF
         (match_operand:SF 1 "register_operand" "f")))]
   "TARGET_FPU"
-  "fstod %1,%0"
-  [(set_attr "type" "fp")])
+  "fstod\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "extendsftf2"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (float_extend:TF
         (match_operand:SF 1 "register_operand" "f")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fstoq %1,%0"
-  [(set_attr "type" "fp")])
+  "fstoq\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "extenddftf2"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (float_extend:TF
         (match_operand:DF 1 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fdtoq %1,%0"
-  [(set_attr "type" "fp")])
+  "fdtoq\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "truncdfsf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (float_truncate:SF
         (match_operand:DF 1 "register_operand" "e")))]
   "TARGET_FPU"
-  "fdtos %1,%0"
-  [(set_attr "type" "fp")])
+  "fdtos\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "trunctfsf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (float_truncate:SF
         (match_operand:TF 1 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fqtos %1,%0"
-  [(set_attr "type" "fp")])
+  "fqtos\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "trunctfdf2"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (float_truncate:DF
         (match_operand:TF 1 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fqtod %1,%0"
-  [(set_attr "type" "fp")])
+  "fqtod\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 \f
 ;; Conversion between fixed point and floating point.
 
@@ -3567,22 +4203,25 @@ return \"srl %1,0,%0\";
   [(set (match_operand:SF 0 "register_operand" "=f")
        (float:SF (match_operand:SI 1 "register_operand" "f")))]
   "TARGET_FPU"
-  "fitos %1,%0"
-  [(set_attr "type" "fp")])
+  "fitos\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "floatsidf2"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (float:DF (match_operand:SI 1 "register_operand" "f")))]
   "TARGET_FPU"
-  "fitod %1,%0"
-  [(set_attr "type" "fp")])
+  "fitod\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "floatsitf2"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (float:TF (match_operand:SI 1 "register_operand" "f")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fitoq %1,%0"
-  [(set_attr "type" "fp")])
+  "fitoq\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 ;; Now the same for 64 bit sources.
 
@@ -3590,22 +4229,25 @@ return \"srl %1,0,%0\";
   [(set (match_operand:SF 0 "register_operand" "=f")
        (float:SF (match_operand:DI 1 "register_operand" "e")))]
   "TARGET_V9 && TARGET_FPU"
-  "fxtos %1,%0"
-  [(set_attr "type" "fp")])
+  "fxtos\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "floatdidf2"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (float:DF (match_operand:DI 1 "register_operand" "e")))]
   "TARGET_V9 && TARGET_FPU"
-  "fxtod %1,%0"
-  [(set_attr "type" "fp")])
+  "fxtod\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "floatditf2"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (float:TF (match_operand:DI 1 "register_operand" "e")))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
-  "fxtoq %1,%0"
-  [(set_attr "type" "fp")])
+  "fxtoq\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 ;; Convert a float to an actual integer.
 ;; Truncation is performed as part of the conversion.
@@ -3614,22 +4256,25 @@ return \"srl %1,0,%0\";
   [(set (match_operand:SI 0 "register_operand" "=f")
        (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
   "TARGET_FPU"
-  "fstoi %1,%0"
-  [(set_attr "type" "fp")])
+  "fstoi\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "fix_truncdfsi2"
   [(set (match_operand:SI 0 "register_operand" "=f")
        (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
   "TARGET_FPU"
-  "fdtoi %1,%0"
-  [(set_attr "type" "fp")])
+  "fdtoi\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "fix_trunctfsi2"
   [(set (match_operand:SI 0 "register_operand" "=f")
        (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fqtoi %1,%0"
-  [(set_attr "type" "fp")])
+  "fqtoi\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 ;; Now the same, for V9 targets
 
@@ -3637,22 +4282,25 @@ return \"srl %1,0,%0\";
   [(set (match_operand:DI 0 "register_operand" "=e")
        (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
   "TARGET_V9 && TARGET_FPU"
-  "fstox %1,%0"
-  [(set_attr "type" "fp")])
+  "fstox\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "fix_truncdfdi2"
   [(set (match_operand:DI 0 "register_operand" "=e")
        (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
   "TARGET_V9 && TARGET_FPU"
-  "fdtox %1,%0"
-  [(set_attr "type" "fp")])
+  "fdtox\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "fix_trunctfdi2"
   [(set (match_operand:DI 0 "register_operand" "=e")
        (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
-  "fqtox %1,%0"
-  [(set_attr "type" "fp")])
+  "fqtox\\t%1, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 \f
 ;;- arithmetic instructions
 
@@ -3675,39 +4323,15 @@ return \"srl %1,0,%0\";
     }
 }")
 
-(define_insn "*adddi3_sp32"
+(define_insn "adddi3_insn_sp32"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
                 (match_operand:DI 2 "arith_double_operand" "rHI")))
    (clobber (reg:CC 100))]
   "! TARGET_ARCH64"
-  "*
-{
-  rtx op2 = operands[2];
-
-  if (GET_CODE (op2) == CONST_INT
-      || GET_CODE (op2) == CONST_DOUBLE)
-    {
-      rtx xoperands[4];
-      xoperands[0] = operands[0];
-      xoperands[1] = operands[1];
-      if (WORDS_BIG_ENDIAN)
-       split_double (op2, &xoperands[2], &xoperands[3]);
-      else
-       split_double (op2, &xoperands[3], &xoperands[2]);
-      if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
-       output_asm_insn (\"add %H1,%2,%H0\", xoperands);
-      else
-       output_asm_insn (\"addcc %L1,%3,%L0\;addx %H1,%2,%H0\", xoperands);
-      return \"\";
-    }
-  return \"addcc %L1,%L2,%L0\;addx %H1,%H2,%H0\";
-}"
+  "#"
   [(set_attr "length" "2")])
 
-
-;; Split DImode arithmetic
-
 (define_split
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
@@ -3777,23 +4401,56 @@ return \"srl %1,0,%0\";
 }")
 
 ;; LTU here means "carry set"
-(define_insn "*addx"
+(define_insn "addx"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (plus:SI (match_operand:SI 1 "arith_operand" "%r")
                          (match_operand:SI 2 "arith_operand" "rI"))
                 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
   ""
-  "addx %1,%2,%0"
-  [(set_attr "type" "unary")])
+  "addx\\t%1, %2, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
+
+(define_insn "*addx_extend"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+                         (match_operand:SI 2 "arith_operand" "rI"))
+                (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+  ""
+  "addx\\t%r1, %2, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
-(define_insn "*subx"
+(define_insn "subx"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
+       (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+                           (match_operand:SI 2 "arith_operand" "rI"))
+                 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+  ""
+  "subx\\t%r1, %2, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
+
+(define_insn "*subx_extend"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
                            (match_operand:SI 2 "arith_operand" "rI"))
                  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
   ""
-  "subx %1,%2,%0"
-  [(set_attr "type" "unary")])
+  "subx\\t%r1, %2, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
+
+;; This is only for splits at the moment.
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+                            (match_operand:SI 2 "arith_operand" "rI"))
+                  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+  "TARGET_ARCH64"
+  "subx\\t%r1, %2, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -3801,15 +4458,31 @@ return \"srl %1,0,%0\";
                (match_operand:DI 2 "register_operand" "r")))
    (clobber (reg:CC 100))]
   "! TARGET_ARCH64"
-  "addcc %L2,%1,%L0\;addx %H2,0,%H0"
-  [(set_attr "type" "multi")])
+  "#"
+  [(set_attr "type" "multi")
+   (set_attr "length" "2")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
+                 (match_operand:DI 2 "register_operand" "")))
+   (clobber (reg:CC 100))]
+  "! TARGET_ARCH64"
+  [(set (reg:CC_NOOV 100)
+        (compare:CC_NOOV (plus:SI (match_dup 3) (match_dup 1))
+                         (const_int 0)))
+   (set (match_dup 0)
+        (plus:SI (plus:SI (match_dup 4) (const_int 0))
+                 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+  "operands[3] = gen_lowpart (SImode, operands[2]);
+   operands[4] = gen_highpart (SImode, operands[2]);")
 
 (define_insn "*adddi3_sp64"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
   "TARGET_ARCH64"
-  "add %1,%2,%0")
+  "add\\t%1, %2, %0")
 
 (define_insn "addsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -3817,18 +4490,20 @@ return \"srl %1,0,%0\";
                 (match_operand:SI 2 "arith_operand" "rI,d")))]
   ""
   "@
-   add %1,%2,%0
-   fpadd32s %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   add\\t%1, %2, %0
+   fpadd32s\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_plus"
   [(set (reg:CC_NOOV 100)
        (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
                                  (match_operand:SI 1 "arith_operand" "rI"))
                         (const_int 0)))]
-  ""
-  "addcc %0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "addcc\\t%0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_plus"
   [(set (reg:CCX_NOOV 100)
@@ -3836,8 +4511,9 @@ return \"srl %1,0,%0\";
                                   (match_operand:DI 1 "arith_double_operand" "rHI"))
                          (const_int 0)))]
   "TARGET_ARCH64"
-  "addcc %0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "addcc\\t%0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_plus_set"
   [(set (reg:CC_NOOV 100)
@@ -3847,7 +4523,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "addcc %1,%2,%0")
+  "addcc\\t%1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_plus_set"
   [(set (reg:CCX_NOOV 100)
@@ -3857,7 +4535,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_dup 1) (match_dup 2)))]
   "TARGET_ARCH64"
-  "addcc %1,%2,%0")
+  "addcc\\t%1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_expand "subdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -3884,29 +4564,64 @@ return \"srl %1,0,%0\";
                  (match_operand:DI 2 "arith_double_operand" "rHI")))
    (clobber (reg:CC 100))]
   "! TARGET_ARCH64"
-  "*
+  "#"
+  [(set_attr "length" "2")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (minus:DI (match_operand:DI 1 "register_operand" "")
+                  (match_operand:DI 2 "arith_double_operand" "")))
+   (clobber (reg:CC 100))]
+  "! TARGET_ARCH64
+   && reload_completed
+   && (GET_CODE (operands[2]) == CONST_INT
+       || GET_CODE (operands[2]) == CONST_DOUBLE)"
+  [(clobber (const_int 0))]
+  "
 {
-  rtx op2 = operands[2];
+  rtx highp, lowp;
 
-  if (GET_CODE (op2) == CONST_INT
-      || GET_CODE (op2) == CONST_DOUBLE)
+  highp = gen_highpart (SImode, operands[2]);
+  lowp = gen_lowpart (SImode, operands[2]);
+  if ((lowp == const0_rtx)
+      && (operands[0] == operands[1]))
     {
-      rtx xoperands[4];
-      xoperands[0] = operands[0];
-      xoperands[1] = operands[1];
-      if (WORDS_BIG_ENDIAN)
-       split_double (op2, &xoperands[2], &xoperands[3]);
-      else
-       split_double (op2, &xoperands[3], &xoperands[2]);
-      if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
-       output_asm_insn (\"sub %H1,%2,%H0\", xoperands);
-      else
-       output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands);
-      return \"\";
+      emit_insn (gen_rtx_SET (SImode,
+                              gen_highpart (SImode, operands[0]),
+                              gen_rtx_MINUS (SImode,
+                                             gen_highpart (SImode, operands[1]),
+                                             highp)));
     }
-  return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\";
-}"
-  [(set_attr "length" "2")])
+  else
+    {
+      emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
+                                       gen_lowpart (SImode, operands[1]),
+                                       lowp));
+      emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
+                           gen_highpart (SImode, operands[1]),
+                           highp));
+    }
+  DONE;
+}")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (minus:DI (match_operand:DI 1 "register_operand" "")
+                  (match_operand:DI 2 "register_operand" "")))
+   (clobber (reg:CC 100))]
+  "! TARGET_ARCH64
+   && reload_completed"
+  [(clobber (const_int 0))]
+  "
+{
+  emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
+                                   gen_lowpart (SImode, operands[1]),
+                                   gen_lowpart (SImode, operands[2])));
+  emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
+                       gen_highpart (SImode, operands[1]),
+                       gen_highpart (SImode, operands[2])));
+  DONE;
+}")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -3914,15 +4629,33 @@ return \"srl %1,0,%0\";
                 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
    (clobber (reg:CC 100))]
   "! TARGET_ARCH64"
-  "subcc %L1,%2,%L0\;addx %H1,0,%H0"
-  [(set_attr "type" "multi")])
+  "#"
+  [(set_attr "type" "multi")
+   (set_attr "length" "2")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (minus:DI (match_operand:DI 1 "register_operand" "")
+                  (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))
+   (clobber (reg:CC 100))]
+  "! TARGET_ARCH64"
+  [(set (reg:CC_NOOV 100)
+        (compare:CC_NOOV (minus:SI (match_dup 3) (match_dup 2))
+                         (const_int 0)))
+   (set (match_dup 0)
+        (plus:SI (plus:SI (match_dup 4) (const_int 0))
+                 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+  "operands[3] = gen_lowpart (SImode, operands[1]);
+   operands[4] = gen_highpart (SImode, operands[1]);")
 
 (define_insn "*subdi3_sp64"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (minus:DI (match_operand:DI 1 "register_operand" "r")
                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
   "TARGET_ARCH64"
-  "sub %1,%2,%0")
+  "sub\\t%1, %2, %0"
+  [(set_attr "type" "binary")
+   (set_attr "length" "1")])
 
 (define_insn "subsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -3930,18 +4663,20 @@ return \"srl %1,0,%0\";
                  (match_operand:SI 2 "arith_operand" "rI,d")))]
   ""
   "@
-   sub %1,%2,%0
-   fpsub32s %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   sub\\t%1, %2, %0
+   fpsub32s\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_minus_cc"
   [(set (reg:CC_NOOV 100)
-       (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
+       (compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
                                   (match_operand:SI 1 "arith_operand" "rI"))
                         (const_int 0)))]
-  ""
-  "subcc %0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "subcc\\t%r0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_minus_ccx"
   [(set (reg:CCX_NOOV 100)
@@ -3949,18 +4684,21 @@ return \"srl %1,0,%0\";
                                    (match_operand:DI 1 "arith_double_operand" "rHI"))
                          (const_int 0)))]
   "TARGET_ARCH64"
-  "subcc %0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "subcc\\t%0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
-(define_insn "*cmp_minus_cc_set"
+(define_insn "cmp_minus_cc_set"
   [(set (reg:CC_NOOV 100)
-       (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
+       (compare:CC_NOOV (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
                                   (match_operand:SI 2 "arith_operand" "rI"))
                         (const_int 0)))
    (set (match_operand:SI 0 "register_operand" "=r")
        (minus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "subcc %1,%2,%0")
+  "subcc\\t%r1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_minus_ccx_set"
   [(set (reg:CCX_NOOV 100)
@@ -3970,7 +4708,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:DI 0 "register_operand" "=r")
        (minus:DI (match_dup 1) (match_dup 2)))]
   "TARGET_ARCH64"
-  "subcc %1,%2,%0")
+  "subcc\\t%1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 \f
 ;; Integer Multiply/Divide.
 
@@ -3983,8 +4723,9 @@ return \"srl %1,0,%0\";
        (mult:SI (match_operand:SI 1 "arith_operand" "%r")
                 (match_operand:SI 2 "arith_operand" "rI")))]
   "TARGET_HARD_MUL"
-  "smul %1,%2,%0"
-  [(set_attr "type" "imul")])
+  "smul\\t%1, %2, %0"
+  [(set_attr "type" "imul")
+   (set_attr "length" "1")])
 
 (define_expand "muldi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -4005,9 +4746,12 @@ return \"srl %1,0,%0\";
        (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
   "TARGET_ARCH64"
-  "mulx %1,%2,%0")
+  "mulx\\t%1, %2, %0"
+  [(set_attr "type" "imul")
+   (set_attr "length" "1")])
 
 ;; V8plus wide multiply.
+;; XXX
 (define_insn "muldi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=r,h")
        (mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
@@ -4018,15 +4762,15 @@ return \"srl %1,0,%0\";
   "*
 {
   if (sparc_check_64 (operands[1], insn) <= 0)
-    output_asm_insn (\"srl %L1,0,%L1\", operands);
+    output_asm_insn (\"srl\\t%L1, 0, %L1\", operands);
   if (which_alternative == 1)
-    output_asm_insn (\"sllx %H1,32,%H1\", operands);
+    output_asm_insn (\"sllx\\t%H1, 32, %H1\", operands);
   if (sparc_check_64 (operands[2], insn) <= 0)
-    output_asm_insn (\"srl %L2,0,%L2\", operands);
+    output_asm_insn (\"srl\\t%L2, 0, %L2\", operands);
   if (which_alternative == 1)
-    return \"or %L1,%H1,%H1\;sllx %H2,32,%L1\;or %L2,%L1,%L1\;mulx %H1,%L1,%L0\;srlx %L0,32,%H0\";
+    return \"or\\t%L1, %H1, %H1\\n\\tsllx\\t%H2, 32, %L1\\n\\tor\\t%L2, %L1, %L1\\n\\tmulx\\t%H1, %L1, %L0\;srlx\\t%L0, 32, %H0\";
   else
-    return \"sllx %H1,32,%3\;sllx %H2,32,%4\;or %L1,%3,%3\;or %L2,%4,%4\;mulx %3,%4,%3\;srlx %3,32,%H0\;mov %3,%L0\";
+    return \"sllx\\t%H1, 32, %3\\n\\tsllx\\t%H2, 32, %4\\n\\tor\\t%L1, %3, %3\\n\\tor\\t%L2, %4, %4\\n\\tmulx\\t%3, %4, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
 }"
   [(set_attr "length" "9,8")])
 
@@ -4040,8 +4784,9 @@ return \"srl %1,0,%0\";
        (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
                         (const_int 0)))]
   "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
-  "smulcc %1,%2,%0"
-  [(set_attr "type" "imul")])
+  "smulcc\\t%1, %2, %0"
+  [(set_attr "type" "imul")
+   (set_attr "length" "1")])
 
 (define_expand "mulsidi3"
   [(set (match_operand:DI 0 "register_operand" "")
@@ -4070,6 +4815,7 @@ return \"srl %1,0,%0\";
 
 ;; V9 puts the 64 bit product in a 64 bit register.  Only out or global
 ;; registers can hold 64 bit values in the V8plus environment.
+;; XXX
 (define_insn "mulsidi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=h,r")
        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4077,10 +4823,11 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 3 "=X,&h"))]
   "TARGET_V8PLUS"
   "@
-   smul %1,%2,%L0\;srlx %L0,32,%H0
-   smul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+   smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+   smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
   [(set_attr "length" "2,3")])
 
+;; XXX
 (define_insn "const_mulsidi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=h,r")
        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4088,10 +4835,11 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 3 "=X,&h"))]
   "TARGET_V8PLUS"
   "@
-   smul %1,%2,%L0\;srlx %L0,32,%H0
-   smul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+   smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+   smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
   [(set_attr "length" "2,3")])
 
+;; XXX
 (define_insn "*mulsidi3_sp32"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4099,7 +4847,7 @@ return \"srl %1,0,%0\";
   "TARGET_HARD_MUL32"
   "*
 {
-  return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
+  return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
 }"
   [(set (attr "length")
        (if_then_else (eq_attr "isa" "sparclet")
@@ -4107,6 +4855,7 @@ return \"srl %1,0,%0\";
 
 ;; Extra pattern, because sign_extend of a constant isn't valid.
 
+;; XXX
 (define_insn "const_mulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4114,7 +4863,7 @@ return \"srl %1,0,%0\";
   "TARGET_HARD_MUL"
   "*
 {
-  return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
+  return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
 }"
   [(set (attr "length")
        (if_then_else (eq_attr "isa" "sparclet")
@@ -4150,6 +4899,7 @@ return \"srl %1,0,%0\";
     }
 }")
 
+;; XXX
 (define_insn "smulsi3_highpart_v8plus"
   [(set (match_operand:SI 0 "register_operand" "=h,r")
        (truncate:SI
@@ -4164,6 +4914,7 @@ return \"srl %1,0,%0\";
   [(set_attr "length" "2")])
 
 ;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
+;; XXX
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=h,r")
        (subreg:SI
@@ -4175,10 +4926,11 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 4 "=X,&h"))]
   "TARGET_V8PLUS"
   "@
-   smul %1,%2,%0\;srlx %0,%3,%0
-   smul %1,%2,%4\;srlx %4,%3,%0"
+   smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+   smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
   [(set_attr "length" "2")])
 
+;; XXX
 (define_insn "const_smulsi3_highpart_v8plus"
   [(set (match_operand:SI 0 "register_operand" "=h,r")
        (truncate:SI
@@ -4188,28 +4940,32 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 4 "=X,&h"))]
   "TARGET_V8PLUS"
   "@
-   smul %1,%2,%0\;srlx %0,%3,%0
-   smul %1,%2,%4\;srlx %4,%3,%0"
+   smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+   smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
   [(set_attr "length" "2")])
 
+;; XXX
 (define_insn "*smulsi3_highpart_sp32"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (truncate:SI
         (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
                               (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
                      (const_int 32))))]
-  "TARGET_HARD_MUL32"
-  "smul %1,%2,%%g0\;rd %%y,%0"
+  "TARGET_HARD_MUL32
+   && ! TARGET_LIVE_G0"
+  "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
   [(set_attr "length" "2")])
 
+;; XXX
 (define_insn "const_smulsi3_highpart"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (truncate:SI
         (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
                               (match_operand:SI 2 "register_operand" "r"))
                      (const_int 32))))]
-  "TARGET_HARD_MUL32"
-  "smul %1,%2,%%g0\;rd %%y,%0"
+  "TARGET_HARD_MUL32
+   && ! TARGET_LIVE_G0"
+  "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
   [(set_attr "length" "2")])
 
 (define_expand "umulsidi3"
@@ -4237,6 +4993,7 @@ return \"srl %1,0,%0\";
     }
 }")
 
+;; XXX
 (define_insn "umulsidi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=h,r")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4244,10 +5001,11 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 3 "=X,&h"))]
   "TARGET_V8PLUS"
   "@
-   umul %1,%2,%L0\;srlx %L0,32,%H0
-   umul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+   umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+   umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
   [(set_attr "length" "2,3")])
 
+;; XXX
 (define_insn "*umulsidi3_sp32"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4255,7 +5013,7 @@ return \"srl %1,0,%0\";
   "TARGET_HARD_MUL32"
   "*
 {
-  return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
+  return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
 }"
   [(set (attr "length")
        (if_then_else (eq_attr "isa" "sparclet")
@@ -4263,6 +5021,7 @@ return \"srl %1,0,%0\";
 
 ;; Extra pattern, because sign_extend of a constant isn't valid.
 
+;; XXX
 (define_insn "const_umulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4270,12 +5029,13 @@ return \"srl %1,0,%0\";
   "TARGET_HARD_MUL32"
   "*
 {
-  return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
+  return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
 }"
   [(set (attr "length")
        (if_then_else (eq_attr "isa" "sparclet")
                      (const_int 1) (const_int 2)))])
 
+;; XXX
 (define_insn "const_umulsidi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=h,r")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4283,8 +5043,8 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 3 "=X,h"))]
   "TARGET_V8PLUS"
   "@
-   umul %1,%2,%L0\;srlx %L0,32,%H0
-   umul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+   umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+   umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
   [(set_attr "length" "2,3")])
 
 (define_expand "umulsi3_highpart"
@@ -4317,6 +5077,7 @@ return \"srl %1,0,%0\";
     }
 }")
 
+;; XXX
 (define_insn "umulsi3_highpart_v8plus"
   [(set (match_operand:SI 0 "register_operand" "=h,r")
        (truncate:SI
@@ -4326,10 +5087,11 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 4 "=X,h"))]
   "TARGET_V8PLUS"
   "@
-   umul %1,%2,%0\;srlx %0,%3,%0
-   umul %1,%2,%4\;srlx %4,%3,%0"
+   umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+   umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
   [(set_attr "length" "2")])
 
+;; XXX
 (define_insn "const_umulsi3_highpart_v8plus"
   [(set (match_operand:SI 0 "register_operand" "=h,r")
        (truncate:SI
@@ -4339,51 +5101,58 @@ return \"srl %1,0,%0\";
    (clobber (match_scratch:SI 4 "=X,h"))]
   "TARGET_V8PLUS"
   "@
-   umul %1,%2,%0\;srlx %0,%3,%0
-   umul %1,%2,%4\;srlx %4,%3,%0"
+   umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+   umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
   [(set_attr "length" "2")])
 
+;; XXX
 (define_insn "*umulsi3_highpart_sp32"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (truncate:SI
         (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
                               (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
                      (const_int 32))))]
-  "TARGET_HARD_MUL32"
-  "umul %1,%2,%%g0\;rd %%y,%0"
+  "TARGET_HARD_MUL32
+   && ! TARGET_LIVE_G0"
+  "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
   [(set_attr "length" "2")])
 
+;; XXX
 (define_insn "const_umulsi3_highpart"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (truncate:SI
         (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
                               (match_operand:SI 2 "uns_small_int" ""))
                      (const_int 32))))]
-  "TARGET_HARD_MUL32"
-  "umul %1,%2,%%g0\;rd %%y,%0"
+  "TARGET_HARD_MUL32
+   && ! TARGET_LIVE_G0"
+  "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
   [(set_attr "length" "2")])
 
 ;; The v8 architecture specifies that there must be 3 instructions between
 ;; a y register write and a use of it for correct results.
 
+;; XXX SHEESH
 (define_insn "divsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (div:SI (match_operand:SI 1 "register_operand" "r,r")
-               (match_operand:SI 2 "move_operand" "rI,m")))
+               (match_operand:SI 2 "input_operand" "rI,m")))
    (clobber (match_scratch:SI 3 "=&r,&r"))]
-  "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+  "(TARGET_V8
+    || TARGET_DEPRECATED_V8_INSNS)
+   && ! TARGET_LIVE_G0"
   "*
 {
   if (which_alternative == 0)
   if (TARGET_V9)
-    return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdiv %1,%2,%0\";
+    return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tsdiv\\t%1, %2, %0\";
   else
-    return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0\";
+    return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %2, %0\";
   else
     if (TARGET_V9)
-      return \"sra %1,31,%3\;wr %%g0,%3,%%y\;ld %2,%3\;sdiv %1,%3,%0\";
+      return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tld\\t%2, %3\\n\\tsdiv\\t%1, %3, %0\";
     else
-      return \"sra %1,31,%3\;wr %%g0,%3,%%y\;ld %2,%3\;nop\;nop\;sdiv %1,%3,%0\";
+      return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tld\\t%2, %3\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %3, %0\";
 }"
   [(set (attr "length")
        (if_then_else (eq_attr "isa" "v9")
@@ -4394,10 +5163,11 @@ return \"srl %1,0,%0\";
        (div:DI (match_operand:DI 1 "register_operand" "r")
                (match_operand:DI 2 "arith_double_operand" "rHI")))]
   "TARGET_ARCH64"
-  "sdivx %1,%2,%0")
+  "sdivx\\t%1, %2, %0")
 
 ;; It is not known whether this will match.
 
+;; XXX I hope it doesn't fucking match...
 (define_insn "*cmp_sdiv_cc_set"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (div:SI (match_operand:SI 1 "register_operand" "r")
@@ -4406,36 +5176,41 @@ return \"srl %1,0,%0\";
        (compare:CC (div:SI (match_dup 1) (match_dup 2))
                    (const_int 0)))
    (clobber (match_scratch:SI 3 "=&r"))]
-  "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+  "(TARGET_V8
+    || TARGET_DEPRECATED_V8_INSNS)
+   && ! TARGET_LIVE_G0"
   "*
 {
   if (TARGET_V9)
-    return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdivcc %1,%2,%0\";
+    return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tsdivcc\\t%1, %2, %0\";
   else
-    return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0\";
+    return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdivcc\\t%1, %2, %0\";
 }"
   [(set (attr "length")
        (if_then_else (eq_attr "isa" "v9")
                      (const_int 3) (const_int 6)))])
 
+;; XXX
 (define_insn "udivsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
        (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
-                (match_operand:SI 2 "move_operand" "rI,m,r")))]
-  "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+                (match_operand:SI 2 "input_operand" "rI,m,r")))]
+  "(TARGET_V8
+    || TARGET_DEPRECATED_V8_INSNS)
+   && ! TARGET_LIVE_G0"
   "*
 {
-  output_asm_insn (\"wr %%g0,%%g0,%%y\", operands);
+  output_asm_insn (\"wr\\t%%g0, %%g0, %%y\", operands);
   switch (which_alternative)
     {
     default:
   if (TARGET_V9)
-       return \"udiv %1,%2,%0\";
-      return \"nop\;nop\;nop\;udiv %1,%2,%0\";
+       return \"udiv\\t%1, %2, %0\";
+      return \"nop\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %2, %0\";
     case 1:
-      return \"ld %2,%0\;nop\;nop\;udiv %1,%0,%0\";
+      return \"ld\\t%2, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %0, %0\";
     case 2:
-      return \"ld %1,%0\;nop\;nop\;udiv %0,%2,%0\";
+      return \"ld\\t%1, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%0, %2, %0\";
     }
 }"
   [(set (attr "length")
@@ -4448,10 +5223,11 @@ return \"srl %1,0,%0\";
        (udiv:DI (match_operand:DI 1 "register_operand" "r")
                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
   "TARGET_ARCH64"
-  "udivx %1,%2,%0")
+  "udivx\\t%1, %2, %0")
 
 ;; It is not known whether this will match.
 
+;; XXX I hope it doesn't fucking match...
 (define_insn "*cmp_udiv_cc_set"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (udiv:SI (match_operand:SI 1 "register_operand" "r")
@@ -4459,13 +5235,15 @@ return \"srl %1,0,%0\";
    (set (reg:CC 100)
        (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
                    (const_int 0)))]
-  "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+  "(TARGET_V8
+    || TARGET_DEPRECATED_V8_INSNS)
+   && ! TARGET_LIVE_G0"
   "*
 {
   if (TARGET_V9)
-    return \"wr %%g0,%%g0,%%y\;udivcc %1,%2,%0\";
+    return \"wr\\t%%g0, %%g0, %%y\\n\\tudivcc\\t%1, %2, %0\";
   else
-    return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0\";
+    return \"wr\\t%%g0, %%g0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tudivcc\\t%1, %2, %0\";
 }"
   [(set (attr "length")
        (if_then_else (eq_attr "isa" "v9")
@@ -4479,8 +5257,9 @@ return \"srl %1,0,%0\";
                          (match_operand:SI 2 "arith_operand" "rI"))
                 (match_operand:SI 3 "register_operand" "0")))]
   "TARGET_SPARCLET"
-  "smac %1,%2,%0"
-  [(set_attr "type" "imul")])
+  "smac\\t%1, %2, %0"
+  [(set_attr "type" "imul")
+   (set_attr "length" "1")])
 
 (define_insn "*smacdi"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -4490,8 +5269,9 @@ return \"srl %1,0,%0\";
                           (match_operand:SI 2 "register_operand" "r")))
                 (match_operand:DI 3 "register_operand" "0")))]
   "TARGET_SPARCLET"
-  "smacd %1,%2,%L0"
-  [(set_attr "type" "imul")])
+  "smacd\\t%1, %2, %L0"
+  [(set_attr "type" "imul")
+   (set_attr "length" "1")])
 
 (define_insn "*umacdi"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -4501,8 +5281,9 @@ return \"srl %1,0,%0\";
                           (match_operand:SI 2 "register_operand" "r")))
                 (match_operand:DI 3 "register_operand" "0")))]
   "TARGET_SPARCLET"
-  "umacd %1,%2,%L0"
-  [(set_attr "type" "imul")])
+  "umacd\\t%1, %2, %L0"
+  [(set_attr "type" "imul")
+   (set_attr "length" "1")])
 \f
 ;;- Boolean instructions
 ;; We define DImode `and' so with DImode `not' we can get
@@ -4520,36 +5301,22 @@ return \"srl %1,0,%0\";
        (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
                (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
   "! TARGET_ARCH64"
-  "*
-{
-  rtx op2 = operands[2];
-
-  if (which_alternative == 1)
-    return \"fand %1,%2,%0\";
-
-  if (GET_CODE (op2) == CONST_INT
-      || GET_CODE (op2) == CONST_DOUBLE)
-    {
-      rtx xoperands[4];
-      xoperands[0] = operands[0];
-      xoperands[1] = operands[1];
-      if (WORDS_BIG_ENDIAN)
-       split_double (op2, &xoperands[2], &xoperands[3]);
-      else
-       split_double (op2, &xoperands[3], &xoperands[2]);
-      output_asm_insn (\"and %L1,%3,%L0\;and %H1,%2,%H0\", xoperands);
-      return \"\";
-    }
-  return \"and %1,%2,%0\;and %R1,%R2,%R0\";
-}"
-  [(set_attr "length" "2,1")])
+  "@
+  #
+  fand\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "2,1")])
 
 (define_insn "*anddi3_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
-               (match_operand:DI 2 "arith_double_operand" "rHI")))]
+  [(set (match_operand:DI 0 "register_operand" "=r,b")
+       (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
+               (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
   "TARGET_ARCH64"
-  "and %1,%2,%0")
+  "@
+   and\\t%1, %2, %0
+   fand\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_insn "andsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4557,9 +5324,10 @@ return \"srl %1,0,%0\";
                (match_operand:SI 2 "arith_operand" "rI,d")))]
   ""
   "@
-   and %1,%2,%0
-   fands %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   and\\t%1, %2, %0
+   fands\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
@@ -4582,8 +5350,10 @@ return \"srl %1,0,%0\";
        (match_operator:DI 1 "cc_arithop"       ; AND, IOR, XOR
                           [(match_operand:DI 2 "register_operand" "")
                            (match_operand:DI 3 "arith_double_operand" "")]))]
-  "! TARGET_ARCH64 && reload_completed
-   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < 32"
+  "! TARGET_ARCH64
+   && reload_completed
+   && GET_CODE (operands[0]) == REG
+   && REGNO (operands[0]) < 32"
   [(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
    (set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
   "
@@ -4610,16 +5380,38 @@ return \"srl %1,0,%0\";
                (match_operand:DI 2 "register_operand" "r,b")))]
   "! TARGET_ARCH64"
   "@
-   andn %2,%1,%0\;andn %R2,%R1,%R0
-   fandnot1 %1,%2,%0"
-  [(set_attr "length" "2,1")])
+   #
+   fandnot1\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "2,1")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (and:DI (not:DI (match_operand:DI 1 "register_operand" ""))
+                (match_operand:DI 2 "register_operand" "")))]
+  "! TARGET_ARCH64
+   && reload_completed
+   && GET_CODE (operands[0]) == REG
+   && REGNO (operands[0]) < 32"
+  [(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
+   (set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
+  "operands[3] = gen_highpart (SImode, operands[0]);
+   operands[4] = gen_highpart (SImode, operands[1]);
+   operands[5] = gen_highpart (SImode, operands[2]);
+   operands[6] = gen_lowpart (SImode, operands[0]);
+   operands[7] = gen_lowpart (SImode, operands[1]);
+   operands[8] = gen_lowpart (SImode, operands[2]);")
 
 (define_insn "*and_not_di_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
-               (match_operand:DI 2 "register_operand" "r")))]
+  [(set (match_operand:DI 0 "register_operand" "=r,b")
+       (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
+               (match_operand:DI 2 "register_operand" "r,b")))]
   "TARGET_ARCH64"
-  "andn %2,%1,%0")
+  "@
+   andn\\t%2, %1, %0
+   fandnot1\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_insn "*and_not_si"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4627,9 +5419,10 @@ return \"srl %1,0,%0\";
                (match_operand:SI 2 "register_operand" "r,d")))]
   ""
   "@
-   andn %2,%1,%0
-   fandnot1s %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   andn\\t%2, %1, %0
+   fandnot1s\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_expand "iordi3"
   [(set (match_operand:DI 0 "register_operand" "")
@@ -4643,36 +5436,22 @@ return \"srl %1,0,%0\";
        (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
                (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
   "! TARGET_ARCH64"
-  "*
-{
-  rtx op2 = operands[2];
-
-  if (which_alternative == 1)
-    return \"for %1,%2,%0\";
-
-  if (GET_CODE (op2) == CONST_INT
-      || GET_CODE (op2) == CONST_DOUBLE)
-    {
-      rtx xoperands[4];
-      xoperands[0] = operands[0];
-      xoperands[1] = operands[1];
-      if (WORDS_BIG_ENDIAN)
-       split_double (op2, &xoperands[2], &xoperands[3]);
-      else
-       split_double (op2, &xoperands[3], &xoperands[2]);
-      output_asm_insn (\"or %L1,%3,%L0\;or %H1,%2,%H0\", xoperands);
-      return \"\";
-    }
-  return \"or %1,%2,%0\;or %R1,%R2,%R0\";
-}"
-  [(set_attr "length" "2,1")])
+  "@
+  #
+  for\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "2,1")])
 
 (define_insn "*iordi3_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
-               (match_operand:DI 2 "arith_double_operand" "rHI")))]
+  [(set (match_operand:DI 0 "register_operand" "=r,b")
+       (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
+               (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
   "TARGET_ARCH64"
-  "or %1,%2,%0")
+  "@
+  or\\t%1, %2, %0
+  for\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_insn "iorsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4680,9 +5459,10 @@ return \"srl %1,0,%0\";
                (match_operand:SI 2 "arith_operand" "rI,d")))]
   ""
   "@
-   or %1,%2,%0
-   fors %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   or\\t%1, %2, %0
+   fors\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
@@ -4705,16 +5485,38 @@ return \"srl %1,0,%0\";
                (match_operand:DI 2 "register_operand" "r,b")))]
   "! TARGET_ARCH64"
   "@
-   orn %2,%1,%0\;orn %R2,%R1,%R0
-   fornot1 %1,%2,%0"
-  [(set_attr "length" "2,1")])
+   #
+   fornot1\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "2,1")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (ior:DI (not:DI (match_operand:DI 1 "register_operand" ""))
+                (match_operand:DI 2 "register_operand" "")))]
+  "! TARGET_ARCH64
+   && reload_completed
+   && GET_CODE (operands[0]) == REG
+   && REGNO (operands[0]) < 32"
+  [(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
+   (set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
+  "operands[3] = gen_highpart (SImode, operands[0]);
+   operands[4] = gen_highpart (SImode, operands[1]);
+   operands[5] = gen_highpart (SImode, operands[2]);
+   operands[6] = gen_lowpart (SImode, operands[0]);
+   operands[7] = gen_lowpart (SImode, operands[1]);
+   operands[8] = gen_lowpart (SImode, operands[2]);")
 
 (define_insn "*or_not_di_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
-               (match_operand:DI 2 "register_operand" "r")))]
+  [(set (match_operand:DI 0 "register_operand" "=r,b")
+       (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
+               (match_operand:DI 2 "register_operand" "r,b")))]
   "TARGET_ARCH64"
-  "orn %2,%1,%0")
+  "@
+  orn\\t%2, %1, %0
+  fornot1\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_insn "*or_not_si"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4722,9 +5524,10 @@ return \"srl %1,0,%0\";
                (match_operand:SI 2 "register_operand" "r,d")))]
   ""
   "@
-   orn %2,%1,%0
-   fornot1s %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   orn\\t%2, %1, %0
+   fornot1s\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_expand "xordi3"
   [(set (match_operand:DI 0 "register_operand" "")
@@ -4738,37 +5541,36 @@ return \"srl %1,0,%0\";
        (xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
                (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
   "! TARGET_ARCH64"
-  "*
-{
-  rtx op2 = operands[2];
-
-  if (which_alternative == 1)
-    return \"fxor %1,%2,%0\";
-
-  if (GET_CODE (op2) == CONST_INT
-      || GET_CODE (op2) == CONST_DOUBLE)
-    {
-      rtx xoperands[4];
-      xoperands[0] = operands[0];
-      xoperands[1] = operands[1];
-      if (WORDS_BIG_ENDIAN)
-       split_double (op2, &xoperands[2], &xoperands[3]);
-      else
-       split_double (op2, &xoperands[3], &xoperands[2]);
-      output_asm_insn (\"xor %L1,%3,%L0\;xor %H1,%2,%H0\", xoperands);
-      return \"\";
-    }
-  return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
-}"
+  "@
+  #
+  fxor\\t%1, %2, %0"
   [(set_attr "length" "2,1")
    (set_attr "type" "ialu,fp")])
 
 (define_insn "*xordi3_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ")
-               (match_operand:DI 2 "arith_double_operand" "rHI")))]
+  [(set (match_operand:DI 0 "register_operand" "=r,b")
+       (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ,b")
+               (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
   "TARGET_ARCH64"
-  "xor %r1,%2,%0")
+  "@
+  xor\\t%r1, %2, %0
+  fxor\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
+
+(define_insn "*xordi3_sp64_dbl"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (xor:DI (match_operand:DI 1 "register_operand" "%r")
+               (match_operand:DI 2 "const_double_operand" "")))]
+  "TARGET_ARCH64
+   && CONST_DOUBLE_HIGH (operands[2]) == 0"
+  "*
+{
+  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+  return \"xor\\t%1, %2, %0\";
+}"
+  [(set_attr "type" "ialu")
+   (set_attr "length" "1")])
 
 (define_insn "xorsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4776,9 +5578,10 @@ return \"srl %1,0,%0\";
                (match_operand:SI 2 "arith_operand" "rI,d")))]
   ""
   "@
-   xor %r1,%2,%0
-   fxors %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   xor\\t%r1, %2, %0
+   fxors\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
@@ -4818,18 +5621,38 @@ return \"srl %1,0,%0\";
                        (match_operand:DI 2 "register_operand" "r,b"))))]
   "! TARGET_ARCH64"
   "@
-   xnor %1,%2,%0\;xnor %R1,%R2,%R0
-   fxnor %1,%2,%0"
+   #
+   fxnor\\t%1, %2, %0"
   [(set_attr "length" "2,1")
    (set_attr "type" "ialu,fp")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (not:DI (xor:DI (match_operand:DI 1 "register_operand" "")
+                        (match_operand:DI 2 "register_operand" ""))))]
+  "! TARGET_ARCH64
+   && reload_completed
+   && GET_CODE (operands[0]) == REG
+   && REGNO (operands[0]) < 32"
+  [(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
+   (set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
+  "operands[3] = gen_highpart (SImode, operands[0]);
+   operands[4] = gen_highpart (SImode, operands[1]);
+   operands[5] = gen_highpart (SImode, operands[2]);
+   operands[6] = gen_lowpart (SImode, operands[0]);
+   operands[7] = gen_lowpart (SImode, operands[1]);
+   operands[8] = gen_lowpart (SImode, operands[2]);")
+
 (define_insn "*xor_not_di_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
-                       (match_operand:DI 2 "arith_double_operand" "rHI"))))]
+  [(set (match_operand:DI 0 "register_operand" "=r,b")
+       (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,b")
+                       (match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
   "TARGET_ARCH64"
-  "xnor %r1,%2,%0"
-  [(set_attr "type" "ialu")])
+  "@
+  xnor\\t%r1, %2, %0
+  fxnor\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 (define_insn "*xor_not_si"
   [(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4837,9 +5660,10 @@ return \"srl %1,0,%0\";
                        (match_operand:SI 2 "arith_operand" "rI,d"))))]
   ""
   "@
-   xnor %r1,%2,%0
-   fxnors %1,%2,%0"
-  [(set_attr "type" "ialu,fp")])
+   xnor\\t%r1, %2, %0
+   fxnors\\t%1, %2, %0"
+  [(set_attr "type" "ialu,fp")
+   (set_attr "length" "1,1")])
 
 ;; These correspond to the above in the case where we also (or only)
 ;; want to set the condition code.  
@@ -4851,9 +5675,10 @@ return \"srl %1,0,%0\";
                            [(match_operand:SI 0 "arith_operand" "%r")
                             (match_operand:SI 1 "arith_operand" "rI")])
         (const_int 0)))]
-  ""
-  "%A2cc %0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "%A2cc\\t%0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_arith_op"
   [(set (reg:CCX 100)
@@ -4863,8 +5688,9 @@ return \"srl %1,0,%0\";
                             (match_operand:DI 1 "arith_double_operand" "rHI")])
         (const_int 0)))]
   "TARGET_ARCH64"
-  "%A2cc %0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "%A2cc\\t%0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_arith_op_set"
   [(set (reg:CC 100)
@@ -4876,7 +5702,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (match_dup 3))]
   ""
-  "%A3cc %1,%2,%0")
+  "%A3cc\\t%1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_arith_op_set"
   [(set (reg:CCX 100)
@@ -4888,7 +5716,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:DI 0 "register_operand" "=r")
        (match_dup 3))]
   "TARGET_ARCH64"
-  "%A3cc %1,%2,%0")
+  "%A3cc\\t%1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_xor_not"
   [(set (reg:CC 100)
@@ -4896,9 +5726,10 @@ return \"srl %1,0,%0\";
         (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
                         (match_operand:SI 1 "arith_operand" "rI")))
         (const_int 0)))]
-  ""
-  "xnorcc %r0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "xnorcc\\t%r0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_xor_not"
   [(set (reg:CCX 100)
@@ -4907,8 +5738,9 @@ return \"srl %1,0,%0\";
                         (match_operand:DI 1 "arith_double_operand" "rHI")))
         (const_int 0)))]
   "TARGET_ARCH64"
-  "xnorcc %r0,%1,%%g0"
-  [(set_attr "type" "compare")])
+  "xnorcc\\t%r0, %1, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_xor_not_set"
   [(set (reg:CC 100)
@@ -4919,7 +5751,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
   ""
-  "xnorcc %r1,%2,%0")
+  "xnorcc\\t%r1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_xor_not_set"
   [(set (reg:CCX 100)
@@ -4930,7 +5764,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:DI 0 "register_operand" "=r")
        (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
   "TARGET_ARCH64"
-  "xnorcc %r1,%2,%0")
+  "xnorcc\\t%r1, %2, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_arith_op_not"
   [(set (reg:CC 100)
@@ -4939,9 +5775,10 @@ return \"srl %1,0,%0\";
                            [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
                             (match_operand:SI 1 "reg_or_0_operand" "rJ")])
         (const_int 0)))]
-  ""
-  "%B2cc %r1,%0,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "%B2cc\\t%r1, %0, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_arith_op_not"
   [(set (reg:CCX 100)
@@ -4951,8 +5788,9 @@ return \"srl %1,0,%0\";
                             (match_operand:DI 1 "reg_or_0_operand" "rJ")])
         (const_int 0)))]
   "TARGET_ARCH64"
-  "%B2cc %r1,%0,%%g0"
-  [(set_attr "type" "compare")])
+  "%B2cc\\t%r1, %0, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_arith_op_not_set"
   [(set (reg:CC 100)
@@ -4964,7 +5802,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (match_dup 3))]
   ""
-  "%B3cc %r2,%1,%0")
+  "%B3cc\\t%r2, %1, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_arith_op_not_set"
   [(set (reg:CCX 100)
@@ -4976,7 +5816,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:DI 0 "register_operand" "=r")
        (match_dup 3))]
   "TARGET_ARCH64"
-  "%B3cc %r2,%1,%0")
+  "%B3cc\\t%r2, %1, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 ;; We cannot use the "neg" pseudo insn because the Sun assembler
 ;; does not know how to make it work for constants.
@@ -5002,54 +5844,81 @@ return \"srl %1,0,%0\";
   [(set (match_operand:DI 0 "register_operand" "=r")
        (neg:DI (match_operand:DI 1 "register_operand" "r")))
    (clobber (reg:CC 100))]
-  "! TARGET_ARCH64"
-  "*
-{
-  if (TARGET_LIVE_G0)
-    output_asm_insn (\"and %%g0,0,%%g0\", operands);
-  return \"subcc %%g0,%L1,%L0\;subx %%g0,%H1,%H0\";
-}"
+  "! TARGET_ARCH64
+   && ! TARGET_LIVE_G0"
+  "#"
   [(set_attr "type" "unary")
-   ;; ??? This is wrong for TARGET_LIVE_G0 but it's not critical.
    (set_attr "length" "2")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (neg:DI (match_operand:DI 1 "register_operand" "")))
+   (clobber (reg:CC 100))]
+  "! TARGET_ARCH64
+   && ! TARGET_LIVE_G0
+   && reload_completed"
+  [(parallel [(set (reg:CC_NOOV 100)
+                   (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
+                                    (const_int 0)))
+              (set (match_dup 4) (minus:SI (const_int 0) (match_dup 5)))])
+   (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
+                                (ltu:SI (reg:CC 100) (const_int 0))))]
+  "operands[2] = gen_highpart (SImode, operands[0]);
+   operands[3] = gen_highpart (SImode, operands[1]);
+   operands[4] = gen_lowpart (SImode, operands[0]);
+   operands[5] = gen_lowpart (SImode, operands[1]);")
+
 (define_insn "*negdi2_sp64"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (neg:DI (match_operand:DI 1 "register_operand" "r")))]
   "TARGET_ARCH64"
-  "sub %%g0,%1,%0"
+  "sub\\t%%g0, %1, %0"
   [(set_attr "type" "unary")
    (set_attr "length" "1")])
 
-(define_insn "negsi2"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+(define_expand "negsi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (neg:SI (match_operand:SI 1 "arith_operand" "")))]
   ""
-  "*
+  "
 {
   if (TARGET_LIVE_G0)
-    return \"and %%g0,0,%%g0\;sub %%g0,%1,%0\";
-  return \"sub %%g0,%1,%0\";
-}"
+    {
+      rtx zero_reg = gen_reg_rtx (SImode);
+
+      emit_insn (gen_rtx_SET (SImode, zero_reg, const0_rtx));
+      emit_insn (gen_rtx_SET (SImode, operands[0],
+                                      gen_rtx_MINUS (SImode, zero_reg,
+                                                             operands[1])));
+      DONE;
+    }
+}")
+
+(define_insn "*negsi2_not_liveg0"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+  "! TARGET_LIVE_G0"
+  "sub\\t%%g0, %1, %0"
   [(set_attr "type" "unary")
-   (set (attr "length")
-       (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1)))])
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_neg"
   [(set (reg:CC_NOOV 100)
        (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
                         (const_int 0)))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%0,%%g0"
-  [(set_attr "type" "compare")])
+  "subcc\\t%%g0, %0, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_neg"
   [(set (reg:CCX_NOOV 100)
        (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
                          (const_int 0)))]
   "TARGET_ARCH64"
-  "subcc %%g0,%0,%%g0"
-  [(set_attr "type" "compare")])
+  "subcc\\t%%g0, %0, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_set_neg"
   [(set (reg:CC_NOOV 100)
@@ -5058,8 +5927,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (match_dup 1)))]
   "! TARGET_LIVE_G0"
-  "subcc %%g0,%1,%0"
-  [(set_attr "type" "unary")])
+  "subcc\\t%%g0, %1, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_set_neg"
   [(set (reg:CCX_NOOV 100)
@@ -5068,8 +5938,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:DI 0 "register_operand" "=r")
        (neg:DI (match_dup 1)))]
   "TARGET_ARCH64"
-  "subcc %%g0,%1,%0"
-  [(set_attr "type" "unary")])
+  "subcc\\t%%g0, %1, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 ;; We cannot use the "not" pseudo insn because the Sun assembler
 ;; does not know how to make it work for constants.
@@ -5084,53 +5955,93 @@ return \"srl %1,0,%0\";
        (not:DI (match_operand:DI 1 "register_operand" "r,b")))]
   "! TARGET_ARCH64"
   "@
-   xnor %1,0,%0\;xnor %R1,0,%R0
-   fnot1 %1,%0"
+   #
+   fnot1\\t%1, %0"
   [(set_attr "type" "unary,fp")
    (set_attr "length" "2,1")])
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (not:DI (match_operand:DI 1 "register_operand" "")))]
+  "! TARGET_ARCH64
+   && reload_completed
+   && GET_CODE (operands[0]) == REG
+   && REGNO (operands[0]) < 32"
+  [(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
+   (set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
+  "operands[2] = gen_highpart (SImode, operands[0]);
+   operands[3] = gen_highpart (SImode, operands[1]);
+   operands[4] = gen_lowpart (SImode, operands[0]);
+   operands[5] = gen_lowpart (SImode, operands[1]);")
+
 (define_insn "*one_cmpldi2_sp64"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
   "TARGET_ARCH64"
-  "xnor %1,0,%0"
-  [(set_attr "type" "unary")])
+  "xnor\\t%1, 0, %0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "1")])
 
-(define_insn "one_cmplsi2"
-  [(set (match_operand:SI 0 "register_operand" "=r,r,d")
-       (not:SI (match_operand:SI 1 "arith_operand" "r,I,d")))]
+(define_expand "one_cmplsi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (not:SI (match_operand:SI 1 "arith_operand" "")))]
   ""
-  "*
+  "
 {
-  if (which_alternative == 0)
-    return \"xnor %1,0,%0\";
-  if (which_alternative == 2)
-    return \"fnot1s %1,%0\";
-  if (TARGET_LIVE_G0)
-    output_asm_insn (\"and %%g0,0,%%g0\", operands);
-  return \"xnor %%g0,%1,%0\";
-}"
+  if (TARGET_LIVE_G0
+      && GET_CODE (operands[1]) == CONST_INT)
+    {
+      rtx zero_reg = gen_reg_rtx (SImode);
+
+      emit_insn (gen_rtx_SET (SImode, zero_reg, const0_rtx));
+      emit_insn (gen_rtx_SET (SImode,
+                              operands[0],
+                              gen_rtx_NOT (SImode,
+                                           gen_rtx_XOR (SImode,
+                                                        zero_reg,
+                                                        operands[1]))));
+      DONE;
+    }
+}")
+
+(define_insn "*one_cmplsi2_not_liveg0"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,d")
+       (not:SI (match_operand:SI 1 "arith_operand" "r,I,d")))]
+  "! TARGET_LIVE_G0"
+  "@
+  xnor\\t%1, 0, %0
+  xnor\\t%%g0, %1, %0
+  fnot1s\\t%1, %0"
   [(set_attr "type" "unary,unary,fp")
-   (set_attr_alternative "length"
-     [(const_int 1)
-      (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1))
-      (const_int 1)])])
+   (set_attr "length" "1,1,1")])
+
+(define_insn "*one_cmplsi2_liveg0"
+  [(set (match_operand:SI 0 "register_operand" "=r,d")
+       (not:SI (match_operand:SI 1 "arith_operand" "r,d")))]
+  "TARGET_LIVE_G0"
+  "@
+  xnor\\t%1, 0, %0
+  fnot1s\\t%1, %0"
+  [(set_attr "type" "unary,fp")
+   (set_attr "length" "1,1")])
 
 (define_insn "*cmp_cc_not"
   [(set (reg:CC 100)
        (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
                    (const_int 0)))]
   "! TARGET_LIVE_G0"
-  "xnorcc %%g0,%0,%%g0"
-  [(set_attr "type" "compare")])
+  "xnorcc\\t%%g0, %0, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_not"
   [(set (reg:CCX 100)
        (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
                     (const_int 0)))]
   "TARGET_ARCH64"
-  "xnorcc %%g0,%0,%%g0"
-  [(set_attr "type" "compare")])
+  "xnorcc\\t%%g0, %0, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_set_not"
   [(set (reg:CC 100)
@@ -5139,8 +6050,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (not:SI (match_dup 1)))]
   "! TARGET_LIVE_G0"
-  "xnorcc %%g0,%1,%0"
-  [(set_attr "type" "unary")])
+  "xnorcc\\t%%g0, %1, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_ccx_set_not"
   [(set (reg:CCX 100)
@@ -5149,8 +6061,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:DI 0 "register_operand" "=r")
        (not:DI (match_dup 1)))]
   "TARGET_ARCH64"
-  "xnorcc %%g0,%1,%0"
-  [(set_attr "type" "unary")])
+  "xnorcc\\t%%g0, %1, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 \f
 ;; Floating point arithmetic instructions.
 
@@ -5159,88 +6072,99 @@ return \"srl %1,0,%0\";
        (plus:TF (match_operand:TF 1 "register_operand" "e")
                 (match_operand:TF 2 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "faddq %1,%2,%0"
-  [(set_attr "type" "fp")])
+  "faddq\\t%1, %2, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "adddf3"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (plus:DF (match_operand:DF 1 "register_operand" "e")
                 (match_operand:DF 2 "register_operand" "e")))]
   "TARGET_FPU"
-  "faddd %1,%2,%0"
-  [(set_attr "type" "fp")])
+  "faddd\\t%1, %2, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "addsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (plus:SF (match_operand:SF 1 "register_operand" "f")
                 (match_operand:SF 2 "register_operand" "f")))]
   "TARGET_FPU"
-  "fadds %1,%2,%0"
-  [(set_attr "type" "fp")])
+  "fadds\\t%1, %2, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "subtf3"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (minus:TF (match_operand:TF 1 "register_operand" "e")
                  (match_operand:TF 2 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fsubq %1,%2,%0"
-  [(set_attr "type" "fp")])
+  "fsubq\\t%1, %2, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "subdf3"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (minus:DF (match_operand:DF 1 "register_operand" "e")
                  (match_operand:DF 2 "register_operand" "e")))]
   "TARGET_FPU"
-  "fsubd %1,%2,%0"
-  [(set_attr "type" "fp")])
+  "fsubd\\t%1, %2, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "subsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (minus:SF (match_operand:SF 1 "register_operand" "f")
                  (match_operand:SF 2 "register_operand" "f")))]
   "TARGET_FPU"
-  "fsubs %1,%2,%0"
-  [(set_attr "type" "fp")])
+  "fsubs\\t%1, %2, %0"
+  [(set_attr "type" "fp")
+   (set_attr "length" "1")])
 
 (define_insn "multf3"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (mult:TF (match_operand:TF 1 "register_operand" "e")
                 (match_operand:TF 2 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fmulq %1,%2,%0"
-  [(set_attr "type" "fpmul")])
+  "fmulq\\t%1, %2, %0"
+  [(set_attr "type" "fpmul")
+   (set_attr "length" "1")])
 
 (define_insn "muldf3"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (mult:DF (match_operand:DF 1 "register_operand" "e")
                 (match_operand:DF 2 "register_operand" "e")))]
   "TARGET_FPU"
-  "fmuld %1,%2,%0"
-  [(set_attr "type" "fpmul")])
+  "fmuld\\t%1, %2, %0"
+  [(set_attr "type" "fpmul")
+   (set_attr "length" "1")])
 
 (define_insn "mulsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (mult:SF (match_operand:SF 1 "register_operand" "f")
                 (match_operand:SF 2 "register_operand" "f")))]
   "TARGET_FPU"
-  "fmuls %1,%2,%0"
-  [(set_attr "type" "fpmul")])
+  "fmuls\\t%1, %2, %0"
+  [(set_attr "type" "fpmul")
+   (set_attr "length" "1")])
 
 (define_insn "*muldf3_extend"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
                 (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
   "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
-  "fsmuld %1,%2,%0"
-  [(set_attr "type" "fpmul")])
+  "fsmuld\\t%1, %2, %0"
+  [(set_attr "type" "fpmul")
+   (set_attr "length" "1")])
 
 (define_insn "*multf3_extend"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
                 (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
   "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
-  "fdmulq %1,%2,%0"
-  [(set_attr "type" "fpmul")])
+  "fdmulq\\t%1, %2, %0"
+  [(set_attr "type" "fpmul")
+   (set_attr "length" "1")])
 
 ;; don't have timing for quad-prec. divide.
 (define_insn "divtf3"
@@ -5248,25 +6172,29 @@ return \"srl %1,0,%0\";
        (div:TF (match_operand:TF 1 "register_operand" "e")
                (match_operand:TF 2 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fdivq %1,%2,%0"
-  [(set_attr "type" "fpdivd")])
+  "fdivq\\t%1, %2, %0"
+  [(set_attr "type" "fpdivd")
+   (set_attr "length" "1")])
 
 (define_insn "divdf3"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (div:DF (match_operand:DF 1 "register_operand" "e")
                (match_operand:DF 2 "register_operand" "e")))]
   "TARGET_FPU"
-  "fdivd %1,%2,%0"
-  [(set_attr "type" "fpdivd")])
+  "fdivd\\t%1, %2, %0"
+  [(set_attr "type" "fpdivd")
+   (set_attr "length" "1")])
 
 (define_insn "divsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (div:SF (match_operand:SF 1 "register_operand" "f")
                (match_operand:SF 2 "register_operand" "f")))]
   "TARGET_FPU"
-  "fdivs %1,%2,%0"
-  [(set_attr "type" "fpdivs")])
+  "fdivs\\t%1, %2, %0"
+  [(set_attr "type" "fpdivs")
+   (set_attr "length" "1")])
 
+;; XXX
 (define_insn "negtf2"
   [(set (match_operand:TF 0 "register_operand" "=e,e")
        (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
@@ -5286,6 +6214,7 @@ return \"srl %1,0,%0\";
      [(const_int 1)
       (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
 
+;; XXX
 (define_insn "negdf2"
   [(set (match_operand:DF 0 "register_operand" "=e,e")
        (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
@@ -5308,9 +6237,11 @@ return \"srl %1,0,%0\";
   [(set (match_operand:SF 0 "register_operand" "=f")
        (neg:SF (match_operand:SF 1 "register_operand" "f")))]
   "TARGET_FPU"
-  "fnegs %1,%0"
-  [(set_attr "type" "fpmove")])
+  "fnegs\\t%1, %0"
+  [(set_attr "type" "fpmove")
+   (set_attr "length" "1")])
 
+;; XXX
 (define_insn "abstf2"
   [(set (match_operand:TF 0 "register_operand" "=e,e")
        (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
@@ -5330,6 +6261,7 @@ return \"srl %1,0,%0\";
      [(const_int 1)
       (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
 
+;; XXX
 (define_insn "absdf2"
   [(set (match_operand:DF 0 "register_operand" "=e,e")
        (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
@@ -5352,29 +6284,33 @@ return \"srl %1,0,%0\";
   [(set (match_operand:SF 0 "register_operand" "=f")
        (abs:SF (match_operand:SF 1 "register_operand" "f")))]
   "TARGET_FPU"
-  "fabss %1,%0"
-  [(set_attr "type" "fpmove")])
+  "fabss\\t%1, %0"
+  [(set_attr "type" "fpmove")
+   (set_attr "length" "1")])
 
 (define_insn "sqrttf2"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
-  "fsqrtq %1,%0"
-  [(set_attr "type" "fpsqrt")])
+  "fsqrtq\\t%1, %0"
+  [(set_attr "type" "fpsqrt")
+   (set_attr "length" "1")])
 
 (define_insn "sqrtdf2"
   [(set (match_operand:DF 0 "register_operand" "=e")
        (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
   "TARGET_FPU"
-  "fsqrtd %1,%0"
-  [(set_attr "type" "fpsqrt")])
+  "fsqrtd\\t%1, %0"
+  [(set_attr "type" "fpsqrt")
+   (set_attr "length" "1")])
 
 (define_insn "sqrtsf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
   "TARGET_FPU"
-  "fsqrts %1,%0"
-  [(set_attr "type" "fpsqrt")])
+  "fsqrts\\t%1, %0"
+  [(set_attr "type" "fpsqrt")
+   (set_attr "length" "1")])
 \f
 ;;- arithmetic shift instructions
 
@@ -5389,9 +6325,10 @@ return \"srl %1,0,%0\";
       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
 
-  return \"sll %1,%2,%0\";
+  return \"sll\\t%1, %2, %0\";
 }"
-  [(set_attr "type" "shift")])
+  [(set_attr "type" "shift")
+   (set_attr "length" "1")])
 
 (define_expand "ashldi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -5420,9 +6357,12 @@ return \"srl %1,0,%0\";
       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
 
-  return \"sllx %1,%2,%0\";
-}")
+  return \"sllx\\t%1, %2, %0\";
+}"
+  [(set_attr "type" "shift")
+   (set_attr "length" "1")])
 
+;; XXX UGH!
 (define_insn "ashldi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
        (ashift:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
@@ -5433,6 +6373,7 @@ return \"srl %1,0,%0\";
   [(set_attr "length" "5,5,6")])
 
 ;; Optimize (1LL<<x)-1
+;; XXX
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=h")
        (plus:DI (ashift:DI (const_int 1)
@@ -5452,9 +6393,10 @@ return \"srl %1,0,%0\";
        (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
                                    (const_int 1))
                         (const_int 0)))]
-  ""
-  "addcc %0,%0,%%g0"
-  [(set_attr "type" "compare")])
+  "! TARGET_LIVE_G0"
+  "addcc\\t%0, %0, %%g0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "*cmp_cc_set_ashift_1"
   [(set (reg:CC_NOOV 100)
@@ -5464,7 +6406,9 @@ return \"srl %1,0,%0\";
    (set (match_operand:SI 0 "register_operand" "=r")
        (ashift:SI (match_dup 1) (const_int 1)))]
   ""
-  "addcc %1,%1,%0")
+  "addcc\\t%1, %1, %0"
+  [(set_attr "type" "compare")
+   (set_attr "length" "1")])
 
 (define_insn "ashrsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
@@ -5477,9 +6421,10 @@ return \"srl %1,0,%0\";
       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
 
-  return \"sra %1,%2,%0\";
+  return \"sra\\t%1, %2, %0\";
 }"
-  [(set_attr "type" "shift")])
+  [(set_attr "type" "shift")
+   (set_attr "length" "1")])
 
 (define_expand "ashrdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -5487,13 +6432,15 @@ return \"srl %1,0,%0\";
                     (match_operand:SI 2 "arith_operand" "rI")))]
   "TARGET_ARCH64 || TARGET_V8PLUS"
   "
-if (! TARGET_ARCH64)
-  {
-    if (GET_CODE (operands[2]) == CONST_INT)
-      FAIL;    /* prefer generic code in this case */
-    emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
-    DONE;
-  }")
+{
+  if (! TARGET_ARCH64)
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+        FAIL;  /* prefer generic code in this case */
+      emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+}")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -5506,9 +6453,12 @@ if (! TARGET_ARCH64)
       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
 
-  return \"srax %1,%2,%0\";
-}")
+  return \"srax\\t%1, %2, %0\";
+}"
+  [(set_attr "type" "shift")
+   (set_attr "length" "1")])
 
+;; XXX
 (define_insn "ashrdi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
        (ashiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
@@ -5529,9 +6479,10 @@ if (! TARGET_ARCH64)
       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
 
-  return \"srl %1,%2,%0\";
+  return \"srl\\t%1, %2, %0\";
 }"
-  [(set_attr "type" "shift")])
+  [(set_attr "type" "shift")
+   (set_attr "length" "1")])
 
 (define_expand "lshrdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -5539,13 +6490,15 @@ if (! TARGET_ARCH64)
                     (match_operand:SI 2 "arith_operand" "rI")))]
   "TARGET_ARCH64 || TARGET_V8PLUS"
   "
-if (! TARGET_ARCH64)
-  {
-    if (GET_CODE (operands[2]) == CONST_INT)
-      FAIL;
-    emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
-    DONE;
-  }")
+{
+  if (! TARGET_ARCH64)
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+        FAIL;
+      emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+}")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -5558,9 +6511,12 @@ if (! TARGET_ARCH64)
       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
 
-  return \"srlx %1,%2,%0\";
-}")
+  return \"srlx\\t%1, %2, %0\";
+}"
+  [(set_attr "type" "shift")
+   (set_attr "length" "1")])
 
+;; XXX
 (define_insn "lshrdi3_v8plus"
   [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
        (lshiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
@@ -5589,9 +6545,9 @@ if (! TARGET_ARCH64)
   if (flag_delayed_branch
       && (insn_addresses[INSN_UID (operands[0])]
          == insn_addresses[INSN_UID (insn)]))
-    return \"b %l0%#\";
+    return TARGET_V9 ? \"b,pt\\t%%xcc, %l0%#\" : \"b\\t%l0%#\";
   else
-    return \"b%* %l0%(\";
+    return TARGET_V9 ? \"b,pt%*\\t%%xcc, %l0%(\" : \"b%*\\t%l0%(\";
 }"
   [(set_attr "type" "uncond_branch")])
 
@@ -5604,46 +6560,30 @@ if (! TARGET_ARCH64)
   if (GET_MODE (operands[0]) != Pmode)
     abort ();
 
-  /* We need to use the PC value in %o7 that was set up when the address
-     of the label was loaded into a register, so we need different RTL.  */
+  /* In pic mode, our address differences are against the base of the
+     table.  Add that base value back in; CSE ought to be able to combine
+     the two address loads.  */
   if (flag_pic)
     {
-      if (!TARGET_PTR64)
-       emit_jump_insn (gen_pic_tablejump_32 (operands[0], operands[1]));
-      else
-       emit_jump_insn (gen_pic_tablejump_64 (operands[0], operands[1]));
-      DONE;
+      rtx tmp;
+      tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
+      tmp = gen_rtx_PLUS (Pmode, operands[0], tmp);
+      operands[0] = memory_address (Pmode, tmp);
     }
 }")
 
-(define_insn "pic_tablejump_32"
-  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
-   (use (label_ref (match_operand 1 "" "")))
-   (use (reg:SI 15))]
-  "! TARGET_PTR64"
-  "jmp %%o7+%0%#"
-  [(set_attr "type" "uncond_branch")])
-
-(define_insn "pic_tablejump_64"
-  [(set (pc) (match_operand:DI 0 "register_operand" "r"))
-   (use (label_ref (match_operand 1 "" "")))
-   (use (reg:DI 15))]
-  "TARGET_PTR64"
-  "jmp %%o7+%0%#"
-  [(set_attr "type" "uncond_branch")])
-
 (define_insn "*tablejump_sp32"
   [(set (pc) (match_operand:SI 0 "address_operand" "p"))
    (use (label_ref (match_operand 1 "" "")))]
   "! TARGET_PTR64"
-  "jmp %a0%#"
+  "jmp\\t%a0%#"
   [(set_attr "type" "uncond_branch")])
 
 (define_insn "*tablejump_sp64"
   [(set (pc) (match_operand:DI 0 "address_operand" "p"))
    (use (label_ref (match_operand 1 "" "")))]
   "TARGET_PTR64"
-  "jmp %a0%#"
+  "jmp\\t%a0%#"
   [(set_attr "type" "uncond_branch")])
 
 ;; This pattern recognizes the "instruction" that appears in 
@@ -5652,7 +6592,7 @@ if (! TARGET_ARCH64)
 ;(define_insn "*unimp_insn"
 ;  [(match_operand:SI 0 "immediate_operand" "")]
 ;  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
-;  "unimp %0"
+;  "unimp\\t%0"
 ;  [(set_attr "type" "marker")])
 
 ;;- jump to subroutine
@@ -5751,7 +6691,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
   "! TARGET_PTR64"
-  "call %a0,%1%#"
+  "call\\t%a0, %1%#"
   [(set_attr "type" "call")])
 
 (define_insn "*call_symbolic_sp32"
@@ -5760,7 +6700,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
   "! TARGET_PTR64"
-  "call %a0,%1%#"
+  "call\\t%a0, %1%#"
   [(set_attr "type" "call")])
 
 (define_insn "*call_address_sp64"
@@ -5769,7 +6709,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:DI 15))]
   ;;- Do not use operand 1 for most machines.
   "TARGET_PTR64"
-  "call %a0,%1%#"
+  "call\\t%a0, %1%#"
   [(set_attr "type" "call")])
 
 (define_insn "*call_symbolic_sp64"
@@ -5778,7 +6718,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:DI 15))]
   ;;- Do not use operand 1 for most machines.
   "TARGET_PTR64"
-  "call %a0,%1%#"
+  "call\\t%a0, %1%#"
   [(set_attr "type" "call")])
 
 ;; This is a call that wants a structure value.
@@ -5790,7 +6730,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
-  "call %a0,%1\;nop\;unimp %2"
+  "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
   [(set_attr "type" "call_no_delay_slot")])
 
 ;; This is a call that wants a structure value.
@@ -5802,7 +6742,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
-  "call %a0,%1\;nop\;unimp %2"
+  "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
   [(set_attr "type" "call_no_delay_slot")])
 
 ;; This is a call that may want a structure value.  This is used for
@@ -5814,7 +6754,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
-  "call %a0,%1\;nop\;nop"
+  "call\\t%a0, %1\\n\\tnop\\n\\tnop"
   [(set_attr "type" "call_no_delay_slot")])
 
 ;; This is a call that wants a structure value.
@@ -5825,7 +6765,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
-  "call %a0,%1\;nop\;nop"
+  "call\\t%a0, %1\\n\\tnop\\n\\tnop"
   [(set_attr "type" "call_no_delay_slot")])
 
 (define_expand "call_value"
@@ -5873,7 +6813,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 2 for most machines.
   "! TARGET_PTR64"
-  "call %a1,%2%#"
+  "call\\t%a1, %2%#"
   [(set_attr "type" "call")])
 
 (define_insn "*call_value_symbolic_sp32"
@@ -5883,7 +6823,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:SI 15))]
   ;;- Do not use operand 2 for most machines.
   "! TARGET_PTR64"
-  "call %a1,%2%#"
+  "call\\t%a1, %2%#"
   [(set_attr "type" "call")])
 
 (define_insn "*call_value_address_sp64"
@@ -5893,7 +6833,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:DI 15))]
   ;;- Do not use operand 2 for most machines.
   "TARGET_PTR64"
-  "call %a1,%2%#"
+  "call\\t%a1, %2%#"
   [(set_attr "type" "call")])
 
 (define_insn "*call_value_symbolic_sp64"
@@ -5903,7 +6843,7 @@ if (! TARGET_ARCH64)
    (clobber (reg:DI 15))]
   ;;- Do not use operand 2 for most machines.
   "TARGET_PTR64"
-  "call %a1,%2%#"
+  "call\\t%a1, %2%#"
   [(set_attr "type" "call")])
 
 (define_expand "untyped_call"
@@ -6008,7 +6948,7 @@ if (! TARGET_ARCH64)
    (parallel [(return)
              (use (reg:SI 31))])]
   "sparc_return_peephole_ok (operands[0], operands[1])"
-  "return %%i7+8\;mov %Y1,%Y0")
+  "return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0")
 
 (define_insn "nop"
   [(const_int 0)]
@@ -6023,13 +6963,13 @@ if (! TARGET_ARCH64)
 (define_insn "*branch_sp32"
   [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
   "! TARGET_PTR64"
- "jmp %a0%#"
+ "jmp\\t%a0%#"
  [(set_attr "type" "uncond_branch")])
  
 (define_insn "*branch_sp64"
   [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
   "TARGET_PTR64"
-  "jmp %a0%#"
+  "jmp\\t%a0%#"
   [(set_attr "type" "uncond_branch")])
 
 ;; ??? Doesn't work with -mflat.
@@ -6092,13 +7032,13 @@ if (! TARGET_ARCH64)
 (define_insn "flush_register_windows"
   [(unspec_volatile [(const_int 0)] 1)]
   ""
-  "* return TARGET_V9 ? \"flushw\" : \"ta 3\";"
+  "* return TARGET_V9 ? \"flushw\" : \"ta\\t3\";"
   [(set_attr "type" "misc")])
 
 (define_insn "goto_handler_and_restore"
   [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r")] 2)]
   ""
-  "jmp %0+0\;restore"
+  "jmp\\t%0+0\\n\\trestore"
   [(set_attr "type" "misc")
    (set_attr "length" "2")])
 
@@ -6108,8 +7048,8 @@ if (! TARGET_ARCH64)
                     (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
   "TARGET_V9 && ! TARGET_ARCH64"
   "@
-   return %0+0\;mov %2,%Y1
-   sethi %%hi(%2),%1\;return %0+0\;or %Y1,%%lo(%2),%Y1"
+   return\\t%0+0\\n\\tmov\\t%2, %Y1
+   sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
   [(set_attr "type" "misc")
    (set_attr "length" "2,3")])
 
@@ -6119,8 +7059,8 @@ if (! TARGET_ARCH64)
                     (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
   "TARGET_V9 && TARGET_ARCH64"
   "@
-   return %0+0\;mov %2,%Y1
-   sethi %%hi(%2),%1\;return %0+0\;or %Y1,%%lo(%2),%Y1"
+   return\\t%0+0\\n\\tmov\\t%2, %Y1
+   sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
   [(set_attr "type" "misc")
    (set_attr "length" "2,3")])
 
@@ -6156,9 +7096,9 @@ if (! TARGET_ARCH64)
 ;; Special pattern for the FLUSH instruction.
 
 (define_insn "flush"
-  [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 3)]
+  [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 4)]
   ""
-  "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";"
+  "* return TARGET_V9 ? \"flush\\t%f0\" : \"iflush\\t%f0\";"
   [(set_attr "type" "misc")])
 \f
 ;; find first set.
@@ -6168,6 +7108,7 @@ if (! TARGET_ARCH64)
 ;; zero also differ.  It takes at least 7 instructions to get the proper
 ;; result.  Here is an obvious 8 instruction sequence.
 
+;; XXX
 (define_insn "ffssi2"
   [(set (match_operand:SI 0 "register_operand" "=&r")
        (ffs:SI (match_operand:SI 1 "register_operand" "r")))
@@ -6196,205 +7137,7 @@ if (! TARGET_ARCH64)
 ;  "neg %1,%2\;xnor %1,%2,%2\;popc %2,%0\;movzr %1,0,%0"
 ;  [(set_attr "type" "multi")
 ;   (set_attr "length" "4")])
-\f
-;; Split up troublesome insns for better scheduling.  */
-
-;; The following patterns are straightforward.  They can be applied
-;; either before or after register allocation.
-
-(define_split
-  [(set (match_operand 0 "splittable_symbolic_memory_operand" "")
-       (match_operand 1 "reg_or_0_operand" ""))
-   (clobber (match_operand:SI 2 "register_operand" ""))]
-  "! flag_pic"
-  [(set (match_dup 2) (high:SI (match_dup 3)))
-   (set (match_dup 4) (match_dup 1))]
-  "
-{
-  operands[3] = XEXP (operands[0], 0);
-  operands[4] = gen_rtx_MEM (GET_MODE (operands[0]),
-                        gen_rtx_LO_SUM (SImode, operands[2], operands[3]));
-  MEM_IN_STRUCT_P (operands[4]) = MEM_IN_STRUCT_P (operands[0]);
-  MEM_VOLATILE_P (operands[4]) = MEM_VOLATILE_P (operands[0]);
-  RTX_UNCHANGING_P (operands[4]) = RTX_UNCHANGING_P (operands[0]);
-}")
-
-(define_split
-  [(set (match_operand 0 "splittable_immediate_memory_operand" "")
-       (match_operand 1 "general_operand" ""))
-   (clobber (match_operand:SI 2 "register_operand" ""))]
-  "flag_pic"
-  [(set (match_dup 3) (match_dup 1))]
-  "
-{
-  rtx addr = legitimize_pic_address (XEXP (operands[0], 0),
-                                    GET_MODE (operands[0]),
-                                    operands[2]);
-  operands[3] = gen_rtx_MEM (GET_MODE (operands[0]), addr);
-  MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[0]);
-  MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[0]);
-  RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[0]);
-}")
-
-(define_split
-  [(set (match_operand 0 "register_operand" "")
-       (match_operand 1 "splittable_immediate_memory_operand" ""))]
-  "flag_pic"
-  [(set (match_dup 0) (match_dup 2))]
-  "
-{
-  rtx addr = legitimize_pic_address (XEXP (operands[1], 0),
-                                    GET_MODE (operands[1]),
-                                    operands[0]);
-  operands[2] = gen_rtx_MEM (GET_MODE (operands[1]), addr);
-  MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
-  MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]);
-  RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
-}")
-
-;; Sign- and Zero-extend operations can have symbolic memory operands.
-
-(define_split
-  [(set (match_operand 0 "register_operand" "")
-       (match_operator 1 "extend_op" [(match_operand 2 "splittable_immediate_memory_operand" "")]))]
-  "flag_pic"
-  [(set (match_dup 0) (match_op_dup 1 [(match_dup 3)]))]
-  "
-{
-  rtx addr = legitimize_pic_address (XEXP (operands[2], 0),
-                                    GET_MODE (operands[2]),
-                                    operands[0]);
-  operands[3] = gen_rtx_MEM (GET_MODE (operands[2]), addr);
-  MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[2]);
-  MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[2]);
-  RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[2]);
-}")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (match_operand:SI 1 "immediate_operand" ""))]
-  "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
-                 || GET_CODE (operands[1]) == CONST
-                 || GET_CODE (operands[1]) == LABEL_REF)"
-  [(set (match_dup 0) (high:SI (match_dup 1)))
-   (set (match_dup 0)
-       (lo_sum:SI (match_dup 0) (match_dup 1)))]
-  "")
-
-;; LABEL_REFs are not modified by `legitimize_pic_address'
-;; so do not recurse infinitely in the PIC case.
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (match_operand:SI 1 "immediate_operand" ""))]
-  "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
-               || GET_CODE (operands[1]) == CONST)"
-  [(set (match_dup 0) (match_dup 1))]
-  "
-{
-  operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]);
-}")
-\f
-;; These split sne/seq insns.  The forms of the resulting insns are 
-;; somewhat bogus, but they avoid extra patterns and show data dependency.
-;; Nothing will look at these in detail after splitting has occurred.
-
-;; ??? v9 DImode versions are missing because addc and subc use %icc.
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (ne:SI (match_operand:SI 1 "register_operand" "")
-              (const_int 0)))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
-  "")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
-                      (const_int 0))))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
-  "")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (eq:SI (match_operand:SI 1 "register_operand" "")
-              (const_int 0)))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
-  "")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
-                      (const_int 0))))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
-  "")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
-                       (const_int 0))
-                (match_operand:SI 2 "register_operand" "")))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
-                              (match_dup 2)))]
-  "")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (minus:SI (match_operand:SI 2 "register_operand" "")
-                 (ne:SI (match_operand:SI 1 "register_operand" "")
-                        (const_int 0))))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (minus:SI (match_dup 2)
-                               (ltu:SI (reg:CC 100) (const_int 0))))]
-  "")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
-                       (const_int 0))
-                (match_operand:SI 2 "register_operand" "")))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
-                              (match_dup 2)))]
-  "")
 
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (minus:SI (match_operand:SI 2 "register_operand" "")
-                 (eq:SI (match_operand:SI 1 "register_operand" "")
-                        (const_int 0))))
-   (clobber (reg:CC 100))]
-  ""
-  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
-                                          (const_int 0)))
-   (set (match_dup 0) (minus:SI (match_dup 2)
-                               (geu:SI (reg:CC 100) (const_int 0))))]
-  "")
 \f
 ;; Peepholes go at the end.
 
@@ -6408,9 +7151,10 @@ if (! TARGET_ARCH64)
    (set (match_operand:SI 1 "memory_operand" "")
       (const_int 0))]
   "TARGET_V9
-   && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[1])
+   && ! MEM_VOLATILE_P (operands[0])
+   && ! MEM_VOLATILE_P (operands[1])
    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[1], 0))"
-  "stx %%g0,%0")
+  "stx\\t%%g0, %0")
 
 (define_peephole
   [(set (match_operand:SI 0 "memory_operand" "")
@@ -6418,89 +7162,98 @@ if (! TARGET_ARCH64)
    (set (match_operand:SI 1 "memory_operand" "")
       (const_int 0))]
   "TARGET_V9
-   && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[1])
+   && ! MEM_VOLATILE_P (operands[0])
+   && ! MEM_VOLATILE_P (operands[1])
    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[0], 0))"
-  "stx %%g0,%1")
+  "stx\\t%%g0, %1")
 
 (define_peephole
   [(set (match_operand:SI 0 "register_operand" "=rf")
         (match_operand:SI 1 "memory_operand" ""))
    (set (match_operand:SI 2 "register_operand" "=rf")
         (match_operand:SI 3 "memory_operand" ""))]
-   "registers_ok_for_ldd_peep (operands[0], operands[2]) 
-   && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
+  "registers_ok_for_ldd_peep (operands[0], operands[2]) 
+   && ! MEM_VOLATILE_P (operands[1])
+   && ! MEM_VOLATILE_P (operands[3])
    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 
-  "ldd %1,%0")
+  "ldd\\t%1, %0")
 
 (define_peephole
   [(set (match_operand:SI 0 "memory_operand" "")
         (match_operand:SI 1 "register_operand" "rf"))
    (set (match_operand:SI 2 "memory_operand" "")
         (match_operand:SI 3 "register_operand" "rf"))]
-   "registers_ok_for_ldd_peep (operands[1], operands[3]) 
-   && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
+  "registers_ok_for_ldd_peep (operands[1], operands[3]) 
+   && ! MEM_VOLATILE_P (operands[0])
+   && ! MEM_VOLATILE_P (operands[2])
    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
-  "std %1,%0")
+  "std\\t%1, %0")
  
 (define_peephole
   [(set (match_operand:SF 0 "register_operand" "=fr")
         (match_operand:SF 1 "memory_operand" ""))
    (set (match_operand:SF 2 "register_operand" "=fr")
         (match_operand:SF 3 "memory_operand" ""))]
-   "registers_ok_for_ldd_peep (operands[0], operands[2]) 
-   && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
+  "registers_ok_for_ldd_peep (operands[0], operands[2]) 
+   && ! MEM_VOLATILE_P (operands[1])
+   && ! MEM_VOLATILE_P (operands[3])
    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
-  "ldd %1,%0")
+  "ldd\\t%1, %0")
 
 (define_peephole
   [(set (match_operand:SF 0 "memory_operand" "")
         (match_operand:SF 1 "register_operand" "fr"))
    (set (match_operand:SF 2 "memory_operand" "")
         (match_operand:SF 3 "register_operand" "fr"))]
-   "registers_ok_for_ldd_peep (operands[1], operands[3]) 
-   && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
-   && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
-  "std %1,%0")
+  "registers_ok_for_ldd_peep (operands[1], operands[3]) 
+  && ! MEM_VOLATILE_P (operands[0])
+  && ! MEM_VOLATILE_P (operands[2])
+  && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
+  "std\\t%1, %0")
 
 (define_peephole
   [(set (match_operand:SI 0 "register_operand" "=rf")
         (match_operand:SI 1 "memory_operand" ""))
    (set (match_operand:SI 2 "register_operand" "=rf")
         (match_operand:SI 3 "memory_operand" ""))]
-   "registers_ok_for_ldd_peep (operands[2], operands[0]) 
-   && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
-   && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
-  "ldd %3,%2")
+  "registers_ok_for_ldd_peep (operands[2], operands[0]) 
+  && ! MEM_VOLATILE_P (operands[3])
+  && ! MEM_VOLATILE_P (operands[1])
+  && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
+  "ldd\\t%3, %2")
 
 (define_peephole
   [(set (match_operand:SI 0 "memory_operand" "")
         (match_operand:SI 1 "register_operand" "rf"))
    (set (match_operand:SI 2 "memory_operand" "")
         (match_operand:SI 3 "register_operand" "rf"))]
-   "registers_ok_for_ldd_peep (operands[3], operands[1]) 
-   && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
-   && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 
-  "std %3,%2")
+  "registers_ok_for_ldd_peep (operands[3], operands[1]) 
+  && ! MEM_VOLATILE_P (operands[2])
+  && ! MEM_VOLATILE_P (operands[0])
+  && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 
+  "std\\t%3, %2")
  
 (define_peephole
   [(set (match_operand:SF 0 "register_operand" "=fr")
         (match_operand:SF 1 "memory_operand" ""))
    (set (match_operand:SF 2 "register_operand" "=fr")
         (match_operand:SF 3 "memory_operand" ""))]
-   "registers_ok_for_ldd_peep (operands[2], operands[0]) 
-   && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
-   && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
-  "ldd %3,%2")
+  "registers_ok_for_ldd_peep (operands[2], operands[0]) 
+  && ! MEM_VOLATILE_P (operands[3])
+  && ! MEM_VOLATILE_P (operands[1])
+  && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
+  "ldd\\t%3, %2")
 
 (define_peephole
   [(set (match_operand:SF 0 "memory_operand" "")
         (match_operand:SF 1 "register_operand" "fr"))
    (set (match_operand:SF 2 "memory_operand" "")
         (match_operand:SF 3 "register_operand" "fr"))]
-   "registers_ok_for_ldd_peep (operands[3], operands[1]) 
-   && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
-   && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
-  "std %3,%2")
+  "registers_ok_for_ldd_peep (operands[3], operands[1]) 
+  && ! MEM_VOLATILE_P (operands[2])
+  && ! MEM_VOLATILE_P (operands[0])
+  && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
+  "std\\t%3, %2")
  
 ;; Optimize the case of following a reg-reg move with a test
 ;; of reg just moved.  Don't allow floating point regs for operand 0 or 1.
@@ -6514,8 +7267,9 @@ if (! TARGET_ARCH64)
                    (const_int 0)))]
   "(rtx_equal_p (operands[2], operands[0])
     || rtx_equal_p (operands[2], operands[1]))
-   && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
-  "orcc %1,0,%0")
+   && ! FP_REG_P (operands[0])
+   && ! FP_REG_P (operands[1])"
+  "orcc\\t%1, 0, %0")
 
 (define_peephole
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -6526,37 +7280,9 @@ if (! TARGET_ARCH64)
   "TARGET_ARCH64
    && (rtx_equal_p (operands[2], operands[0])
        || rtx_equal_p (operands[2], operands[1]))
-   && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
-  "orcc %1,0,%0")
-
-;; Floating-point move peepholes
-;; ??? v9: Do we want similar ones?
-
-(define_peephole
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (lo_sum:SI (match_dup 0)
-                  (match_operand:SI 1 "immediate_operand" "i")))
-   (set (match_operand:DF 2 "register_operand" "=er")
-       (mem:DF (match_dup 0)))]
-  "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
-  "*
-{
-  /* Go by way of output_move_double in case the register in operand 2
-     is not properly aligned for ldd.  */
-  operands[1] = gen_rtx_MEM (DFmode,
-                        gen_rtx_LO_SUM (SImode, operands[0], operands[1]));
-  operands[0] = operands[2];
-  return output_move_double (operands);
-}")
-
-(define_peephole
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (lo_sum:SI (match_dup 0)
-                  (match_operand:SI 1 "immediate_operand" "i")))
-   (set (match_operand:SF 2 "register_operand" "=fr")
-       (mem:SF (match_dup 0)))]
-  "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
-  "ld [%0+%%lo(%a1)],%2")
+   && ! FP_REG_P (operands[0])
+   && ! FP_REG_P (operands[1])"
+  "orcc\\t%1, 0, %0")
 
 ;; Return peepholes.  First the "normal" ones.
 ;; These are necessary to catch insns ending up in the epilogue delay list.
@@ -6569,12 +7295,12 @@ if (! TARGET_ARCH64)
   "*
 {
   if (! TARGET_ARCH64 && current_function_returns_struct)
-    return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+    return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
                         || IN_OR_GLOBAL_P (operands[1])))
-    return \"return %%i7+8\;mov %Y1,%Y0\";
+    return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
   else
-    return \"ret\;restore %%g0,%1,%Y0\";
+    return \"ret\\n\\trestore %%g0, %1, %Y0\";
 }"
   [(set_attr "type" "multi")])
 
@@ -6586,12 +7312,12 @@ if (! TARGET_ARCH64)
   "*
 {
   if (! TARGET_ARCH64 && current_function_returns_struct)
-    return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+    return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
                         || IN_OR_GLOBAL_P (operands[1])))
-    return \"return %%i7+8\;mov %Y1,%Y0\";
+    return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
   else
-    return \"ret\;restore %%g0,%1,%Y0\";
+    return \"ret\;restore %%g0, %1, %Y0\";
 }"
   [(set_attr "type" "multi")])
 
@@ -6603,31 +7329,32 @@ if (! TARGET_ARCH64)
   "*
 {
   if (! TARGET_ARCH64 && current_function_returns_struct)
-    return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+    return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
                         || IN_OR_GLOBAL_P (operands[1])))
-    return \"return %%i7+8\;mov %Y1,%Y0\";
+    return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
   else
-    return \"ret\;restore %%g0,%1,%Y0\";
+    return \"ret\;restore %%g0, %1, %Y0\";
 }"
   [(set_attr "type" "multi")])
 
 ;; The following pattern is only generated by delayed-branch scheduling,
-;; when the insn winds up in the epilogue.  This can only happen when
-;; ! TARGET_FPU because otherwise fp return values are in %f0.
+;; when the insn winds up in the epilogue.  This can happen not only when
+;; ! TARGET_FPU because we move complex types around by parts using
+;; SF mode SUBREGs.
 (define_insn "*return_sf_no_fpu"
   [(set (match_operand:SF 0 "restore_operand" "r")
        (match_operand:SF 1 "register_operand" "r"))
    (return)]
-  "! TARGET_FPU && ! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
+  "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
   "*
 {
   if (! TARGET_ARCH64 && current_function_returns_struct)
-    return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+    return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
-    return \"return %%i7+8\;mov %Y1,%Y0\";
+    return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
   else
-    return \"ret\;restore %%g0,%1,%Y0\";
+    return \"ret\;restore %%g0, %1, %Y0\";
 }"
   [(set_attr "type" "multi")])
 
@@ -6640,14 +7367,14 @@ if (! TARGET_ARCH64)
   "*
 {
   if (! TARGET_ARCH64 && current_function_returns_struct)
-    return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
+    return \"jmp\\t%%i7+12\\n\\trestore %r1, %2, %Y0\";
   /* If operands are global or in registers, can use return */
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
           && (GET_CODE (operands[2]) == CONST_INT
               || IN_OR_GLOBAL_P (operands[2])))
-    return \"return %%i7+8\;add %Y1,%Y2,%Y0\";
+    return \"return\\t%%i7+8\\n\\tadd\\t%Y1, %Y2, %Y0\";
   else
-    return \"ret\;restore %r1,%2,%Y0\";
+    return \"ret\;restore %r1, %2, %Y0\";
 }"
   [(set_attr "type" "multi")])
 
@@ -6656,7 +7383,7 @@ if (! TARGET_ARCH64)
        (match_operand:DI 1 "arith_double_operand" "rHI"))
    (return)]
   "TARGET_ARCH64 && ! TARGET_EPILOGUE"
-  "ret\;restore %%g0,%1,%Y0"
+  "ret\;restore %%g0, %1, %Y0"
   [(set_attr "type" "multi")])
 
 (define_insn "*return_adddi"
@@ -6665,7 +7392,7 @@ if (! TARGET_ARCH64)
                 (match_operand:DI 2 "arith_double_operand" "rHI")))
    (return)]
   "TARGET_ARCH64 && ! TARGET_EPILOGUE"
-  "ret\;restore %r1,%2,%Y0"
+  "ret\;restore %r1, %2, %Y0"
   [(set_attr "type" "multi")])
 
 ;; The following pattern is only generated by delayed-branch scheduling,
@@ -6675,7 +7402,7 @@ if (! TARGET_ARCH64)
        (match_operand:SF 0 "register_operand" "f"))
    (return)]
   "! TARGET_EPILOGUE"
-  "ret\;fmovs %0,%%f0"
+  "ret\;fmovs\\t%0, %%f0"
   [(set_attr "type" "multi")])
 
 ;; Now peepholes to do a call followed by a jump.
@@ -6686,16 +7413,20 @@ if (! TARGET_ARCH64)
                         (match_operand 2 "" "")))
              (clobber (reg:SI 15))])
    (set (pc) (label_ref (match_operand 3 "" "")))]
-  "short_branch (INSN_UID (insn), INSN_UID (operands[3])) && in_same_eh_region (insn, operands[3]) && in_same_eh_region (insn, ins1)"
-  "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
+  "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
+   && in_same_eh_region (insn, operands[3])
+   && in_same_eh_region (insn, ins1)"
+  "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
 
 (define_peephole
   [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
                    (match_operand 1 "" ""))
              (clobber (reg:SI 15))])
    (set (pc) (label_ref (match_operand 2 "" "")))]
-  "short_branch (INSN_UID (insn), INSN_UID (operands[2])) && in_same_eh_region (insn, operands[2]) && in_same_eh_region (insn, ins1)"
-  "call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
+  "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
+   && in_same_eh_region (insn, operands[2])
+   && in_same_eh_region (insn, ins1)"
+  "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
 
 (define_peephole
   [(parallel [(set (match_operand 0 "" "")
@@ -6703,30 +7434,36 @@ if (! TARGET_ARCH64)
                         (match_operand 2 "" "")))
              (clobber (reg:DI 15))])
    (set (pc) (label_ref (match_operand 3 "" "")))]
-  "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[3])) && in_same_eh_region (insn, operands[3]) && in_same_eh_region (insn, ins1)"
-  "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
+  "TARGET_ARCH64
+   && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
+   && in_same_eh_region (insn, operands[3])
+   && in_same_eh_region (insn, ins1)"
+  "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
 
 (define_peephole
   [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
                    (match_operand 1 "" ""))
              (clobber (reg:DI 15))])
    (set (pc) (label_ref (match_operand 2 "" "")))]
-  "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[2])) && in_same_eh_region (insn, operands[2]) && in_same_eh_region (insn, ins1)"
-  "call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
+  "TARGET_ARCH64
+   && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
+   && in_same_eh_region (insn, operands[2])
+   && in_same_eh_region (insn, ins1)"
+  "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
 
 ;; After a nonlocal goto, we need to restore the PIC register, but only
 ;; if we need it.  So do nothing much here, but we'll check for this in
 ;; finalize_pic.
 
 (define_insn "nonlocal_goto_receiver"
-  [(unspec_volatile [(const_int 0)] 4)]
+  [(unspec_volatile [(const_int 0)] 5)]
   "flag_pic"
   "")
 \f
 (define_insn "trap"
   [(trap_if (const_int 1) (const_int 5))]
   ""
-  "ta 5"
+  "ta\\t5"
   [(set_attr "type" "misc")])
 
 (define_expand "conditional_trap"
@@ -6742,13 +7479,13 @@ if (! TARGET_ARCH64)
   [(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
            (match_operand:SI 1 "arith_operand" "rM"))]
   ""
-  "t%C0 %1"
+  "t%C0\\t%1"
   [(set_attr "type" "misc")])
 
 (define_insn ""
   [(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
            (match_operand:SI 1 "arith_operand" "rM"))]
   "TARGET_V9"
-  "t%C0 %%xcc,%1"
+  "t%C0\\t%%xcc, %1"
   [(set_attr "type" "misc")])
 
index 7e90bdd4036dfa35ab9ea68b6ea92b2db4da974a..5a614e5ffa9d31f8d68f7fb47a07317c61364bc2 100644 (file)
@@ -66,7 +66,9 @@ Boston, MA 02111-1307, USA.  */
 /* The native assembler can't compute differences between symbols in different
    sections when generating pic code, so we must put jump tables in the
    text section.  */
-#define JUMP_TABLES_IN_TEXT_SECTION 1
+/* But we now defer the tables to the end of the function, so we make
+   this 0 to not confuse the branch shortening code.  */
+#define JUMP_TABLES_IN_TEXT_SECTION 0
 
 /* Pass -K to the assembler when PIC.  */
 #undef ASM_SPEC
index 4b05fc70c46ca9fcff18f6f39e43fb6a0693bd97..e6a1d5347a67d97c083f91690c8cf5932daed5fa 100644 (file)
@@ -2326,6 +2326,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          if (GET_CODE (nextbody) == ADDR_VEC
              || GET_CODE (nextbody) == ADDR_DIFF_VEC)
            {
+#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
+             /* In this case, the case vector is being moved by the
+                target, so don't output the label at all.  Leave that
+                to the back end macros.  */
+#else
              if (! JUMP_TABLES_IN_TEXT_SECTION)
                {
                  readonly_data_section ();
@@ -2343,6 +2348,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
                                     NEXT_INSN (insn));
 #else
              ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
+#endif
 #endif
              break;
            }
@@ -2397,6 +2403,24 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
                app_on = 0;
              }
 
+#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
+           if (GET_CODE (body) == ADDR_VEC)
+             {
+#ifdef ASM_OUTPUT_ADDR_VEC
+               ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
+#else
+               abort();
+#endif
+             }
+           else
+             {
+#ifdef ASM_OUTPUT_ADDR_DIFF_VEC
+               ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
+#else
+               abort();
+#endif
+             }
+#else
            vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
            for (idx = 0; idx < vlen; idx++)
              {
@@ -2426,6 +2450,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
            ASM_OUTPUT_CASE_END (file,
                                 CODE_LABEL_NUMBER (PREV_INSN (insn)),
                                 insn);
+#endif
 #endif
 
            function_section (current_function_decl);
index 69c43238cb51e088fbb02cdce288c48fc0a3b9a2..fb855a9f221596a14b9a6c00d160d4d28c9f9222 100644 (file)
@@ -4660,6 +4660,13 @@ dbr_schedule (first, file)
     {
       int pred_flags;
 
+      if (GET_CODE (insn) == INSN)
+        {
+         rtx pat = PATTERN (insn);
+
+         if (GET_CODE (pat) == SEQUENCE)
+           insn = XVECEXP (pat, 0, 0);
+       }
       if (GET_CODE (insn) != JUMP_INSN)
        continue;