s390.md (prologue, [...]): New.
authorUlrich Weigand <uweigand@de.ibm.com>
Sun, 16 Dec 2001 01:48:16 +0000 (01:48 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Sun, 16 Dec 2001 01:48:16 +0000 (01:48 +0000)
* s390.md (prologue, epilogue, *return_si, *return_di): New.
s390.c (find_unused_clobbered_reg, s390_frame_info,
save_fpr, restore_fpr, s390_emit_prologue, s390_emit_epilogue): New.
s390-protos.h (s390_emit_prologue, s390_emit_epilogue): Declare.
s390.c (s390_arg_frame_offset): Use s390_frame_info.
(leaf_function_flag, cur_is_leaf_function,
save_fprs, restore_fprs, force_const_mem_late): Remove.
(s390_function_prologue, s390_function_epilogue): Mostly remove.
s390.md (lit): New.  Uses ...
s390.c (s390_output_constant_pool): ... this, so adapt and make global.
s390-protos.h (s390_output_constant_pool): Declare.
s390.md (load_multiple, store_multiple): Allow use after reload.
s390.c (load_multiple_operation, store_multiple_operation): Likewise.
s390.h (INCOMING_FRAME_SP_OFFSET): Define.
s390.h (CALL_REALLY_USED_REGISTERS): Define.
config/s390/linux64.h (CALL_USED_REGISTERS): Remove, now handled ...
s390.h (CONDITIONAL_REGISTER_USAGE): ... here.
s390.c (s390_sr_alias_set): New global variable, initialized ...
(override_options): ... here.  New.
s390-protos.h (override_options): Declare.
s390.h (OVERRIDE_OPTIONS): Call it.
s390.c (s390_function_profiler): New.
s390-protos.h (s390_function_profiler): Declare.
s390.h (FUNCTION_PROFILER): Call it.
s390.c (s390_profile): Remove.

* s390.c (reg_used_in_mem_p): PC reload counts as memory access.
(addr_generation_dependency_p): Consider literal pool register loads.
(s390_adjust_priority): Do not schedule load_multiple.
s390.md (attribute "type"): Define some additional types.
(function_unit "integer"): Adapt.
(many insns): Adapt "type" attribute setting.

* s390.c (general_s_operand, s_imm_operand): New.
(s_operand): Remove old definition, call general_s_operand instead.
s390-protos.h (s_imm_operand): Declare.
s390.c (base_n_index_p, r_or_s_operand, r_or_s_or_im8_operand,
r_or_x_or_im16_operand, r_or_im8_operand): Remove.
s390-protos.h (r_or_s_operand, r_or_s_or_im8_operand,
r_or_x_or_im16_operand, r_or_im8_operand): Likewise.
s390.h (PREDICATE_CODES): Add s_imm_operand, remove r_or_s*_operand.
s390.md (many insns): Rework insn predicates.

* s390.c (legitimate_pic_operand_p, legitimate_constant_p): Accept all
non-symbolic constants.  Reload will force them because of ...
(s390_preferred_reload_class): ... this.  New.
s390-protos.h (s390_preferred_reload_class): Declare.
s390.h (PREFERRED_RELOAD_CLASS): Call it.
s390.md (movdi, movsi, movdf, movsf, *reload_la_64 splitters,
*reload_la_31 splitters): Handle constants after reload.
(many insns): no longer force all constants immediately.
s390.c (legitimate_reload_constant_p): New helper routine.
s390-protos.h (legitimate_reload_constant_p): Declare.
s390.c (print_operand): Clean up CONST_INT case, add CONST_DOUBLE case.

* s390.h (FIRST_PSEUDO_REGISTER, FRAME_POINTER_REGNUM,
HARD_FRAME_POINTER_REGNUM, REGISTER_NAMES): Add virtual frame pointer.
(CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Update.
(ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): Likewise.
(REGNO_OK_FOR_INDEX_P, REG_OK_FOR_INDEX_NONSTRICT_P): Likewise.
(DWARF_FRAME_REGISTERS): Define.
s390.c (regclass_map): Add virtual frame pointer.
(legitimate_la_operand_p): Allow use of virtual frame pointer.
s390.md (*la_ccclobber, *addaddr_ccclobber): New.
(addaddr, addsi_64): Delete.

* s390.h (HARD_REGNO_MODE_OK): Allow SImode and DImode values in
floating point registers.
(CLASS_CANNOT_CHANGE_MODE, CLASS_CANNOT_CHANGE_MODE_P): Define.
(ADDR_FP_REGS, GENERAL_FP_REGS): New register classes.
(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update.

* s390.md (movti): Replace multi-insn output with splitters.
(movdi_31, movdf_31): Likewise.
(movti_ss, movdi_ss, movsi_ss, movdf_ss, movsf_ss): New.
(movdi_lhi, movdi_lli, movdi_larl, movsi_lhi, movsi_lli): New.
(movdi_64, movdi_31, movsi, movdf_64, movdf_31): Adapt.
(movdf_soft_64, movdf_soft_31, movsf_soft): Remove.
(movsf_64, movsf_31): Remove, replace by ...
(movsf): ... this.
(movqi_64): Use lhi instead of llill.
(*movstrictqi, *movstricthi): Don't use (strict_low_part (mem)).

* s390.md (extendsidi2, *extendsidi2, extendhidi2, *extendhidi2,
extendqidi2, extendhisi2, *extendhisi2, extendqisi2,
extendqihi2 and associated splitters): Reworked.
(zero_extendsidi2, zero_extendsidi2, *zero_extendsidi2,
zero_extendhidi2, *zero_extendhidi2, zero_extendqidi2,
zero_extendqidi2, *zero_extendqidi2, zero_extendhisi2,
*zero_extendhisi2_64, zero_extendhisi2_31, zero_extendqisi2,
*zero_extendqisi2_64, *zero_extendqisi2_mem_31,
zero_extendqisi2_reg_31, zero_extendqihi2, *zero_extendqisi2_64,
zero_extendqihi2, zero_extendqihi2_64, zero_extendqihi2_31,
and associated splitters): Likewise.
(*sethighqisi, *sethighhisi, *sethighqidi_64, *sethighqidi_31
and associated splitters): New.
(truncdisi2, truncdihi2, truncdiqi2, truncsihi2, do_truncsihi2,
*truncsihi2_64, truncsiqi2, trunchiqi2): Remove.
(ashlhi3, ashrhi3, lshrhi3, abshi3): Remove.
s390.h (PROMOTE_PROTOTYPES): Remove.
config/s390/linux64.h (PROMOTE_PROTOTYPES): Likewise.

* s390.md (muldi3): Delete, use instead ...
(mulsidi3): ... this.
(*muldi3_64): Rename to muldi3.
(mulsi_6432): Fix template.
(divdi3, moddi3): Delete, replace by ...
(divmoddi4): ... this.
(divmodtidi3): Fix template.
(divmodtisi3): New.
(udivdi3, umoddi3): Delete, replace by ...
(udivmoddi4): ... this.
(udivmodtidi3): Fix template.
(divsi3, modsi3): Delete, replace by ...
(divmodsi4): ... this.
(divmoddisi3): Fix template.
(udivsi3, umodsi3): Adapt.

* s390.md (anddi3): Remove SS alternative, use instead ...
(anddi3_ss, anddi3_ss_inv): ... these.
(anddi3_ni): New.
(andsi3*, andhi3*, andqi3*): Likewise.
(iordi3): Remove SS alternative, use instead ...
(iordi3_ss, iordi3_ss_inv): ... these.
(iordi3_oi): New.
(iorsi3*, iorhi3*, iorqi3*): Likewise.
(iordi3_cc, iordi3_cconly, iorsi3_cc, iorsi3_cconly): New.
(xordi3): Remove SS alternative, use instead ...
(xordi3_ss, xordi3_ss_inv): ... these.
(xordi3_oi): New.
(xorsi3*, xorhi3*, xorqi3*): Likewise.
(xordi3_cc, xordi3_cconly, xorsi3_cc, xorsi3_cconly): New.
(one_cmpldi2, one_cmplsi2, one_cmplhi2, one_cmplqi2):
Expand to XOR with -1.
(*one_cmpldi2, *one_cmplsi2, *one_cmplhi2): Remove.
(cmpdi_tm): Delete, replace by ...
(cmpdi_tm_reg, cmpdi_tm_mem): ... these.
(cmpsi_cct): Delete, replace by ...
(cmpsi_tm_reg, cmpsi_tm_mem): ... these.
(cmpdi_tm2, cmpsi_tm2): Improve.
(cmphi_tm_sub, cmpqi_tm_sub, cmpqi_tm2, cmpqi_tm): New.
s390.c (s390_single_hi, s390_extract_hi,
s390_single_qi, s390_extract_qi): New helper routines.
s390-protos.h (s390_single_hi, s390_extract_hi,
s390_single_qi, s390_extract_qi): Declare.
s390.c (tmxx_operand, const1_operand): Remove.
s390-protos.h (tmxx_operand, const1_operand): Likewise.
s390.h (PREDICATE_CODES): Likewise.

* s390.md (sqrtdf2, sqrtsf2): New.

* s390.h (CRT_CALL_STATIC_FUNCTION): Define.
(check_and_change_labels): Remove section-change special case.

* s390.h (RETURN_ADDR_RTX): Fix use of __builtin_return_address
in leaf functions.  Needs ...
(DYNAMIC_CHAIN_RTX):  ... this.  New.

* s390.c (emit_pic_move): Don't generate pseudos if no_new_pseudos.

* s390.md (movstrdix_64, movstrsix_31, movstrdi_64, movstrsi_31,
clrstrsi_64, clrstrsi_31, cmpstr_64, cmpstr_31): Do not clobber
input operands using a match_dup clause.
(movstrdi, movstrsi, clrstrdi, clrstrsi, cmpstrdi, cmpstrsi): Adapt.

* s390.md (floatdidf2, floatdisf2, floatsidf2, floatsidf2_ieee,
floatsisf2, floatsisf2_ieee): Add missing CC clobber.

* s390.md (floatsidf2_ibm): Use correct operand.

* s390.md (fixuns_truncdfdi2, fixuns_truncdfsi2, fix_truncdfsi2,
fixuns_truncsfdi2, fixuns_truncsfsi2, floatsidf2): Remove use of
non-portable constants.
s390.c (s390_gen_rtx_const_DI): New helper routine.
s390-protos.h (s390_gen_rtx_const_DI): Declare.

* s390.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Fix alignment.

* config/s390/linux.h (ASM_OUTPUT_SHORT, ASM_OUTPUT_CHAR,
ASM_OUTPUT_BYTE): Clean up assembly output.
(ASM_OUTPUT_SKIP, ASM_OUTPUT_ALIGN): Remove duplicate definitions.
(ASM_OUTPUT_ASCII): Remove.

* config/s390/t-linux (CRTSTUFF_T_CFLAGS_S): Define.

From-SVN: r48058

gcc/ChangeLog
gcc/config/s390/linux.h
gcc/config/s390/linux64.h
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md
gcc/config/s390/t-linux

index 47570f93415f7c5034a49017f2e398e497b1736c..7eba0097c9d6c5a2bd02d3b12457b9927e630a74 100644 (file)
@@ -1,3 +1,190 @@
+2001-12-15  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * s390.md (prologue, epilogue, *return_si, *return_di): New.
+       s390.c (find_unused_clobbered_reg, s390_frame_info, 
+       save_fpr, restore_fpr, s390_emit_prologue, s390_emit_epilogue): New.
+       s390-protos.h (s390_emit_prologue, s390_emit_epilogue): Declare.
+       s390.c (s390_arg_frame_offset): Use s390_frame_info.
+       (leaf_function_flag, cur_is_leaf_function,
+       save_fprs, restore_fprs, force_const_mem_late): Remove.
+       (s390_function_prologue, s390_function_epilogue): Mostly remove.
+       s390.md (lit): New.  Uses ...
+       s390.c (s390_output_constant_pool): ... this, so adapt and make global.
+       s390-protos.h (s390_output_constant_pool): Declare.
+       s390.md (load_multiple, store_multiple): Allow use after reload.
+       s390.c (load_multiple_operation, store_multiple_operation): Likewise.
+       s390.h (INCOMING_FRAME_SP_OFFSET): Define.
+       s390.h (CALL_REALLY_USED_REGISTERS): Define.
+       config/s390/linux64.h (CALL_USED_REGISTERS): Remove, now handled ...
+       s390.h (CONDITIONAL_REGISTER_USAGE): ... here.
+       s390.c (s390_sr_alias_set): New global variable, initialized ...
+       (override_options): ... here.  New.
+       s390-protos.h (override_options): Declare.
+       s390.h (OVERRIDE_OPTIONS): Call it.
+       s390.c (s390_function_profiler): New.
+       s390-protos.h (s390_function_profiler): Declare.
+       s390.h (FUNCTION_PROFILER): Call it.
+       s390.c (s390_profile): Remove.
+
+       * s390.c (reg_used_in_mem_p): PC reload counts as memory access.
+       (addr_generation_dependency_p): Consider literal pool register loads.
+       (s390_adjust_priority): Do not schedule load_multiple.
+       s390.md (attribute "type"): Define some additional types.
+       (function_unit "integer"): Adapt.
+       (many insns): Adapt "type" attribute setting.
+
+       * s390.c (general_s_operand, s_imm_operand): New.
+       (s_operand): Remove old definition, call general_s_operand instead.
+       s390-protos.h (s_imm_operand): Declare.
+       s390.c (base_n_index_p, r_or_s_operand, r_or_s_or_im8_operand, 
+       r_or_x_or_im16_operand, r_or_im8_operand): Remove.
+       s390-protos.h (r_or_s_operand, r_or_s_or_im8_operand,
+       r_or_x_or_im16_operand, r_or_im8_operand): Likewise.
+       s390.h (PREDICATE_CODES): Add s_imm_operand, remove r_or_s*_operand.
+       s390.md (many insns): Rework insn predicates.
+
+       * s390.c (legitimate_pic_operand_p, legitimate_constant_p): Accept all
+       non-symbolic constants.  Reload will force them because of ...
+       (s390_preferred_reload_class): ... this.  New.
+       s390-protos.h (s390_preferred_reload_class): Declare.
+       s390.h (PREFERRED_RELOAD_CLASS): Call it.
+       s390.md (movdi, movsi, movdf, movsf, *reload_la_64 splitters,
+       *reload_la_31 splitters): Handle constants after reload.
+       (many insns): no longer force all constants immediately.
+       s390.c (legitimate_reload_constant_p): New helper routine.
+       s390-protos.h (legitimate_reload_constant_p): Declare.
+       s390.c (print_operand): Clean up CONST_INT case, add CONST_DOUBLE case.
+
+       * s390.h (FIRST_PSEUDO_REGISTER, FRAME_POINTER_REGNUM, 
+       HARD_FRAME_POINTER_REGNUM, REGISTER_NAMES): Add virtual frame pointer.
+       (CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Update.
+       (ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): Likewise.
+       (REGNO_OK_FOR_INDEX_P, REG_OK_FOR_INDEX_NONSTRICT_P): Likewise.
+       (DWARF_FRAME_REGISTERS): Define.
+       s390.c (regclass_map): Add virtual frame pointer.
+       (legitimate_la_operand_p): Allow use of virtual frame pointer.
+       s390.md (*la_ccclobber, *addaddr_ccclobber): New.
+       (addaddr, addsi_64): Delete.
+
+       * s390.h (HARD_REGNO_MODE_OK): Allow SImode and DImode values in 
+       floating point registers.
+       (CLASS_CANNOT_CHANGE_MODE, CLASS_CANNOT_CHANGE_MODE_P): Define.
+       (ADDR_FP_REGS, GENERAL_FP_REGS): New register classes.
+       (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update.
+
+       * s390.md (movti): Replace multi-insn output with splitters.
+       (movdi_31, movdf_31): Likewise.
+       (movti_ss, movdi_ss, movsi_ss, movdf_ss, movsf_ss): New.
+       (movdi_lhi, movdi_lli, movdi_larl, movsi_lhi, movsi_lli): New.
+       (movdi_64, movdi_31, movsi, movdf_64, movdf_31): Adapt.
+       (movdf_soft_64, movdf_soft_31, movsf_soft): Remove.
+       (movsf_64, movsf_31): Remove, replace by ...
+       (movsf): ... this.
+       (movqi_64): Use lhi instead of llill.
+       (*movstrictqi, *movstricthi): Don't use (strict_low_part (mem)).
+
+       * s390.md (extendsidi2, *extendsidi2, extendhidi2, *extendhidi2,
+       extendqidi2, extendhisi2, *extendhisi2, extendqisi2,
+       extendqihi2 and associated splitters): Reworked.
+       (zero_extendsidi2, zero_extendsidi2, *zero_extendsidi2,
+       zero_extendhidi2, *zero_extendhidi2, zero_extendqidi2,
+       zero_extendqidi2, *zero_extendqidi2, zero_extendhisi2,
+       *zero_extendhisi2_64, zero_extendhisi2_31, zero_extendqisi2,
+       *zero_extendqisi2_64, *zero_extendqisi2_mem_31,
+       zero_extendqisi2_reg_31, zero_extendqihi2, *zero_extendqisi2_64,
+       zero_extendqihi2, zero_extendqihi2_64, zero_extendqihi2_31,
+       and associated splitters): Likewise.
+       (*sethighqisi, *sethighhisi, *sethighqidi_64, *sethighqidi_31 
+       and associated splitters): New.
+       (truncdisi2, truncdihi2, truncdiqi2, truncsihi2, do_truncsihi2, 
+       *truncsihi2_64, truncsiqi2, trunchiqi2): Remove.
+       (ashlhi3, ashrhi3, lshrhi3, abshi3): Remove.
+       s390.h (PROMOTE_PROTOTYPES): Remove.
+       config/s390/linux64.h (PROMOTE_PROTOTYPES): Likewise.
+
+       * s390.md (muldi3): Delete, use instead ...
+       (mulsidi3): ... this.
+       (*muldi3_64): Rename to muldi3.
+       (mulsi_6432): Fix template.
+       (divdi3, moddi3): Delete, replace by ...
+       (divmoddi4): ... this.
+       (divmodtidi3): Fix template.
+       (divmodtisi3): New.
+       (udivdi3, umoddi3): Delete, replace by ...
+       (udivmoddi4): ... this.
+       (udivmodtidi3): Fix template.
+       (divsi3, modsi3): Delete, replace by ...
+       (divmodsi4): ... this.
+       (divmoddisi3): Fix template.
+       (udivsi3, umodsi3): Adapt.
+
+       * s390.md (anddi3): Remove SS alternative, use instead ...
+       (anddi3_ss, anddi3_ss_inv): ... these.
+       (anddi3_ni): New.
+       (andsi3*, andhi3*, andqi3*): Likewise.
+       (iordi3): Remove SS alternative, use instead ...
+       (iordi3_ss, iordi3_ss_inv): ... these.
+       (iordi3_oi): New.
+       (iorsi3*, iorhi3*, iorqi3*): Likewise.
+       (iordi3_cc, iordi3_cconly, iorsi3_cc, iorsi3_cconly): New.
+       (xordi3): Remove SS alternative, use instead ...
+       (xordi3_ss, xordi3_ss_inv): ... these.
+       (xordi3_oi): New.
+       (xorsi3*, xorhi3*, xorqi3*): Likewise.
+       (xordi3_cc, xordi3_cconly, xorsi3_cc, xorsi3_cconly): New.
+       (one_cmpldi2, one_cmplsi2, one_cmplhi2, one_cmplqi2):
+       Expand to XOR with -1.
+       (*one_cmpldi2, *one_cmplsi2, *one_cmplhi2): Remove.
+       (cmpdi_tm): Delete, replace by ...
+       (cmpdi_tm_reg, cmpdi_tm_mem): ... these.
+       (cmpsi_cct): Delete, replace by ...
+       (cmpsi_tm_reg, cmpsi_tm_mem): ... these.
+       (cmpdi_tm2, cmpsi_tm2): Improve.
+       (cmphi_tm_sub, cmpqi_tm_sub, cmpqi_tm2, cmpqi_tm): New.
+       s390.c (s390_single_hi, s390_extract_hi, 
+       s390_single_qi, s390_extract_qi): New helper routines.
+       s390-protos.h (s390_single_hi, s390_extract_hi, 
+       s390_single_qi, s390_extract_qi): Declare.
+       s390.c (tmxx_operand, const1_operand): Remove.
+       s390-protos.h (tmxx_operand, const1_operand): Likewise.
+       s390.h (PREDICATE_CODES): Likewise.
+
+       * s390.md (sqrtdf2, sqrtsf2): New.
+
+       * s390.h (CRT_CALL_STATIC_FUNCTION): Define.
+       (check_and_change_labels): Remove section-change special case.
+
+       * s390.h (RETURN_ADDR_RTX): Fix use of __builtin_return_address 
+       in leaf functions.  Needs ...
+       (DYNAMIC_CHAIN_RTX):  ... this.  New.
+
+       * s390.c (emit_pic_move): Don't generate pseudos if no_new_pseudos.
+
+       * s390.md (movstrdix_64, movstrsix_31, movstrdi_64, movstrsi_31,
+       clrstrsi_64, clrstrsi_31, cmpstr_64, cmpstr_31): Do not clobber 
+       input operands using a match_dup clause.
+       (movstrdi, movstrsi, clrstrdi, clrstrsi, cmpstrdi, cmpstrsi): Adapt.
+
+       * s390.md (floatdidf2, floatdisf2, floatsidf2, floatsidf2_ieee,
+       floatsisf2, floatsisf2_ieee): Add missing CC clobber.
+
+       * s390.md (floatsidf2_ibm): Use correct operand.
+
+       * s390.md (fixuns_truncdfdi2, fixuns_truncdfsi2, fix_truncdfsi2,
+       fixuns_truncsfdi2, fixuns_truncsfsi2, floatsidf2): Remove use of
+       non-portable constants.
+       s390.c (s390_gen_rtx_const_DI): New helper routine.
+       s390-protos.h (s390_gen_rtx_const_DI): Declare.
+
+       * s390.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Fix alignment.
+
+       * config/s390/linux.h (ASM_OUTPUT_SHORT, ASM_OUTPUT_CHAR,
+       ASM_OUTPUT_BYTE): Clean up assembly output.
+       (ASM_OUTPUT_SKIP, ASM_OUTPUT_ALIGN): Remove duplicate definitions.
+       (ASM_OUTPUT_ASCII): Remove.
+
+       * config/s390/t-linux (CRTSTUFF_T_CFLAGS_S): Define.
+
 2001-12-15  Zack Weinberg  <zack@codesourcery.com>
 
        * unwind-dw2-fde-glibc.c: #define _Unwind_Find_FDE to itself
index 75a483de8235af98b484d5bc72b43b8cf5411ed9..ce1477e1944bdea651caf8e790307fb01d661f99 100644 (file)
@@ -154,19 +154,19 @@ do { fprintf (FILE, "%s\t", ASM_LONG);          \
    is this supposed to do align too?? */
 
 #define ASM_OUTPUT_SHORT(FILE, VALUE)           \
-( fprintf (FILE, "%s ", ASM_SHORT),             \
+( fprintf (FILE, "%s\t", ASM_SHORT),            \
   output_addr_const (FILE, (VALUE)),            \
   putc ('\n',FILE))
 
 #define ASM_OUTPUT_CHAR(FILE, VALUE)            \
-( fprintf (FILE, "%s ", ASM_BYTE_OP),           \
+( fprintf (FILE, "\t%s\t", ASM_BYTE_OP),        \
   output_addr_const (FILE, (VALUE)),            \
   putc ('\n', FILE))
 
 /* This is how to output an assembler line for a numeric constant byte.  */
 
 #define ASM_OUTPUT_BYTE(FILE, VALUE)  \
-  fprintf ((FILE), "%s 0x%x\n", ASM_BYTE_OP, (int)(VALUE))
+  fprintf ((FILE), "\t%s\t0x%x\n", ASM_BYTE_OP, (int)(VALUE))
 
      /* internal macro to output long */
 #define _ASM_OUTPUT_LONG(FILE, VALUE)                                   \
@@ -191,75 +191,16 @@ do { fprintf (FILE, "%s\t", ASM_LONG);          \
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
 
-#define ASM_OUTPUT_ALIGN(FILE, LOG)      \
-    if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
-
-/* This is how to output an assembler line
-   that says to advance the location counter by SIZE bytes.  */
-
-#undef ASM_OUTPUT_SKIP 
-#define ASM_OUTPUT_SKIP(FILE, SIZE)  \
-  fprintf ((FILE), "\t.set .,.+%u\n", (SIZE))
-
-/* This is how to output an assembler line
-   that says to advance the location counter
-   to a multiple of 2**LOG bytes.  */
-
+#undef ASM_OUTPUT_ALIGN
 #define ASM_OUTPUT_ALIGN(FILE, LOG)    \
-    if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+    if ((LOG)!=0) fprintf ((FILE), "\t.align\t%d\n", 1<<(LOG))
 
 /* This is how to output an assembler line
    that says to advance the location counter by SIZE bytes.  */
 
+#undef ASM_OUTPUT_SKIP
 #define ASM_OUTPUT_SKIP(FILE, SIZE)  \
-  fprintf ((FILE), "\t.set .,.+%u\n", (SIZE))
-
-/* The routine used to output sequences of byte values.  We use a special
-   version of this for most svr4 targets because doing so makes the
-   generated assembly code more compact (and thus faster to assemble)
-   as well as more readable.  Note that if we find subparts of the
-   character sequence which end with NUL (and which are shorter than
-   STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING.  */
-
-#undef ASM_OUTPUT_ASCII
-#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH)                             \
-do {                                                                    \
-      register const unsigned char *_ascii_bytes = (const unsigned char *) (STR);   \
-      register const unsigned char *limit = _ascii_bytes + (LENGTH);          \
-      register unsigned bytes_in_chunk = 0;                             \
-      for (; _ascii_bytes < limit; _ascii_bytes++)                      \
-        {                                                               \
-          register const unsigned char *p;                                    \
-          if (bytes_in_chunk >= 64)                                     \
-            {                                                           \
-              fputc ('\n', (FILE));                                     \
-              bytes_in_chunk = 0;                                       \
-            }                                                           \
-          for (p = _ascii_bytes; p < limit && *p != '\0'; p++)          \
-            continue;                                                   \
-          if (p < limit && (p - _ascii_bytes) <= (long)STRING_LIMIT)    \
-            {                                                           \
-              if (bytes_in_chunk > 0)                                   \
-                {                                                       \
-                  fputc ('\n', (FILE));                                 \
-                  bytes_in_chunk = 0;                                   \
-                }                                                       \
-              ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes);         \
-              _ascii_bytes = p;                                         \
-            }                                                           \
-          else                                                          \
-            {                                                           \
-              if (bytes_in_chunk == 0)                                  \
-                fprintf ((FILE), "%s\t", ASM_BYTE_OP);                  \
-              else                                                      \
-                fputc (',', (FILE));                                    \
-              fprintf ((FILE), "0x%02x", *_ascii_bytes);                \
-              bytes_in_chunk += 5;                                      \
-            }                                                           \
-        }                                                               \
-      if (bytes_in_chunk > 0)                                           \
-        fprintf ((FILE), "\n");                                         \
-} while (0)
+  fprintf ((FILE), "\t.set\t.,.+%u\n", (SIZE))
 
 /* Output before read-only data.  */
 
index 0fdd173cc3a79962dc3623af4a83b6f8812cebbd..a65cf90f7d38d5ba0f73d1a782eac2aa045f44e7 100644 (file)
@@ -59,21 +59,7 @@ Boston, MA 02111-1307, USA.  */
        %{static:-static}}}"
 #endif
 
-#undef PROMOTE_PROTOTYPES 
 #undef MASK_RETURN_ADDR 
 #undef SELECT_SECTION
 
-/* With 64 bit new linkage for floating point registers.  */
-#undef CALL_USED_REGISTERS                     
-#define CALL_USED_REGISTERS                    \
-{ 1, 1, 1, 1,                                  \
-  1, 1, 0, 0,                                  \
-  0, 0, 0, 0,                                  \
-  0, 1, 1, 1,                                  \
-  1, 1, 1, 1,                                  \
-  1, 1, 1, 1,                                  \
-  0, 0, 0, 0,                                  \
-  0, 0, 0, 0,                                  \
-  1, 1 }
-
 #endif
index baee5a09ea05fcbda98e4979869a1974aaea4f5b..b426daca275a60098119b60af9e68893ffb9281d 100644 (file)
@@ -22,24 +22,27 @@ Boston, MA 02111-1307, USA.  */
 /* Declare functions in s390.c.  */
 
 extern void optimization_options PARAMS ((int, int));
+extern void override_options PARAMS ((void));
 extern int s390_arg_frame_offset PARAMS ((void));
 extern void s390_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 extern void s390_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+extern void s390_emit_prologue PARAMS ((void));
+extern void s390_emit_epilogue PARAMS ((void));
+extern void s390_function_profiler PARAMS ((FILE *, int));
 
 #ifdef RTX_CODE
 extern int const0_operand PARAMS ((rtx, enum machine_mode));
-extern int const1_operand PARAMS ((rtx, enum machine_mode));
 extern int larl_operand PARAMS ((rtx, enum machine_mode));
 extern int fp_operand PARAMS ((rtx, enum machine_mode));
 extern int s_operand PARAMS ((rtx, enum machine_mode));
-extern int r_or_s_operand PARAMS ((rtx, enum machine_mode));
-extern int r_or_s_or_im8_operand PARAMS ((rtx, enum machine_mode));
-extern int r_or_x_or_im16_operand PARAMS ((rtx, enum machine_mode));
-extern int r_or_im8_operand PARAMS ((rtx, enum machine_mode));
-extern int tmxx_operand PARAMS ((rtx, enum machine_mode));
+extern int s_imm_operand PARAMS ((rtx, enum machine_mode));
 extern int bras_sym_operand PARAMS ((rtx, enum machine_mode));
 extern int load_multiple_operation PARAMS ((rtx, enum machine_mode));
 extern int store_multiple_operation PARAMS ((rtx, enum machine_mode));
+extern int s390_single_hi PARAMS ((rtx, enum machine_mode, int));
+extern int s390_extract_hi PARAMS ((rtx, enum machine_mode, int));
+extern int s390_single_qi PARAMS ((rtx, enum machine_mode, int));
+extern int s390_extract_qi PARAMS ((rtx, enum machine_mode, int));
 
 extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
 extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx));
@@ -47,18 +50,22 @@ extern int symbolic_reference_mentioned_p PARAMS ((rtx));
 extern int legitimate_la_operand_p PARAMS ((rtx));
 extern int legitimate_pic_operand_p PARAMS ((rtx));
 extern int legitimate_constant_p PARAMS ((rtx));
+extern int legitimate_reload_constant_p PARAMS ((rtx));
 extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
 extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
 extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
+extern enum reg_class s390_preferred_reload_class PARAMS ((rtx, enum reg_class));
 extern void emit_pic_move PARAMS ((rtx *, enum machine_mode));
 
 extern void s390_output_symbolic_const PARAMS ((FILE *, rtx));
 extern void print_operand_address PARAMS ((FILE *, rtx));
 extern void print_operand PARAMS ((FILE *, rtx, int));
+extern void s390_output_constant_pool PARAMS ((FILE *));
 extern int s390_stop_dump_lit_p PARAMS ((rtx));
 extern void s390_dump_literal_pool PARAMS ((rtx, rtx));
 extern void s390_trampoline_template PARAMS ((FILE *));
 extern void s390_initialize_trampoline PARAMS ((rtx, rtx, rtx));
+extern rtx s390_gen_rtx_const_DI PARAMS ((int, int));
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
index 34945b054a97348d27a067a84b68e2a970db1302..743276c4da25a2b10b4121d9829c95f79a8a228b 100644 (file)
@@ -39,6 +39,7 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "toplev.h"
 #include "basic-block.h"
+#include "integrate.h"
 #include "ggc.h"
 #include "target.h"
 #include "target-def.h"
@@ -70,6 +71,9 @@ struct gcc_target targetm = TARGET_INITIALIZER;
 
 extern int reload_completed;
 
+/* The alias set for prologue/epilogue register save/restore.  */
+static int s390_sr_alias_set = 0;
+
 /* Function count for creating unique internal labels in a compile unit.  */
 int  s390_function_count = 0;
 
@@ -93,11 +97,26 @@ struct s390_address
   rtx disp;
 };
 
+/* Structure containing information for prologue and epilogue.  */ 
+
+struct s390_frame
+{
+  int frame_pointer_p;
+  int return_reg_saved_p;
+  int save_fprs_p;
+  int first_save_gpr;
+  int first_restore_gpr;
+  int last_save_gpr;
+  int arg_frame_offset;
+
+  HOST_WIDE_INT frame_size;
+};
+
 static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode));
 static int s390_branch_condition_mask PARAMS ((rtx));
 static const char *s390_branch_condition_mnemonic PARAMS ((rtx, int));
-static int base_n_index_p PARAMS ((rtx));
 static int check_mode PARAMS ((rtx, enum machine_mode *));
+static int general_s_operand PARAMS ((rtx, enum machine_mode, int));
 static int s390_decompose_address PARAMS ((rtx, struct s390_address *, int));
 static int reg_used_in_mem_p PARAMS ((int, rtx));
 static int addr_generation_dependency_p PARAMS ((rtx, rtx));
@@ -106,12 +125,10 @@ static int far_away PARAMS ((int, int));
 static rtx check_and_change_labels PARAMS ((rtx, int *));
 static void s390_final_chunkify PARAMS ((int));
 static int save_fprs_p PARAMS ((void));
-static int cur_is_leaf_function PARAMS ((void));
-static int save_fprs PARAMS ((FILE *, long, int));
-static int restore_fprs PARAMS ((FILE *, long, int));
-static void s390_output_constant_pool PARAMS ((FILE *));
-static rtx s390_force_const_mem_late PARAMS ((rtx));
-static rtx s390_force_const_mem_symbol PARAMS ((const char *, int, int));
+static int find_unused_clobbered_reg PARAMS ((void));
+static void s390_frame_info PARAMS ((struct s390_frame *));
+static rtx save_fpr PARAMS ((rtx, int, int));
+static rtx restore_fpr PARAMS ((rtx, int, int));
 static int s390_function_arg_size PARAMS ((enum machine_mode, tree));
 
  
@@ -339,6 +356,212 @@ s390_branch_condition_mnemonic (code, inv)
   return mnemonic[mask];
 }
 
+/* If OP is an integer constant of mode MODE with exactly one
+   HImode subpart unequal to DEF, return the number of that 
+   subpart.  As a special case, all HImode subparts of OP are
+   equal to DEF, return zero.  Otherwise, return -1.  */
+
+int
+s390_single_hi (op, mode, def)
+     rtx op;
+     enum machine_mode mode;
+     int def;
+{
+  if (GET_CODE (op) == CONST_INT)
+    {
+      unsigned HOST_WIDE_INT value;
+      int n_parts = GET_MODE_SIZE (mode) / 2;
+      int i, part = -1;
+
+      for (i = 0; i < n_parts; i++)
+        {
+          if (i == 0)
+            value = (unsigned HOST_WIDE_INT) INTVAL (op);
+          else
+            value >>= 16;
+
+          if ((value & 0xffff) != (unsigned)(def & 0xffff))
+            {
+              if (part != -1)
+                return -1;
+              else
+                part = i;
+            }
+        }
+
+      return part == -1 ? 0 : (n_parts - 1 - part);
+    }
+
+  else if (GET_CODE (op) == CONST_DOUBLE
+           && GET_MODE (op) == VOIDmode)
+    {
+      unsigned HOST_WIDE_INT value;
+      int n_parts = GET_MODE_SIZE (mode) / 2;
+      int i, part = -1;
+
+      for (i = 0; i < n_parts; i++)
+        {
+          if (i == 0)
+            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+          else if (i == HOST_BITS_PER_WIDE_INT / 16)
+            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op);
+          else
+            value >>= 16;
+
+          if ((value & 0xffff) != (unsigned)(def & 0xffff))
+            {
+              if (part != -1)
+                return -1;
+              else
+                part = i;
+            }
+        }
+
+      return part == -1 ? 0 : (n_parts - 1 - part);
+    }
+
+  return -1;      
+}
+
+/* Extract the HImode part number PART from integer 
+   constant OP of mode MODE.  */
+
+int
+s390_extract_hi (op, mode, part)
+    rtx op;
+    enum machine_mode mode;
+    int part;
+{
+  int n_parts = GET_MODE_SIZE (mode) / 2;
+  if (part < 0 || part >= n_parts)
+    abort();
+  else
+    part = n_parts - 1 - part;
+
+  if (GET_CODE (op) == CONST_INT)
+    {
+      unsigned HOST_WIDE_INT value = (unsigned HOST_WIDE_INT) INTVAL (op);
+      return ((value >> (16 * part)) & 0xffff);
+    }
+  else if (GET_CODE (op) == CONST_DOUBLE
+           && GET_MODE (op) == VOIDmode)
+    {
+      unsigned HOST_WIDE_INT value;
+      if (part < HOST_BITS_PER_WIDE_INT / 16)
+        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+      else
+        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op),
+        part -= HOST_BITS_PER_WIDE_INT / 16;
+
+      return ((value >> (16 * part)) & 0xffff); 
+    }
+
+  abort ();
+}
+
+/* If OP is an integer constant of mode MODE with exactly one
+   QImode subpart unequal to DEF, return the number of that 
+   subpart.  As a special case, all QImode subparts of OP are
+   equal to DEF, return zero.  Otherwise, return -1.  */
+
+int
+s390_single_qi (op, mode, def)
+     rtx op;
+     enum machine_mode mode;
+     int def;
+{
+  if (GET_CODE (op) == CONST_INT)
+    {
+      unsigned HOST_WIDE_INT value;
+      int n_parts = GET_MODE_SIZE (mode);
+      int i, part = -1;
+
+      for (i = 0; i < n_parts; i++)
+        {
+          if (i == 0)
+            value = (unsigned HOST_WIDE_INT) INTVAL (op);
+          else
+            value >>= 8;
+
+          if ((value & 0xff) != (unsigned)(def & 0xff))
+            {
+              if (part != -1)
+                return -1;
+              else
+                part = i;
+            }
+        }
+
+      return part == -1 ? 0 : (n_parts - 1 - part);
+    }
+
+  else if (GET_CODE (op) == CONST_DOUBLE
+           && GET_MODE (op) == VOIDmode)
+    {
+      unsigned HOST_WIDE_INT value;
+      int n_parts = GET_MODE_SIZE (mode);
+      int i, part = -1;
+
+      for (i = 0; i < n_parts; i++)
+        {
+          if (i == 0)
+            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+          else if (i == HOST_BITS_PER_WIDE_INT / 8)
+            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op);
+          else
+            value >>= 8;
+
+          if ((value & 0xff) != (unsigned)(def & 0xff))
+            {
+              if (part != -1)
+                return -1;
+              else
+                part = i;
+            }
+        }
+
+      return part == -1 ? 0 : (n_parts - 1 - part);
+    }
+
+  return -1;      
+}
+
+/* Extract the QImode part number PART from integer 
+   constant OP of mode MODE.  */
+
+int
+s390_extract_qi (op, mode, part)
+    rtx op;
+    enum machine_mode mode;
+    int part;
+{
+  int n_parts = GET_MODE_SIZE (mode);
+  if (part < 0 || part >= n_parts)
+    abort();
+  else
+    part = n_parts - 1 - part;
+
+  if (GET_CODE (op) == CONST_INT)
+    {
+      unsigned HOST_WIDE_INT value = (unsigned HOST_WIDE_INT) INTVAL (op);
+      return ((value >> (8 * part)) & 0xff);
+    }
+  else if (GET_CODE (op) == CONST_DOUBLE
+           && GET_MODE (op) == VOIDmode)
+    {
+      unsigned HOST_WIDE_INT value;
+      if (part < HOST_BITS_PER_WIDE_INT / 8)
+        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+      else
+        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op),
+        part -= HOST_BITS_PER_WIDE_INT / 8;
+
+      return ((value >> (8 * part)) & 0xff); 
+    }
+
+  abort ();
+}
+
 
 /* Change optimizations to be performed, depending on the 
    optimization level.
@@ -360,6 +583,13 @@ optimization_options (level, size)
 #endif
 }
 
+void
+override_options ()
+{
+  /* Acquire a unique set number for our register saves and restores.  */
+  s390_sr_alias_set = new_alias_set ();
+}
+
 
 /* Map for smallest class containing reg regno.  */
 
@@ -372,7 +602,7 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
   FP_REGS,      FP_REGS,   FP_REGS,   FP_REGS,
   FP_REGS,      FP_REGS,   FP_REGS,   FP_REGS,
   FP_REGS,      FP_REGS,   FP_REGS,   FP_REGS,
-  ADDR_REGS,    NO_REGS 
+  ADDR_REGS,    NO_REGS,   ADDR_REGS 
 };
 
 
@@ -388,32 +618,6 @@ const0_operand (op, mode)
   return op == CONST0_RTX (mode);
 }
 
-/* Return true if OP a (const_int 1) operand.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-int
-const1_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
-{
-  return op == CONST1_RTX (mode);
-}
-
-/* Return true if OP needs base and index register.  */
-
-static int 
-base_n_index_p (op)
-     register rtx op;
-{
-  if ((GET_CODE (op) == PLUS) &&
-      (GET_CODE (XEXP (op, 0)) == PLUS ||
-       GET_CODE (XEXP (op, 1)) == PLUS ||
-       GET_CODE (XEXP (op, 1)) == REG ))
-    return 1;
-  return 0;
-}
-
 /* Return true if the mode of operand OP matches MODE.
    If MODE is set to VOIDmode, set it to the mode of OP.  */ 
 
@@ -503,146 +707,90 @@ fp_operand (op, mode)
     return 0;
 }
 
-/* Return true if OP is a valid S operand for an RS, SI or SS type instruction.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-s_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
-{
-  register enum rtx_code code = GET_CODE (op);
-
-  if (! check_mode (op,&mode))
-    return 0;
-
-  if (code == MEM) {
-    if (base_n_index_p (XEXP (op, 0)))
-      return 0;
-  }
-
-  return memory_operand (op, mode);
-}
-
-/* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
-   instruction.
+/* Helper routine to implement s_operand and s_imm_operand.
    OP is the current operation.
-   MODE is the current operation mode.  */
+   MODE is the current operation mode.
+   ALLOW_IMMEDIATE specifies whether immediate operands should
+   be accepted or not.  */
 
-int
-r_or_s_operand (op, mode)
+static int
+general_s_operand (op, mode, allow_immediate)
      register rtx op;
      enum machine_mode mode;
+     int allow_immediate;
 {
-  register enum rtx_code code = GET_CODE (op);
+  struct s390_address addr;
 
+  /* Call general_operand first, so that we don't have to
+     check for many special cases.  */
   if (!general_operand (op, mode))
     return 0;
 
-  if (code == MEM) {
-    if (base_n_index_p (XEXP (op, 0)))
-      return 0;
-    else
-      return memory_operand (op, mode);
-  }
-  return register_operand (op, mode);
-}
+  /* Just like memory_operand, allow (subreg (mem ...))
+     after reload.  */
+  if (reload_completed 
+      && GET_CODE (op) == SUBREG 
+      && GET_CODE (SUBREG_REG (op)) == MEM)
+    op = SUBREG_REG (op);
 
-/* Return true if OP is a valid R or S or immediate operand for 
-   RS, SI or SS type instruction.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-r_or_s_or_im8_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
-{
-  register enum rtx_code code = GET_CODE (op);
+  switch (GET_CODE (op))
+    {
+      /* Constants that we are sure will be forced to the
+         literal pool in reload are OK as s-operand.  Note
+        that we cannot call s390_preferred_reload_class here
+        because it might not be known yet at this point 
+        whether the current function is a leaf or not.  */
+      case CONST_INT:
+      case CONST_DOUBLE:
+       if (!allow_immediate || reload_completed)
+         break;
+       if (!legitimate_reload_constant_p (op))
+         return 1;
+       if (!TARGET_64BIT)
+         return 1;
+       break;
+
+      /* Memory operands are OK unless they already use an
+        index register.  */
+      case MEM:
+       if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
+         return 1;
+       if (s390_decompose_address (XEXP (op, 0), &addr, FALSE) 
+           && !addr.indx)
+         return 1;
+       break;
 
-  if (!general_operand (op, mode))
-    return 0;
+      default:
+       break;
+    }
 
-  if (code == MEM) {
-    if (base_n_index_p (XEXP (op, 0)))
-      return 0;
-    else
-      return memory_operand (op, mode);
-  }
-  return register_operand (op, mode) || immediate_operand (op, mode);
+  return 0;
 }
 
-/* Return true if OP is a valid R or X or 16 bit immediate operand for 
-   RX, RR or RI type instruction.
+/* Return true if OP is a valid S-type operand.
    OP is the current operation.
    MODE is the current operation mode.  */
 
 int
-r_or_x_or_im16_operand (op, mode)
+s_operand (op, mode)
      register rtx op;
      enum machine_mode mode;
 {
-
-  if (! general_operand (op, mode))
-    return 0;
-
-  if (GET_CODE (op) == CONST_INT)
-    return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'));
-  return register_operand (op, mode) || memory_operand (op, mode);
+  return general_s_operand (op, mode, 0);
 }
 
-/* Return true if OP is a valid R or 8 bit immediate operand.
+/* Return true if OP is a valid S-type operand or an immediate 
+   operand that can be addressed as S-type operand by forcing 
+   it into the literal pool.
    OP is the current operation.
    MODE is the current operation mode.  */
 
 int
-r_or_im8_operand (op, mode)
+s_imm_operand (op, mode)
      register rtx op;
      enum machine_mode mode;
 {
-
-  if (!general_operand (op, mode))
-    return 0;
-
-  if (GET_CODE (op) == CONST_INT)
-    return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'));
-  return register_operand (op, mode) || memory_operand (op, mode);
-}
-
-/* Return true if OP is a valid operand for the 'test under mask'
-   instruction with 16 bit immediate.  
-   The value should only have set bits in one halfword.
-   OP is the current operation.
-   MODE is the current operation mode.  */
-
-int
-tmxx_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  rtx con;
-  if (GET_CODE (op) == CONST_INT)
-    return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
-  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == SYMBOL_REF &&
-      CONSTANT_POOL_ADDRESS_P (XEXP (op, 0))) 
-    {
-      con = get_pool_constant (XEXP (op, 0));
-
-      if (GET_CODE (con) == CONST_INT)
-       {
-         unsigned HOST_WIDEST_INT c;
-         
-         c = (unsigned HOST_WIDEST_INT) INTVAL (con);
-         
-         return ((c & 0xffff) ? ((c & 0xffffffffffff0000ULL)==0) : 
-                 (c & 0xffff0000U) ? ((c & 0xffffffff0000ffffULL)==0) :
-                 (c & 0xffff00000000ULL) ? ((c & 0xffff0000ffffffffULL)==0) :
-                 (c & 0xffff000000000000ULL) ? ((c & 0xffffffffffffULL)==0) : 1);
-                 
-       }
-    }
-  return 0;
+  return general_s_operand (op, mode, 1);
 }
 
 /* Return true if OP is a valid operand for the BRAS instruction.
@@ -682,7 +830,7 @@ load_multiple_operation (op, mode)
   int count = XVECLEN (op, 0);
   unsigned int dest_regno;
   rtx src_addr;
-  int i;
+  int i, off;
 
 
   /* Perform a quick check so we don't blow up below.  */
@@ -695,6 +843,23 @@ load_multiple_operation (op, mode)
   dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
   src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
 
+  /* Check, is base, or base + displacement.  */
+
+  if (GET_CODE (src_addr) == REG)
+    off = 0;
+  else if (GET_CODE (src_addr) == PLUS
+          && GET_CODE (XEXP (src_addr, 0)) == REG 
+          && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
+    {
+      off = INTVAL (XEXP (src_addr, 1));
+      src_addr = XEXP (src_addr, 0);
+    }
+  else
+    return 0;
+
+  if (src_addr == frame_pointer_rtx || src_addr == arg_pointer_rtx)
+    return 0;
+
   for (i = 1; i < count; i++)
     {
       rtx elt = XVECEXP (op, 0, i);
@@ -708,7 +873,8 @@ load_multiple_operation (op, mode)
          || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
          || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
          || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
-         || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
+         || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))
+            != off + i * UNITS_PER_WORD)
        return 0;
     }
 
@@ -725,10 +891,10 @@ store_multiple_operation (op, mode)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  int count = XVECLEN (op, 0) - 1;
+  int count = XVECLEN (op, 0);
   unsigned int src_regno;
   rtx dest_addr;
-  int i;
+  int i, off;
 
   /* Perform a quick check so we don't blow up below.  */
   if (count <= 1
@@ -740,6 +906,23 @@ store_multiple_operation (op, mode)
   src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
   dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
 
+  /* Check, is base, or base + displacement.  */
+
+  if (GET_CODE (dest_addr) == REG)
+    off = 0;
+  else if (GET_CODE (dest_addr) == PLUS
+          && GET_CODE (XEXP (dest_addr, 0)) == REG 
+          && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
+    {
+      off = INTVAL (XEXP (dest_addr, 1));
+      dest_addr = XEXP (dest_addr, 0);
+    }
+  else
+    return 0;
+
+  if (dest_addr == frame_pointer_rtx || dest_addr == arg_pointer_rtx)
+    return 0;
+
   for (i = 1; i < count; i++)
     {
       rtx elt = XVECEXP (op, 0, i);
@@ -753,7 +936,8 @@ store_multiple_operation (op, mode)
          || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
          || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
          || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
-         || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
+         || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
+            != off + i * UNITS_PER_WORD)
        return 0;
     }
   return 1;
@@ -800,8 +984,7 @@ int
 legitimate_pic_operand_p (op)
      register rtx op;
 {
-  /* All non-symbolic constants that made it 
-     up to here are fine.  */
+  /* Accept all non-symbolic constants.  */
   if (!SYMBOLIC_CONST (op))
     return 1;
 
@@ -821,13 +1004,7 @@ int
 legitimate_constant_p (op)
      register rtx op;
 {
-  /* Reject doubles and integers out of range.  */
-  if (GET_CODE (op) == CONST_DOUBLE ||
-      (GET_CODE (op) == CONST_INT &&
-       (INTVAL (op) < -32768 || INTVAL (op) > 32767)))
-    return 0;
-
-  /* Accept all other non-symbolic constants.  */
+  /* Accept all non-symbolic constants.  */
   if (!SYMBOLIC_CONST (op))
     return 1;
 
@@ -847,6 +1024,93 @@ legitimate_constant_p (op)
   return 0;
 }
 
+/* Returns true if the constant value OP is a legitimate general
+   operand during and after reload.  The difference to 
+   legitimate_constant_p is that this function will not accept
+   a constant that would need to be forced to the literal pool
+   before it can be used as operand.  */
+
+int
+legitimate_reload_constant_p (op)
+     register rtx op;
+{
+  /* Accept l(g)hi operands.  */
+  if (GET_CODE (op) == CONST_INT
+      && CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
+    return 1;
+
+  /* Accept lliXX operands.  */
+  if (TARGET_64BIT
+      && s390_single_hi (op, DImode, 0) >= 0)
+  return 1;
+
+  /* Accept larl operands.  */
+  if (TARGET_64BIT
+      && larl_operand (op, VOIDmode))
+    return 1;
+
+  /* If reload is completed, and we do not already have a
+     literal pool, and OP must be forced to the literal 
+     pool, then something must have gone wrong earlier.
+     We *cannot* force the constant any more, because the
+     prolog generation already decided we don't need to 
+     set up the base register.  */
+  if (reload_completed && !regs_ever_live[BASE_REGISTER])
+    abort ();
+
+  /* Everything else cannot be handled without reload.  */
+  return 0;
+}
+
+/* Given an rtx OP being reloaded into a reg required to be in class CLASS,
+   return the class of reg to actually use.  */
+
+enum reg_class
+s390_preferred_reload_class (op, class)
+     rtx op;
+     enum reg_class class;
+{
+  /* This can happen if a floating point constant is being
+     reloaded into an integer register.  Leave well alone.  */
+  if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+      && class != FP_REGS)
+    return class;
+
+  switch (GET_CODE (op))
+    {
+      /* Constants we cannot reload must be forced into the
+        literal pool.  For constants we *could* handle directly,
+        it might still be preferable to put them in the pool and
+        use a memory-to-memory instruction.
+
+        However, try to avoid needlessly allocating a literal
+        pool in a routine that wouldn't otherwise need any.
+        Heuristically, we assume that 64-bit leaf functions
+        typically don't need a literal pool, all others do.  */
+      case CONST_DOUBLE:
+      case CONST_INT:
+       if (!legitimate_reload_constant_p (op))
+         return NO_REGS;
+
+       if (TARGET_64BIT && current_function_is_leaf)
+         return class;
+
+       return NO_REGS;
+
+      /* If a symbolic constant or a PLUS is reloaded,
+        it is most likely being used as an address.  */
+      case PLUS:
+      case LABEL_REF:
+      case SYMBOL_REF:
+      case CONST:
+        return ADDR_REGS;
+
+      default:
+       break;
+    }
+
+  return class;
+}
 
 /* Decompose a RTL expression ADDR for a memory address into
    its components, returned in OUT.  The boolean STRICT 
@@ -1063,14 +1327,16 @@ legitimate_la_operand_p (op)
   if (addr.base && GET_CODE (addr.base) == REG)
     {
       if (REGNO (addr.base) == BASE_REGISTER
-          || REGNO (addr.base) == STACK_POINTER_REGNUM)
+         || REGNO (addr.base) == STACK_POINTER_REGNUM
+         || REGNO (addr.base) == FRAME_POINTER_REGNUM)
         return TRUE;
     }
 
   if (addr.indx && GET_CODE (addr.indx) == REG)
     {
       if (REGNO (addr.indx) == BASE_REGISTER
-          || REGNO (addr.indx) == STACK_POINTER_REGNUM)
+          || REGNO (addr.indx) == STACK_POINTER_REGNUM
+         || REGNO (addr.base) == FRAME_POINTER_REGNUM)
         return TRUE;
     }
 
@@ -1364,7 +1630,7 @@ emit_pic_move (operands, mode)
      rtx *operands;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+  rtx temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
 
   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
     operands[1] = force_reg (Pmode, operands[1]);
@@ -1532,7 +1798,7 @@ print_operand_address (file, addr)
   struct s390_address ad;
 
   if (!s390_decompose_address (addr, &ad, TRUE))
-    output_operand_lossage ("cannot decompose address.\n");
+    output_operand_lossage ("Cannot decompose address.");
  
   if (ad.disp)
     s390_output_symbolic_const (file, ad.disp);
@@ -1657,15 +1923,26 @@ print_operand (file, x, code)
 
     case CONST_INT:
       if (code == 'b')
-        fprintf (file, "%d", (int)(INTVAL (x) & 0xff));
-      else if (code == 'X')
-        fprintf (file, "%d", (int)(INTVAL (x) & 0xff));
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
+      else if (code == 'x')
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffff);
+      else if (code == 'h')
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xffff) ^ 0x8000) - 0x8000);
+      else
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+      break;
+
+    case CONST_DOUBLE:
+      if (GET_MODE (x) != VOIDmode)
+        abort ();
+      if (code == 'b')
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xff);
       else if (code == 'x')
-        fprintf (file, "0x%x", (int)(INTVAL (x) & 0xffff));
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xffff);
       else if (code == 'h')
-        fprintf (file, "%d", (int)(INTVAL (x) << 16) >> 16);
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((CONST_DOUBLE_LOW (x) & 0xffff) ^ 0x8000) - 0x8000);
       else
-        fprintf (file, "%d", (int)INTVAL (x));
+        abort ();
       break;
 
     default:
@@ -1694,6 +1971,13 @@ reg_used_in_mem_p (regno, x)
                             XEXP (x, 0), 0))
        return 1;
     }
+  else if (code == SET 
+          && GET_CODE (SET_DEST (x)) == PC)
+    {
+      if (refers_to_regno_p (regno, regno+1,
+                            SET_SRC (x), 0))
+       return 1;
+    }
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
@@ -1718,7 +2002,7 @@ addr_generation_dependency_p (dep_rtx, insn)
      rtx dep_rtx; 
      rtx insn;
 {
-  rtx target;
+  rtx target, pat;
 
   if (GET_CODE (dep_rtx) == SET)
     {
@@ -1729,11 +2013,22 @@ addr_generation_dependency_p (dep_rtx, insn)
          int regno = REGNO (target);
 
          if (get_attr_type (insn) == TYPE_LA)
-           return refers_to_regno_p (regno, regno+1,
-                                     SET_SRC (PATTERN (insn)), 0);
-         else if (get_attr_atype (insn) == ATYPE_MEM)
-           return reg_used_in_mem_p (regno, PATTERN (insn));
-       }
+           {
+             pat = PATTERN (insn);
+             if (GET_CODE (pat) == PARALLEL)
+               {
+                 if (XVECLEN (pat, 0) != 2)
+                   abort();
+                 pat = XVECEXP (pat, 0, 0);
+               }
+             if (GET_CODE (pat) == SET)
+               return refers_to_regno_p (regno, regno+1, SET_SRC (pat), 0);
+             else
+               abort();
+           }
+         else if (get_attr_atype (insn) == ATYPE_MEM)
+           return reg_used_in_mem_p (regno, PATTERN (insn));
+       }
     }
   return 0;
 }
@@ -1839,6 +2134,14 @@ s390_adjust_priority (insn, priority)
       if (priority >= 0 && priority < 0x01000000)
        priority <<= 3;
       break;
+    case TYPE_LM:
+      /* LM in epilogue should never be scheduled. This
+        is due to literal access done in function body.
+        The usage of register 13 is not mentioned explicitly,
+        leading to scheduling 'LM' accross this instructions.  
+      */ 
+      priority = 0x7fffffff;
+      break;
     }
   
   return priority;
@@ -2114,8 +2417,6 @@ s390_final_chunkify (chunkify)
   int addr, naddr = 0, uids;
   int chunk_max = 0;
 
-  const char *asms;
-
   int size = insn_current_address;
 
   int *ltorg_uids;
@@ -2171,19 +2472,6 @@ s390_final_chunkify (chunkify)
              warning ("no code label found");
            }
        } 
-      else if (GET_CODE (PATTERN (insn)) == ASM_INPUT && !TARGET_64BIT) 
-       {
-         asms = XSTR (PATTERN (insn),0);
-         
-         if ((memcmp (asms,".section",8) == 0) ||
-             (memcmp (asms,".text",5) == 0)    ||
-             (memcmp (asms,"\t.section",9) == 0) ||
-             (memcmp (asms,"\t.text",6) == 0))  {
-           ltorg_uids[max_ltorg++] = INSN_UID (insn);
-           INSN_ADDRESSES_NEW (emit_insn_before (gen_rtx_ASM_INPUT (VOIDmode,
-                                          ".align 4"), insn), -1);
-         }
-       }
     }
   ltorg_uids[max_ltorg] = 0;
   for (insn=get_insns (),uids=0; insn;insn = next_real_insn (insn)) 
@@ -2253,19 +2541,6 @@ s390_dump_literal_pool (act_insn, stop)
   function_section (current_function_decl);
 }
 
-
-#ifdef DWARF2_DEBUGGING_INFO
-extern char *dwarf2out_cfi_label PARAMS ((void));
-#endif
-
-/* Flag set in prologue, used in epilog to know
-   if stack is allocated or not.  */
-static int leaf_function_flag;
-
-/* Symbol references needed by the profile code;
-   set up by the function prologue routine if necessary.  */
-rtx s390_profile[10];
-
 /* Number of elements of current constant pool.  */
 int s390_nr_constants;
 
@@ -2285,111 +2560,14 @@ save_fprs_p ()
   return 0;
 }
 
-/* Return true if urrent function is a leaf function, 
-   without automatics, alloca or vararg stuff.  */
-
-static int
-cur_is_leaf_function ()
-{
-  int lsize =  get_frame_size () + current_function_outgoing_args_size
-    + save_fprs_p () * 64;
-
-  if (leaf_function_p () && ((lsize) == 0) &&
-      ! (current_function_calls_alloca) &&
-      ! (current_function_stdarg) && ! (current_function_varargs))
-    return 1;
-  return 0;
-}
-
-/* Return offset between argument pointer and frame pointer 
-   initially after prologue.  */
-
-int 
-s390_arg_frame_offset ()
-{
-  int lsize =  get_frame_size () + current_function_outgoing_args_size
-    + save_fprs_p () * 64;
-
-  if (cur_is_leaf_function ())
-    return STACK_POINTER_OFFSET;
-  else
-    return 2*STACK_POINTER_OFFSET + lsize;
-}
-
-/* Output code to stdio stream FILE to save floating point 
-   registers on current stack, at offset OFFSET to the frame
-   pointer register FP.  */
-
-static int 
-save_fprs (file, offset, fp)
-     FILE *file;
-     long offset;
-     int fp;
-{
-  int i;
-
-  if (!TARGET_64BIT)
-    return 0;
-
-  for (i=24; i<=31; i++) 
-    {
-      if (regs_ever_live[i] == 1)
-       {
-         fprintf (file, "\tstd\t%s,%ld(%s)\n", reg_names[i], 
-                  (i-24) * 8 + offset, reg_names[fp]); 
-       }
-    }
-
-  return 1;
-}
-
-/* Output code to stdio stream FILE to restore floating point 
-   registers from current stack, at offset OFFSET to the frame
-   pointer register FP.  */
-
-static int 
-restore_fprs (file, offset, fp)
-     FILE *file;
-     long offset;
-     int fp;
-{
-  int i;
-
-  if (!TARGET_64BIT)
-    return 0;
-
-  if (!save_fprs_p ())
-    return 0;
-
-  if (offset < 0) 
-    {
-      fp = 1;
-      offset = 0;
-      fprintf (file, "\tlgr\t%s,%s\n", reg_names[fp], 
-              reg_names[STACK_POINTER_REGNUM]); 
-      fprintf (file, "\taghi\t%s,-64\n", reg_names[fp]); 
-    }
-
-  for (i=24; i<=31; i++) 
-    {
-      if (regs_ever_live[i] == 1)
-       {
-         fprintf (file, "\tld\t%s,%ld(%s)\n", reg_names[i], 
-                  (i-24) * 8 + offset, reg_names[fp]); 
-       }
-    }
-
-  return 1;
-}
-
 /* Output main constant pool to stdio stream FILE.  */ 
 
-static void
+void
 s390_output_constant_pool (file)
      FILE *file;
 {
   /* Output constant pool.  */
-  if (s390_nr_constants || regs_ever_live[BASE_REGISTER])
+  if (s390_nr_constants)
     {
       s390_pool_count = 0;
       if (TARGET_64BIT)
@@ -2410,66 +2588,150 @@ s390_output_constant_pool (file)
               s390_pool_count);
       if (TARGET_64BIT)
        function_section (current_function_decl);
-      
-      regs_ever_live[BASE_REGISTER] = 1;
     }
 }
 
-/* Add constant CTX to the constant pool at a late time 
-   (after the initial pass to count the number of constants
-   was already done).  Returns the resulting constant 
-   pool reference.  */
+/* Find first call clobbered register unsused in a function.
+   This could be used as base register in a leaf function
+   or for holding the return address before epilogue.  */
 
-static rtx
-s390_force_const_mem_late (cst)
-     rtx cst;
+static int
+find_unused_clobbered_reg ()
+{
+  int i;
+  for (i = 0; i < 6; i++)
+    if (!regs_ever_live[i])
+      return i;
+  return 0;
+}
+
+/* Fill FRAME with info about frame of current function.  */
+
+static void
+s390_frame_info (frame)
+     struct s390_frame *frame;
+{
+  int i, j;
+  HOST_WIDE_INT fsize = get_frame_size ();
+
+  if (fsize > 0x7fff0000)
+    fatal_error ("Total size of local variables exceeds architecture limit.");
+
+  /* fprs 8 - 15 are caller saved for 64 Bit ABI.  */
+  frame->save_fprs_p = save_fprs_p ();
+
+  frame->frame_size = fsize + frame->save_fprs_p * 64;
+
+  /* Does function need to setup frame and save area.  */
+  
+  if (! current_function_is_leaf
+      || frame->frame_size > 0
+      || current_function_calls_alloca 
+      || current_function_stdarg
+      || current_function_varargs)
+    frame->frame_size += STARTING_FRAME_OFFSET;
+
+  /* If we need to allocate a frame, the stack pointer is changed.  */ 
+
+  if (frame->frame_size > 0)
+    regs_ever_live[STACK_POINTER_REGNUM] = 1;
+
+  /* If there is (possibly) any pool entry, we need to 
+     load base register.  */
+
+  if (get_pool_size () 
+      || !CONST_OK_FOR_LETTER_P (frame->frame_size, 'K')
+      || (!TARGET_64BIT && current_function_uses_pic_offset_table))
+    regs_ever_live[BASE_REGISTER] = 1; 
+
+  /* If we need the GOT pointer, remember to save/restore it.  */
+
+  if (current_function_uses_pic_offset_table)
+    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+
+  /* Frame pointer needed.   */
+    
+  frame->frame_pointer_p = frame_pointer_needed;
+
+  /* Find first and last gpr to be saved.  */
+  
+  for (i = 6; i < 16; i++)
+    if (regs_ever_live[i])
+      break;
+
+  for (j = 15; j > i; j--)
+    if (regs_ever_live[j])
+      break;
+  
+  if (i == 16)
+    {
+      /* Nothing to save / restore.  */ 
+      frame->first_save_gpr = -1;
+      frame->first_restore_gpr = -1;
+      frame->last_save_gpr = -1;
+      frame->return_reg_saved_p = 0;
+    }
+  else
+    {
+      /* Save / Restore from gpr i to j.  */
+      frame->first_save_gpr = i;
+      frame->first_restore_gpr = i;
+      frame->last_save_gpr  = j;
+      frame->return_reg_saved_p = (j >= RETURN_REGNUM && i <= RETURN_REGNUM);
+    }
+
+  if (current_function_stdarg || current_function_varargs)
+    {
+      /* Varargs function need to save from gpr 2 to gpr 15.  */
+      frame->first_save_gpr = 2;
+    }
+}
+
+/* Return offset between argument pointer and frame pointer 
+   initially after prologue.  */
+
+int 
+s390_arg_frame_offset ()
 {
-  cst = force_const_mem (Pmode, cst);
+  struct s390_frame frame;
 
-  s390_nr_constants++;
-  regs_ever_live[BASE_REGISTER] = 1;
+  /* Compute frame_info.  */
 
-  emit_insn_before (gen_rtx (USE, Pmode, cst), get_insns ());
+  s390_frame_info (&frame);
 
-  return cst;
+  return frame.frame_size + STACK_POINTER_OFFSET;
 }
 
-/* Add a reference to the symbol NAME to the constant pool.
-   FUNC specifies whether NAME refers to a function, while
-   GLOBAL specifies whether NAME is a global symbol.  Depending
-   on these flags, the appopriate PLT or GOT references are
-   generated.  Returns the constant pool reference.  */
+/* Emit insn to save fpr REGNUM at offset OFFSET relative
+   to register BASE.  Return generated insn.  */ 
 
 static rtx
-s390_force_const_mem_symbol (name, func, global)
-     const char *name;
-     int func;
-     int global;
+save_fpr (base, offset, regnum)
+     rtx base;
+     int offset;
+     int regnum;     
 {
-  rtx symbol;
+  rtx addr;
+  addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
+  set_mem_alias_set (addr, s390_sr_alias_set);
 
-  if (TARGET_64BIT)
-    abort ();
+  return emit_move_insn (addr, gen_rtx_REG (DFmode, regnum));
+}
 
-  symbol = gen_rtx (SYMBOL_REF, Pmode, name);
-  SYMBOL_REF_FLAG (symbol) = !global;
+/* Emit insn to restore fpr REGNUM from offset OFFSET relative
+   to register BASE.  Return generated insn.  */ 
 
-  if (flag_pic)
-    {
-      if (global)
-        {
-          current_function_uses_pic_offset_table = 1;
-          symbol = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, symbol), func? 114 : 112);
-          symbol = gen_rtx_CONST (VOIDmode, symbol);
-        }
-      else
-        {
-          symbol = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, symbol), 100);
-          symbol = gen_rtx_CONST (VOIDmode, symbol);
-        }
-    }
+static rtx
+restore_fpr (base, offset, regnum)
+     rtx base;
+     int offset;
+     int regnum;
+{
+  rtx addr;
+  addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
+  set_mem_alias_set (addr, s390_sr_alias_set);
 
-  return s390_force_const_mem_late (symbol);
+  return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
 }
 
 /* Output the function prologue assembly code to the 
@@ -2478,401 +2740,396 @@ s390_force_const_mem_symbol (name, func, global)
 
 void
 s390_function_prologue (file, lsize)
-     FILE *file;
-     HOST_WIDE_INT lsize;
+     FILE *file ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT lsize ATTRIBUTE_UNUSED;
 {
-  extern int profile_label_no;
-  int i, j;
-  long frame_size;
-  rtx stack_label = 0, got_label = 0;
-  char *l;
-  const char *const b64 = TARGET_64BIT ? "g" : "";
+  if (get_pool_size () > S390_POOL_MAX)
+    s390_final_chunkify (1);
+  else
+    s390_final_chunkify (0);
+}
 
-  /* Check for too large size of local variables */
+/* Output the function epilogue assembly code to the 
+   stdio stream FILE.  The local frame size is passed
+   in LSIZE.  */
 
-  if (lsize > 0x7fff0000)
-    fatal_error ("total size of local variables exceeds architecture limit");
+void
+s390_function_epilogue (file, lsize)
+     FILE *file ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT lsize ATTRIBUTE_UNUSED;
+{
+  current_function_uses_pic_offset_table = 0;
+  s390_pool_start_insn = NULL_RTX;
+  s390_pool_count = -1;
+  s390_function_count++;
+}
 
-  /* Profile code (-p, -a, -ax needs some literals).  */
+/* Expand the prologue into a bunch of separate insns.  */
 
-  if (profile_flag && !TARGET_64BIT)
-    {
-      static char label[128];
-      sprintf (label, "%sP%d", LPREFIX, profile_label_no);
+void
+s390_emit_prologue ()
+{
+  struct s390_frame frame;
+  rtx insn, addr;
+  rtx temp_reg;
+  int i, limit;
 
-      s390_profile[4] = s390_force_const_mem_symbol ("_mcount", 1, 1);
-      s390_profile[9] = s390_force_const_mem_symbol (label, 0, 0);
-    }
+  /* Compute frame_info.  */
 
-  if (get_pool_size () > S390_POOL_MAX)
-    s390_final_chunkify (1);
+  s390_frame_info (&frame);
+
+  /* Choose best register to use for temp use within prologue.  */
+  
+  if (frame.return_reg_saved_p
+      && !has_hard_reg_initial_val (Pmode, RETURN_REGNUM))
+    temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
   else
-    s390_final_chunkify (0);
+    temp_reg = gen_rtx_REG (Pmode, 1);
 
-  if (current_function_uses_pic_offset_table)
-    regs_ever_live[12] = 1;
+  /* Save call saved gprs.  */
 
-  if (!TARGET_64BIT && current_function_uses_pic_offset_table)
+  if (frame.first_save_gpr != -1)
     {
-      got_label = s390_force_const_mem_symbol ("_GLOBAL_OFFSET_TABLE_", 0, 0);
-    }
+      addr = plus_constant (stack_pointer_rtx, 
+                           frame.first_save_gpr * UNITS_PER_WORD);
+      addr = gen_rtx_MEM (Pmode, addr);
+      set_mem_alias_set (addr, s390_sr_alias_set);
 
-  if ((frame_size = 
-       STARTING_FRAME_OFFSET + lsize + save_fprs_p () * 64) > 0x7fff)
-    {
-      stack_label = s390_force_const_mem_late (GEN_INT (frame_size));
-    }
+      if (frame.first_save_gpr != frame.last_save_gpr )
+       {
+         insn = emit_insn (gen_store_multiple (addr,
+                             gen_rtx_REG (Pmode, frame.first_save_gpr),
+                             GEN_INT (frame.last_save_gpr 
+                                      - frame.first_save_gpr + 1)));
 
-  if (!optimize)
-    {
-      /* Stupid register allocation is stupid ...
-         It does not always recognize the base register is used.  */
-      
-      regs_ever_live[BASE_REGISTER] = 1;
-    }
-
- if (cur_is_leaf_function ())
-   {
-      leaf_function_flag = 1;
-      fprintf (file, "%s\tleaf function\n", ASM_COMMENT_START);
-      fprintf (file, "%s\thas varargs             %d\n", ASM_COMMENT_START,
-              current_function_stdarg);
-      fprintf (file, "%s\tincoming args (stack)   %d\n", ASM_COMMENT_START,
-              current_function_args_size);
-      fprintf (file, "%s\tfunction length         %d\n", ASM_COMMENT_START,
-              insn_current_address);
-      fprintf (file, "%s\tregister live           ", ASM_COMMENT_START);
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       fprintf (file, "%d", regs_ever_live[i]);
-      fputc   ('\n',file);
-      
-      /* Save gprs 6 - 15 and fprs 4 and 6.  */
-      for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+         /* Set RTX_FRAME_RELATED_P for all sets within store multiple.  */
 
-      if (s390_nr_constants || regs_ever_live[13] || i != 13)
-       {
-         fprintf (file, "\tstm%s\t%s,%s,%d(%s)\n", 
-                         b64, reg_names[i], reg_names[13],
-                         i * UNITS_PER_WORD,
-                        reg_names[STACK_POINTER_REGNUM]);
-#ifdef INCOMING_RETURN_ADDR_RTX
-         if (dwarf2out_do_frame ())
+         limit = XVECLEN (PATTERN (insn), 0);
+         
+         for (i = 0; i < limit; i++)
            {
-             l = dwarf2out_cfi_label ();
-             dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, 
-                                STACK_POINTER_OFFSET);
-             for (j = i; j <= 14; j++)
-               dwarf2out_reg_save (l, j, (TARGET_64BIT ? (j-20) : (j-24))
-                                   * UNITS_PER_WORD);
-             if (regs_ever_live[18])
-               dwarf2out_reg_save (l, 18, -16);
-             if (regs_ever_live[19])
-               dwarf2out_reg_save (l, 19, -8);
+             rtx x = XVECEXP (PATTERN (insn), 0, i);
+             
+             if (GET_CODE (x) == SET)
+               RTX_FRAME_RELATED_P (x) = 1;
            }
-#endif
        }
-
-      s390_output_constant_pool (file);
-
-      /* Save fprs.  */
-
-      if (!TARGET_64BIT)
+      else
        {
-         if (regs_ever_live[18])
-           fprintf (file, "\tstd\t4,80(%s)\n", reg_names[STACK_POINTER_REGNUM]);
-         if (regs_ever_live[19])
-           fprintf (file, "\tstd\t6,88(%s)\n", reg_names[STACK_POINTER_REGNUM]);
+         insn = emit_move_insn (addr, 
+                                gen_rtx_REG (Pmode, frame.first_save_gpr));
        }
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
-  else
-    {                          /* No leaf function.  */
-      fprintf (file, "%s\tleaf function           %d\n", ASM_COMMENT_START,
-              leaf_function_p ());
-      fprintf (file, "%s\tautomatics              %d\n", ASM_COMMENT_START,
-              (int)lsize);
-      fprintf (file, "%s\toutgoing args           %d\n", ASM_COMMENT_START,
-              current_function_outgoing_args_size);
-      fprintf (file, "%s\tneed frame pointer      %d\n", ASM_COMMENT_START,
-              frame_pointer_needed);
-      fprintf (file, "%s\tcall alloca             %d\n", ASM_COMMENT_START,
-              current_function_calls_alloca);
-      fprintf (file, "%s\thas varargs             %d\n", ASM_COMMENT_START,
-              current_function_stdarg || current_function_varargs);
-      fprintf (file, "%s\tincoming args (stack)   %d\n", ASM_COMMENT_START,
-              current_function_args_size);
-      fprintf (file, "%s\tfunction length         %d\n", ASM_COMMENT_START,
-              insn_current_address);
-      fprintf (file, "%s\tregister live           ", ASM_COMMENT_START);
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       fprintf (file, "%d", regs_ever_live[i]);
-      fputc   ('\n',file);
-
-      /* Save gprs 6 - 15 and fprs 4 and 6.  */
+
+  /* Dump constant pool and set constant pool register (13).  */
+  insn = emit_insn (gen_lit ());
+  
+  /* Save fprs for variable args.  */
+
+  if (current_function_stdarg || current_function_varargs)
+    {
+      /* Save fpr 0 and 2.  */ 
+
+      save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 32, 16); 
+      save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 24, 17); 
       
-      if (current_function_stdarg || current_function_varargs)
-       {
-         i = 2;
-       }
-      else
+      if (TARGET_64BIT)
        {
-         for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+         /* Save fpr 4 and 6.  */
+         save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 16, 18); 
+         save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 8, 19); 
        }
+    }
 
-      fprintf (file, "\tstm%s\t%s,%s,%d(%s)\n", 
-                     b64, reg_names[i], reg_names[15], i * UNITS_PER_WORD,
-                    reg_names[STACK_POINTER_REGNUM]);
+  /* Save fprs 4 and 6 if used (31 bit ABI).  */
 
-#ifdef INCOMING_RETURN_ADDR_RTX
-      if (dwarf2out_do_frame ())
+  if (!TARGET_64BIT)
+    {
+      /* Save fpr 4 and 6.  */
+      if (regs_ever_live[18])
        {
-         l = dwarf2out_cfi_label ();
-         dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, STACK_POINTER_OFFSET);
-         for (j = i; j <= 15; j++)
-           dwarf2out_reg_save (l, j, (TARGET_64BIT ? (j-20) : (j-24)) *
-                               UNITS_PER_WORD);
-         if (regs_ever_live[18])
-           dwarf2out_reg_save (l, 18, -16);
-         if (regs_ever_live[19])
-           dwarf2out_reg_save (l, 19, -8);
+         insn = save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 16, 18);
+         RTX_FRAME_RELATED_P (insn) = 1;
        }
-#endif
+      if (regs_ever_live[19]) 
+       {
+         insn = save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 8, 19); 
+         RTX_FRAME_RELATED_P (insn) = 1;
+       }
+    }
 
-      s390_output_constant_pool (file);
+  /* Decrement stack pointer.  */
 
-      /* Save fprs.  */
+  if (frame.frame_size > 0)
+    {
+      rtx frame_off = GEN_INT (-frame.frame_size);
 
-      if (current_function_stdarg || current_function_varargs)
-       {
-         fprintf (file, "\tstd\t%s,%d(%s)\n", 
-                  reg_names[16],
-                  STACK_POINTER_OFFSET-32,
-                  reg_names[STACK_POINTER_REGNUM]);
-         fprintf (file, "\tstd\t%s,%d(%s)\n",
-                  reg_names[17],
-                  STACK_POINTER_OFFSET-24,
-                  reg_names[STACK_POINTER_REGNUM]);
-         if (TARGET_64BIT)
-           {
-             fprintf (file, "\tstd\t%s,%d(%s)\n", 
-                      reg_names[18],
-                      STACK_POINTER_OFFSET-16,
-                      reg_names[STACK_POINTER_REGNUM]);
-             fprintf (file, "\tstd\t%s,%d(%s)\n", 
-                      reg_names[19],
-                      STACK_POINTER_OFFSET-8,
-                      reg_names[STACK_POINTER_REGNUM]);
-           }
-       }
-      if (!TARGET_64BIT)
+      /* Save incoming stack pointer into temp reg.  */
+      
+      if (TARGET_BACKCHAIN || frame.save_fprs_p)
        {
-         if (regs_ever_live[18])
-           fprintf (file, "\tstd\t%s,%d(%s)\n", 
-                    reg_names[18],
-                    STACK_POINTER_OFFSET-16,
-                    reg_names[STACK_POINTER_REGNUM]);
-         if (regs_ever_live[19])
-           fprintf (file, "\tstd\t%s,%d(%s)\n",
-                    reg_names[19],
-                    STACK_POINTER_OFFSET-8,
-                    reg_names[STACK_POINTER_REGNUM]);
+         insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
        }
-
       
-      if (save_fprs_p () && frame_size > 4095) 
+      /* Substract frame size from stack pointer.  */
+
+      frame_off = GEN_INT (-frame.frame_size);
+      if (!CONST_OK_FOR_LETTER_P (-frame.frame_size, 'K'))
+       frame_off = force_const_mem (Pmode, frame_off);
+
+      insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      REG_NOTES (insn) = 
+       gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+                          gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                                  gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+                                  GEN_INT (-frame.frame_size))),
+                          REG_NOTES (insn));
+
+      /* Set backchain.  */
+      
+      if (TARGET_BACKCHAIN)
        {
-         int fp = 1;
-         fprintf (file, "\tlgr\t%s,%s\n", reg_names[fp], 
-                  reg_names[STACK_POINTER_REGNUM]); 
-         fprintf (file, "\taghi\t%s,-64\n", reg_names[fp]);
-         save_fprs (file, 0, fp);
+         addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
+         set_mem_alias_set (addr, s390_sr_alias_set);
+         insn = emit_insn (gen_move_insn (addr, temp_reg));
        }
+    }
 
-      /* Decrement stack.  */
+  /* Save fprs 8 - 15 (64 bit ABI).  */
+  
+  if (frame.save_fprs_p)
+    {
+      insn = emit_insn (gen_add2_insn (temp_reg, GEN_INT(-64)));
 
-      if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
-                              || frame_pointer_needed
-                              || current_function_calls_alloca))
-       {
+      for (i = 24; i < 32; i++)
+       if (regs_ever_live[i])
+         {
+           rtx addr = plus_constant (stack_pointer_rtx, 
+                                     frame.frame_size - 64 + (i-24)*8);
+
+           insn = save_fpr (temp_reg, (i-24)*8, i);
+           RTX_FRAME_RELATED_P (insn) = 1;
+           REG_NOTES (insn) = 
+             gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+               gen_rtx_SET (VOIDmode, 
+                            gen_rtx_MEM (DFmode, addr),
+                            gen_rtx_REG (DFmode, i)),
+               REG_NOTES (insn));
+         }
+    }
+           
+  /* Set frame pointer, if needed.  */
+  
+  if (frame.frame_pointer_p)
+    {
+      insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
-         fprintf (file, "\tl%sr\t%s,%s\n", b64, 
-                        reg_names[1], reg_names[STACK_POINTER_REGNUM]);
-       }
+  /* Set up got pointer, if needed.  */
+  
+  if (current_function_uses_pic_offset_table)
+    {
+      rtx got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+      SYMBOL_REF_FLAG (got_symbol) = 1;
 
-      if (stack_label)
+      if (TARGET_64BIT)
        {
-         rtx operands[2];
+         insn = emit_insn (gen_movdi (pic_offset_table_rtx,
+                                      got_symbol));             
 
-         operands[0] = stack_pointer_rtx;
-         operands[1] = stack_label;
-         if (TARGET_64BIT)
-           output_asm_insn ("sg\t%0,%1", operands);
-         else
-           output_asm_insn ("s\t%0,%1", operands);
+          /* It can happen that the GOT pointer isn't really needed ...  */
+          REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
+                                               REG_NOTES (insn));
        }
       else
        {
-         fprintf (file, "\ta%shi\t%s,-%ld\n",b64, 
-                  reg_names[STACK_POINTER_REGNUM], frame_size);
-       }
-#ifdef INCOMING_RETURN_ADDR_RTX
-      if (dwarf2out_do_frame ())
-       {
-         if (frame_pointer_needed)
-           dwarf2out_def_cfa ("", HARD_FRAME_POINTER_REGNUM,
-                              STACK_POINTER_OFFSET+frame_size);
-         else
-           dwarf2out_def_cfa ("", STACK_POINTER_REGNUM,
-                              STACK_POINTER_OFFSET+frame_size);
+          got_symbol = gen_rtx_UNSPEC (VOIDmode, 
+                                      gen_rtvec (1, got_symbol), 100);
+          got_symbol = gen_rtx_CONST (VOIDmode, got_symbol);
+         got_symbol = force_const_mem (Pmode, got_symbol);
+         insn = emit_move_insn (pic_offset_table_rtx,
+                                got_symbol);            
+         insn = emit_insn (gen_add2_insn (pic_offset_table_rtx,
+                                          gen_rtx_REG (Pmode, BASE_REGISTER)));
+
+         /* We need the GOT pointer even if we don't know it ...  */
+         emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
        }
-#endif
+    }      
+}
 
+/* Expand the epilogue into a bunch of separate insns. */
 
-      /* Generate backchain.  */
+void
+s390_emit_epilogue ()
+{
+  struct s390_frame frame;
+  rtx frame_pointer, return_reg;
+  int area_bottom, area_top, offset;
+  rtvec p;
 
-      if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
-                              || frame_pointer_needed
-                              || current_function_calls_alloca))
-       {
-         fprintf (file, "\tst%s\t%s,0(%s)\n", 
-                         b64, reg_names[1], reg_names[STACK_POINTER_REGNUM]);
-       }
-    }
+  /* Compute frame_info.  */
+  s390_frame_info (&frame);
+
+  /* Check whether to use frame or stack pointer for restore.  */
 
-  if (frame_pointer_needed)
+  frame_pointer = frame.frame_pointer_p ? 
+    hard_frame_pointer_rtx : stack_pointer_rtx;
+
+  /* Compute which parts of the save area we need to access.  */
+
+  if (frame.first_restore_gpr != -1)
     {
-      fprintf (file, "\tl%sr\t%s,%s\n", b64, 
-                     reg_names[FRAME_POINTER_REGNUM], 
-                     reg_names[STACK_POINTER_REGNUM]);
+      area_bottom = frame.first_restore_gpr * UNITS_PER_WORD;
+      area_top = (frame.last_save_gpr + 1) * UNITS_PER_WORD;
+    }
+  else
+    {
+      area_bottom = INT_MAX;
+      area_top = INT_MIN;
     }
 
-  /* Load GOT if used and emit use insn that optimizer does not
-     erase literal pool entry.  */
-
-  if (current_function_uses_pic_offset_table)
+  if (TARGET_64BIT)
     {
-      rtx operands[3];
-      if (TARGET_64BIT)
+      if (frame.save_fprs_p)
        {
-         fprintf (file, "\tlarl\t%s,_GLOBAL_OFFSET_TABLE_\n",
-                        reg_names[PIC_OFFSET_TABLE_REGNUM]);
+         if (area_bottom > -64)
+           area_bottom = -64;
+         if (area_top < 0)
+           area_top = 0;
        }
-      else
+    }
+  else
+    {
+      if (regs_ever_live[18])
        {
-         operands[0] = gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM);
-         operands[1] = got_label;
-         operands[2] = gen_rtx (REG, Pmode, BASE_REGISTER);
-         output_asm_insn ("l\t%0,%1\n\tar\t%0,%2", operands);
+         if (area_bottom > STACK_POINTER_OFFSET - 16)
+           area_bottom = STACK_POINTER_OFFSET - 16;
+         if (area_top < STACK_POINTER_OFFSET - 8)
+           area_top = STACK_POINTER_OFFSET - 8;
+       }
+      if (regs_ever_live[19])
+       {
+         if (area_bottom > STACK_POINTER_OFFSET - 8)
+           area_bottom = STACK_POINTER_OFFSET - 8;
+         if (area_top < STACK_POINTER_OFFSET)
+           area_top = STACK_POINTER_OFFSET;
        }
     }
-  /* Save FPRs below save area.  */
 
-  if (frame_size <= 4095)
-    save_fprs (file, frame_size - 64, STACK_POINTER_REGNUM);
+  /* Check whether we can access the register save area.  
+     If not, increment the frame pointer as required.  */
 
-  return;
-}
+  if (area_top <= area_bottom)
+    {
+      /* Nothing to restore.  */
+    }
+  else if (frame.frame_size + area_bottom >= 0
+           && frame.frame_size + area_top <= 4096)
+    {
+      /* Area is in range.  */
+      offset = frame.frame_size;
+    }
+  else
+    {
+      rtx insn, frame_off;
 
-/* Output the function epilogue assembly code to the 
-   stdio stream FILE.  The local frame size is passed
-   in LSIZE.  */
+      offset = area_bottom < 0 ? -area_bottom : 0; 
+      frame_off = GEN_INT (frame.frame_size - offset);
 
-void
-s390_function_epilogue (file, lsize)
-     FILE *file;
-     HOST_WIDE_INT lsize;
-{
-/* Register is call clobbered and not used for eh or return.  */
-#define FREE_REG 4
+      if (!CONST_OK_FOR_LETTER_P (INTVAL (frame_off), 'K'))
+       frame_off = force_const_mem (Pmode, frame_off);
 
-  int i;
-  long frame_size;
-  int return_reg = RETURN_REGNUM;
-  int fp, offset;
-  const char *const b64 = TARGET_64BIT ? "g" : "";
+      insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
-  frame_size = STARTING_FRAME_OFFSET + lsize + save_fprs_p () * 64;
-  
-  if (current_function_uses_pic_offset_table)
-    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
-  
-  if (leaf_function_flag)
+  /* Restore call saved fprs.  */
+
+  if (TARGET_64BIT)
     {
-      for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+      int i;
 
-      if (s390_nr_constants || regs_ever_live[13] || i != 13)
-       {
-           fprintf (file, "\tlm%s\t%s,%s,%d(%s)\n", b64, 
-                     reg_names[i], reg_names[13],
-                    UNITS_PER_WORD * i,
-                    reg_names[STACK_POINTER_REGNUM]);
-       }
-      if (!TARGET_64BIT)
-       {
-         if (regs_ever_live[18])
-           fprintf (file, "\tld\t%s,%d(%s)\n", 
-                    reg_names[18],
-                    STACK_POINTER_OFFSET-16,
-                    reg_names[STACK_POINTER_REGNUM]);
-         if (regs_ever_live[19])
-           fprintf (file, "\tld\t%s,%d(%s)\n",
-                    reg_names[19],
-                    STACK_POINTER_OFFSET-8,
-                    reg_names[STACK_POINTER_REGNUM]);
-       }
+      if (frame.save_fprs_p)
+       for (i = 24; i < 32; i++)
+         if (regs_ever_live[i])
+           restore_fpr (frame_pointer, 
+                        offset - 64 + (i-24) * 8, i);
     }
   else
     {
-      for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+      if (regs_ever_live[18])
+       restore_fpr (frame_pointer, offset + STACK_POINTER_OFFSET - 16, 18);
+      if (regs_ever_live[19]) 
+       restore_fpr (frame_pointer, offset + STACK_POINTER_OFFSET - 8, 19);
+    }
 
-      if (frame_size + STACK_POINTER_OFFSET > 4095)    
+  /* Return register.  */
+
+  return_reg = gen_rtx_REG (Pmode, RETURN_REGNUM); 
+
+  /* Restore call saved gprs.  */
+
+  if (frame.first_restore_gpr != -1)
+    {
+      rtx addr;
+
+      /* Fetch return address from stack before load multiple,
+        this will do good for scheduling.  */
+
+      if (frame.last_save_gpr >= RETURN_REGNUM 
+         && frame.first_restore_gpr < RETURN_REGNUM)
        {
-         offset = 0;
-         fp = STACK_POINTER_REGNUM;
+         int return_regnum = find_unused_clobbered_reg();
+         if (!return_regnum)
+           return_regnum = 4;
+         return_reg = gen_rtx_REG (Pmode, return_regnum);
+       
+         addr = plus_constant (frame_pointer, 
+                               offset + RETURN_REGNUM * UNITS_PER_WORD); 
+         addr = gen_rtx_MEM (Pmode, addr);
+         set_mem_alias_set (addr, s390_sr_alias_set);
+         emit_move_insn (return_reg, addr);
        }
-      else if (frame_pointer_needed || current_function_calls_alloca)
+
+      /* ??? As references to the base register are not made
+        explicit in insn RTX code, we have to add a barrier here
+        to prevent incorrect scheduling.  */
+
+      emit_insn (gen_blockage());      
+
+      addr = plus_constant (frame_pointer, 
+                           offset + frame.first_restore_gpr * UNITS_PER_WORD);
+      addr = gen_rtx_MEM (Pmode, addr);
+      set_mem_alias_set (addr, s390_sr_alias_set);
+
+      if (frame.first_restore_gpr != frame.last_save_gpr)
        {
-         offset = frame_size;
-         fp = FRAME_POINTER_REGNUM;
+         emit_insn (gen_load_multiple (
+                      gen_rtx_REG (Pmode, frame.first_restore_gpr),
+                       addr,
+                      GEN_INT (frame.last_save_gpr - frame.first_restore_gpr + 1)));
        }
       else
        {
-         offset = frame_size;
-         fp = STACK_POINTER_REGNUM;
+         emit_move_insn (gen_rtx_REG (Pmode, frame.first_restore_gpr),
+                         addr); 
        }
+    }
 
-      /* Restore from offset below save area.  */
+  /* Return to caller.  */
 
-      if (offset == 0)
-       fprintf (file, "\tl%s\t%s,0(%s)\n", b64, 
-                      reg_names[fp], reg_names[fp]);
-      restore_fprs (file, offset-64, fp);
-      return_reg = FREE_REG;
-      fprintf (file, "\tl%s\t%s,%d(%s)\n", b64, reg_names[return_reg], 
-              UNITS_PER_WORD*RETURN_REGNUM+offset, reg_names[fp]);
-      if (!TARGET_64BIT)
-       {
-         if (regs_ever_live[18])
-           fprintf (file, "\tld\t%s,%d(%s)\n", 
-                    reg_names[18],
-                    offset+STACK_POINTER_OFFSET-16, reg_names[fp]);
-         if (regs_ever_live[19])
-           fprintf (file, "\tld\t%s,%d(%s)\n",
-                    reg_names[19],
-                    offset+STACK_POINTER_OFFSET-8, reg_names[fp]);
-       }
-      fprintf (file, "\tlm%s\t%s,%s,%d(%s)\n", b64, 
-                    reg_names[i], reg_names[15],
-                    (UNITS_PER_WORD * i) + offset, reg_names[fp]);
-    }
+  p = rtvec_alloc (2);
   
-  fprintf (file, "\tbr\t%s\n", reg_names[return_reg]);
-
-  current_function_uses_pic_offset_table = 0;
-  leaf_function_flag = 0;
-  s390_pool_start_insn = NULL_RTX;
-  s390_pool_count = -1;
-  s390_function_count++;
-  return;
+  RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
+  RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
+  emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
 }
 
 
@@ -3369,3 +3626,98 @@ s390_initialize_trampoline (addr, fnaddr, cxt)
                   memory_address (Pmode, 
                   plus_constant (addr, (TARGET_64BIT ? 28 : 16) ))), fnaddr);
 }
+
+/* Return rtx for 64-bit constant formed from the 32-bit subwords
+   LOW and HIGH, independent of the host word size.  */
+
+rtx
+s390_gen_rtx_const_DI (high, low)
+     int high;
+     int low;
+{
+#if HOST_BITS_PER_WIDE_INT >= 64
+  HOST_WIDE_INT val;
+  val = (HOST_WIDE_INT)high;
+  val <<= 32;
+  val |= (HOST_WIDE_INT)low;
+  
+  return GEN_INT (val);
+#else
+#if HOST_BITS_PER_WIDE_INT >= 32
+  return immed_double_const ((HOST_WIDE_INT)low, (HOST_WIDE_INT)high, DImode);
+#else
+  abort ();
+#endif
+#endif
+} 
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+   for profiling a function entry.  */
+
+void
+s390_function_profiler (file, labelno)
+     FILE *file;
+     int labelno;
+{
+  rtx op[7];
+
+  char label[128];
+  sprintf (label, "%sP%d", LPREFIX, labelno);
+
+  fprintf (file, "# function profiler \n");
+
+  op[0] = gen_rtx_REG (Pmode, RETURN_REGNUM);
+  op[1] = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+  op[1] = gen_rtx_MEM (Pmode, plus_constant (op[1], UNITS_PER_WORD));
+
+  op[2] = gen_rtx_REG (Pmode, 1);
+  op[3] = gen_rtx_SYMBOL_REF (Pmode, label);
+  SYMBOL_REF_FLAG (op[3]) = 1;
+
+  op[4] = gen_rtx_SYMBOL_REF (Pmode, "_mcount");
+  if (flag_pic)
+    {
+      op[4] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[4]), 113);
+      op[4] = gen_rtx_CONST (Pmode, op[4]);
+    }
+
+  if (TARGET_64BIT)
+    {
+      output_asm_insn ("stg\t%0,%1", op);
+      output_asm_insn ("larl\t%2,%3", op);
+      output_asm_insn ("brasl\t%0,%4", op);
+      output_asm_insn ("lg\t%0,%1", op);
+    }
+  else if (!flag_pic)
+    {
+      op[6] = gen_label_rtx ();
+
+      output_asm_insn ("st\t%0,%1", op);
+      output_asm_insn ("bras\t%2,%l6", op);
+      output_asm_insn (".long\t%3", op);
+      output_asm_insn (".long\t%4", op);
+      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
+      output_asm_insn ("l\t%0,0(%2)", op);
+      output_asm_insn ("l\t%2,4(%2)", op);
+      output_asm_insn ("basr\t%0,%0", op);
+      output_asm_insn ("l\t%0,%1", op);
+    }
+  else
+    {
+      op[5] = gen_label_rtx ();
+      op[6] = gen_label_rtx ();
+
+      output_asm_insn ("st\t%0,%1", op);
+      output_asm_insn ("bras\t%2,%l6", op);
+      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
+      output_asm_insn (".long\t%3-%l5", op);
+      output_asm_insn (".long\t%4-%l5", op);
+      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
+      output_asm_insn ("lr\t%0,%2", op);
+      output_asm_insn ("a\t%0,0(%2)", op);
+      output_asm_insn ("a\t%2,4(%2)", op);
+      output_asm_insn ("basr\t%0,%0", op);
+      output_asm_insn ("l\t%0,%1", op);
+    }
+}
+
index e9fa7e41a1497640a6cfd4bc24a48e57b53eacad..988d7e26563820b93d87065e389f9a860b7d0837 100644 (file)
@@ -65,6 +65,14 @@ extern int target_flags;
 /* Define this to change the optimizations performed by default.  */
 #define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options(LEVEL, SIZE)
 
+/* Sometimes certain combinations of command options do not make sense
+   on a particular target machine.  You can define a macro
+   `OVERRIDE_OPTIONS' to take account of this.  This macro, if
+   defined, is executed once just after all the command options have
+   been parsed.  */
+#define OVERRIDE_OPTIONS override_options ()
+
+
 /* Defines for REAL_ARITHMETIC.  */
 #define IEEE_FLOAT 1
 #define TARGET_IBM_FLOAT           0
@@ -236,7 +244,12 @@ if (INTEGRAL_MODE_P (MODE) &&                              \
    G5 and following have 16 IEEE floating point register,
    which get numbers 16-31.  */
 
-#define FIRST_PSEUDO_REGISTER 34
+#define FIRST_PSEUDO_REGISTER 35
+
+/* Number of hardware registers that go into the DWARF-2 unwind info.
+   If not defined, equals FIRST_PSEUDO_REGISTER.  */
+
+#define DWARF_FRAME_REGISTERS 34
 
 /* The following register have a fix usage
    GPR 12: GOT register points to the GOT, setup in prologue,
@@ -260,7 +273,7 @@ if (INTEGRAL_MODE_P (MODE) &&                               \
   0, 0, 0, 0,                                  \
   0, 0, 0, 0,                                  \
   0, 0, 0, 0,                                  \
-  1, 1 }
+  1, 1, 1 }
 
 /* 1 for registers not available across function calls.  These must include
    the FIXED_REGISTERS and also any registers that can be used without being
@@ -273,22 +286,49 @@ if (INTEGRAL_MODE_P (MODE) &&                             \
   1, 1, 0, 0,                                  \
   0, 0, 0, 0,                                  \
   0, 1, 1, 1,                                  \
+  1, 1, 1, 1,                                  \
+  1, 1, 1, 1,                                  \
+  1, 1, 1, 1,                                  \
+  1, 1, 1, 1,                                  \
+  1, 1, 1 }
+
+/* Like `CALL_USED_REGISTERS' except this macro doesn't require that
+   the entire set of `FIXED_REGISTERS' be included.
+   (`CALL_USED_REGISTERS' must be a superset of `FIXED_REGISTERS').  */
+
+#define CALL_REALLY_USED_REGISTERS             \
+{ 1, 1, 1, 1,                                  \
   1, 1, 0, 0,                                  \
+  0, 0, 0, 0,                                  \
+  0, 0, 0, 0,                                  \
   1, 1, 1, 1,                                  \
   1, 1, 1, 1,                                  \
   1, 1, 1, 1,                                  \
-  1, 1 }
+  1, 1, 1, 1,                                  \
+  1, 1, 1 }
 
-/* If not pic code, gpr 12 can be used.  */
+/* Macro to conditionally modify fixed_regs/call_used_regs.  */
 
 #define CONDITIONAL_REGISTER_USAGE                             \
 do                                                             \
   {                                                            \
+    int i;                                                     \
+                                                               \
     if (flag_pic)                                              \
       {                                                                \
        fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                \
        call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;            \
       }                                                                \
+    if (TARGET_64BIT)                                          \
+      {                                                                \
+        for (i = 24; i < 32; i++)                              \
+           call_used_regs[i] = call_really_used_regs[i] = 0;   \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+        for (i = 18; i < 20; i++)                              \
+           call_used_regs[i] = call_really_used_regs[i] = 0;   \
+      }                                                                \
  } while (0)
 
 /* The following register have a special usage
@@ -298,7 +338,8 @@ do                                                          \
           with stack- or frame-pointer. 
    GPR 33: Condition code 'register' */
 
-#define FRAME_POINTER_REGNUM 11
+#define HARD_FRAME_POINTER_REGNUM 11
+#define FRAME_POINTER_REGNUM 34
 
 #define ARG_POINTER_REGNUM 32
 
@@ -333,7 +374,8 @@ do                                                          \
 #define HARD_REGNO_MODE_OK(REGNO, MODE)                             \
   (FLOAT_REGNO_P(REGNO)?                                            \
    (GET_MODE_CLASS(MODE) == MODE_FLOAT ||                           \
-    GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT) :                   \
+    GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT ||                   \
+    (MODE) == SImode || (MODE) == DImode) :                         \
    INT_REGNO_P(REGNO)?                                              \
     (HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1)) :        \
    CC_REGNO_P(REGNO)?                                               \
@@ -349,6 +391,15 @@ do                                                         \
    (((MODE1) == SFmode || (MODE1) == DFmode)   \
    == ((MODE2) == SFmode || (MODE2) == DFmode))
 
+/* If defined, gives a class of registers that cannot be used as the
+   operand of a SUBREG that changes the mode of the object illegally.  */
+
+#define CLASS_CANNOT_CHANGE_MODE FP_REGS
+
+/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
+
+#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
+  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
 
 /* Define this macro if references to a symbol must be treated
    differently depending on something about the variable or
@@ -383,15 +434,20 @@ while (0)
 
 #define ELIMINABLE_REGS                                        \
 {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},    \
  { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},          \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}}  
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}  
 
 #define CAN_ELIMINATE(FROM, TO) (1)
 
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                     \
 { if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)    \
   { (OFFSET) = 0; }                                                      \
-  else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)  \
+  else  if ((FROM) == FRAME_POINTER_REGNUM                                \
+           && (TO) == HARD_FRAME_POINTER_REGNUM)                         \
+  { (OFFSET) = 0; }                                                      \
+  else if ((FROM) == ARG_POINTER_REGNUM                                   \
+            && (TO) == HARD_FRAME_POINTER_REGNUM)                         \
   { (OFFSET) = s390_arg_frame_offset (); }                                       \
   else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)  \
   { (OFFSET) = s390_arg_frame_offset (); }                                       \
@@ -433,7 +489,8 @@ while (0)
 enum reg_class
 {
   NO_REGS, ADDR_REGS, GENERAL_REGS,
-  FP_REGS, ALL_REGS, LIM_REG_CLASSES
+  FP_REGS, ADDR_FP_REGS, GENERAL_FP_REGS,
+  ALL_REGS, LIM_REG_CLASSES
 };
 
 #define N_REG_CLASSES (int) LIM_REG_CLASSES
@@ -441,7 +498,8 @@ enum reg_class
 /* Give names of register classes as strings for dump file.  */
 
 #define REG_CLASS_NAMES                                                 \
-{ "NO_REGS","ADDR_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
+{ "NO_REGS", "ADDR_REGS", "GENERAL_REGS",                              \
+  "FP_REGS", "ADDR_FP_REGS", "GENERAL_FP_REGS", "ALL_REGS" }
 
 /* Define which registers fit in which classes.  This is an initializer for
    a vector of HARD_REG_SET of length N_REG_CLASSES.
@@ -450,10 +508,12 @@ enum reg_class
 #define REG_CLASS_CONTENTS \
 {                                                      \
   { 0x00000000, 0x00000000 },  /* NO_REGS */           \
-  { 0x0000fffe, 0x00000001 },  /* ADDR_REGS */         \
-  { 0x0000ffff, 0x00000001 },  /* GENERAL_REGS */      \
+  { 0x0000fffe, 0x00000005 },  /* ADDR_REGS */         \
+  { 0x0000ffff, 0x00000005 },  /* GENERAL_REGS */      \
   { 0xffff0000, 0x00000000 },  /* FP_REGS */           \
-  { 0xffffffff, 0x00000003 },  /* ALL_REGS */          \
+  { 0xfffffffe, 0x00000005 },  /* ADDR_FP_REGS */      \
+  { 0xffffffff, 0x00000005 },  /* GENERAL_FP_REGS */   \
+  { 0xffffffff, 0x00000007 },  /* ALL_REGS */          \
 }
 
 
@@ -506,15 +566,8 @@ extern enum reg_class regclass_map[];      /* smalled class containing REGNO   */
    but on some machines in some cases it is preferable to use a more
    restrictive class.  */
 
-#define PREFERRED_RELOAD_CLASS(X, CLASS)                                 \
-    (GET_CODE (X) == CONST_DOUBLE ?                                      \
-     (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? FP_REGS : ADDR_REGS) :\
-     (GET_CODE (X) == CONST_INT ?                                        \
-     (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? FP_REGS : ADDR_REGS) :\
-     GET_CODE (X) == PLUS ||                                            \
-     GET_CODE (X) == LABEL_REF ||                                        \
-     GET_CODE (X) == SYMBOL_REF ||                                       \
-     GET_CODE (X) == CONST ? ADDR_REGS : (CLASS)))
+#define PREFERRED_RELOAD_CLASS(X, CLASS)       \
+       s390_preferred_reload_class ((X), (CLASS))
 
 /* Return the maximum number of consecutive registers needed to represent
    mode MODE in a register of class CLASS.  */
@@ -557,26 +610,21 @@ extern enum reg_class regclass_map[];     /* smalled class containing REGNO   */
 
 /* Stack layout; function entry, exit and calling.  */
 
-/* The current return address is on Offset 56 of the current frame
-   if we are in an leaf_function. Otherwise we have to go one stack
-   back.
-   The return address of anything farther back is accessed normally
-   at an offset of 56 from the frame pointer.
-
-   FIXME: builtin_return_addr does not work correctly in a leaf
-          function, we need to find way to find out, if we
-          are in a leaf function
-  */
-
-#define _RETURN_ADDR_OFFSET (TARGET_64BIT ? 112 : 56)
-
-#define RETURN_ADDR_RTX(count, frame)                                   \
-   gen_rtx (MEM, Pmode,                                                 \
-            memory_address (Pmode,                                      \
-                              plus_constant (                           \
-                              copy_to_reg (gen_rtx (MEM, Pmode,         \
-                              memory_address (Pmode, frame))),          \
-                              _RETURN_ADDR_OFFSET)));
+/* The return address of the current frame is retrieved 
+   from the initial value of register RETURN_REGNUM.
+   For frames farther back, we use the stack slot where
+   the corresponding RETURN_REGNUM register was saved.  */
+
+#define DYNAMIC_CHAIN_ADDRESS(FRAME)                                           \
+  ((FRAME) != hard_frame_pointer_rtx ? (FRAME) :                               \
+   plus_constant (arg_pointer_rtx, -STACK_POINTER_OFFSET))
+     
+#define RETURN_ADDR_RTX(COUNT, FRAME)                                          \
+  ((COUNT) == 0 ? get_hard_reg_initial_val (Pmode, RETURN_REGNUM) :            \
+   gen_rtx_MEM (Pmode,                                                         \
+                memory_address (Pmode,                                                 \
+                                plus_constant (DYNAMIC_CHAIN_ADDRESS ((FRAME)),        \
+                                               RETURN_REGNUM * UNITS_PER_WORD))))
 
 /* The following macros will turn on dwarf2 exception hndling
    Other code location for this exception handling are 
@@ -588,6 +636,11 @@ extern enum reg_class regclass_map[];      /* smalled class containing REGNO   */
 
 #define MASK_RETURN_ADDR (GEN_INT (0x7fffffff))
 
+/* The offset from the incoming value of %sp to the top of the stack frame
+   for the current function.  */
+
+#define INCOMING_FRAME_SP_OFFSET STACK_POINTER_OFFSET
+
 /* Location, from where return address to load.  */
 
 #define DWARF_FRAME_RETURN_COLUMN  14
@@ -813,47 +866,7 @@ CUMULATIVE_ARGS;
    for profiling a function entry.  */
 
 #define FUNCTION_PROFILER(FILE, LABELNO)                       \
-do {                                                           \
-  extern rtx s390_profile[];                                   \
-  extern int s390_pool_count;                                  \
-  static char label[128];                                      \
-  fprintf (FILE, "# function profiler \n");                    \
-  if (TARGET_64BIT)                                            \
-    {                                                          \
-      rtx tmp[1];                                              \
-      output_asm_insn ("stg\t14,8(15)", tmp);                  \
-      sprintf (label, "%sP%d", LPREFIX, LABELNO);              \
-      tmp[0] = gen_rtx_SYMBOL_REF (Pmode, label);              \
-      SYMBOL_REF_FLAG (tmp[0]) = 1;                            \
-      output_asm_insn ("larl\t1,%0", tmp);                     \
-      tmp[0] = gen_rtx_SYMBOL_REF (Pmode, "_mcount");          \
-      if (flag_pic)                                            \
-        {                                                      \
-          tmp[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp[0]), 113); \
-          tmp[0] = gen_rtx_CONST (Pmode, tmp[0]);              \
-        }                                                      \
-      output_asm_insn ("brasl\t14,%0", tmp);                   \
-      output_asm_insn ("lg\t14,8(15)", tmp);                   \
-    }                                                          \
-  else                                                         \
-    {                                                                  \
-      output_asm_insn ("l     14,4(15)", s390_profile);                \
-      s390_pool_count = 0;                                             \
-      output_asm_insn ("st    14,4(15)", s390_profile);                \
-      output_asm_insn ("l     14,%4", s390_profile);           \
-      output_asm_insn ("l     1,%9", s390_profile);            \
-      if (flag_pic)                                            \
-       {                                                       \
-         output_asm_insn ("ar    1,13", s390_profile);         \
-         output_asm_insn ("bas   14,0(14,13)", s390_profile);  \
-       }                                                       \
-      else                                                     \
-       {                                                       \
-         output_asm_insn ("basr  14,14", s390_profile);        \
-       }                                                       \
-      output_asm_insn ("l     14,4(15)", s390_profile);                \
-    }                                                          \
-} while (0)
+       s390_function_profiler ((FILE), ((LABELNO)))
 
 /* #define PROFILE_BEFORE_PROLOGUE */
 
@@ -875,9 +888,9 @@ do {                                                        \
    reg currently allocated to a suitable hard reg.
    These definitions are NOT overridden anywhere.  */
 
-#define REGNO_OK_FOR_INDEX_P(REGNO)                                     \
-  (((REGNO) > 0 && (REGNO) < 16) || (REGNO) == ARG_POINTER_REGNUM       \
-   /* || (REGNO) == FRAME_POINTER_REGNUM */                                 \
+#define REGNO_OK_FOR_INDEX_P(REGNO)                                    \
+    (((REGNO) < FIRST_PSEUDO_REGISTER                                  \
+     && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS)                        \
     || (reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 16))
 
 #define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
@@ -947,11 +960,10 @@ do {                                                      \
  * a pseudo reg.  
  */
 
-#define REG_OK_FOR_INDEX_NONSTRICT_P(X)                                \
-((GET_MODE (X) == Pmode) &&                                            \
- ((REGNO (X) > 0 && REGNO (X) < 16) ||                                 \
-  (REGNO (X) == ARG_POINTER_REGNUM) ||                                 \
-  (REGNO (X) >= FIRST_PSEUDO_REGISTER)))
+#define REG_OK_FOR_INDEX_NONSTRICT_P(X)        \
+((GET_MODE (X) == Pmode) &&                    \
+ ((REGNO (X) >= FIRST_PSEUDO_REGISTER)                 \
+  || REGNO_REG_CLASS (REGNO (X)) == ADDR_REGS))  
 
 /* Nonzero if X is a hard reg that can be used as a base reg or if it is
    a pseudo reg.  */
@@ -1080,10 +1092,6 @@ do {                                                             \
 
 /* #define STORE_FLAG_VALUE -1 */
 
-/* When a prototype says `char' or `short', really pass an `int'.  */
-
-#define PROMOTE_PROTOTYPES 1
-
 /* Don't perform CSE on function addresses.  */
 
 #define NO_FUNCTION_CSE
@@ -1269,13 +1277,14 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
   "%r8",  "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",       \
   "%f0",  "%f2",  "%f4",  "%f6",  "%f1",  "%f3",  "%f5",  "%f7",       \
   "%f8",  "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15",       \
-  "%ap", "%cc"                                                         \
+  "%ap",  "%cc",  "%fp"                                                        \
 }
 
 /* implicit call of memcpy, not bcopy   */
 
 #define TARGET_MEM_FUNCTIONS
 
+
 /* Print operand X (an rtx) in assembler syntax to file FILE.
    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
    For `%' followed by punctuation, CODE is the punctuation and X is null.  */
@@ -1287,17 +1296,29 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
 
 /* Define the codes that are matched by predicates in aux-output.c.  */
 
-#define PREDICATE_CODES                                                 \
-  {"s_operand",       { MEM }},                                          \
-  {"bras_sym_operand",{ SYMBOL_REF, CONST }},                            \
-  {"r_or_s_operand",  { MEM, SUBREG, REG }},                             \
-  {"r_or_im8_operand",  { CONST_INT, SUBREG, REG }},                     \
-  {"r_or_s_or_im8_operand",  { MEM, SUBREG, REG, CONST_INT }},           \
-  {"r_or_x_or_im16_operand", { MEM, SUBREG, REG, CONST_INT }},           \
-  {"const0_operand", { CONST_INT, CONST_DOUBLE }},                      \
-  {"const1_operand", { CONST_INT, CONST_DOUBLE }},                      \
-  {"tmxx_operand", { CONST_INT, MEM }},
-
+#define PREDICATE_CODES                                                        \
+  {"s_operand",       { SUBREG, MEM }},                                        \
+  {"s_imm_operand",   { CONST_INT, CONST_DOUBLE, SUBREG, MEM }},       \
+  {"bras_sym_operand",{ SYMBOL_REF, CONST }},                          \
+  {"larl_operand",    { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }}, \
+  {"load_multiple_operation", {PARALLEL}},                             \
+  {"store_multiple_operation", {PARALLEL}},                            \
+  {"const0_operand",  { CONST_INT, CONST_DOUBLE }},
+
+
+/* S/390 constant pool breaks the devices in crtstuff.c to control section
+   in where code resides.  We have to write it as asm code.  */
+#ifndef __s390x__
+#define CRT_CALL_STATIC_FUNCTION(func) \
+  if (0) \
+     func (); /* ... to avoid warnings.  */ \
+  else \
+    asm \
+      ("bras\t%%r2,1f\n\
+0:     .long\t" #func " - 0b\n\
+1:     l\t%%r3,0(%%r2)\n\
+       bas\t%%r14,0(%%r3,%%r2)" : : : "2", "3", "cc", "memory");
+#endif
 
 /* Constant Pool for all symbols operands which are changed with
    force_const_mem during insn generation (expand_insn).  */
@@ -1397,7 +1418,11 @@ extern int s390_nr_constants;
           fputc ('\n', (FILE));                                                    \
        }                                                                   \
       else                                                                 \
-        assemble_integer (EXP, GET_MODE_SIZE (MODE), ALIGN, 1);                    \
+       {                                                                   \
+         assemble_integer (EXP, GET_MODE_SIZE (MODE), ALIGN, 1);           \
+         if (GET_MODE_SIZE (MODE) == 1)                                    \
+           ASM_OUTPUT_SKIP ((FILE), 1);                                    \
+       }                                                                   \
       break;                                                               \
                                                                            \
     default:                                                               \
index ea0edac4929141999ad9d58f45c95f68fb4302af..a056110378acd8baec8d5356a4a1a70ae5aedff7 100644 (file)
 ;;
 ;;   s_operand -- Matches a valid S operand in a RS, SI or SS type instruction.
 ;;
-;;   r_or_s_operand -- Matches a register or a valid S operand in a RS, SI
-;;                     or SS type instruction or a register
-;;
-
-;; Insn type.  Used to default other attribute values.
 
 
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations.
 
-(define_attr "type" "integer,load,lr,la,store,imul,lmul,fmul,idiv,ldiv,fdiv,branch,jsr,other,o2,o3"
+(define_attr "type" "none,integer,load,lr,la,lm,stm,cs,vs,store,imul,lmul,fmul,idiv,ldiv,fdiv,branch,jsr,other,o2,o3"
   (const_string "integer"))
 
 ;; Insn are devide in two classes:
@@ -65,6 +60,9 @@
 
 ;; Generic pipeline function unit.  
 
+(define_function_unit "integer" 1 0
+  (eq_attr "type" "none") 0 0)
+
 (define_function_unit "integer" 1 0
   (eq_attr "type" "integer") 1 1)
 
 (define_function_unit "integer" 1 0
   (eq_attr "type" "store") 1 1)
 
+(define_function_unit "integer" 1 0
+  (eq_attr "type" "lm") 2 2)
+
+(define_function_unit "integer" 1 0
+  (eq_attr "type" "stm") 2 2)
+
+(define_function_unit "integer" 1 0
+  (eq_attr "type" "cs") 5 5)
+
+(define_function_unit "integer" 1 0
+  (eq_attr "type" "vs") 30 30)
+
 (define_function_unit "integer" 1 0
   (eq_attr "type" "jsr") 5 5)
 
 (define_insn "*cmpdi_tm2"
   [(set (reg 33)
         (compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d")
-                         (match_operand:DI 1 "const1_operand" "")
-                          (match_operand:DI 2 "immediate_operand"  "I"))
+                                 (match_operand:DI 1 "const_int_operand" "n")
+                                  (match_operand:DI 2 "const_int_operand" "n"))
                  (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode) &&
-   INTVAL(operands[2]) >= 0 && INTVAL(operands[2]) < 64"
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 
+   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 64
+   && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
+      == INTVAL (operands[2]) >> 4"
   "*
 {
-  if (INTVAL (operands[2]) > 47)
-  {
-    operands[1] = GEN_INT (1 << (63 - INTVAL(operands[2])));
-    return \"tmll\\t%0,%x1\";
-  }
-  else if (INTVAL (operands[2]) > 31)
-  {
-    operands[1] = GEN_INT (1 << (47 - INTVAL(operands[2])));
-    return \"tmlh\\t%0,%x1\";
-  } 
-  else if (INTVAL (operands[2]) > 15)
-  {
-    operands[1] = GEN_INT (1 << (31 - INTVAL(operands[2])));
-    return \"tmhl\\t%0,%x1\";
-  }
-  operands[1] = GEN_INT (1 << (15 - INTVAL(operands[2])));
-  return \"tmhh\\t%0,%x1\";
-}"
-  [(set_attr "op_type" "RX")
-   (set_attr "type"    "integer")])
+  int part = INTVAL (operands[2]) >> 4;
+  int block = (1 << INTVAL (operands[1])) - 1;
+  int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
 
+  operands[2] = GEN_INT (block << shift);
 
-(define_insn "*cmpdi_tm"
+  switch (part)
+    {
+      case 0: return \"tmhh\\t%0,%x2\";
+      case 1: return \"tmhl\\t%0,%x2\";
+      case 2: return \"tmlh\\t%0,%x2\";
+      case 3: return \"tmll\\t%0,%x2\";
+      default: abort ();
+    }
+}"
+  [(set_attr "op_type" "RI")])
+
+(define_insn "*cmpdi_tm_reg"
   [(set (reg 33)
         (compare (and:DI (match_operand:DI 0 "register_operand" "%d")
-                         (match_operand:DI 1 "tmxx_operand"  "Lm"))
+                         (match_operand:DI 1 "immediate_operand" "n"))
                  (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)"
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+   && s390_single_hi (operands[1], DImode, 0) >= 0"
   "*
 {
-  unsigned HOST_WIDEST_INT i;
-  if (GET_CODE (operands[1]) == MEM && 
-      GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF &&
-      CONSTANT_POOL_ADDRESS_P (XEXP (operands[1],0))) 
-    {
-      operands[1] = get_pool_constant (XEXP (operands[1],0));
-    }
-       
-  i = (unsigned HOST_WIDEST_INT) INTVAL (operands[1]);
+  int part = s390_single_hi (operands[1], DImode, 0);
+  operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
 
-  if (i >= 0x1000000000000ULL)
-    {
-      operands[1] = GEN_INT (i >> 48);
-      return \"tmhh\\t%0,%x1\";
-    }
-  else if (i > 0x100000000ULL)
+  switch (part)
     {
-      operands[1] = GEN_INT (i >> 32);
-      return \"tmhl\\t%0,%x1\";
+      case 0: return \"tmhh\\t%0,%x1\";
+      case 1: return \"tmhl\\t%0,%x1\";
+      case 2: return \"tmlh\\t%0,%x1\";
+      case 3: return \"tmll\\t%0,%x1\";
+      default: abort ();
     }
-  else if (i >= 0x10000ULL)
-    {
-      operands[1] = GEN_INT (i >> 16);
-      return \"tmlh\\t%0,%x1\";
-    } 
-  else
-    return \"tmll\\t%0,%x1\";
 }"
-  [(set_attr "op_type" "RX")
-   (set_attr "type"    "integer")])
+  [(set_attr "op_type" "RI")])
+
+(define_insn "*cmpdi_tm_mem"
+  [(set (reg 33)
+        (compare (and:DI (match_operand:DI 0 "s_operand" "%Qo")
+                         (match_operand:DI 1 "immediate_operand" "n"))
+                 (const_int 0)))]
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+   && s390_single_qi (operands[1], DImode, 0) >= 0"
+  "*
+{
+  int part = s390_single_qi (operands[1], DImode, 0);
+  operands[1] = GEN_INT (s390_extract_qi (operands[1], DImode, part));
 
+  operands[0] = gen_rtx_MEM (QImode, 
+                            plus_constant (XEXP (operands[0], 0), part));
+  return \"tm\\t%0,%b1\";
+}"
+  [(set_attr "op_type" "SI")
+   (set_attr "atype"   "mem")])
 
 (define_insn "*ltgr"
   [(set (reg 33)
         (match_dup 0))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
   "ltgr\\t%2,%0"
-  [(set_attr "op_type" "RRE")
-   (set_attr "type"    "integer")])
+  [(set_attr "op_type" "RRE")])
 
 (define_insn "*cmpdi_ccs_0_64"
   [(set (reg 33)
                  (match_operand:DI 1 "const0_operand" "")))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
   "ltgr\\t%0,%0"
-  [(set_attr "op_type" "RRE")
-   (set_attr "type"    "integer")])
+  [(set_attr "op_type" "RRE")])
 
 (define_insn "*cmpdi_ccs_0_31"
   [(set (reg 33)
                  (match_operand:DI 1 "const0_operand" "")))]
   "s390_match_ccmode(insn, CCSmode)"
   "srda\\t%0,0"
-  [(set_attr "op_type" "RS")
-   (set_attr "type"    "integer")])
+  [(set_attr "op_type" "RS")])
 
 (define_insn "*cmpdi_ccs"
   [(set (reg 33)
 
 (define_insn "*cmpdi_ccu_mem"
   [(set (reg 33)
-        (compare (match_operand:DI 0 "s_operand" "oQ")
-                 (match_operand:DI 1 "s_operand" "oQ")))]
+        (compare (match_operand:DI 0 "s_imm_operand" "oQ")
+                 (match_operand:DI 1 "s_imm_operand" "oQ")))]
   "s390_match_ccmode(insn, CCUmode)"
   "clc\\t%O0(8,%R0),%1"
   [(set_attr "op_type" "SS")
 
 ; SI instructions
 
-(define_insn "*cmpsi_cct"
+(define_insn "*cmpsi_tm2"
   [(set (reg 33)
         (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
-                         (match_operand:SI 1 "const1_operand" "")
-                          (match_operand:SI 2 "immediate_operand"  "I"))
+                                 (match_operand:SI 1 "const_int_operand" "n")
+                                  (match_operand:SI 2 "const_int_operand" "n"))
                  (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode) &&
-   INTVAL(operands[2]) >= 0 && INTVAL(operands[2]) < 32"
+  "s390_match_ccmode(insn, CCTmode)
+   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 
+   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
+   && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
+      == INTVAL (operands[2]) >> 4"
   "*
 {
-  if (INTVAL (operands[2]) > 15)
+  int part = INTVAL (operands[2]) >> 4;
+  int block = (1 << INTVAL (operands[1])) - 1;
+  int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
+
+  operands[2] = GEN_INT (block << shift);
+
+  switch (part)
     {
-      operands[1] = GEN_INT (1 << (31 - INTVAL(operands[2])));
-      return \"tml\\t%0,%x1\";
+      case 0: return \"tmh\\t%0,%x2\";
+      case 1: return \"tml\\t%0,%x2\";
+      default: abort ();
     }
-  operands[1] = GEN_INT (1 << (15 - INTVAL(operands[2])));
-  return \"tmh\\t%0,%x1\";
 }"
   [(set_attr "op_type" "RI")])
 
-(define_insn "*cmpsi_tm"
+(define_insn "*cmpsi_tm_reg"
   [(set (reg 33)
         (compare (and:SI (match_operand:SI 0 "register_operand" "%d")
-                         (match_operand:SI 1 "tmxx_operand"  "Lm"))
+                         (match_operand:SI 1 "immediate_operand" "n"))
                  (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)"
+  "s390_match_ccmode(insn, CCTmode)
+   && s390_single_hi (operands[1], SImode, 0) >= 0"
   "*
 {
-  unsigned long i;
-  if (GET_CODE (operands[1]) == MEM && 
-      GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF &&
-      CONSTANT_POOL_ADDRESS_P (XEXP (operands[1],0))) 
-    {
-      operands[1] = get_pool_constant (XEXP (operands[1],0));
-    }
+  int part = s390_single_hi (operands[1], SImode, 0);
+  operands[1] = GEN_INT (s390_extract_hi (operands[1], SImode, part));
 
-  i = (unsigned long) INTVAL (operands[1]);
-  if (i > 0xffff)
+  switch (part)
     {
-      operands[1] = GEN_INT (i / 0x10000);
-      return \"tmh\\t%0,%x1\";
+      case 0: return \"tmh\\t%0,%x1\";
+      case 1: return \"tml\\t%0,%x1\";
+      default: abort ();
     }
-  return \"tml\\t%0,%x1\";
 }"
-  [(set_attr "op_type" "RX")])
+  [(set_attr "op_type" "RI")])
+
+(define_insn "*cmpsi_tm_mem"
+  [(set (reg 33)
+        (compare (and:SI (match_operand:SI 0 "s_operand" "%Qo")
+                         (match_operand:SI 1 "immediate_operand" "n"))
+                 (const_int 0)))]
+  "s390_match_ccmode(insn, CCTmode)
+   && s390_single_qi (operands[1], SImode, 0) >= 0"
+  "*
+{
+  int part = s390_single_qi (operands[1], SImode, 0);
+  operands[1] = GEN_INT (s390_extract_qi (operands[1], SImode, part));
+
+  operands[0] = gen_rtx_MEM (QImode, 
+                            plus_constant (XEXP (operands[0], 0), part));
+  return \"tm\\t%0,%b1\";
+}"
+  [(set_attr "op_type" "SI")
+   (set_attr "atype"   "mem")])
 
 (define_insn "*ltr"
   [(set (reg 33)
 
 (define_insn "*cmpsi_ccu_mem"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "s_operand" "oQ")
-                 (match_operand:SI 1 "s_operand" "oQ")))]
+        (compare (match_operand:SI 0 "s_imm_operand" "oQ")
+                 (match_operand:SI 1 "s_imm_operand" "oQ")))]
   "s390_match_ccmode(insn, CCUmode)"
   "clc\\t%O0(4,%R0),%1"
    [(set_attr "op_type" "SS")
     (set_attr "atype"   "mem")])
 
+
 ; HI instructions
 
+(define_insn "*cmphi_tm_sub"
+  [(set (reg 33)
+        (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Qo") 0)
+                         (match_operand:SI 1 "immediate_operand" "n"))
+                 (const_int 0)))]
+  "s390_match_ccmode(insn, CCTmode)
+   && s390_single_qi (operands[1], HImode, 0) >= 0"
+  "*
+{
+  int part = s390_single_qi (operands[1], HImode, 0);
+  operands[1] = GEN_INT (s390_extract_qi (operands[1], HImode, part));
+
+  operands[0] = gen_rtx_MEM (QImode, 
+                            plus_constant (XEXP (operands[0], 0), part));
+  return \"tm\\t%0,%b1\";
+}"
+  [(set_attr "op_type" "SI")
+   (set_attr "atype"   "mem")])
+
 (define_insn "*icm3"
   [(set (reg 33)
         (compare (match_operand:HI 0 "s_operand" "Qo")
 (define_insn "*cmphi_ccu"
   [(set (reg 33)
         (compare (match_operand:HI 0 "register_operand" "d")
-                 (match_operand:HI 1 "s_operand"        "Qo")))]
+                 (match_operand:HI 1 "s_imm_operand" "Qo")))]
   "s390_match_ccmode(insn, CCUmode)"
   "clm\\t%0,3,%1"
   [(set_attr "op_type" "RS")
 
 (define_insn "*cmphi_ccu_mem"
   [(set (reg 33)
-        (compare (match_operand:HI 0 "s_operand" "oQ")
-                 (match_operand:HI 1 "s_operand" "oQ")))]
+        (compare (match_operand:HI 0 "s_imm_operand" "oQ")
+                 (match_operand:HI 1 "s_imm_operand" "oQ")))]
   "s390_match_ccmode(insn, CCUmode)"
   "clc\\t%O0(2,%R0),%1"
   [(set_attr "op_type" "SS")
 
 ; QI instructions
 
+(define_insn "*cmpqi_tm2"
+  [(set (reg 33)
+        (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Qo")
+                                 (match_operand:SI 1 "const_int_operand" "n")
+                                  (match_operand:SI 2 "const_int_operand" "n"))
+                 (const_int 0)))]
+  "s390_match_ccmode(insn, CCTmode)
+   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 
+   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
+  "*
+{
+  int block = (1 << INTVAL (operands[1])) - 1;
+  int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
+
+  operands[2] = GEN_INT (block << shift);
+  return \"tm\\t%0,%b2\";
+}"
+  [(set_attr "op_type" "SI")
+   (set_attr "atype"   "mem")])
+
+(define_insn "*cmpqi_tm"
+  [(set (reg 33)
+        (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%d,Q")
+                         (match_operand:QI 1 "immediate_operand" "n,n"))
+                 (const_int 0)))]
+  "s390_match_ccmode(insn, CCTmode)"
+  "@
+   tml\\t%0,%b1
+   tm\\t%0,%b1"
+  [(set_attr "op_type" "RI,SI")
+   (set_attr "atype"   "reg,mem")])
+
+(define_insn "*cmpqi_tm_sub"
+  [(set (reg 33)
+        (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Qo") 0)
+                         (match_operand:SI 1 "immediate_operand" "n"))
+                 (const_int 0)))]
+  "s390_match_ccmode(insn, CCTmode)"
+  "tm\\t%0,%b1"
+  [(set_attr "op_type" "SI")
+   (set_attr "atype"   "mem")])
+
 (define_insn "*icm1"
   [(set (reg 33)
         (compare (match_operand:QI 0 "s_operand" "Qo")
    (clobber (match_scratch:QI 2 "=d"))]
   "s390_match_ccmode(insn, CCSmode)"
   "icm\\t%2,1,%0"
-  [(set_attr "op_type" "RS")])
+  [(set_attr "op_type" "RS")
+   (set_attr "atype"   "mem")])
 
 (define_insn "*cmpqi_ccu_0"
   [(set (reg 33)
 (define_insn "*cmpqi_ccu"
   [(set (reg 33)
         (compare (match_operand:QI 0 "register_operand" "d")
-                 (match_operand:QI 1 "s_operand"        "Qo")))]
+                 (match_operand:QI 1 "s_imm_operand" "Qo")))]
   "s390_match_ccmode(insn, CCUmode)"
   "clm\\t%0,1,%1"
   [(set_attr "op_type" "RS")
 
 (define_insn "*cmpqi_ccu_immed"
   [(set (reg 33)
-        (compare (match_operand:QI 0 "s_operand"      "Qo")
-                 (match_operand:QI 1 "immediate_operand" "")))]
+        (compare (match_operand:QI 0 "s_operand" "Qo")
+                 (match_operand:QI 1 "const_int_operand" "n")))]
   "s390_match_ccmode(insn, CCUmode) &&
    INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
   "cli\\t%0,%1"
 
 (define_insn "*cmpqi_ccu_mem"
   [(set (reg 33)
-        (compare (match_operand:QI 0 "s_operand" "oQ")
-                 (match_operand:QI 1 "s_operand" "oQ")))]
+        (compare (match_operand:QI 0 "s_imm_operand" "oQ")
+                 (match_operand:QI 1 "s_imm_operand" "oQ")))]
   "s390_match_ccmode(insn, CCUmode)"
   "clc\\t%O0(1,%R0),%1"
   [(set_attr "op_type" "SS")
 (define_insn "*cmpdf_ccs"
   [(set (reg 33)
         (compare (match_operand:DF 0 "register_operand" "f,f")
-                 (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+                 (match_operand:DF 1 "general_operand" "f,m")))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
    cdbr\\t%0,%1
 (define_insn "*cmpdf_ccs_ibm"
   [(set (reg 33)
         (compare (match_operand:DF 0 "register_operand" "f,f")
-                 (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+                 (match_operand:DF 1 "general_operand" "f,m")))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
    cdr\\t%0,%1
 (define_insn "*cmpsf_ccs"
   [(set (reg 33)
         (compare (match_operand:SF 0 "register_operand" "f,f")
-                 (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+                 (match_operand:SF 1 "general_operand" "f,m")))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
    cebr\\t%0,%1
 (define_insn "*cmpsf_ccs"
   [(set (reg 33)
         (compare (match_operand:SF 0 "register_operand" "f,f")
-                 (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+                 (match_operand:SF 1 "general_operand" "f,m")))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
    cer\\t%0,%1
 ; movti instruction pattern(s).
 ;
 
+(define_insn "*movti_ss"
+  [(set (match_operand:TI 0 "s_operand" "=Qo")
+        (match_operand:TI 1 "s_imm_operand" "Qo"))]
+  ""
+  "mvc\\t%O0(16,%R0),%1"       
+  [(set_attr "op_type" "SS")
+   (set_attr "atype"   "mem")])
+
 (define_insn "movti"
-  [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,Q")
-        (match_operand:TI 1 "general_operand" "d,K,m,d,Q"))]
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,m")
+        (match_operand:TI 1 "general_operand" "Q,d,dKm,d"))]
   "TARGET_64BIT"
-  "*
+  "@
+   lmg\\t%0,%N0,%1
+   stmg\\t%1,%N1,%0
+   #
+   #"
+  [(set_attr "op_type" "RSE,RSE,NN,NN")
+   (set_attr "atype"   "mem")])
+
+(define_split
+  [(set (match_operand:TI 0 "nonimmediate_operand" "")
+        (match_operand:TI 1 "general_operand" ""))]
+  "TARGET_64BIT && reload_completed
+   && !s_operand (operands[0], VOIDmode)
+   && !s_operand (operands[1], VOIDmode)
+   && (register_operand (operands[0], VOIDmode)
+       || register_operand (operands[1], VOIDmode))
+   && (!register_operand (operands[0], VOIDmode)
+       || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
+                                    operands[1])
+       || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, TImode),
+                                    operands[1]))"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+  "
 {
-  switch (which_alternative)
+  if (!register_operand (operands[0], VOIDmode)
+      || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
+                                   operands[1]))
     {
-      case 0: /* d <- d */
-        if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-          return \"lgr\\t%M0,%M1\;lgr\\t%0,%1\";
-        else
-          return \"lgr\\t%0,%1\;lgr\\t%M0,%M1\";
-
-      case 1: /* d <- K */
-        if (INTVAL(operands[1]) < 0)
-          return \"lghi\\t%0,-1\;lghi\\t%M0,%h1\";
-        else
-          return \"lghi\\t%0,0\;lghi\\t%M0,%h1\";
-
-      case 2: /* d <- m */
-        if (s_operand (operands[1], GET_MODE (operands[1])))
-          return \"lmg\\t%0,%M0,%1\";
-        else 
-          return \"la\\t%M0,%1\;lmg\\t%0,%M0,0(%M0)\";
-
-      case 3: /* m <- d */
-        if (!s_operand (operands[0], GET_MODE (operands[0])))
-          return \"stg\\t%1,%0\;stg\\t%M1,%M0\";
-        else
-          return \"stmg\\t%1,%M1,%0\";
-
-      case 4: /* m <- m */
-        return \"mvc\\t%O0(16,%R0),%1\";
-
-      default:
-        abort();
+      operands[2] = operand_subword (operands[0], 0, 0, TImode);
+      operands[3] = operand_subword (operands[0], 1, 0, TImode);
+      operands[4] = operand_subword (operands[1], 0, 0, TImode);
+      operands[5] = operand_subword (operands[1], 1, 0, TImode);
     }
-}"
-  [(set_attr "op_type" "NN,NN,RS,RS,SS")
-   (set_attr "atype"   "reg,reg,mem,mem,mem")
-   (set_attr "type"    "o2")
-   (set_attr "length"  "12,8,10,10,*")])
+  else
+    {
+      operands[2] = operand_subword (operands[0], 1, 0, TImode);
+      operands[3] = operand_subword (operands[0], 0, 0, TImode);
+      operands[4] = operand_subword (operands[1], 1, 0, TImode);
+      operands[5] = operand_subword (operands[1], 0, 0, TImode);
+    }
+}")
+
+(define_split
+  [(set (match_operand:TI 0 "register_operand" "")
+        (match_operand:TI 1 "memory_operand" ""))]
+  "TARGET_64BIT && reload_completed
+   && !s_operand (operands[1], VOIDmode)"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 0) (mem:TI (match_dup 2)))]
+  "operands[2] = operand_subword (operands[0], 0, 0, TImode);
+   operands[3] = XEXP (operands[1], 0);")
 
 ;
 ; movdi instruction pattern(s).
   ""
   "
 {
-  if (CONSTANT_P (operands[1]) 
-      && !LEGITIMATE_CONSTANT_P (operands[1]))
-    operands[1] = force_const_mem (DImode, operands[1]);
-
+  /* Handle PIC symbolic constants.  */
   if (TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1]))
     emit_pic_move (operands, DImode);
+
+  /* During and after reload, we need to force constants
+     to the literal pool ourselves, if necessary.  */
+  if ((reload_in_progress || reload_completed)
+      && CONSTANT_P (operands[1]) 
+      && (!legitimate_reload_constant_p (operands[1])
+          || fp_operand (operands[0], VOIDmode)))
+    operands[1] = force_const_mem (DImode, operands[1]);
 }")
 
+(define_insn "*movdi_lhi"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (match_operand:DI 1 "immediate_operand" "K"))]
+  "TARGET_64BIT
+   && GET_CODE (operands[1]) == CONST_INT
+   && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
+   && !fp_operand (operands[0], VOIDmode)"
+  "lghi\\t%0,%h1"
+  [(set_attr "op_type" "RI")
+   (set_attr "atype"   "reg")])
+
+(define_insn "*movdi_lli"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (match_operand:DI 1 "immediate_operand" "n"))]
+  "TARGET_64BIT && s390_single_hi (operands[1], DImode, 0) >= 0
+   && !fp_operand (operands[0], VOIDmode)"
+  "*
+{
+  int part = s390_single_hi (operands[1], DImode, 0);
+  operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
+
+  switch (part)
+    {
+      case 0: return \"llihh\\t%0,%x1\";
+      case 1: return \"llihl\\t%0,%x1\";
+      case 2: return \"llilh\\t%0,%x1\";
+      case 3: return \"llill\\t%0,%x1\";
+      default: abort ();
+    }
+}"
+  [(set_attr "op_type" "RI")
+   (set_attr "atype"   "reg")])
+
+(define_insn "*movdi_larl"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (match_operand:DI 1 "larl_operand" "X"))]
+  "TARGET_64BIT
+   && !fp_operand (operands[0], VOIDmode)"
+  "larl\\t%0,%1"
+   [(set_attr "op_type" "RIL")
+    (set_attr "atype"   "reg")
+    (set_attr "type"    "la")])
+
+(define_insn "*movdi_ss"
+  [(set (match_operand:DI 0 "s_operand" "=Qo")
+        (match_operand:DI 1 "s_imm_operand" "Qo"))]
+  ""
+  "mvc\\t%O0(8,%R0),%1"        
+  [(set_attr "op_type" "SS")
+   (set_attr "atype"   "mem")])
+
 (define_insn "*movdi_64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,m,Q")
-        (match_operand:DI 1 "general_operand" "d,K,S,m,d,Q"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,m,f,f,m")
+        (match_operand:DI 1 "general_operand" "d,m,d,f,m,f"))]
   "TARGET_64BIT"
   "@
    lgr\\t%0,%1
-   lghi\\t%0,%h1
-   larl\\t%0,%1
    lg\\t%0,%1
    stg\\t%1,%0
-   mvc\\t%O0(8,%R0),%1"        
-   [(set_attr "op_type" "RRE,RI,RIL,RXE,RXE,SS")
-    (set_attr "type"    "integer,integer,la,integer,integer,integer")
-    (set_attr "atype"   "reg,reg,reg,mem,mem,mem")])
+   ldr\\t%0,%1
+   ld\\t%0,%1
+   std\\t%1,%0"
+  [(set_attr "op_type" "RR,RXE,RXE,RR,RX,RX")
+   (set_attr "atype"   "reg,mem,mem,reg,mem,mem")])
 
 (define_insn "*movdi_31"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,Q")
-        (match_operand:DI 1 "general_operand" "d,K,m,d,Q"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,m,f,f,m")
+        (match_operand:DI 1 "general_operand" "Q,d,dKm,d,f,m,f"))]
   "!TARGET_64BIT"
-  "*
+  "@
+   lm\\t%0,%N0,%1
+   stm\\t%1,%N1,%0
+   #
+   #
+   ldr\\t%0,%1
+   ld\\t%0,%1
+   std\\t%1,%0"
+  [(set_attr "op_type" "RS,RS,NN,NN,RR,RX,RX")
+   (set_attr "atype"   "mem,mem,*,*,reg,mem,mem")])
+
+(define_split
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (match_operand:DI 1 "general_operand" ""))]
+  "!TARGET_64BIT && reload_completed
+   && !fp_operand (operands[0], VOIDmode)
+   && !fp_operand (operands[1], VOIDmode)
+   && !s_operand (operands[0], VOIDmode)
+   && !s_operand (operands[1], VOIDmode)
+   && (register_operand (operands[0], VOIDmode)
+       || register_operand (operands[1], VOIDmode))
+   && (!register_operand (operands[0], VOIDmode)
+       || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
+                                    operands[1])
+       || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DImode),
+                                    operands[1]))"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+  "
 {
-  switch (which_alternative)
+  if (!register_operand (operands[0], VOIDmode)
+      || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
+                                   operands[1]))
     {
-      case 0: /* d <- d */
-        if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-          return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
-        else
-          return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
-
-      case 1: /* d <- K */
-        if (INTVAL (operands[1]) < 0)
-          return \"lhi\\t%0,-1\;lhi\\t%N0,%h1\";
-        else
-          return \"lhi\\t%0,0\;lhi\\t%N0,%h1\";
-
-      case 2: /* d <- m */
-        if (s_operand (operands[1], GET_MODE (operands[1])))
-          return \"lm\\t%0,%N0,%1\";
-        else
-          return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
-
-      case 3: /* m <- d */
-        if (s_operand (operands[0], GET_MODE (operands[0])))
-          return \"stm\\t%1,%N1,%0\";
-        else
-          return \"st\\t%1,%0\;st\\t%N1,%N0\";
-
-      case 4: /* m <- m */
-        return \"mvc\\t%O0(8,%R0),%1\";
-
-      default:
-        abort();
-     }
-}"
-  [(set_attr "op_type" "NN,NN,RS,RS,SS")
-   (set_attr "atype"   "reg,reg,mem,mem,mem")
-   (set_attr "type"    "o2")
-   (set_attr "length"  "4,8,8,8,*")])
+      operands[2] = operand_subword (operands[0], 0, 0, DImode);
+      operands[3] = operand_subword (operands[0], 1, 0, DImode);
+      operands[4] = operand_subword (operands[1], 0, 0, DImode);
+      operands[5] = operand_subword (operands[1], 1, 0, DImode);
+    }
+  else
+    {
+      operands[2] = operand_subword (operands[0], 1, 0, DImode);
+      operands[3] = operand_subword (operands[0], 0, 0, DImode);
+      operands[4] = operand_subword (operands[1], 1, 0, DImode);
+      operands[5] = operand_subword (operands[1], 0, 0, DImode);
+    }
+}")
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (match_operand:DI 1 "memory_operand" ""))]
+  "!TARGET_64BIT && reload_completed
+   && !fp_operand (operands[0], VOIDmode)
+   && !fp_operand (operands[1], VOIDmode)
+   && !s_operand (operands[1], VOIDmode)"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 0) (mem:DI (match_dup 2)))]
+  "operands[2] = operand_subword (operands[0], 1, 0, DImode);
+   operands[3] = XEXP (operands[1], 0);")
 
 ;
 ; movsi instruction pattern(s).
   ""
   "
 {
-  if (CONSTANT_P (operands[1]) 
-      && !LEGITIMATE_CONSTANT_P (operands[1]))
-    operands[1] = force_const_mem (SImode, operands[1]);
-
-  if (flag_pic && SYMBOLIC_CONST (operands[1]))
+  /* Handle PIC symbolic constants.  */
+  if (!TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1]))
     emit_pic_move (operands, SImode);
 
   /* expr.c tries to load an effective address using 
       if (operands[1] == operands[0])
         DONE;
     }
+
+  /* During and after reload, we need to force constants
+     to the literal pool ourselves, if necessary.  */
+  if ((reload_in_progress || reload_completed)
+      && CONSTANT_P (operands[1]) 
+      && (!legitimate_reload_constant_p (operands[1])
+          || fp_operand (operands[0], VOIDmode)))
+    operands[1] = force_const_mem (SImode, operands[1]);
 }")
 
+(define_insn "*movsi_lhi"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (match_operand:SI 1 "immediate_operand" "K"))]
+  "GET_CODE (operands[1]) == CONST_INT
+   && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
+   && !fp_operand (operands[0], VOIDmode)"
+  "lhi\\t%0,%h1"
+  [(set_attr "op_type" "RI")])
+
+(define_insn "*movsi_lli"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (match_operand:SI 1 "immediate_operand" "n"))]
+  "TARGET_64BIT && s390_single_hi (operands[1], SImode, 0) >= 0
+   && !fp_operand (operands[0], VOIDmode)"
+  "*
+{
+  int part = s390_single_hi (operands[1], SImode, 0);
+  operands[1] = GEN_INT (s390_extract_hi (operands[1], SImode, part));
+
+  switch (part)
+    {
+      case 0: return \"llilh\\t%0,%x1\";
+      case 1: return \"llill\\t%0,%x1\";
+      default: abort ();
+    }
+}"
+  [(set_attr "op_type" "RI")])
+
+(define_insn "*movsi_ss"
+  [(set (match_operand:SI 0 "s_operand" "=Qo")
+        (match_operand:SI 1 "s_imm_operand" "Qo"))]
+  ""
+  "mvc\\t%O0(4,%R0),%1"        
+  [(set_attr "op_type" "SS")
+   (set_attr "atype"   "mem")])
+
 (define_insn "*movsi"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,Q")
-        (match_operand:SI 1 "general_operand" "d,K,m,d,Q"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,m,f,f,m")
+        (match_operand:SI 1 "general_operand" "d,m,d,f,m,f"))]
   ""
   "@
    lr\\t%0,%1
-   lhi\\t%0,%h1
    l\\t%0,%1
    st\\t%1,%0
-   mvc\\t%O0(4,%R0),%1"        
-  [(set_attr "op_type" "RR,RI,RX,RX,SS")
-   (set_attr "type"    "lr,*,load,store,store")        
-   (set_attr "atype"   "reg,reg,mem,mem,mem")])
+   ler\\t%0,%1
+   le\\t%0,%1
+   ste\\t%1,%0"
+  [(set_attr "op_type" "RR,RX,RX,RR,RX,RX")
+   (set_attr "atype"   "reg,mem,mem,reg,mem,mem")])
 
 
 ;
 
 (define_insn "movhi"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m")
-        (match_operand:HI 1 "r_or_x_or_im16_operand" "d,K,m,d"))]
+        (match_operand:HI 1 "general_operand" "d,n,m,d"))]
   ""
   "@
    lr\\t%0,%1
   [(set_attr "op_type" "RR,RI,RX,RX")
    (set_attr "atype"   "reg,reg,mem,mem")])
 
+
 ;
 ; movqi instruction pattern(s).
 ;
 
 (define_insn "movqi_64"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
-        (match_operand:QI 1 "general_operand" "d,K,m,d,n"))]
+        (match_operand:QI 1 "general_operand" "d,n,m,d,n"))]
   "TARGET_64BIT"
   "@
    lr\\t%0,%1
-   llill\\t%0,%x1
+   lhi\\t%0,%b1
    llgc\\t%0,%1
    stc\\t%1,%0
    mvi\\t%0,%b1"
   [(set_attr "op_type" "RR,RI,RXE,RX,SI")
    (set_attr "atype"   "reg,reg,mem,mem,mem")])
 
+
 (define_insn "movqi"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
-        (match_operand:QI 1 "r_or_x_or_im16_operand" "d,n,m,d,n"))]
+        (match_operand:QI 1 "general_operand" "d,n,m,d,n"))]
   ""
   "@
    lr\\t%0,%1
-   lhi\\t%0,%c1
+   lhi\\t%0,%b1
    ic\\t%0,%1
    stc\\t%1,%0
    mvi\\t%0,%b1"
-  [(set_attr "op_type" "RR,RX,RX,RX,SI")
+  [(set_attr "op_type" "RR,RI,RX,RX,SI")
    (set_attr "atype"   "reg,reg,mem,mem,mem")])
 
+
 ;
 ; moveqstrictqi instruction pattern(s).
 ;
 
 (define_insn "*movstrictqi"
-  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d,m"))
-                         (match_operand:QI 1 "nonimmediate_operand"  "m,d"))]
+  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
+                         (match_operand:QI 1 "memory_operand" "m"))]
   ""
-  "@
-   ic\\t%0,%1
-   stc\\t%1,%0"
-  [(set_attr "op_type"  "RX,RX")
-   (set_attr "atype"    "mem,mem")])
-
+  "ic\\t%0,%1"
+  [(set_attr "op_type"  "RX")
+   (set_attr "atype"    "mem")])
 
 ;
 ; movstricthi instruction pattern(s).
 ;
 
 (define_insn "*movstricthi"
-  [(set (strict_low_part (match_operand:HI 0 "r_or_s_operand" "+d,Q"))
-                         (match_operand:HI 1 "r_or_s_operand"  "Q,d"))
+  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
+                         (match_operand:HI 1 "s_imm_operand" "Qo"))
    (clobber (reg:CC 33))]
   ""
-  "@
-   icm\\t%0,3,%1
-   stcm\\t%1,3,%0"
-  [(set_attr "op_type" "RS,RS")
+  "icm\\t%0,3,%1"
+  [(set_attr "op_type" "RS")
    (set_attr "atype"   "mem")])
 
 
 ;
 
 (define_insn "movestrictsi"
-  [(set (strict_low_part (match_operand:SI 0 "nonimmediate_operand" "+d,d,m"))
-                         (match_operand:SI 1 "nonimmediate_operand"  "d,m,d"))]
+  [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d"))
+                         (match_operand:SI 1 "general_operand" "d,m"))]
   "TARGET_64BIT"
   "@
    lr\\t%0,%1
-   l\\t%0,%1
-   st\\t%1,%0"
-  [(set_attr "op_type" "RR,RS,RS")
-   (set_attr "atype"   "reg,mem,mem")])
+   l\\t%0,%1"
+  [(set_attr "op_type" "RR,RS")
+   (set_attr "atype"   "reg,mem")])
 
 
 ;
   ""
   "
 {
-  if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    operands[1] = force_const_mem (DFmode, operands[1]);       
+  /* During and after reload, we need to force constants
+     to the literal pool ourselves, if necessary.  */
+  if ((reload_in_progress || reload_completed)
+      && CONSTANT_P (operands[1]))
+    operands[1] = force_const_mem (DFmode, operands[1]);
 }")
 
+(define_insn "*movdf_ss"
+  [(set (match_operand:DF 0 "s_operand" "=Qo")
+        (match_operand:DF 1 "s_imm_operand" "Qo"))]
+  ""
+  "mvc\\t%O0(8,%R0),%1"        
+  [(set_attr "op_type" "SS")
+   (set_attr "atype"   "mem")])
+
 (define_insn "*movdf_64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
-        (match_operand:DF 1 "general_operand" "f,m,f,m,d,d,Q"))]
-  "TARGET_64BIT && TARGET_HARD_FLOAT"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,d,m")
+        (match_operand:DF 1 "general_operand" "f,m,f,d,m,d"))]
+  "TARGET_64BIT"
   "@
    ldr\\t%0,%1
    ld\\t%0,%1
    std\\t%1,%0
-   lg\\t%0,%1
-   stg\\t%1,%0
    lgr\\t%0,%1
-   mvc\\t%O0(8,%R0),%1"        
-  [(set_attr "op_type" "RR,RX,RX,RXE,RXE,RR,SS")
-   (set_attr "atype"   "reg,mem,mem,mem,mem,mem,mem")])
+   lg\\t%0,%1
+   stg\\t%1,%0"
+  [(set_attr "op_type" "RR,RX,RX,RR,RXE,RXE")
+   (set_attr "atype"   "reg,mem,mem,reg,mem,mem")])
 
 (define_insn "*movdf_31"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
-        (match_operand:DF 1 "general_operand" "f,m,f,m,d,d,Q"))]
-  "TARGET_HARD_FLOAT"
-  "*
-{
-  switch (which_alternative)
-    {
-      case 0: /* f <- f */
-        return \"ldr\\t%0,%1\";
-
-      case 1: /* f <- m */
-        return \"ld\\t%0,%1\";
-
-      case 2: /* m <- f */
-        return \"std\\t%1,%0\";
-
-      case 3: /* d <- m */
-        if (s_operand (operands[1], GET_MODE (operands[1])))
-          return \"lm\\t%0,%N0,%1\";
-        else
-         return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
-
-      case 4: /* m <- d */
-        if (s_operand (operands[0], GET_MODE (operands[0])))
-          return \"stm\\t%1,%N1,%0\";
-        else
-          return \"st\\t%1,%0\;st\\t%N1,%N0\";
-
-      case 5: /* d <- d */
-        if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-          return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
-        else
-          return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
-
-      case 6: /* m <- m */
-        return \"mvc\\t%O0(8,%R0),%1\";
-
-      default:
-        abort();
-     }
-}"
-  [(set_attr "op_type" "RR,RX,RX,RS,RS,NN,SS")
-   (set_attr "atype"   "reg,mem,mem,mem,mem,reg,mem")
-   (set_attr "length"  "*,*,*,*,*,4,*")])
-
-(define_insn "*movdf_soft_64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,m,d,Q")
-        (match_operand:DF 1 "general_operand" "m,d,d,Q"))]
-  "TARGET_64BIT && TARGET_SOFT_FLOAT"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,m")
+        (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKm,d"))]
+  "!TARGET_64BIT"
   "@
-   lg\\t%0,%1
-   stg\\t%1,%0
-   lgr\\t%0,%1
-   mvc\\t%O0(8,%R0),%1"        
-  [(set_attr "op_type" "RXE,RXE,RR,SS")
-   (set_attr "atype"   "mem,mem,mem,mem")])
-
-(define_insn "*movdf_soft_31"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=!d,d,m,Q")
-        (match_operand:DF 1 "general_operand" "!d,m,d,Q"))]
-  "TARGET_SOFT_FLOAT"
-  "*
+   ldr\\t%0,%1
+   ld\\t%0,%1
+   std\\t%1,%0
+   lm\\t%0,%N0,%1
+   stm\\t%1,%N1,%0
+   #
+   #"
+  [(set_attr "op_type" "RR,RX,RX,RS,RS,NN,NN")
+   (set_attr "atype"   "reg,mem,mem,mem,mem,*,*")])
+
+(define_split
+  [(set (match_operand:DF 0 "nonimmediate_operand" "")
+        (match_operand:DF 1 "general_operand" ""))]
+  "!TARGET_64BIT && reload_completed
+   && !fp_operand (operands[0], VOIDmode)
+   && !fp_operand (operands[1], VOIDmode)
+   && !s_operand (operands[0], VOIDmode)
+   && !s_operand (operands[1], VOIDmode)
+   && (register_operand (operands[0], VOIDmode)
+       || register_operand (operands[1], VOIDmode))
+   && (!register_operand (operands[0], VOIDmode)
+       || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
+                                    operands[1])
+       || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DFmode),
+                                    operands[1]))"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+  "
 {
-  switch (which_alternative) 
+  if (!register_operand (operands[0], VOIDmode)
+      || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
+                                   operands[1]))
     {
-      case 0: /* d <- d */
-        if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-          return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
-        else
-          return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
-
-      case 1: /* d <- m */
-        if (s_operand (operands[1], GET_MODE (operands[1])))
-          return \"lm\\t%0,%N0,%1\";
-        else
-         return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
-
-      case 2: /* m <- d */
-        if (s_operand (operands[0], GET_MODE (operands[0])))
-          return \"stm\\t%1,%N1,%0\";
-        else
-          return \"st\\t%1,%0\;st\\t%N1,%N0\";
-
-      case 3: /* m <- m */
-        return \"mvc\\t%O0(8,%R0),%1\";
-
-      default:
-        abort();
+      operands[2] = operand_subword (operands[0], 0, 0, DFmode);
+      operands[3] = operand_subword (operands[0], 1, 0, DFmode);
+      operands[4] = operand_subword (operands[1], 0, 0, DFmode);
+      operands[5] = operand_subword (operands[1], 1, 0, DFmode);
     }
-}"
-  [(set_attr "op_type" "NN,RS,RS,SS")
-   (set_attr "atype"   "reg,mem,mem,mem")
-   (set_attr "length"  "8,*,*,*")])
+  else
+    {
+      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
+      operands[3] = operand_subword (operands[0], 0, 0, DFmode);
+      operands[4] = operand_subword (operands[1], 1, 0, DFmode);
+      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
+    }
+}")
 
+(define_split
+  [(set (match_operand:DF 0 "register_operand" "")
+        (match_operand:DF 1 "memory_operand" ""))]
+  "!TARGET_64BIT && reload_completed
+   && !fp_operand (operands[0], VOIDmode)
+   && !fp_operand (operands[1], VOIDmode)
+   && !s_operand (operands[1], VOIDmode)"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 0) (mem:DI (match_dup 2)))]
+  "operands[2] = operand_subword (operands[0], 1, 0, DFmode);
+   operands[3] = XEXP (operands[1], 0);")
 
 ;
 ; movsf instruction pattern(s).
   ""
   "
 {
-  if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    operands[1] = force_const_mem (SFmode, operands[1]);       
+  /* During and after reload, we need to force constants
+     to the literal pool ourselves, if necessary.  */
+  if ((reload_in_progress || reload_completed)
+      && CONSTANT_P (operands[1]))
+    operands[1] = force_const_mem (SFmode, operands[1]);
 }")
 
-(define_insn "*movsf_64"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
-        (match_operand:SF 1 "general_operand" "f,m,f,m,d,d,Q"))]
-  "TARGET_64BIT && TARGET_HARD_FLOAT"
-  "@
-   ler\\t%0,%1
-   le\\t%0,%1
-   ste\\t%1,%0
-   llgf\\t%0,%1
-   st\\t%1,%0
-   lgr\\t%0,%1
-   mvc\\t%O0(4,%R0),%1"        
-  [(set_attr "op_type" "RR,RX,RX,RXE,RX,RR,SS")
-   (set_attr "atype"   "reg,mem,mem,mem,mem,reg,mem")])
+(define_insn "*movsf_ss"
+  [(set (match_operand:SF 0 "s_operand" "=Qo")
+        (match_operand:SF 1 "s_imm_operand" "Qo"))]
+  ""
+  "mvc\\t%O0(4,%R0),%1"        
+  [(set_attr "op_type" "SS")
+   (set_attr "atype"   "mem")])
 
-(define_insn "*movsf_31"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
-        (match_operand:SF 1 "general_operand" "f,m,f,m,d,d,Q"))]
-  "TARGET_HARD_FLOAT"
+(define_insn "*movsf"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,d,m")
+        (match_operand:SF 1 "general_operand" "f,m,f,d,m,d"))]
+  ""
   "@
    ler\\t%0,%1
    le\\t%0,%1
    ste\\t%1,%0
-   l\\t%0,%1
-   st\\t%1,%0
-   lr\\t%0,%1
-   mvc\\t%O0(4,%R0),%1"        
-  [(set_attr "op_type" "RR,RX,RX,RX,RX,RR,SS")
-   (set_attr "atype"   "reg,mem,mem,mem,mem,reg,mem")])
-
-(define_insn "*movsf_soft"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m,Q")
-        (match_operand:SF 1 "general_operand" "d,m,d,Q"))]
-  "TARGET_SOFT_FLOAT"
-  "@
    lr\\t%0,%1
    l\\t%0,%1
-   st\\t%1,%0
-   mvc\\t%O0(4,%R0),%1"        
-  [(set_attr "op_type" "RR,RX,RX,SS")
-   (set_attr "atype"   "reg,mem,mem,mem")])
+   st\\t%1,%0"
+  [(set_attr "op_type" "RR,RX,RX,RR,RX,RX")
+   (set_attr "atype"   "reg,mem,mem,reg,mem,mem")])
+
 ;
 ; load_multiple pattern(s).
 ;
   int regno;
   int count;
   rtx from;
-  int i;
+  int i, off;
 
   /* Support only loading a constant number of fixed-point registers from
      memory and only bother with this if more than two */
   if (GET_CODE (operands[2]) != CONST_INT
-      || INTVAL (operands[2]) <= 2
+      || INTVAL (operands[2]) < 2
       || INTVAL (operands[2]) > 16
       || GET_CODE (operands[1]) != MEM
       || GET_CODE (operands[0]) != REG
   regno = REGNO (operands[0]);
 
   operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
-  from = force_reg (Pmode, XEXP (operands[1], 0));
+  if (no_new_pseudos)
+    {
+      if (GET_CODE (XEXP (operands[1], 0)) == REG)
+       {
+         from = XEXP (operands[1], 0);
+         off = 0;
+       }
+      else if (GET_CODE (XEXP (operands[1], 0)) == PLUS
+              && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
+              && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
+       {
+         from = XEXP (XEXP (operands[1], 0), 0);
+         off = INTVAL (XEXP (XEXP (operands[1], 0), 1));
+       }
+      else
+       FAIL;
+
+      if (from == frame_pointer_rtx || from == arg_pointer_rtx)
+       FAIL;
+    }
+  else
+    {
+      from = force_reg (Pmode, XEXP (operands[1], 0));
+      off = 0;
+    }
 
   for (i = 0; i < count; i++)
     XVECEXP (operands[3], 0, i)
       = gen_rtx_SET (VOIDmode, gen_rtx_REG (Pmode, regno + i),
                     change_address (operands[1], Pmode,
-                                    plus_constant (from, i * 4)));
+                                    plus_constant (from,
+                                                   off + i * UNITS_PER_WORD)));
 }")
 
 (define_insn "*load_multiple_di"
     return \"lmg\\t%1,%0,%2\";
 }"
    [(set_attr "op_type" "RXE")
-    (set_attr "atype"   "mem")])
+    (set_attr "atype"   "mem")
+    (set_attr "type"    "lm")])
 
 (define_insn "*load_multiple_si"
   [(match_parallel 0 "load_multiple_operation"
     return \"lm\\t%1,%0,%2\";
 }"
    [(set_attr "op_type" "RXE")
-    (set_attr "atype"   "mem")])
+    (set_attr "atype"   "mem")
+    (set_attr "type"    "lm")])
 
 ;
 ; store multiple pattern(s). 
   int regno;
   int count;
   rtx to;
-  int i;
+  int i, off;
 
   /* Support only storing a constant number of fixed-point registers to
      memory and only bother with this if more than two.  */
   if (GET_CODE (operands[2]) != CONST_INT
-      || INTVAL (operands[2]) <= 2
+      || INTVAL (operands[2]) < 2
       || INTVAL (operands[2]) > 16
       || GET_CODE (operands[0]) != MEM
       || GET_CODE (operands[1]) != REG
   regno = REGNO (operands[1]);
 
   operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
-  to = force_reg (Pmode, XEXP (operands[0], 0));
+
+  if (no_new_pseudos)
+    {
+      if (GET_CODE (XEXP (operands[0], 0)) == REG)
+       {
+         to = XEXP (operands[0], 0);
+         off = 0;
+       }
+      else if (GET_CODE (XEXP (operands[0], 0)) == PLUS
+              && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG
+              && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
+       {
+         to = XEXP (XEXP (operands[0], 0), 0);
+         off = INTVAL (XEXP (XEXP (operands[0], 0), 1));
+       }
+      else
+       FAIL;
+
+      if (to == frame_pointer_rtx || to == arg_pointer_rtx)
+       FAIL;
+    }
+  else 
+    {
+      to = force_reg (Pmode, XEXP (operands[0], 0));
+      off = 0;
+    }
 
   for (i = 0; i < count; i++)
     XVECEXP (operands[3], 0, i)
       = gen_rtx_SET (VOIDmode,
                     change_address (operands[0], Pmode,
-                                    plus_constant (to, i * 4)),
+                                    plus_constant (to,
+                                                   off + i * UNITS_PER_WORD)),
                     gen_rtx_REG (Pmode, regno + i));
 }")
 
 }"
    [(set_attr "op_type" "RXE")
     (set_attr "atype"   "mem")
-    (set_attr "type"    "other")])
+    (set_attr "type"    "stm")])
 
 
 (define_insn "*store_multiple_si"
 }"
    [(set_attr "op_type" "RXE")
     (set_attr "atype"   "mem")
-    (set_attr "type"    "other")])
+    (set_attr "type"    "stm")])
 
 ;;
 ;; String instructions.
 
           /* Load up the address+length pairs.  */
 
-          emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr0);
-          emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 8), len);
+          emit_move_insn (gen_highpart (DImode, reg0), addr0);
+          emit_move_insn (gen_lowpart (DImode, reg0), len);
 
-          emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 0), addr1);
-          emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 8), len);
+          emit_move_insn (gen_highpart (DImode, reg1), addr1);
+          emit_move_insn (gen_lowpart (DImode, reg1), len);
 
           /* MOVE */
-          emit_insn (gen_movstrdi_64 (reg0, reg1));
+          emit_insn (gen_movstrdi_64 (reg0, reg1, reg0, reg1));
           DONE;
         }
       else
           emit_move_insn (reg0, addr0);
           emit_move_insn (reg1, addr1);
           emit_insn (gen_adddi3 (len, len, constm1_rtx));
-          emit_insn (gen_movstrdix_64 (reg0, reg1, len));
+          emit_insn (gen_movstrdix_64 (reg0, reg1, reg0, reg1, len));
           emit_label (label); 
           DONE;           
        }        
 
           /* Load up the address+length pairs.  */
 
-          emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 0), addr0);
-          emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 4), len);
+          emit_move_insn (gen_highpart (SImode, reg0), addr0);
+          emit_move_insn (gen_lowpart (SImode, reg0), len);
 
-          emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), addr1);
-          emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 4), len);
+          emit_move_insn (gen_highpart (SImode, reg1), addr1);
+          emit_move_insn (gen_lowpart (SImode, reg1), len);
 
           /* MOVE */
-          emit_insn (gen_movstrsi_31 (reg0, reg1));
+          emit_insn (gen_movstrsi_31 (reg0, reg1, reg0, reg1));
           DONE;
         }
       else
           emit_move_insn (reg0, addr0);
           emit_move_insn (reg1, addr1);
           emit_insn (gen_addsi3 (len, len, constm1_rtx));
-          emit_insn (gen_movstrsix_31 (reg0, reg1, len));
+          emit_insn (gen_movstrsix_31 (reg0, reg1, reg0, reg1, len));
           emit_label (label); 
           DONE;           
        }        
 ; Move a block that is more than 256 bytes in lenght or length in register
 
 (define_insn "movstrdix_64"
-  [(set (mem:BLK (match_operand:DI 0 "register_operand" "a"))
-        (mem:BLK (match_operand:DI 1 "register_operand" "a")))
-   (use (match_operand:DI 2 "register_operand" "a"))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
-   (clobber (match_scratch:DI 3 "=&a"))
+  [(clobber (match_operand:DI 0 "register_operand" "=a"))
+   (clobber (match_operand:DI 1 "register_operand" "=a"))
+   (set (mem:BLK (match_operand:DI 2 "register_operand" "0"))
+        (mem:BLK (match_operand:DI 3 "register_operand" "1")))
+   (use (match_operand:DI 4 "register_operand" "a"))
+   (clobber (match_scratch:DI 5 "=&a"))
    (clobber (reg:CC 33))]
   ""
   "*
   xop[0] = gen_label_rtx ();
   xop[1] = gen_label_rtx ();
   xop[2] = gen_label_rtx ();
-  xop[3] = operands[3];
-  output_asm_insn (\"srag\\t%3,%2,8\",operands);
-  output_asm_insn (\"jz\\t%l1\",xop);
+  xop[3] = operands[5];
+  output_asm_insn (\"srag\\t%5,%4,8\", operands);
+  output_asm_insn (\"jz\\t%l1\", xop);
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (xop[0]));
-  output_asm_insn (\"mvc\\t0(256,%0),0(%1)\",operands);
-  output_asm_insn (\"la\\t%0,256(%0)\",operands);
-  output_asm_insn (\"la\\t%1,256(%1)\",operands);
-  xop[3] = operands[3];
-  output_asm_insn (\"brct\\t%3,%l0\",xop);
+  output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands);
+  output_asm_insn (\"la\\t%0,256(%0)\", operands);
+  output_asm_insn (\"la\\t%1,256(%1)\", operands);
+  output_asm_insn (\"brct\\t%3,%l0\", xop);
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (xop[1]));
-  xop[3] = operands[3];
-  output_asm_insn (\"bras\\t%3,%l2\",xop);
-  output_asm_insn (\"mvc\\t0(1,%0),0(%1)\",operands);
+  output_asm_insn (\"bras\\t%3,%l2\", xop);
+  output_asm_insn (\"mvc\\t0(1,%0),0(%1)\", operands);
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (xop[2]));
-  return \"ex\\t%2,0(%3)\";
+  return \"ex\\t%4,0(%5)\";
 }"
   [(set_attr "op_type" "NN")
    (set_attr "atype"   "mem")
    (set_attr "length" "44")])
 
 (define_insn "movstrsix_31"
-  [(set (mem:BLK (match_operand:SI 0 "register_operand" "a"))
-        (mem:BLK (match_operand:SI 1 "register_operand" "a")))
-   (use (match_operand:SI 2 "register_operand" "a"))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
-   (clobber (match_scratch:SI 3 "=&a"))
+  [(clobber (match_operand:SI 0 "register_operand" "=a"))
+   (clobber (match_operand:SI 1 "register_operand" "=a"))
+   (set (mem:BLK (match_operand:SI 2 "register_operand" "0"))
+        (mem:BLK (match_operand:SI 3 "register_operand" "1")))
+   (use (match_operand:SI 4 "register_operand" "a"))
+   (clobber (match_scratch:SI 5 "=&a"))
    (clobber (reg:CC 33))]
   ""
   "*
   xop[0] = gen_label_rtx ();
   xop[1] = gen_label_rtx ();
   xop[2] = gen_label_rtx ();
-  xop[3] = operands[3];
-  output_asm_insn (\"lr\\t%3,%2\",operands);
-  output_asm_insn (\"sra\\t%3,8\",operands);
-  output_asm_insn (\"jz\\t%l1\",xop);
+  xop[3] = operands[5];
+  output_asm_insn (\"lr\\t%5,%4\", operands);
+  output_asm_insn (\"sra\\t%5,8\", operands);
+  output_asm_insn (\"jz\\t%l1\", xop);
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (xop[0]));
-  output_asm_insn (\"mvc\\t0(256,%0),0(%1)\",operands);
-  output_asm_insn (\"la\\t%0,256(%0)\",operands);
-  output_asm_insn (\"la\\t%1,256(%1)\",operands);
-  xop[3] = operands[3];
-  output_asm_insn (\"brct\\t%3,%l0\",xop);
+  output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands);
+  output_asm_insn (\"la\\t%0,256(%0)\", operands);
+  output_asm_insn (\"la\\t%1,256(%1)\", operands);
+  output_asm_insn (\"brct\\t%3,%l0\", xop);
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (xop[1]));
-  xop[3] = operands[3];
-  output_asm_insn (\"bras\\t%3,%l2\",xop);
-  output_asm_insn (\"mvc\\t0(1,%0),0(%1)\",operands);
+  output_asm_insn (\"bras\\t%3,%l2\", xop);
+  output_asm_insn (\"mvc\\t0(1,%0),0(%1)\", operands);
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (xop[2]));
-  return \"ex\\t%2,0(%3)\";
+  return \"ex\\t%4,0(%5)\";
 }"
    [(set_attr "op_type" "NN")
     (set_attr "length" "42")
 ; Move a block that is larger than 255 bytes in length.
 
 (define_insn "movstrdi_64"
-  [(set (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
-        (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0)))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
+  [(clobber (match_operand:TI 0 "register_operand" "=d"))
+   (clobber (match_operand:TI 1 "register_operand" "=d"))
+   (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
+        (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0)))
    (clobber (reg:CC 33))]
   ""
   "mvcle\\t%0,%1,0\;jo\\t.-4"
    (set_attr "length"  "8")])
 
 (define_insn "movstrsi_31"
-  [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
-        (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0)))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
+  [(clobber (match_operand:DI 0 "register_operand" "=d"))
+   (clobber (match_operand:DI 1 "register_operand" "=d"))
+   (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
+        (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0)))
    (clobber (reg:CC 33))]
   ""
   "mvcle\\t%0,%1,0\;jo\\t.-4"
 
       /* Load up the address+length pairs.  */
 
-      emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr);
-      emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 8), len);
+      emit_move_insn (gen_highpart (DImode, reg0), addr);
+      emit_move_insn (gen_lowpart (DImode, reg0), len);
 
-      emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 8), const0_rtx);
+      emit_move_insn (gen_lowpart (DImode, reg1), const0_rtx);
  
       /* Clear! */
-      emit_insn (gen_clrstrsi_64 (reg0, reg1));
+      emit_insn (gen_clrstrsi_64 (reg0, reg1, reg0, reg1));
       DONE;    
      }
 }")
 
       /* Load up the address+length pairs.  */
 
-      emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 0), addr);
-      emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 4), len);
+      emit_move_insn (gen_highpart (SImode, reg0), addr);
+      emit_move_insn (gen_lowpart (SImode, reg0), len);
 
-      emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 4), const0_rtx);
+      emit_move_insn (gen_lowpart (SImode, reg1), const0_rtx);
  
       /* CLear! */
-      emit_insn (gen_clrstrsi_31 (reg0, reg1));
+      emit_insn (gen_clrstrsi_31 (reg0, reg1, reg0, reg1));
       DONE;    
      }
 }")
   ""
   "xc\\t%O0(%1,%R0),%0"        
   [(set_attr "op_type" "RS")
+   (set_attr "type"    "cs")
    (set_attr "atype"   "mem")])
 
 ; Clear memory with length greater 256 bytes or lenght not constant
 
 (define_insn "clrstrsi_64"
-  [(set (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
+  [(clobber (match_operand:TI 0 "register_operand" "=d"))
+   (clobber (match_operand:TI 1 "register_operand" "=d"))
+   (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
         (const_int 0))
-   (use (match_operand:TI 1 "register_operand" "d"))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
+   (use (match_operand:TI 3 "register_operand" "1"))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
   "mvcle\\t%0,%1,0\;jo\\t.-4"
   [(set_attr "op_type" "NN")
    (set_attr "atype"   "mem")
-   (set_attr "type"   "other")
+   (set_attr "type"    "vs")
    (set_attr "length"  "8")])
 
 (define_insn "clrstrsi_31"
-  [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
+  [(clobber (match_operand:DI 0 "register_operand" "=d"))
+   (clobber (match_operand:DI 1 "register_operand" "=d"))
+   (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
         (const_int 0))
-   (use (match_operand:DI 1 "register_operand" "d"))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
+   (use (match_operand:DI 3 "register_operand" "1"))
    (clobber (reg:CC 33))]
   "!TARGET_64BIT"
   "mvcle\\t%0,%1,0\;jo\\t.-4"
   [(set_attr "op_type" "NN")
    (set_attr "atype"   "mem")
-   (set_attr "type"    "other")
+   (set_attr "type"    "vs")
    (set_attr "length"  "8")])
 
 ;
           len = force_reg (DImode, len);
 
       /* Load up the address+length pairs.  */
-      emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr0); 
-      emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 8), len);
+      emit_move_insn (gen_highpart (DImode, reg0), addr0); 
+      emit_move_insn (gen_lowpart (DImode, reg0), len);
 
-      emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 0), addr1);
-      emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 8), len);
+      emit_move_insn (gen_highpart (DImode, reg1), addr1);
+      emit_move_insn (gen_lowpart (DImode, reg1), len);
 
       /* Compare! */
-      emit_insn (gen_cmpstr_64 (reg0, reg1));
+      emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
       emit_insn (gen_cmpint_di (operands[0]));
       DONE;
     }
           len = force_reg (Pmode, len);
 
       /* Load up the address+length pairs.  */
-      emit_move_insn (gen_rtx_SUBREG (Pmode, reg0, 0), addr0); 
-      emit_move_insn (gen_rtx_SUBREG (Pmode, reg0, 
-       GET_MODE_SIZE (Pmode)), len);
+      emit_move_insn (gen_highpart (Pmode, reg0), addr0); 
+      emit_move_insn (gen_lowpart (Pmode, reg0), len);
 
-      emit_move_insn (gen_rtx_SUBREG (Pmode, reg1, 0), addr1);
-      emit_move_insn (gen_rtx_SUBREG (Pmode, reg1, 
-       GET_MODE_SIZE (Pmode)), len);
+      emit_move_insn (gen_highpart (Pmode, reg1), addr1);
+      emit_move_insn (gen_lowpart (Pmode, reg1), len);
 
       /* Compare! */
       if (TARGET_64BIT) 
-          emit_insn (gen_cmpstr_64 (reg0, reg1));
+          emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
       else
-          emit_insn (gen_cmpstr_31 (reg0, reg1));
+          emit_insn (gen_cmpstr_31 (reg0, reg1, reg0, reg1));
 
       emit_insn (gen_cmpint_si (operands[0]));
       DONE;
   "clc\\t%O0(%c2,%R0),%1"
   [(set_attr "op_type" "SS")
    (set_attr "atype"   "mem")
-   (set_attr "type"    "other")])
+   (set_attr "type"    "cs")])
 
 ; Compare a block that is larger than 255 bytes in length.
 
 (define_insn "cmpstr_64"
-  [(set (reg:CCS 33)
-        (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
-                     (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0))))
-   (clobber (subreg:DI (match_dup 0) 0))
-   (clobber (subreg:DI (match_dup 0) 8))
-   (clobber (subreg:DI (match_dup 1) 0))
-   (clobber (subreg:DI (match_dup 1) 8))]
+  [(clobber (match_operand:TI 0 "register_operand" "=d"))
+   (clobber (match_operand:TI 1 "register_operand" "=d"))
+   (set (reg:CCS 33)
+        (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
+                     (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0))))]
   "TARGET_64BIT"
   "clcl\\t%0,%1"
   [(set_attr "op_type" "RR")
    (set_attr "atype"   "mem")
-   (set_attr "type"    "other")])
+   (set_attr "type"    "vs")])
 
 (define_insn "cmpstr_31"
-  [(set (reg:CCS 33)
-        (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
-                     (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0))))
-   (clobber (subreg:SI (match_dup 0) 0))
-   (clobber (subreg:SI (match_dup 0) 4))
-   (clobber (subreg:SI (match_dup 1) 0))
-   (clobber (subreg:SI (match_dup 1) 4))]
+  [(clobber (match_operand:DI 0 "register_operand" "=d"))
+   (clobber (match_operand:DI 1 "register_operand" "=d"))
+   (set (reg:CCS 33)
+        (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
+                     (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0))))]
   "!TARGET_64BIT"
   "clcl\\t%0,%1"
   [(set_attr "op_type" "RR")
    (set_attr "atype"   "mem")
-   (set_attr "type"    "other")])
+   (set_attr "type"    "vs")])
 
 ; Convert condition code to integer in range (-1, 0, 1)
 
    (set_attr "atype"   "reg")
    (set_attr "type"    "other")])
 
+
 ;;
 ;;- Conversion instructions.
 ;;
 
+(define_insn "*sethighqisi"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (unspec:SI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+   (clobber (reg:CC 33))]
+  ""
+  "icm\\t%0,8,%1"
+  [(set_attr "op_type" "RS")
+   (set_attr "atype"   "mem")])
+
+(define_insn "*sethighhisi"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (unspec:SI [(match_operand:HI 1 "s_operand" "Qo")] 10))
+   (clobber (reg:CC 33))]
+  ""
+  "icm\\t%0,12,%1"
+  [(set_attr "op_type" "RS")
+   (set_attr "atype"   "mem")])
+
+(define_insn "*sethighqidi_64"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "icmh\\t%0,8,%1"
+  [(set_attr "op_type" "RSE")
+   (set_attr "atype"   "mem")])
+
+(define_insn "*sethighqidi_31"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+   (clobber (reg:CC 33))]
+  "!TARGET_64BIT"
+  "icm\\t%0,8,%1"
+  [(set_attr "op_type" "RS")
+   (set_attr "atype"   "mem")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (zero_extract:SI (match_operand:QI 1 "s_operand" "")
+                         (match_operand 2 "const_int_operand" "")
+                         (const_int 0)))]
+  "!TARGET_64BIT && !reload_completed
+   && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8"
+  [(parallel
+    [(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
+     (clobber (reg:CC 33))])
+    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+  "
+{
+  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+  operands[1] = change_address (operands[1], QImode, 0);
+}")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (zero_extract:SI (match_operand:QI 1 "s_operand" "")
+                         (match_operand 2 "const_int_operand" "")
+                         (const_int 0)))]
+  "!TARGET_64BIT && !reload_completed
+   && INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16"
+  [(parallel
+    [(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
+     (clobber (reg:CC 33))])
+    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+  "
+{
+  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+  operands[1] = change_address (operands[1], HImode, 0);
+}")
+
 ;
 ; extendsidi2 instruction pattern(s).
 ;
 
-(define_insn "extendsidi2"
+(define_expand "extendsidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
+  ""
+  "
+{
+  if (!TARGET_64BIT)
+    {
+      rtx insns, subword;
+
+      operands[1] = force_reg (SImode, operands[1]);
+      subword = operand_subword (operands[0], 0, 1, DImode);
+
+      start_sequence ();
+      emit_move_insn (subword, operands[1]);
+      emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (32))); 
+      insns = get_insns ();
+      end_sequence ();
+
+      emit_no_conflict_block (insns, operands[0], operands[1], 0, 
+                              gen_rtx_SIGN_EXTEND (DImode, operands[1]));
+
+      /* Avoid having the REG_RETVAL destroyed by someone attaching 
+         other REG_EQUAL notes.  */
+      emit_move_insn (operands[0], operands[0]);
+      DONE;
+    }
+}
+")
+
+(define_insn "*extendsidi2"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")))]
   "TARGET_64BIT"
   [(set_attr "op_type" "RRE,RXE")
    (set_attr "atype"   "reg,mem")])
 
-
 ;
 ; extendhidi2 instruction pattern(s).
 ;
 
-(define_insn "extendhidi2"
+(define_expand "extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
+  ""
+  "
+{
+  if (!TARGET_64BIT)
+    {
+      rtx tmp = gen_reg_rtx (SImode);
+      emit_insn (gen_extendhisi2 (tmp, operands[1]));
+      emit_insn (gen_extendsidi2 (operands[0], tmp));
+      DONE;
+    }
+  else
+    {
+      operands[1] = gen_lowpart (DImode, operands[1]);
+      emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (48)));
+      emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (48))); 
+      DONE;
+    }
+}
+")
+
+(define_insn "*extendhidi2"
   [(set (match_operand:DI 0 "register_operand" "=d")
-        (sign_extend:DI (match_operand:HI 1 "register_operand" "d")))
-   (clobber (reg:CC 33))]
+        (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
   "TARGET_64BIT"
-  "sllg\\t%0,%1,48\;srag\\t%0,%0,48"
-  [(set_attr "op_type" "NN")
-   (set_attr "length"  "12")
-   (set_attr "type"   "o2")])  
+  "lgh\\t%0,%1"
+  [(set_attr "op_type" "RXE")
+   (set_attr "atype"   "mem")])
 
 ;
 ; extendqidi2 instruction pattern(s).
 ;
 
-(define_insn "extendqidi2"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (sign_extend:DI (match_operand:QI 1 "register_operand" "d")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "sllg\\t%0,%1,56\;srag\\t%0,%0,56"
-  [(set_attr "op_type" "NN")
-   (set_attr "length"  "12")
-   (set_attr "type"    "o2")])
+(define_expand "extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
+  ""
+  "
+{
+  if (!TARGET_64BIT)
+    {
+      rtx tmp = gen_reg_rtx (SImode);
+      emit_insn (gen_extendqisi2 (tmp, operands[1]));
+      emit_insn (gen_extendsidi2 (operands[0], tmp));
+      DONE;
+    }
+  else
+    {
+      operands[1] = gen_lowpart (DImode, operands[1]);
+      emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (56)));
+      emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (56))); 
+      DONE;
+    }
+}
+")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (sign_extend:DI (match_operand:QI 1 "s_operand" "")))]
+  "TARGET_64BIT && !reload_completed"
+  [(parallel
+    [(set (match_dup 0) (unspec:DI [(match_dup 1)] 10))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
+     (clobber (reg:CC 33))])]
+  "")
 
 ;
 ; extendhisi2 instruction pattern(s).
 ;
 
-(define_insn "extendhisi2"
-  [(set (match_operand:SI 0 "register_operand" "=d,!d,d")
-        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,d,m")))
-   (clobber (reg:CC 33))]
+(define_expand "extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
   ""
-  "@
-   sll\\t%1,16\;sra\\t%1,16
-   lr\\t%0,%1\;sll\\t%0,16\;sra\\t%0,16
-   lh\\t%0,%1"
-  [(set_attr "op_type" "NN,NN,RX")
-   (set_attr "type"   "o2,o3,integer")
-   (set_attr "atype"   "reg,reg,mem")
-   (set_attr "length"  "8,10,*")])
+  "
+{
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  emit_insn (gen_ashlsi3 (operands[0], operands[1], GEN_INT (16)));
+  emit_insn (gen_ashrsi3 (operands[0], operands[0], GEN_INT (16))); 
+  DONE;
+}
+")
 
+(define_insn "*extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+  ""
+  "lh\\t%0,%1"
+  [(set_attr "op_type" "RX")
+   (set_attr "atype"   "mem")])
 
 ;
 ; extendqisi2 instruction pattern(s).
 ;
 
-(define_insn "extendqisi2"
-  [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (sign_extend:SI (match_operand:QI 1 "r_or_s_operand" "0,Q")))
-   (clobber (reg:CC 33))]
+(define_expand "extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
   ""
-  "@
-   sll\\t%0,24\;sra\\t%0,24
-   icm\\t%0,8,%1\;sra\\t%0,24"
-  [(set_attr "op_type" "NN,NN")
-   (set_attr "type"    "o2")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "length"  "8,8")])
+  "
+{
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  emit_insn (gen_ashlsi3 (operands[0], operands[1], GEN_INT (24)));
+  emit_insn (gen_ashrsi3 (operands[0], operands[0], GEN_INT (24))); 
+  DONE;
+}
+")
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (sign_extend:SI (match_operand:QI 1 "s_operand" "")))]
+  "!reload_completed"
+  [(parallel
+    [(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
+     (clobber (reg:CC 33))])]
+  "")
 
 ;
 ; extendqihi2 instruction pattern(s).
 ;
 
-(define_insn "extendqihi2"
-  [(set (match_operand:HI 0 "register_operand" "=d,d")
-        (sign_extend:HI (match_operand:QI 1 "r_or_s_operand" "0,Q")))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   sll\\t%0,24\;sra\\t%0,24
-   icm\\t%0,8,%1\;sra\\t%0,24"
-  [(set_attr "op_type" "NN,NN")
-   (set_attr "type"    "o2")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "length"  "8,8")])
-
 
 ;
 ; zero_extendsidi2 instruction pattern(s).
 ;
 
-(define_insn "zero_extendsidi2"
+(define_expand "zero_extendsidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
+  ""
+  "
+{
+  if (!TARGET_64BIT)
+    {
+      rtx insns, subword;
+
+      operands[1] = force_reg (SImode, operands[1]);
+      subword = operand_subword (operands[0], 0, 1, DImode);
+
+      start_sequence ();
+      emit_move_insn (subword, operands[1]);
+      emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (32))); 
+      insns = get_insns ();
+      end_sequence ();
+
+      emit_no_conflict_block (insns, operands[0], operands[1], 0, 
+                              gen_rtx_ZERO_EXTEND (DImode, operands[1]));
+
+      /* Avoid having the REG_RETVAL destroyed by someone attaching 
+         other REG_EQUAL notes.  */
+      emit_move_insn (operands[0], operands[0]);
+      DONE;
+    }
+}
+")
+
+(define_insn "*zero_extendsidi2"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")))]
   "TARGET_64BIT"
   [(set_attr "op_type" "RRE,RXE")
    (set_attr "atype"   "reg,mem")])
 
-
 ;
 ; zero_extendhidi2 instruction pattern(s).
 ;
 
-(define_insn "zero_extendhidi2"
-  [(set (match_operand:DI 0 "register_operand" "=!d,d")
-        (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+(define_expand "zero_extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
+  ""
+  "
+{
+  if (!TARGET_64BIT)
+    {
+      rtx tmp = gen_reg_rtx (SImode);
+      emit_insn (gen_zero_extendhisi2 (tmp, operands[1]));
+      emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
+      DONE;
+    }
+  else
+    {
+      operands[1] = gen_lowpart (DImode, operands[1]);
+      emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (48)));
+      emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (48))); 
+      DONE;
+    }
+}
+")
+
+(define_insn "*zero_extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
   "TARGET_64BIT"
-  "@
-   llgfr\\t%0,%1\;iilh\\t%0,0
-   llgh\\t%0,%1"
-  [(set_attr "op_type" "NN,RXE")
-   (set_attr "type"   "o2,integer")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "length"  "12,*")])       
+  "llgh\\t%0,%1"
+  [(set_attr "op_type" "RXE")
+   (set_attr "atype"   "mem")])
 
 ;
 ; zero_extendqidi2 instruction pattern(s)
 ;
 
-(define_insn "zero_extendqidi2"
-  [(set (match_operand:DI 0 "register_operand" "=!d,d")
-        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "d,m")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "@
-   sllg\\t%0,%1,56\;srlg\\t%0,%0,56
-   llgc\\t%0,%1"
-  [(set_attr "op_type" "NN,RXE")
-   (set_attr "type"   "o2,integer")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "length"  "12,*")])
+(define_expand "zero_extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
+  ""
+  "
+{
+  if (!TARGET_64BIT)
+    {
+      rtx tmp = gen_reg_rtx (SImode);
+      emit_insn (gen_zero_extendqisi2 (tmp, operands[1]));
+      emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
+      DONE;
+    }
+  else
+    {
+      operands[1] = gen_lowpart (DImode, operands[1]);
+      emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (56)));
+      emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (56))); 
+      DONE;
+    }
+}
+")
 
+(define_insn "*zero_extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (zero_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
+  "TARGET_64BIT"
+  "llgc\\t%0,%1"
+  [(set_attr "op_type" "RXE")
+   (set_attr "atype"   "mem")])
 
 ;
 ; zero_extendhisi2 instruction pattern(s).
 
 (define_expand "zero_extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "")
-        (zero_extend:SI (match_operand:HI 1 "r_or_s_operand" "")))]
+        (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
   ""
   "
 {
-  if (!TARGET_64BIT)
-    {
-      emit_insn (gen_zero_extendhisi2_31 (operands[0], operands[1],
-                force_const_mem (SImode, const0_rtx)));
-      DONE;
-    }
-}")
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  emit_insn (gen_andsi3 (operands[0], operands[1], GEN_INT (0xffff)));
+  DONE;
+}
+")
 
 (define_insn "*zero_extendhisi2_64"
-  [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,m")))]
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
   "TARGET_64BIT"
-  "@
-   iilh\\t%0,0
-   llgh\\t%0,%1"
-  [(set_attr "op_type" "RI,RXE")
-   (set_attr "atype"   "reg,mem")])
-
-(define_insn "zero_extendhisi2_31"
-  [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (zero_extend:SI (match_operand:HI 1 "r_or_s_operand" "0,Q")))
-   (use (match_operand:SI 2 "memory_operand" "m,m"))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   icm\\t%0,12,%2
-   icm\\t%0,12,%1\;srl\\t%0,16"
-  [(set_attr "op_type" "RX,NN")
-   (set_attr "type"   "integer,o2")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "length"  "*,8")])
-
-
+  "llgh\\t%0,%1"
+  [(set_attr "op_type" "RXE")
+   (set_attr "atype"   "mem")])
 ;
 ; zero_extendqisi2 instruction pattern(s).
 ;
 
-(define_insn "*zero_extendqisi2_mem_31"
-  [(set (match_operand:SI 0 "register_operand" "=&d")
-        (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))
-   (use (match_operand:SI 2 "memory_operand" "m" ))
-   (clobber (reg:CC 33))]
+(define_expand "zero_extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
   ""
-  "sr\\t%0,%0\;ic\\t%0,%1"
-  [(set_attr "op_type" "NN")
-   (set_attr "type"    "o2")
-   (set_attr "atype"   "mem")
-   (set_attr "length"  "6")])
+  "
+{
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  emit_insn (gen_andsi3 (operands[0], operands[1], GEN_INT (0xff)));
+  DONE;
+}
+")
 
-(define_insn "zero_extendqisi2_reg_31"
+(define_insn "*zero_extendqisi2_64"
   [(set (match_operand:SI 0 "register_operand" "=d")
-        (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))
-   (use (match_operand:SI 2 "memory_operand" "m" ))
-   (clobber (reg:CC 33))]
-  ""
-  "icm\\t%0,14,%2"
-  [(set_attr "op_type" "RX")
+        (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+  "TARGET_64BIT"
+  "llgc\\t%0,%1"
+  [(set_attr "op_type" "RXE")
    (set_attr "atype"   "mem")])
+;
+; zero_extendqihi2 instruction pattern(s).
+;
 
-(define_insn "*zero_extendqisi2_64"
-  [(set                 (match_operand:SI 0 "register_operand" "=!d,d")
-        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand"  "d,m")))]
+(define_expand "zero_extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "")
+        (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
   "TARGET_64BIT"
-  "@
-   sllg\\t%0,%1,56\;srlg\\t%0,%0,56
-   llgc\\t%0,%1"
-  [(set_attr "op_type" "NN,RXE")
-   (set_attr "type"   "o2,integer")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "length"  "12,*")])
-
-(define_expand "zero_extendqisi2"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (zero_extend:SI (match_operand:QI 1 "r_or_s_operand"  "")))]
-  ""
   "
 {
-  if (!TARGET_64BIT)
-    {
-      emit_insn (gen_zero_extendqisi2_reg_31 (operands[0], operands[1],
-                              force_const_mem (SImode, const0_rtx)));
-      DONE;
-    }
-}")
-
-
-;
-; zero_extendqihi2 instruction pattern(s).
-;
-
-(define_insn "zero_extendqihi2_64"
-  [(set (match_operand:HI 0 "register_operand" "=d,d")
-        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,m")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "@
-   nill\\t%0,0x00FF
-   llgc\\t%0,%1"
-  [(set_attr "op_type" "RI,RXE")
-   (set_attr "atype"   "reg,mem")])
-
-(define_insn "zero_extendqihi2_31"
-  [(set (match_operand:HI 0 "register_operand" "=d,&d")
-        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,m")))
-   (use (match_operand:SI 2 "memory_operand" "m,m"))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   icm\\t%0,14,%2
-   sr\\t%0,%0\;ic\\t%0,%1"
-  [(set_attr "op_type" "RX,NN")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "length"  "*,8")])
-
-(define_expand "zero_extendqihi2"
-  [(set (match_operand:HI 0 "register_operand" "")
-        (zero_extend:HI (match_operand:QI 1 "general_operand" "")))]
-  ""
-  "
-{
-  if (!TARGET_64BIT)
-    {
-      emit_insn (gen_zero_extendqihi2_31 (operands[0], operands[1],
-                              force_const_mem (SImode, const0_rtx)));
-      DONE;
-    }
-  else
-   {
-      emit_insn (gen_zero_extendqihi2_64 (operands[0], operands[1]));
-      DONE;
-    }
-}")
-
-
-;
-; truncdisi2 instruction pattern(s).
-;
-
-(define_insn "truncdisi2"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (truncate:SI (match_operand:DI 1 "register_operand" "d")))]
-  "TARGET_64BIT"
-  "llgfr\\t%0,%1"
-  [(set_attr "op_type" "RRE")])
-
-
-;
-; truncdihi2 instruction pattern(s).
-;
-
-(define_insn "truncdihi2"
-  [(set (match_operand:HI 0 "register_operand" "=d")
-        (truncate:HI (match_operand:DI 1 "register_operand" "d")))]
-  "TARGET_64BIT"
-  "llgfr\\t%0,%1\;iilh\\t%0,0"
-   [(set_attr "op_type" "NN")
-    (set_attr "length" "10")])
-
-
-;
-; truncdiqi2 instruction pattern(s).
-;
-
-(define_insn "truncdiqi2"
-  [(set (match_operand:QI 0 "register_operand" "=d")
-        (truncate:QI (match_operand:DI 1 "register_operand" "d")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "sllg\\t%0,%1,56\;srlg\\t%0,%0,56"
-  [(set_attr "op_type" "NN")
-   (set_attr "type"    "o2")   
-   (set_attr "length"  "12")])
-
-
-;
-; truncsihi2 instruction pattern(s).
-;
-
-(define_expand "truncsihi2"
-  [(set (match_operand:HI 0 "register_operand" "")
-        (truncate:HI (match_operand:SI 1 "register_operand" "")))]
-  ""
-  "
-{
-  if (!TARGET_64BIT)
-    {
-      emit_insn (gen_do_truncsihi2 (operands[0], operands[1],
-                              force_const_mem (SImode, const0_rtx)));
-      DONE;
-    }
-}")
-
-
-(define_insn "do_truncsihi2"
-  [(set (match_operand:HI 0 "register_operand" "=d")
-        (truncate:HI (match_operand:SI 1 "register_operand"  "0")))
-        (use (match_operand:SI 2 "memory_operand" "m"))
-   (clobber (reg:CC 33))]
-  ""
-  "icm\\t%0,12,%2"
-   [(set_attr "op_type" "RX")])
+  operands[1] = gen_lowpart (HImode, operands[1]);
+  emit_insn (gen_andhi3 (operands[0], operands[1], GEN_INT (0xff)));
+  DONE;
+}
+")
 
-(define_insn "*truncsihi2_64"
+(define_insn "*zero_extendqihi2_64"
   [(set (match_operand:HI 0 "register_operand" "=d")
-        (truncate:HI (match_operand:SI 1 "register_operand" "0")))]
-  "TARGET_64BIT"
-  "iilh\\t%0,0"
-  [(set_attr "op_type" "RI")])
-
-
-;
-; truncsiqi2 instruction pattern(s).
-;
-
-(define_insn "truncsiqi2"
-  [(set (match_operand:QI 0 "register_operand" "=d")
-        (truncate:QI (match_operand:SI 1 "register_operand" "0")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "iilh\\t%0,0\;nill\\t%0,0x00FF"
-  [(set_attr "op_type" "NN")
-   (set_attr "type"    "o2")
-   (set_attr "length"  "8")])
-
-
-;
-; trunchiqi2 instruction pattern(s).
-;
-
-(define_insn "trunchiqi2"
-  [(set (match_operand:QI 0 "register_operand" "=d")
-        (truncate:QI (match_operand:HI 1 "register_operand" "0")))
+        (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
-  "nill\\t%0,0x00FF"
-  [(set_attr "op_type" "RI")])
-
+  "llgc\\t%0,%1"
+  [(set_attr "op_type" "RXE")
+   (set_attr "atype"   "mem")])
 
 ;
 ; fixuns_truncdfdi2 and fix_truncdfsi2 instruction pattern(s).
   rtx temp = gen_reg_rtx (DFmode);
   operands[1] = force_reg (DFmode, operands[1]);
 
-  emit_insn (gen_cmpdf (operands[1], force_const_mem (DFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x8000000000000000ULL, DFmode))));
+  emit_insn (gen_cmpdf (operands[1], 
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"9223372036854775808.0\", DFmode), DFmode)));
   emit_jump_insn (gen_blt (label1));
-
-  emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, DFmode))));
+  emit_insn (gen_subdf3 (temp, operands[1],
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"18446744073709551616.0\", DFmode), DFmode)));
   emit_insn (gen_fix_truncdfdi2_ieee (operands[0], temp, GEN_INT(7)));
   emit_jump (label2);
 
   "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cgdbr\\t%0,%h2,%1"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"   "other")])
+   (set_attr "type"    "other")])
 
 ;
 ; fixuns_truncdfsi2 and fix_truncdfsi2 instruction pattern(s).
   rtx temp = gen_reg_rtx (DFmode);
 
   operands[1] = force_reg (DFmode,operands[1]);
-  emit_insn (gen_cmpdf (operands[1], force_const_mem (DFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x80000000ULL, DFmode))));
+  emit_insn (gen_cmpdf (operands[1], 
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"2147483648.0\", DFmode), DFmode)));
   emit_jump_insn (gen_blt (label1));
-  emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, DFmode))));
+  emit_insn (gen_subdf3 (temp, operands[1],
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"4294967296.0\", DFmode), DFmode)));
   emit_insn (gen_fix_truncdfsi2_ieee (operands[0], temp, GEN_INT (7)));
   emit_jump (label2);
 
       /* This is the algorithm from POP chapter A.5.7.2.  */
 
       rtx temp   = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
-      rtx two31r = force_const_mem (DFmode,
-                                    gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
-                                             0x08000000, 0x4F000000));
-      rtx two32  = force_const_mem (DFmode,
-                                    gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
-                                             0x0, 0x4E000001));
+      rtx two31r = s390_gen_rtx_const_DI (0x4f000000, 0x08000000);
+      rtx two32  = s390_gen_rtx_const_DI (0x4e000001, 0x00000000);
 
       operands[1] = force_reg (DFmode, operands[1]);
       emit_insn (gen_fix_truncdfsi2_ibm (operands[0], operands[1], 
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cfdbr\\t%0,%h2,%1"
    [(set_attr "op_type" "RRE")
-    (set_attr "type"   "other" )])
+    (set_attr "type"    "other" )])
 
 (define_insn "fix_truncdfsi2_ibm"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (fix:SI (match_operand:DF 1 "nonimmediate_operand" "+f")))
-   (use (match_operand:DF 2 "memory_operand" "m"))
-   (use (match_operand:DF 3 "memory_operand" "m"))
+   (use (match_operand:DI 2 "immediate_operand" "m"))
+   (use (match_operand:DI 3 "immediate_operand" "m"))
    (use (match_operand:BLK 4 "memory_operand" "m"))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
    return \"l\\t%0,%N4\";
 }"
   [(set_attr "op_type" "NN")
-   (set_attr "type"   "other")
+   (set_attr "type"    "other")
    (set_attr "length"  "20")])
 
 ;
   rtx temp = gen_reg_rtx (SFmode);
 
   operands[1] = force_reg (SFmode, operands[1]);
-  emit_insn (gen_cmpsf (operands[1], force_const_mem (SFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x8000000000000000ULL, SFmode))));
+  emit_insn (gen_cmpsf (operands[1], 
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"9223372036854775808.0\", SFmode), SFmode)));
   emit_jump_insn (gen_blt (label1));
 
-  emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, SFmode))));
+  emit_insn (gen_subsf3 (temp, operands[1],
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"18446744073709551616.0\", SFmode), SFmode)));
   emit_insn (gen_fix_truncsfdi2_ieee (operands[0], temp, GEN_INT(7)));
   emit_jump (label2);
 
   "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cgebr\\t%0,%h2,%1"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"   "other")])
+   (set_attr "type"    "other")])
 
 ;
 ; fixuns_truncsfsi2 and fix_truncsfsi2 instruction pattern(s).
   rtx temp = gen_reg_rtx (SFmode);
 
   operands[1] = force_reg (SFmode, operands[1]);
-  emit_insn (gen_cmpsf (operands[1], force_const_mem (SFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x80000000ULL, SFmode))));
+  emit_insn (gen_cmpsf (operands[1],
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"2147483648.0\", SFmode), SFmode)));
   emit_jump_insn (gen_blt (label1));
-  emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, SFmode))));
+  emit_insn (gen_subsf3 (temp, operands[1],
+       CONST_DOUBLE_FROM_REAL_VALUE (
+          REAL_VALUE_ATOF (\"4294967296.0\", SFmode), SFmode)));
   emit_insn (gen_fix_truncsfsi2_ieee (operands[0], temp, GEN_INT (7)));
   emit_jump (label2);
 
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cfebr\\t%0,%h2,%1"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"   "other")])
+   (set_attr "type"    "other")])
 
 ;
 ; floatdidf2 instruction pattern(s).
 
 (define_insn "floatdidf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
-        (float:DF (match_operand:DI 1 "register_operand" "d")))]
+        (float:DF (match_operand:DI 1 "register_operand" "d")))
+   (clobber (reg:CC 33))]
   "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cdgbr\\t%0,%1"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"   "other" )])
+   (set_attr "type"    "other" )])
 
 ;
 ; floatdisf2 instruction pattern(s).
 
 (define_insn "floatdisf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
-        (float:SF (match_operand:DI 1 "register_operand" "d")))]
+        (float:SF (match_operand:DI 1 "register_operand" "d")))
+   (clobber (reg:CC 33))]
   "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cegbr\\t%0,%1"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"   "other" )])
+   (set_attr "type"    "other" )])
 
 ;
 ; floatsidf2 instruction pattern(s).
 ;
 
 (define_expand "floatsidf2"
-  [(set (match_operand:DF 0 "register_operand" "")
-        (float:DF (match_operand:SI 1 "register_operand" "")))]
+  [(parallel
+    [(set (match_operand:DF 0 "register_operand" "")
+          (float:DF (match_operand:SI 1 "register_operand" "")))
+     (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "
 {
       /* This is the algorithm from POP chapter A.5.7.1.  */
 
       rtx temp  = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
-      rtx two31 = force_const_mem (DFmode,
-                                   gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
-                                            0x80000000U, 0x4E000000U));
+      rtx two31 = s390_gen_rtx_const_DI (0x4e000000, 0x80000000);         
 
       emit_insn (gen_floatsidf2_ibm (operands[0], operands[1], two31, temp));
       DONE;
 
 (define_insn "floatsidf2_ieee"
   [(set (match_operand:DF 0 "register_operand" "=f")
-        (float:DF (match_operand:SI 1 "register_operand"  "d")))]
+        (float:DF (match_operand:SI 1 "register_operand"  "d")))
+   (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cdfbr\\t%0,%1"
   [(set_attr "op_type" "RRE")
 (define_insn "floatsidf2_ibm"
   [(set (match_operand:DF 0 "register_operand" "=f")
         (float:DF (match_operand:SI 1 "register_operand" "d")))
-   (use (match_operand:DF 2 "memory_operand" "m"))
+   (use (match_operand:DI 2 "immediate_operand" "m"))
    (use (match_operand:BLK 3 "memory_operand" "m"))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "*
 {
-   output_asm_insn (\"st\\t%0,%N3\", operands);
+   output_asm_insn (\"st\\t%1,%N3\", operands);
    output_asm_insn (\"xi\\t%N3,128\", operands);
    output_asm_insn (\"mvc\\t%O3(4,%R3),%2\", operands);
    output_asm_insn (\"ld\\t%0,%3\", operands);
    return \"sd\\t%0,%2\";
 }"
   [(set_attr "op_type" "NN")
-   (set_attr "type"   "other" )
+   (set_attr "type"    "other" )
    (set_attr "length"  "20")])
 
 ;
 ;
 
 (define_expand "floatsisf2"
-  [(set (match_operand:SF 0 "register_operand" "")
-        (float:SF (match_operand:SI 1 "register_operand" "")))]
+  [(parallel
+    [(set (match_operand:SF 0 "register_operand" "")
+          (float:SF (match_operand:SI 1 "register_operand" "")))
+     (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "
 {
 
 (define_insn "floatsisf2_ieee"
   [(set (match_operand:SF 0 "register_operand" "=f")
-        (float:SF (match_operand:SI 1 "register_operand" "d")))]
+        (float:SF (match_operand:SI 1 "register_operand" "d")))
+   (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "cefbr\\t%0,%1"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"   "other" )])
+   (set_attr "type"    "other" )])
 
 ;
 ; truncdfsf2 instruction pattern(s).
   [(set (match_operand:SF 0 "register_operand" "")
         (float_truncate:SF (match_operand:DF 1 "general_operand" "")))]
   "TARGET_HARD_FLOAT"
-  "
-{
-  if (CONSTANT_P(operands[1]))
-      operands[1] =  force_const_mem (DFmode, operands[1]);
-}")
+  "")
 
 (define_insn "truncdfsf2_ieee"
   [(set (match_operand:SF 0 "register_operand" "=f")
-        (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "f")))]
+        (float_truncate:SF (match_operand:DF 1 "general_operand" "f")))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "ledbr\\t%0,%1"
   [(set_attr "op_type"  "RR")])
 
 (define_insn "truncdfsf2_ibm"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
-        (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+        (float_truncate:SF (match_operand:DF 1 "general_operand" "f,m")))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
    lrer\\t%0,%1
    le\\t%0,%1"
-  [(set_attr "op_type"  "RR,RX")])
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
 
 ;
 ; extendsfdf2 instruction pattern(s).
   "@
    sdr\\t%0,%0\;ler\\t%0,%1
    sdr\\t%0,%0\;le\\t%0,%1"
-  [(set_attr "op_type"  "RRE,RXE")])
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")
+   (set_attr "type"     "o2,o2")]) 
 
 
 ;;
   "!TARGET_64BIT"
   "*
 {
-   switch(which_alternative)
+   switch (which_alternative)
      {
      case 0: /* d <- d */
        output_asm_insn (\"ar\\t%0,%2\", operands);
        output_asm_insn (\"a\\t%0,%2\", operands);
        output_asm_insn (\"al\\t%N0,%N2\", operands);
        break;
+
+     default:
+       abort ();
      }
 
    output_asm_insn (\"brc\\t12,.+8\", operands);
 }"
   [(set_attr "op_type" "NN,NN")
    (set_attr "atype"   "reg,mem")
+   (set_attr "type"    "o2,o2")
    (set_attr "length"  "12,16")])
 
 (define_expand "adddi3"
    && !rtx_equal_p (operands[0], operands[2])"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
-  "")
+  "
+{
+  if (CONSTANT_P (operands[1]) 
+      && !legitimate_reload_constant_p (operands[1]))
+    operands[1] = force_const_mem (DImode, operands[1]);
+}")
+
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
    && !rtx_equal_p (operands[0], operands[2])"
   [(set (match_dup 0) (match_dup 2))
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))]
-  "")
+  "
+{
+  if (CONSTANT_P (operands[2]) 
+      && !legitimate_reload_constant_p (operands[2]))
+    operands[2] = force_const_mem (DImode, operands[2]);
+}")
  
 ;
 ; addsi3 instruction pattern(s).
 ;
-; The following insn is used when it is known that operand one is the stack pointer,
-; and operand two is small enough to fit in the displacement field
-; In this case, the result will be an address
-;
 
-(define_insn "addaddr"
+(define_insn "*la_ccclobber"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+        (match_operand:QI 1 "address_operand"  "p"))
+   (clobber (reg:CC 33))]
+  "legitimate_la_operand_p (operands[1])"
+  "la\\t%0,%a1"
+   [(set_attr "op_type"  "RX")
+    (set_attr "atype"    "mem")
+    (set_attr "type"     "la")])
+
+(define_insn "*addaddr_ccclobber"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (plus:SI (match_operand:SI 1 "register_operand" "%a,a")
-                 (match_operand:SI 2 "nonmemory_operand" "J,a")))]
+                 (match_operand:SI 2 "nonmemory_operand" "J,a")))
+   (clobber (reg:CC 33))]
   "(((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
+     (REGNO (operands[1]) == FRAME_POINTER_REGNUM ) || 
      (REGNO (operands[1]) == BASE_REGISTER)) && 
-       (GET_CODE (operands[2]) == REG ||
+        (GET_CODE (operands[2]) == REG ||
         CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
   "@
    la\\t%0,%c2(,%1)
   [(set_attr "op_type"  "RR,RI,RX")
    (set_attr "atype"    "reg,reg,mem")])
 
-(define_insn "*do_la"
+(define_insn "*la"
   [(set (match_operand:SI 0 "register_operand" "=a")
         (match_operand:QI 1 "address_operand" "p"))]
   "reload_in_progress || reload_completed
    && !rtx_equal_p (operands[0], operands[2])"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
-  "")
+  "
+{
+  if (CONSTANT_P (operands[1]) 
+      && !legitimate_reload_constant_p (operands[1]))
+    operands[1] = force_const_mem (SImode, operands[1]);
+}")
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
    && !rtx_equal_p (operands[0], operands[2])"
   [(set (match_dup 0) (match_dup 2))
    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
-  "")
+  "
+{
+  if (CONSTANT_P (operands[2]) 
+      && !legitimate_reload_constant_p (operands[2]))
+    operands[2] = force_const_mem (SImode, operands[2]);
+}")
  
-(define_insn "addsi_64"
-  [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (plus:SI (match_operand:SI 1 "register_operand" "%a,a")
-                 (match_operand:SI 2 "nonmemory_operand" "J,a")))]
-  "TARGET_64BIT"
-  "@
-   la\\t%0,%c2(,%1)
-   la\\t%0,0(%1,%2)"
-  [(set_attr "op_type"  "RX")
-   (set_attr "atype"    "mem")
-   (set_attr "type"     "la")])
 
 ;
 ; addhi3 instruction pattern(s).
   [(parallel
     [(set (match_operand:DF 0 "register_operand" "=f,f")
           (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
-                   (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                   (match_operand:DF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 (define_insn "*adddf3"
   [(set (match_operand:DF 0 "register_operand" "=f,f")
         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
-                 (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
 (define_insn "*adddf3_ibm"
   [(set (match_operand:DF 0 "register_operand" "=f,f")
         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
-                 (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
   [(parallel
     [(set (match_operand:SF 0 "register_operand" "=f,f")
           (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
-                   (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                   (match_operand:SF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 (define_insn "*addsf3"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
         (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
-                 (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
 (define_insn "*addsf3"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
         (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
-                 (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
         (minus:DI (match_operand:DI 1 "register_operand" "0,0")
-                  (match_operand:DI 2 "nonimmediate_operand" "d,m")))
+                  (match_operand:DI 2 "general_operand" "d,m")))
    (clobber (reg:CC 33))]
   ""
   "*
        output_asm_insn (\"s\\t%0,%2\", operands);
        output_asm_insn (\"sl\\t%N0,%N2\", operands);
        break;
+
+     default:
+       abort ();
      }
 
    output_asm_insn (\"brc\\t11,.+8\", operands);
 }"
   [(set_attr "op_type"  "NN,NN")
    (set_attr "atype"    "reg,mem")
+   (set_attr "type"     "other,other")
    (set_attr "length"   "12,16")])
 
 ;
 ;
 
 (define_insn "subhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,d,d")
-        (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
-                  (match_operand:HI 2 "nonimmediate_operand" "d,K,m")))
+  [(set (match_operand:HI 0 "register_operand" "=d,d")
+        (minus:HI (match_operand:HI 1 "register_operand" "0,0")
+                  (match_operand:HI 2 "general_operand" "d,m")))
    (clobber (reg:CC 33))]
   ""
   "@
    sr\\t%0,%2
-   ahi\\t%0,-%h2
    sh\\t%0,%2"
-  [(set_attr "op_type"  "RR,RI,RX")
-   (set_attr "atype"    "reg,reg,mem")])
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
 
 ;
 ; subqi3 instruction pattern(s).
   [(parallel
     [(set (match_operand:DF 0 "register_operand" "=f,f")
           (minus:DF (match_operand:DF 1 "register_operand" "0,0")
-                    (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                    (match_operand:DF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 (define_insn "*subdf3"
   [(set (match_operand:DF 0 "register_operand" "=f,f")
         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
-                  (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                  (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
 (define_insn "*subdf3_ibm"
   [(set (match_operand:DF 0 "register_operand" "=f,f")
         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
-                  (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                  (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
   [(parallel
     [(set (match_operand:SF 0 "register_operand" "=f,f")
           (minus:SF (match_operand:SF 1 "register_operand" "0,0")
-                    (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                    (match_operand:SF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 (define_insn "*subsf3"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
         (minus:SF (match_operand:SF 1 "register_operand" "0,0")
-                  (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                  (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
 (define_insn "*subsf3_ibm"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
         (minus:SF (match_operand:SF 1 "register_operand" "0,0")
-                  (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                  (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
 ;;- Multiply instructions.
 ;;
 
-(define_expand "muldi3"
-  [(parallel
-    [(set (match_operand:DI 0 "register_operand" "")
-          (mult:DI (match_operand:DI 1 "register_operand" "")
-                   (match_operand:DI 2 "register_operand" "")))
-     (clobber (reg:CC 33))])]
-  ""
-  "
-{
-  if (!TARGET_64BIT)
-    {
-      rtx label1 = gen_label_rtx ();
-      rtx label2 = gen_label_rtx ();
-      rtx op0_0 = operand_subword (operands[0], 0 ,1, DImode);
-      rtx op0_1 = operand_subword (operands[0], 1 ,1, DImode);
-      rtx temp1_0 = gen_reg_rtx (SImode); 
-      rtx temp1_1 = gen_reg_rtx (SImode);
-      rtx temp2_0 = gen_reg_rtx (SImode);
-      rtx temp2_1 = gen_reg_rtx (SImode);
-      emit_move_insn (temp1_0, operand_subword (operands[1], 0 ,1, DImode)); 
-      emit_move_insn (temp1_1, operand_subword (operands[1], 1 ,1, DImode));
-      emit_move_insn (temp2_0, operand_subword (operands[2], 0 ,1, DImode));
-      emit_move_insn (temp2_1, operand_subword (operands[2], 1 ,1, DImode));
-      emit_move_insn (op0_1, temp1_1);
-      emit_insn (gen_mulsi_6432 (operands[0], operands[0], temp2_1));
-      
-      emit_insn (gen_cmpsi (temp1_1, const0_rtx));
-      emit_jump_insn (gen_bge (label1));
-      emit_insn (gen_addsi3 (op0_0, op0_0, temp2_1));
-      emit_label (label1);
-      emit_insn (gen_cmpsi (temp2_1, const0_rtx));
-      emit_jump_insn (gen_bge (label2));
-      emit_insn (gen_addsi3 (op0_0, op0_0, temp1_1));
-      emit_label (label2);
-
-      emit_insn (gen_mulsi3 (temp2_1, temp2_1, temp1_0));
-      emit_insn (gen_addsi3 (op0_0, op0_0, temp2_1));
-      
-      emit_insn (gen_mulsi3 (temp1_1, temp1_1, temp2_0));
-      emit_insn (gen_addsi3 (op0_0, op0_0, temp1_1));
-      
-      DONE;
-    }
-}")
+;
+; muldi3 instruction pattern(s).
+;
 
-(define_insn "*muldi3_64"
+(define_insn "muldi3"
   [(set (match_operand:DI 0 "register_operand" "=d,d,d")
         (mult:DI (match_operand:DI 1 "register_operand" "%0,0,0")
                  (match_operand:DI 2 "general_operand" "d,K,m")))
    (set_attr "atype"    "reg,reg,mem")
    (set_attr "type"     "imul")])
 
-;
-; mulsidi3 instruction pattern(s).
-;
-
-;(define_expand "mulsidi3"
-;  [(set (match_operand:DI 0 "register_operand" "")
-;      (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
-;               (sign_extend:DI (match_operand:SI 2 "general_operand" ""))))]
-;  ""
-;  "
-;{
-;  emit_insn (gen_extendsidi2 (operands[0], operands[1]));
-;  emit_insn (gen_muldisidi3  (operands[0], operands[0], operands[2]));
-;  DONE;
-;}")
-
-;(define_insn "muldisidi3"
-;  [(set (match_operand:DI 0 "register_operand" "=d,d")
-;      (mult:DI (match_operand:DI 1 "register_operand" "0,0")
-;               (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
-;    (clobber (reg:CC 33))]
-;   "!TARGET_64BIT"
-;   "@
-;    mr\\t%0,%2
-;    m\\t%0,%2"
-;  [(set_attr "op_type"  "RR,RX")
-;   (set_attr "atype"    "reg,mem")
-;   (set_attr "type"     "imul")])
-
 ;
 ; mulsi3 instruction pattern(s).
 ;
    (set_attr "atype"    "reg,reg,mem")
    (set_attr "type"     "imul")])
 
+;
+; mulsidi3 instruction pattern(s).
+;
+
+(define_expand "mulsidi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+                (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))))]
+  "!TARGET_64BIT"
+  "
+{
+  rtx insn;
+
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0]));
+  emit_move_insn (gen_lowpart (SImode, operands[0]), operands[1]);
+  insn = emit_insn (gen_mulsi_6432 (operands[0], operands[0], operands[2]));
+
+  REG_NOTES (insn) =
+       gen_rtx_EXPR_LIST (REG_EQUAL, 
+                           gen_rtx_MULT (DImode, 
+                               gen_rtx_SIGN_EXTEND (DImode, operands[1]),
+                               gen_rtx_SIGN_EXTEND (DImode, operands[2])),
+                          REG_NOTES (insn));
+  DONE;
+}")
 (define_insn "mulsi_6432"
    [(set (match_operand:DI 0 "register_operand" "=d,d")
          (mult:DI (sign_extend:DI 
-                   (subreg:SI (match_operand:DI 1 "register_operand" "0,0") 4))
+                   (truncate:SI (match_operand:DI 1 "register_operand" "0,0")))
                   (sign_extend:DI
-                   (match_operand:SI 2 "general_operand" "d,m"))))
+                   (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
     (clobber (reg:CC 33))]
    "!TARGET_64BIT"
    "@
    (set_attr "atype"    "reg,mem")
    (set_attr "type"     "imul")])
  
-
 ;
 ; muldf3 instruction pattern(s).
 ;
   [(parallel
     [(set (match_operand:DF 0 "register_operand" "=f,f")
           (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
-                   (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                   (match_operand:DF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 (define_insn "*muldf3"
   [(set (match_operand:DF 0 "register_operand" "=f,f")
         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
-                 (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
    mdbr\\t%0,%2
    mdb\\t%0,%2"
   [(set_attr "op_type"  "RR,RX")
-   (set_attr "type"    "fmul")
+   (set_attr "type"     "fmul")
    (set_attr "atype"    "reg,mem")])
 
 (define_insn "*muldf3_ibm"
   [(set (match_operand:DF 0 "register_operand" "=f,f")
         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
-                 (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
   [(parallel
     [(set (match_operand:SF 0 "register_operand" "=f,f")
           (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
-                   (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                   (match_operand:SF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 (define_insn "*mulsf3"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
         (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
-                 (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
 (define_insn "*mulsf3_ibm"
   [(set (match_operand:SF 0 "register_operand" "=f,f")
         (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
-                 (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+                 (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
 ;;
 
 ;
-; divdi3 and moddi3 instruction pattern(s).
+; divmoddi4 instruction pattern(s).
 ;
 
-(define_expand "divdi3"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (div:DI (match_operand:DI 1 "register_operand" "d")
-                (match_operand:DI 2 "general_operand" "")))]
-  "TARGET_64BIT"
-  "
-{
-  rtx op3 = gen_reg_rtx (TImode);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (DImode, operands[2]);
-
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);        
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);       
-  emit_insn (gen_divmodtidi3 (op3, op3, operands[2]));
-  emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 8));
-  DONE;
-}")
-
-(define_expand "moddi3"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (mod:DI (match_operand:DI 1 "register_operand" "d")
-                (match_operand:DI 2 "general_operand" "")))]
+(define_expand "divmoddi4"
+  [(parallel [(set (match_operand:DI 0 "general_operand" "")
+                  (div:DI (match_operand:DI 1 "general_operand" "")
+                          (match_operand:DI 2 "general_operand" "")))
+             (set (match_operand:DI 3 "general_operand" "")
+                  (mod:DI (match_dup 1) (match_dup 2)))])
+   (clobber (match_dup 4))]
   "TARGET_64BIT"
   "
 {
-  rtx op3 = gen_reg_rtx (TImode);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (DImode, operands[2]);       
+  rtx insn, div_equal, mod_equal, equal;
+
+  div_equal = gen_rtx_DIV (DImode, operands[1], operands[2]);
+  mod_equal = gen_rtx_MOD (DImode, operands[1], operands[2]);
+  equal = gen_rtx_IOR (TImode,
+                      gen_rtx_ZERO_EXTEND (TImode, div_equal),
+                      gen_rtx_ASHIFT (TImode,
+                                      gen_rtx_ZERO_EXTEND (TImode, mod_equal),
+                                      GEN_INT (64)));
+
+  operands[4] = gen_reg_rtx(TImode);
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[4]));
+  emit_move_insn (gen_lowpart (DImode, operands[4]), operands[1]);
+  insn = emit_insn (gen_divmodtidi3 (operands[4], operands[4], operands[2]));
+  REG_NOTES (insn) =
+       gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+  insn = emit_move_insn (operands[0], gen_lowpart (DImode, operands[4]));
+  REG_NOTES (insn) =
+        gen_rtx_EXPR_LIST (REG_EQUAL, div_equal, REG_NOTES (insn));
+
+  insn = emit_move_insn (operands[3], gen_highpart (DImode, operands[4]));
+  REG_NOTES (insn) =
+        gen_rtx_EXPR_LIST (REG_EQUAL, mod_equal, REG_NOTES (insn));
 
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);        
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);       
-  emit_insn (gen_divmodtidi3 (op3, op3, operands[2]));
-  emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 0));
   DONE;
 }")
 
 (define_insn "divmodtidi3"
-  [(set (subreg:DI (match_operand:TI 0 "register_operand" "=d,d") 0)
-        (truncate:DI 
-          (mod:TI (match_operand:TI 1 "register_operand" "0,0")
-                  (sign_extend:TI 
-                    (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
-   (set (subreg:DI (match_dup 0) 8)
-        (truncate:DI (div:TI (match_dup 1) (sign_extend:TI (match_dup 2)))))
-   (clobber (reg:CC 33))]
+  [(set (match_operand:TI 0 "register_operand" "=d,d")
+        (ior:TI
+          (zero_extend:TI
+            (div:DI (truncate:DI (match_operand:TI 1 "register_operand" "0,0"))
+                    (match_operand:DI 2 "general_operand" "d,m")))
+          (ashift:TI
+            (zero_extend:TI
+              (mod:DI (truncate:DI (match_dup 1)) 
+                      (match_dup 2)))
+            (const_int 64))))]
   "TARGET_64BIT"
   "@
    dsgr\\t%0,%2
    (set_attr "type"     "idiv")
    (set_attr "atype"    "reg,mem")])
 
-;
-; udivdi3 and umoddi3 instruction pattern(s).
-;
-
-(define_expand "udivdi3"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (udiv:DI (match_operand:DI 1 "register_operand" "d")
-                (match_operand:DI 2 "general_operand" "")))]
+(define_insn "divmodtisi3"
+  [(set (match_operand:TI 0 "register_operand" "=d,d")
+        (ior:TI
+          (zero_extend:TI
+            (div:DI (truncate:DI (match_operand:TI 1 "register_operand" "0,0"))
+                    (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
+          (ashift:TI
+            (zero_extend:TI
+              (mod:DI (truncate:DI (match_dup 1)) 
+                      (sign_extend:DI (match_dup 2))))
+            (const_int 64))))]
   "TARGET_64BIT"
-  "
-{
-  rtx op3 = gen_reg_rtx(TImode);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (DImode, operands[2]);
+  "@
+   dsgfr\\t%0,%2
+   dsgf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "type"     "idiv")
+   (set_attr "atype"    "reg,mem")])
 
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);        
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);
-  emit_insn (gen_udivmodtidi3 (op3, op3, operands[2]));
-  emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 8));
-  DONE;
-}")
+;
+; udivmoddi4 instruction pattern(s).
+;
 
-(define_expand "umoddi3"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (umod:DI (match_operand:DI 1 "register_operand" "d")
-                (match_operand:DI 2 "general_operand" "")))]
+(define_expand "udivmoddi4"
+  [(parallel [(set (match_operand:DI 0 "general_operand" "")
+                  (udiv:DI (match_operand:DI 1 "general_operand" "")
+                           (match_operand:DI 2 "nonimmediate_operand" "")))
+             (set (match_operand:DI 3 "general_operand" "")
+                  (umod:DI (match_dup 1) (match_dup 2)))])
+   (clobber (match_dup 4))]
   "TARGET_64BIT"
   "
 {
-  rtx op3 = gen_reg_rtx (TImode);
+  rtx insn, div_equal, mod_equal, equal;
+
+  div_equal = gen_rtx_UDIV (DImode, operands[1], operands[2]);
+  mod_equal = gen_rtx_UMOD (DImode, operands[1], operands[2]);
+  equal = gen_rtx_IOR (TImode,
+                      gen_rtx_ZERO_EXTEND (TImode, div_equal),
+                      gen_rtx_ASHIFT (TImode,
+                                      gen_rtx_ZERO_EXTEND (TImode, mod_equal),
+                                      GEN_INT (64)));
+
+  operands[4] = gen_reg_rtx(TImode);
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[4]));
+  emit_move_insn (gen_lowpart (DImode, operands[4]), operands[1]);
+  emit_move_insn (gen_highpart (DImode, operands[4]), const0_rtx);
+  insn = emit_insn (gen_udivmodtidi3 (operands[4], operands[4], operands[2]));
+  REG_NOTES (insn) =
+       gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+  insn = emit_move_insn (operands[0], gen_lowpart (DImode, operands[4]));
+  REG_NOTES (insn) =
+        gen_rtx_EXPR_LIST (REG_EQUAL, div_equal, REG_NOTES (insn));
+
+  insn = emit_move_insn (operands[3], gen_highpart (DImode, operands[4]));
+  REG_NOTES (insn) =
+        gen_rtx_EXPR_LIST (REG_EQUAL, mod_equal, REG_NOTES (insn));
 
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (DImode, operands[2]);
-
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);        
-  emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);       
-  emit_insn (gen_udivmodtidi3 (op3, op3, operands[2]));
-  emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 0));
   DONE;
 }")
 
 (define_insn "udivmodtidi3"
-  [(set (subreg:DI (match_operand:TI 0 "register_operand" "=d,d") 0)
-        (truncate:DI 
-          (umod:TI (match_operand:TI 1 "register_operand" "0,0")
-                   (zero_extend:TI 
-                     (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
-   (set (subreg:DI (match_dup 0) 8)
-        (truncate:DI (udiv:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))
-   (clobber (reg:CC 33))]
+  [(set (match_operand:TI 0 "register_operand" "=d,d")
+        (ior:TI (zero_extend:TI 
+                  (truncate:DI
+                    (udiv:TI (match_operand:TI 1 "register_operand" "0,0")
+                             (zero_extend:TI
+                               (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
+                (ashift:TI
+                  (zero_extend:TI
+                    (truncate:DI
+                      (umod:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))
+                  (const_int 64))))]
   "TARGET_64BIT"
   "@
    dlgr\\t%0,%2
    (set_attr "atype"    "reg,mem")])
 
 ;
-; divsi3 and modsi3 instruction pattern(s).
+; divmodsi4 instruction pattern(s).
 ;
 
-(define_expand "divsi3"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (div:SI (match_operand:SI 1 "register_operand" "d")
-                (match_operand:SI 2 "nonimmediate_operand" "")))]
-  "!TARGET_64BIT"
-  "
-{
-  rtx tmp = gen_reg_rtx (DImode);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (SImode, operands[2]);       
-  else
-    operands[2] = force_reg (SImode, operands[2]);
-
-  emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
-  emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]);
-  emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32))); 
-  emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
-  emit_move_insn (operands[0], gen_rtx_SUBREG (SImode, tmp, 4));
-  DONE;
-}")
-
-(define_expand "modsi3"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (mod:SI (match_operand:SI 1 "register_operand" "d")
-                (match_operand:SI 2 "nonimmediate_operand" "")))]
+(define_expand "divmodsi4"
+  [(parallel [(set (match_operand:SI 0 "general_operand" "")
+                  (div:SI (match_operand:SI 1 "general_operand" "")
+                          (match_operand:SI 2 "nonimmediate_operand" "")))
+             (set (match_operand:SI 3 "general_operand" "")
+                  (mod:SI (match_dup 1) (match_dup 2)))])
+   (clobber (match_dup 4))]
   "!TARGET_64BIT"
   "
 {
-  rtx tmp = gen_reg_rtx (DImode);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_const_mem (SImode, operands[2]);       
-  else
-    operands[2] = force_reg (SImode, operands[2]);
+  rtx insn, div_equal, mod_equal, equal;
+
+  div_equal = gen_rtx_DIV (SImode, operands[1], operands[2]);
+  mod_equal = gen_rtx_MOD (SImode, operands[1], operands[2]);
+  equal = gen_rtx_IOR (DImode,
+                      gen_rtx_ZERO_EXTEND (DImode, div_equal),
+                      gen_rtx_ASHIFT (DImode,
+                                      gen_rtx_ZERO_EXTEND (DImode, mod_equal),
+                                      GEN_INT (32)));
+
+  operands[4] = gen_reg_rtx(DImode);
+  emit_insn (gen_extendsidi2 (operands[4], operands[1]));
+  insn = emit_insn (gen_divmoddisi3 (operands[4], operands[4], operands[2]));
+  REG_NOTES (insn) =
+       gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+  insn = emit_move_insn (operands[0], gen_lowpart (SImode, operands[4]));
+  REG_NOTES (insn) =
+        gen_rtx_EXPR_LIST (REG_EQUAL, div_equal, REG_NOTES (insn));
+
+  insn = emit_move_insn (operands[3], gen_highpart (SImode, operands[4]));
+  REG_NOTES (insn) =
+        gen_rtx_EXPR_LIST (REG_EQUAL, mod_equal, REG_NOTES (insn));
 
-  emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
-  emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]));
-  emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32))); 
-  emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
-  emit_move_insn (operands[0], gen_rtx_SUBREG (SImode, tmp, 0));
   DONE;
 }")
 
 (define_insn "divmoddisi3"
-  [(set (subreg:SI (match_operand:DI 0 "register_operand" "=d,d") 0)
-        (truncate:SI 
-          (mod:DI (match_operand:DI 1 "register_operand" "0,0")
-                  (sign_extend:DI 
-                    (match_operand:SI 2 "nonimmediate_operand" "d,m")))))
-   (set (subreg:SI (match_dup 0) 4)
-        (truncate:SI (div:DI (match_dup 1) (sign_extend:DI (match_dup 2)))))
-   (clobber (reg:CC 33))]
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (ior:DI (zero_extend:DI
+                  (truncate:SI
+                    (div:DI (match_operand:DI 1 "register_operand" "0,0")
+                            (sign_extend:DI 
+                              (match_operand:SI 2 "nonimmediate_operand" "d,m")))))
+                (ashift:DI
+                  (zero_extend:DI
+                    (truncate:SI
+                      (mod:DI (match_dup 1) (sign_extend:SI (match_dup 2)))))
+                  (const_int 32))))]
   "!TARGET_64BIT"
   "@
    dr\\t%0,%2
 ; udivsi3 and umodsi3 instruction pattern(s).
 ;
 
+
 (define_expand "udivsi3"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (udiv:SI (match_operand:SI 1 "general_operand" "")
-                 (match_operand:SI 2 "general_operand" "")))]
+                 (match_operand:SI 2 "general_operand" "")))
+   (clobber (match_dup 3))]
   "!TARGET_64BIT"
   "
 {
-  rtx dr_0, dr_1, tmp;
+  rtx insn, udiv_equal, umod_equal, equal;
 
-  tmp = gen_reg_rtx (DImode);
-  dr_0 = gen_rtx_SUBREG (SImode, tmp, 0);      
-  dr_1 = gen_rtx_SUBREG (SImode, tmp, 4);
+  udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
+  umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
+  equal = gen_rtx_IOR (DImode,
+                      gen_rtx_ZERO_EXTEND (DImode, udiv_equal),
+                      gen_rtx_ASHIFT (DImode,
+                                      gen_rtx_ZERO_EXTEND (DImode, umod_equal),
+                                      GEN_INT (32)));
+
+  operands[3] = gen_reg_rtx (DImode);
 
   if (CONSTANT_P (operands[2]))
     {
         {
           rtx label1 = gen_label_rtx ();
 
-          emit_move_insn (dr_0, operands[1]);
-          emit_move_insn (dr_1, const0_rtx);
-          emit_insn (gen_cmpsi (dr_0, operands[2]));
+         operands[1] = make_safe_from (operands[1], operands[0]);
+          emit_move_insn (operands[0], const0_rtx);
+          emit_insn (gen_cmpsi (operands[1], operands[2]));
           emit_jump_insn (gen_bltu (label1));
-          emit_move_insn (dr_1, const1_rtx);
+          emit_move_insn (operands[0], const1_rtx);
           emit_label (label1);
         }
       else
         {
-          operands[2] = force_const_mem (SImode, operands[2]);
-          emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
-          emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
-         emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+          operands[2] = force_reg (SImode, operands[2]);       
+          operands[2] = make_safe_from (operands[2], operands[0]);     
+
+         emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+         insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+                                            operands[2]));
+         REG_NOTES (insn) =
+           gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+         
+         insn = emit_move_insn (operands[0], 
+                                gen_lowpart (SImode, operands[3]));
+         REG_NOTES (insn) =
+           gen_rtx_EXPR_LIST (REG_EQUAL, 
+                              udiv_equal, REG_NOTES (insn));
         }
     }
   else
       rtx label3 = gen_label_rtx ();
 
       operands[1] = force_reg (SImode, operands[1]);   
+      operands[1] = make_safe_from (operands[1], operands[0]); 
       operands[2] = force_reg (SImode, operands[2]);   
-       
-      emit_move_insn (dr_1, const0_rtx);
+      operands[2] = make_safe_from (operands[2], operands[0]); 
+
+      emit_move_insn (operands[0], const0_rtx);
       emit_insn (gen_cmpsi (operands[2], operands[1]));
       emit_jump_insn (gen_bgtu (label3));
       emit_insn (gen_cmpsi (operands[2], const1_rtx));
       emit_jump_insn (gen_blt (label2));
       emit_insn (gen_cmpsi (operands[2], const1_rtx));
       emit_jump_insn (gen_beq (label1));
-      emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
-      emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
-      emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+      emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+      insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+                                        operands[2]));
+      REG_NOTES (insn) =
+      gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+      
+      insn = emit_move_insn (operands[0], 
+                            gen_lowpart (SImode, operands[3]));
+      REG_NOTES (insn) =
+      gen_rtx_EXPR_LIST (REG_EQUAL, 
+                              udiv_equal, REG_NOTES (insn));
       emit_jump (label3);
       emit_label (label1);
-      emit_move_insn (dr_1, operands[1]);
+      emit_move_insn (operands[0], operands[1]);
       emit_jump (label3);
       emit_label (label2);
-      emit_move_insn (dr_1, const1_rtx);
+      emit_move_insn (operands[0], const1_rtx);
       emit_label (label3);
     }
-
-  emit_move_insn (operands[0], dr_1);
+  emit_move_insn (operands[0], operands[0]);   
   DONE;
 }")
 
 (define_expand "umodsi3"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (umod:SI (match_operand:SI 1 "nonimmediate_operand" "")
-                 (match_operand:SI 2 "nonimmediate_operand" "")))]
+                 (match_operand:SI 2 "nonimmediate_operand" "")))
+   (clobber (match_dup 3))]
   "!TARGET_64BIT"
   "
 {
-  rtx dr_0, dr_1, tmp;
+  rtx insn, udiv_equal, umod_equal, equal;
+
+  udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
+  umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
+  equal = gen_rtx_IOR (DImode,
+                      gen_rtx_ZERO_EXTEND (DImode, udiv_equal),
+                      gen_rtx_ASHIFT (DImode,
+                                      gen_rtx_ZERO_EXTEND (DImode, umod_equal),
+                                      GEN_INT (32)));
 
-  tmp = gen_reg_rtx (DImode);
-  dr_0 = gen_rtx_SUBREG (SImode, tmp, 0);      
-  dr_1 = gen_rtx_SUBREG (SImode, tmp, 4);
+  operands[3] = gen_reg_rtx (DImode);
 
   if (CONSTANT_P (operands[2]))
     {
         {
           rtx label1 = gen_label_rtx ();
 
-         emit_move_insn (dr_0, operands[1]);
-          emit_insn (gen_cmpsi (dr_0, operands[2]));
+          operands[1] = make_safe_from (operands[1], operands[0]);
+         emit_move_insn (operands[0], operands[1]);
+          emit_insn (gen_cmpsi (operands[0], operands[2]));
           emit_jump_insn (gen_bltu (label1));
-         emit_insn (gen_abssi2 (dr_0, operands[2]));
-          emit_insn (gen_addsi3 (dr_0,dr_0, operands[1]));
+         emit_insn (gen_abssi2 (operands[0], operands[2]));
+          emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
           emit_label (label1);
         }
       else
         {
-          operands[2] = force_const_mem (SImode, operands[2]);
-          emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
-          emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
-         emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+          operands[2] = force_reg (SImode, operands[2]);       
+          operands[2] = make_safe_from (operands[2], operands[0]);     
+
+         emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+         insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+                                            operands[2]));
+         REG_NOTES (insn) =
+           gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+         
+         insn = emit_move_insn (operands[0], 
+                                gen_highpart (SImode, operands[3]));
+         REG_NOTES (insn) =
+           gen_rtx_EXPR_LIST (REG_EQUAL, 
+                              umod_equal, REG_NOTES (insn));
         }
     }
   else
       rtx label3 = gen_label_rtx ();
 
       operands[1] = force_reg (SImode, operands[1]);   
+      operands[1] = make_safe_from (operands[1], operands[0]); 
       operands[2] = force_reg (SImode, operands[2]);   
+      operands[2] = make_safe_from (operands[2], operands[0]); 
 
-      emit_move_insn(dr_0, operands[1]);       
-      emit_insn (gen_cmpsi (operands[2], dr_0));
+      emit_move_insn(operands[0], operands[1]);        
+      emit_insn (gen_cmpsi (operands[2], operands[1]));
       emit_jump_insn (gen_bgtu (label3));
       emit_insn (gen_cmpsi (operands[2], const1_rtx));
       emit_jump_insn (gen_blt (label2));
       emit_insn (gen_cmpsi (operands[2], const1_rtx));
       emit_jump_insn (gen_beq (label1));
-      emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
-      emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
-      emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+      emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+      insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+                                        operands[2]));
+      REG_NOTES (insn) =
+      gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+      
+      insn = emit_move_insn (operands[0], 
+                            gen_highpart (SImode, operands[3]));
+      REG_NOTES (insn) =
+      gen_rtx_EXPR_LIST (REG_EQUAL, 
+                        umod_equal, REG_NOTES (insn));
       emit_jump (label3);
       emit_label (label1);
-      emit_move_insn (dr_0, const0_rtx);
+      emit_move_insn (operands[0], const0_rtx);
       emit_jump (label3);
       emit_label (label2);
-      emit_insn (gen_subsi3 (dr_0, dr_0, operands[2]));
+      emit_insn (gen_subsi3 (operands[0], operands[0], operands[2]));
       emit_label (label3);
     }
-
-  emit_move_insn (operands[0], dr_0);
   DONE;
 }")
 
 
 (define_expand "divdf3"
   [(parallel
-    [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
-          (div:DF (match_operand:DF 1 "general_operand" "0,0")
-                  (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+    [(set (match_operand:DF 0 "register_operand" "=f,f")
+          (div:DF (match_operand:DF 1 "register_operand" "0,0")
+                  (match_operand:DF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 
 (define_insn "*divdf3"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
-        (div:DF (match_operand:DF 1 "general_operand" "0,0")
-                (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+  [(set (match_operand:DF 0 "register_operand" "=f,f")
+        (div:DF (match_operand:DF 1 "register_operand" "0,0")
+                (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
    ddbr\\t%0,%2
    ddb\\t%0,%2"
   [(set_attr "op_type"  "RR,RX")
-   (set_attr "type"    "fdiv")
+   (set_attr "type"     "fdiv")
    (set_attr "atype"    "reg,mem")])
 
 (define_insn "*divdf3_ibm"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
-        (div:DF (match_operand:DF 1 "general_operand" "0,0")
-                (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+  [(set (match_operand:DF 0 "register_operand" "=f,f")
+        (div:DF (match_operand:DF 1 "register_operand" "0,0")
+                (match_operand:DF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
    ddr\\t%0,%2
    dd\\t%0,%2"
   [(set_attr "op_type"  "RR,RX")
-   (set_attr "type"    "fdiv")
+   (set_attr "type"     "fdiv")
    (set_attr "atype"    "reg,mem")])
 
 ;
 
 (define_expand "divsf3"
   [(parallel
-    [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
-          (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
-                  (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+    [(set (match_operand:SF 0 "register_operand" "=f,f")
+          (div:SF (match_operand:SF 1 "register_operand" "0,0")
+                  (match_operand:SF 2 "general_operand" "f,m")))
      (clobber (reg:CC 33))])]
   "TARGET_HARD_FLOAT"
   "")
 
 (define_insn "*divsf3"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
-        (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
-                (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+        (div:SF (match_operand:SF 1 "register_operand" "0,0")
+                (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
   "@
    (set_attr "atype"    "reg,mem")])
 
 (define_insn "*divsf3"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
-        (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
-                (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+        (div:SF (match_operand:SF 1 "register_operand" "0,0")
+                (match_operand:SF 2 "general_operand" "f,m")))
    (clobber (reg:CC 33))]
   "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
   "@
 
 (define_insn "*anddi3_cc"
   [(set (reg 33)
-        (compare (and:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
-                         (match_operand:DI 2 "r_or_s_operand" "d,m,Q"))
+        (compare (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+                         (match_operand:DI 2 "general_operand" "d,m"))
                  (const_int 0)))
-   (set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
+   (set (match_operand:DI 0 "register_operand" "=d,d")
         (and:DI (match_dup 1) (match_dup 2)))]
   "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
   "@
    ngr\\t%0,%2
-   ng\\t%0,%2
-   nc\\t%O0(8,%R0),%2"
-  [(set_attr "op_type"  "RR,RX,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   ng\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
 
 (define_insn "*anddi3_cconly"
   [(set (reg 33)
         (compare (and:DI (match_operand:DI 1 "register_operand" "%0,0")
-                         (match_operand:DI 2 "r_or_s_operand" "d,m"))
+                         (match_operand:DI 2 "general_operand" "d,m"))
                  (const_int 0)))
    (clobber (match_scratch:DI 0 "=d,d"))]
   "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
   "@
    ngr\\t%0,%2
    ng\\t%0,%2"
-  [(set_attr "op_type"  "RR,RX")
+  [(set_attr "op_type"  "RRE,RXE")
    (set_attr "atype"    "reg,mem")])
 
+(define_insn "*anddi3_ni"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (and:DI (match_operand:DI 1 "register_operand" "%0")
+                (match_operand:DI 2 "immediate_operand" "n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT && s390_single_hi (operands[2], DImode, -1) >= 0"
+  "*
+{
+  int part = s390_single_hi (operands[2], DImode, -1);
+  operands[2] = GEN_INT (s390_extract_hi (operands[2], DImode, part));
+
+  switch (part)
+    {
+      case 0: return \"nihh\\t%0,%x2\";
+      case 1: return \"nihl\\t%0,%x2\";
+      case 2: return \"nilh\\t%0,%x2\";
+      case 3: return \"nill\\t%0,%x2\";
+      default: abort ();
+    }
+}"
+  [(set_attr "op_type"  "RI")
+   (set_attr "atype"    "reg")])
+
 (define_insn "anddi3"
-  [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
-        (and:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
-                (match_operand:DI 2 "r_or_s_operand" "d,m,Q")))
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+                (match_operand:DI 2 "general_operand" "d,m")))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
   "@
    ngr\\t%0,%2
-   ng\\t%0,%2
-   nc\\t%O0(8,%R0),%2"
-  [(set_attr "op_type"  "RR,RX,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   ng\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*anddi3_ss"
+  [(set (match_operand:DI 0 "s_operand" "=Qo")
+        (and:DI (match_dup 0)
+                (match_operand:DI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "nc\\t%O0(8,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*anddi3_ss_inv"
+  [(set (match_operand:DI 0 "s_operand" "=Qo")
+        (and:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "nc\\t%O0(8,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
 ; andsi3 instruction pattern(s).
 
 (define_insn "*andsi3_cc"
   [(set (reg 33)
-        (compare (and:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
-                         (match_operand:SI 2 "r_or_s_operand" "d,m,Q"))
+        (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+                         (match_operand:SI 2 "general_operand" "d,m"))
                  (const_int 0)))
-   (set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
+   (set (match_operand:SI 0 "register_operand" "=d,d")
         (and:SI (match_dup 1) (match_dup 2)))]
   "s390_match_ccmode(insn, CCTmode)"
   "@
    nr\\t%0,%2
-   n\\t%0,%2
-   nc\\t%O0(4,%R0),%2"
-  [(set_attr "op_type"  "RR,RX,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   n\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
 
 (define_insn "*andsi3_cconly"
   [(set (reg 33)
         (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0")
-                         (match_operand:SI 2 "r_or_s_operand" "d,m"))
+                         (match_operand:SI 2 "general_operand" "d,m"))
                  (const_int 0)))
    (clobber (match_scratch:SI 0 "=d,d"))]
   "s390_match_ccmode(insn, CCTmode)"
   [(set_attr "op_type"  "RR,RX")
    (set_attr "atype"    "reg,mem")])
 
+(define_insn "*andsi3_ni"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (and:SI (match_operand:SI 1 "register_operand" "%0")
+                (match_operand:SI 2 "immediate_operand" "n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT && s390_single_hi (operands[2], SImode, -1) >= 0"
+  "*
+{
+  int part = s390_single_hi (operands[2], SImode, -1);
+  operands[2] = GEN_INT (s390_extract_hi (operands[2], SImode, part));
+
+  switch (part)
+    {
+      case 0: return \"nilh\\t%0,%x2\";
+      case 1: return \"nill\\t%0,%x2\";
+      default: abort ();
+    }
+}"
+  [(set_attr "op_type"  "RI")
+   (set_attr "atype"    "reg")])
+
 (define_insn "andsi3"
-  [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
-        (and:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
-                (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+        (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "general_operand" "d,m")))
    (clobber (reg:CC 33))]
   ""
   "@
    nr\\t%0,%2
-   n\\t%0,%2
-   nc\\t%O0(4,%R0),%2"
-  [(set_attr "op_type"  "RR,RX,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   n\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*andsi3_ss"
+  [(set (match_operand:SI 0 "s_operand" "=Qo")
+        (and:SI (match_dup 0)
+                (match_operand:SI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "nc\\t%O0(4,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*andsi3_ss_inv"
+  [(set (match_operand:SI 0 "s_operand" "=Qo")
+        (and:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "nc\\t%O0(4,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
 ; andhi3 instruction pattern(s).
 ;
 
-(define_expand "andhi3"
-  [(parallel 
-    [(set (match_operand:HI 0 "r_or_s_operand" "")
-        (and:HI (match_operand:HI 1 "r_or_s_operand" "")
-                (match_operand:HI 2 "r_or_s_operand" "")))
-     (clobber (reg:CC 33))])]
+(define_insn "*andhi3_ni"
+  [(set (match_operand:HI 0 "register_operand" "=d,d")
+        (and:HI (match_operand:HI 1 "register_operand" "%0,0")
+                (match_operand:HI 2 "nonmemory_operand" "d,n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   nr\\t%0,%2
+   nill\\t%0,%x2"
+  [(set_attr "op_type"  "RR,RI")
+   (set_attr "atype"    "reg")])
+
+(define_insn "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "=d")
+        (and:HI (match_operand:HI 1 "register_operand" "%0")
+                (match_operand:HI 2 "nonmemory_operand" "d")))
+   (clobber (reg:CC 33))]
   ""
-  "
-{
-  if (CONSTANT_P (operands[2]))
-      operands[2] = force_const_mem (HImode, operands[2]);
-}")
+  "nr\\t%0,%2"
+  [(set_attr "op_type"  "RR")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*andhi3_ss"
+  [(set (match_operand:HI 0 "s_operand" "=Qo")
+        (and:HI (match_dup 0)
+                (match_operand:HI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "nc\\t%O0(2,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
-(define_insn "*andhi3"
-  [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
-        (and:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
-                (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+(define_insn "*andhi3_ss_inv"
+  [(set (match_operand:HI 0 "s_operand" "=Qo")
+        (and:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
    (clobber (reg:CC 33))]
   ""
-  "@
-   nr\\t%0,%2
-   nc\\t%O0(2,%R0),%2"
-  [(set_attr "op_type"  "RR,SS")
-   (set_attr "atype"    "reg,mem")])
+  "nc\\t%O0(2,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
 ; andqi3 instruction pattern(s).
 ;
 
+(define_insn "*andqi3_ni"
+  [(set (match_operand:QI 0 "register_operand" "=d,d")
+        (and:QI (match_operand:QI 1 "register_operand" "%0,0")
+                (match_operand:QI 2 "nonmemory_operand" "d,n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   nr\\t%0,%2
+   nill\\t%0,%b2"
+  [(set_attr "op_type"  "RR,RI")
+   (set_attr "atype"    "reg")])
+
 (define_insn "andqi3"
-  [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
-        (and:QI (match_operand:QI 1 "r_or_s_operand" "%0,0,0")
-                (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+  [(set (match_operand:QI 0 "register_operand" "=d")
+        (and:QI (match_operand:QI 1 "register_operand" "%0")
+                (match_operand:QI 2 "nonmemory_operand" "d")))
+   (clobber (reg:CC 33))]
+  ""
+  "nr\\t%0,%2"
+  [(set_attr "op_type"  "RR")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*andqi3_ss"
+  [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+        (and:QI (match_dup 0)
+                (match_operand:QI 1 "s_imm_operand" "n,Qo")))
    (clobber (reg:CC 33))]
   ""
   "@
-   nr\\t%0,%2
-   ni\\t%0,%b2
-   nc\\t%O0(1,%R0),%2"
-  [(set_attr "op_type"  "RR,SI,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   ni\\t%0,%b1
+   nc\\t%O0(1,%R0),%1"
+  [(set_attr "op_type"  "SI,SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*andqi3_ss_inv"
+  [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+        (and:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "@
+   ni\\t%0,%b1
+   nc\\t%O0(1,%R0),%1"
+  [(set_attr "op_type"  "SI,SS")
+   (set_attr "atype"    "mem")])
 
 
 ;;
 ; iordi3 instruction pattern(s).
 ;
 
+(define_insn "*iordi3_cc"
+  [(set (reg 33)
+        (compare (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+                         (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d,d")
+        (ior:DI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+  "@
+   ogr\\t%0,%2
+   og\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*iordi3_cconly"
+  [(set (reg 33)
+        (compare (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+                         (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d,d"))]
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+  "@
+   ogr\\t%0,%2
+   og\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*iordi3_oi"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (ior:DI (match_operand:DI 1 "register_operand" "%0")
+                (match_operand:DI 2 "immediate_operand" "n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT && s390_single_hi (operands[2], DImode, 0) >= 0"
+  "*
+{
+  int part = s390_single_hi (operands[2], DImode, 0);
+  operands[2] = GEN_INT (s390_extract_hi (operands[2], DImode, part));
+
+  switch (part)
+    {
+      case 0: return \"oihh\\t%0,%x2\";
+      case 1: return \"oihl\\t%0,%x2\";
+      case 2: return \"oilh\\t%0,%x2\";
+      case 3: return \"oill\\t%0,%x2\";
+      default: abort ();
+    }
+}"
+  [(set_attr "op_type"  "RI")
+   (set_attr "atype"    "reg")])
+
 (define_insn "iordi3"
-  [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q,d")
-        (ior:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0,0")
-                (match_operand:DI 2 "r_or_s_operand" "d,m,Q,L")))
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+                (match_operand:DI 2 "general_operand" "d,m")))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
   "@
    ogr\\t%0,%2
-   og\\t%0,%2
-   oc\\t%O0(8,%R0),%2
-   oill\\t%0,%2"
-  [(set_attr "op_type"  "RRE,RXE,SS,RI")
-   (set_attr "atype"    "reg,mem,mem,reg")])
+   og\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*iordi3_ss"
+  [(set (match_operand:DI 0 "s_operand" "=Qo")
+        (ior:DI (match_dup 0)
+                (match_operand:DI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "oc\\t%O0(8,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*iordi3_ss_inv"
+  [(set (match_operand:DI 0 "s_operand" "=Qo")
+        (ior:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "oc\\t%O0(8,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
 ; iorsi3 instruction pattern(s).
 ;
 
-(define_expand "iorsi3"
-  [(parallel
-    [(set (match_operand:SI 0 "r_or_s_operand" "")
-        (ior:SI (match_operand:SI 1 "r_or_s_operand" "")
-                (match_operand:SI 2 "r_or_s_operand" "")))
-     (clobber (reg:CC 33))])]
+(define_insn "*iorsi3_cc"
+  [(set (reg 33)
+        (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+                         (match_operand:SI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=d,d")
+        (ior:SI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode(insn, CCTmode)"
+  "@
+   or\\t%0,%2
+   o\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*iorsi3_cconly"
+  [(set (reg 33)
+        (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+                         (match_operand:SI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
+  "s390_match_ccmode(insn, CCTmode)"
+  "@
+   or\\t%0,%2
+   o\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*iorsi3_oi"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (ior:SI (match_operand:SI 1 "register_operand" "%0")
+                (match_operand:SI 2 "immediate_operand" "n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT && s390_single_hi (operands[2], SImode, 0) >= 0"
+  "*
+{
+  int part = s390_single_hi (operands[2], SImode, 0);
+  operands[2] = GEN_INT (s390_extract_hi (operands[2], SImode, part));
+
+  switch (part)
+    {
+      case 0: return \"oilh\\t%0,%x2\";
+      case 1: return \"oill\\t%0,%x2\";
+      default: abort ();
+    }
+}"
+  [(set_attr "op_type"  "RI")
+   (set_attr "atype"    "reg")])
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+        (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "general_operand" "d,m")))
+   (clobber (reg:CC 33))]
+  ""
+  "@
+   or\\t%0,%2
+   o\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*iorsi3_ss"
+  [(set (match_operand:SI 0 "s_operand" "=Qo")
+        (ior:SI (match_dup 0)
+                (match_operand:SI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "oc\\t%O0(4,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*iorsi3_ss_inv"
+  [(set (match_operand:SI 0 "s_operand" "=Qo")
+        (ior:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "oc\\t%O0(4,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
+
+;
+; iorhi3 instruction pattern(s).
+;
+
+(define_insn "*iorhi3_oi"
+  [(set (match_operand:HI 0 "register_operand" "=d,d")
+        (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
+                (match_operand:HI 2 "nonmemory_operand" "d,n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   or\\t%0,%2
+   oill\\t%0,%x2"
+  [(set_attr "op_type"  "RR,RI")
+   (set_attr "atype"    "reg")])
+
+(define_insn "iorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=d")
+        (ior:HI (match_operand:HI 1 "register_operand" "%0")
+                (match_operand:HI 2 "nonmemory_operand" "d")))
+   (clobber (reg:CC 33))]
   ""
-  "
-{
-  if (CONSTANT_P (operands[2]))
-      operands[2] =  force_const_mem (SImode, operands[2]);
-}")
+  "or\\t%0,%2"
+  [(set_attr "op_type"  "RR")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*iorhi3_ss"
+  [(set (match_operand:HI 0 "s_operand" "=Qo")
+        (ior:HI (match_dup 0)
+                (match_operand:HI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "oc\\t%O0(2,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
-(define_insn "*iorsi3"
-  [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
-        (ior:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
-                (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+(define_insn "*iorhi3_ss_inv"
+  [(set (match_operand:HI 0 "s_operand" "=Qo")
+        (ior:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
    (clobber (reg:CC 33))]
   ""
-  "@
-   or\\t%0,%2
-   o\\t%0,%2
-   oc\\t%O0(4,%R0),%2"
-  [(set_attr "op_type"  "RR,RX,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+  "oc\\t%O0(2,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
-; iorhi3 instruction pattern(s).
+; iorqi3 instruction pattern(s).
 ;
 
-(define_expand "iorhi3"
-  [(parallel 
-    [(set (match_operand:HI 0 "r_or_s_operand" "")
-        (ior:HI (match_operand:HI 1 "r_or_s_operand" "")
-                (match_operand:HI 2 "r_or_s_operand" "")))
-     (clobber (reg:CC 33))])]
-  ""
-  "
-{
-  if (CONSTANT_P (operands[2]))
-      operands[2] =  force_const_mem (HImode, operands[2]);
-}")
+(define_insn "*iorqi3_oi"
+  [(set (match_operand:QI 0 "register_operand" "=d,d")
+        (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
+                (match_operand:QI 2 "nonmemory_operand" "d,n")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   or\\t%0,%2
+   oill\\t%0,%b2"
+  [(set_attr "op_type"  "RR,RI")
+   (set_attr "atype"    "reg")])
 
-(define_insn "*iorhi3"
-  [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
-        (ior:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
-                (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "register_operand" "=d")
+        (ior:QI (match_operand:QI 1 "register_operand" "%0")
+                (match_operand:QI 2 "nonmemory_operand" "d")))
+   (clobber (reg:CC 33))]
+  ""
+  "or\\t%0,%2"
+  [(set_attr "op_type"  "RR")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*iorqi3_ss"
+  [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+        (ior:QI (match_dup 0)
+                (match_operand:QI 1 "s_imm_operand" "n,Qo")))
    (clobber (reg:CC 33))]
   ""
   "@
-   or\\t%0,%2
-   oc\\t%O0(2,%R0),%2"
-  [(set_attr "op_type"  "RR,SS")
+   oi\\t%0,%b1
+   oc\\t%O0(1,%R0),%1"
+  [(set_attr "op_type"  "SI,SS")
    (set_attr "atype"    "reg,mem")])
 
-;
-; iorqi3 instruction pattern(s).
-;
-
-(define_insn "iorqi3"
-  [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
-        (ior:QI (match_operand:QI 1 "r_or_s_operand" "%0,0,0")
-                (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+(define_insn "*iorqi3_ss_inv"
+  [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+        (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+                (match_dup 0)))
    (clobber (reg:CC 33))]
   ""
   "@
-   or\\t%0,%2
-   oi\\t%0,%b2
-   oc\\t%O0(1,%R0),%2"
-  [(set_attr "op_type"  "RR,SI,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   oi\\t%0,%b1
+   oc\\t%O0(1,%R0),%1"
+  [(set_attr "op_type"  "SI,SS")
+   (set_attr "atype"    "reg,mem")])
 
 
 ;;
 ; xordi3 instruction pattern(s).
 ;
 
+(define_insn "*xordi3_cc"
+  [(set (reg 33)
+        (compare (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+                         (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d,d")
+        (xor:DI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+  "@
+   xgr\\t%0,%2
+   xg\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*xordi3_cconly"
+  [(set (reg 33)
+        (compare (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+                         (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d,d"))]
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+  "@
+   xgr\\t%0,%2
+   xr\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
 (define_insn "xordi3"
-  [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
-        (xor:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
-                (match_operand:DI 2 "r_or_s_operand" "d,m,Q")))
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+                (match_operand:DI 2 "general_operand" "d,m")))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
   "@
    xgr\\t%0,%2
-   xg\\t%0,%2
-   xc\\t%O0(8,%R0),%2"
-  [(set_attr "op_type"  "RRE,RXE,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   xg\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*xordi3_ss"
+  [(set (match_operand:DI 0 "s_operand" "=Qo")
+        (xor:DI (match_dup 0)
+                (match_operand:DI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "xc\\t%O0(8,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*xordi3_ss_inv"
+  [(set (match_operand:DI 0 "s_operand" "=Qo")
+        (xor:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "xc\\t%O0(8,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
 ; xorsi3 instruction pattern(s).
 ;
 
-(define_expand "xorsi3"
-  [(parallel
-    [(set (match_operand:SI 0 "r_or_s_operand" "")
-        (xor:SI (match_operand:SI 1 "r_or_s_operand" "")
-                (match_operand:SI 2 "r_or_s_operand" "")))
-     (clobber (reg:CC 33))])]
-  ""
-  "
-{
-  if (CONSTANT_P (operands[2]))
-      operands[2] =  force_const_mem (SImode, operands[2]);
-}")
+(define_insn "*xorsi3_cc"
+  [(set (reg 33)
+        (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+                         (match_operand:SI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=d,d")
+        (xor:SI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode(insn, CCTmode)"
+  "@
+   xr\\t%0,%2
+   x\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*xorsi3_cconly"
+  [(set (reg 33)
+        (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+                         (match_operand:SI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
+  "s390_match_ccmode(insn, CCTmode)"
+  "@
+   xr\\t%0,%2
+   x\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
 
-(define_insn "*xorsi3"
-  [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
-        (xor:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
-                (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+        (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "general_operand" "d,m")))
    (clobber (reg:CC 33))]
   ""
   "@
    xr\\t%0,%2
-   x\\t%0,%2
-   xc\\t%O0(4,%R0),%2"
-  [(set_attr "op_type"  "RR,RX,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   x\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*xorsi3_ss"
+  [(set (match_operand:SI 0 "s_operand" "=Qo")
+        (xor:SI (match_dup 0)
+                (match_operand:SI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "xc\\t%O0(4,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*xorsi3_ss_inv"
+  [(set (match_operand:SI 0 "s_operand" "=Qo")
+        (xor:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "xc\\t%O0(4,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
 ; xorhi3 instruction pattern(s).
 ;
 
-(define_expand "xorhi3"
-  [(parallel
-    [(set (match_operand:HI 0 "r_or_s_operand" "")
-        (xor:HI (match_operand:HI 1 "r_or_s_operand" "")
-                (match_operand:HI 2 "r_or_s_operand" "")))
-     (clobber (reg:CC 33))])]
+(define_insn "xorhi3"
+  [(set (match_operand:HI 0 "register_operand" "=d")
+        (xor:HI (match_operand:HI 1 "register_operand" "%0")
+                (match_operand:HI 2 "nonmemory_operand" "d")))
+   (clobber (reg:CC 33))]
   ""
-  "
-{
-  if (CONSTANT_P (operands[2]))
-      operands[2] =  force_const_mem (HImode, operands[2]);
-}")
+  "xr\\t%0,%2"
+  [(set_attr "op_type"  "RR")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*xorhi3_ss"
+  [(set (match_operand:HI 0 "s_operand" "=Qo")
+        (xor:HI (match_dup 0)
+                (match_operand:HI 1 "s_imm_operand" "Qo")))
+   (clobber (reg:CC 33))]
+  ""
+  "xc\\t%O0(2,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
-(define_insn "*xorhi3"
-  [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
-        (xor:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
-                (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+(define_insn "*xorhi3_ss_inv"
+  [(set (match_operand:HI 0 "s_operand" "=Qo")
+        (xor:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+                (match_dup 0)))
    (clobber (reg:CC 33))]
   ""
-  "@
-   xr\\t%0,%2
-   xc\\t%O0(2,%R0),%2"
-  [(set_attr "op_type"  "RR,SS")
-   (set_attr "atype"    "reg,mem")])
+  "xc\\t%O0(2,%R0),%1"
+  [(set_attr "op_type"  "SS")
+   (set_attr "atype"    "mem")])
 
 ;
 ; xorqi3 instruction pattern(s).
 ;
 
 (define_insn "xorqi3"
-  [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
-        (xor:QI (match_operand:QI 1 "r_or_s_operand" "0,0,0")
-                (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+  [(set (match_operand:QI 0 "register_operand" "=d")
+        (xor:QI (match_operand:QI 1 "register_operand" "%0")
+                (match_operand:QI 2 "nonmemory_operand" "d")))
+   (clobber (reg:CC 33))]
+  ""
+  "xr\\t%0,%2"
+  [(set_attr "op_type"  "RR")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*xorqi3_ss"
+  [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+        (xor:QI (match_dup 0)
+                (match_operand:QI 1 "s_imm_operand" "n,Qo")))
    (clobber (reg:CC 33))]
   ""
   "@
-   xr\\t%0,%2
-   xi\\t%0,%b2
-   xc\\t%O0(1,%R0),%2"
-  [(set_attr "op_type"  "RR,SI,SS")
-   (set_attr "atype"    "reg,mem,mem")])
+   xi\\t%0,%b1
+   xc\\t%O0(1,%R0),%1"
+  [(set_attr "op_type"  "SI,SS")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*xorqi3_ss_inv"
+  [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+        (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+                (match_dup 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "@
+   xi\\t%0,%b1
+   xc\\t%O0(1,%R0),%1"
+  [(set_attr "op_type"  "SI,SS")
+   (set_attr "atype"    "mem")])
 
 
 ;;
   return \"\";
 }"
   [(set_attr "op_type"  "NN")
-   (set_attr "length"  "10")])
+   (set_attr "type"     "other")
+   (set_attr "length"   "10")])
 
 ;
 ; negsi2 instruction pattern(s).
   "lpr\\t%0,%1"
   [(set_attr "op_type"  "RR")])
 
-;
-; abshi2 instruction pattern(s).
-;
-
-(define_insn "abshi2"
-  [(set (match_operand:HI 0 "register_operand" "=d")
-        (abs:HI (match_operand:HI 1 "register_operand" "d")))
-   (clobber (reg:CC 33))]
-  ""
-  "sll\\t%1,16\;sra\\t%1,16\;lpr\\t%0,%1"
-  [(set_attr "op_type"  "NN")
-   (set_attr "type"    "o3")
-   (set_attr "length"   "10")])
-
 ;
 ; absdf2 instruction pattern(s).
 ;
   "lper\\t%0,%1"
   [(set_attr "op_type"  "RR")])
 
+;;
+;;- Square root instructions.
+;;
+
+;
+; sqrtdf2 instruction pattern(s).
+;
+
+(define_insn "sqrtdf2"
+  [(set (match_operand:DF 0 "register_operand" "=f,f")
+       (sqrt:DF (match_operand:DF 1 "general_operand" "f,m")))]
+  "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+  "@
+   sqdbr\\t%0,%1
+   sqdb\\t%0,%1"
+  [(set_attr "op_type"  "RRE,RSE")])
+
+;
+; sqrtsf2 instruction pattern(s).
+;
+
+(define_insn "sqrtsf2"
+  [(set (match_operand:SF 0 "register_operand" "=f,f")
+       (sqrt:SF (match_operand:SF 1 "general_operand" "f,m")))]
+  "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+  "@
+   sqebr\\t%0,%1
+   sqeb\\t%0,%1"
+  [(set_attr "op_type"  "RRE,RSE")])
 
 ;;
 ;;- One complement instructions.
 ;
 ; one_cmpldi2 instruction pattern(s).
 ;
-
 (define_expand "one_cmpldi2"
   [(parallel
-    [(set (match_operand:DI 0 "r_or_s_operand" "=d")
-          (not:DI (match_operand:DI 1 "r_or_s_operand" "0")))
-     (use (match_dup 2))
+    [(set (match_operand:DI 0 "register_operand" "")
+          (xor:DI (match_operand:DI 1 "register_operand" "")
+                  (const_int -1)))
      (clobber (reg:CC 33))])]
   "TARGET_64BIT"
-  "{ operands[2] = force_const_mem (DImode, constm1_rtx); }")
-
-(define_insn "*one_cmpldi2"
-  [(set (match_operand:DI 0 "r_or_s_operand" "=d,Q")
-        (not:DI (match_operand:DI 1 "r_or_s_operand" "0,0")))
-   (use (match_operand:DI 2 "memory_operand" "m,m"))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   xg\\t%0,%2
-   xc\\t%O0(8,%R0),%2"
-  [(set_attr "op_type"  "RR,SS")
-   (set_attr "atype"    "mem")])
-
+  "")
 ;
 ; one_cmplsi2 instruction pattern(s).
 ;
-
 (define_expand "one_cmplsi2"
   [(parallel
-    [(set (match_operand:SI 0 "r_or_s_operand" "=d")
-          (not:SI (match_operand:SI 1 "r_or_s_operand" "0")))
-     (use (match_dup 2))
+    [(set (match_operand:SI 0 "register_operand" "")
+          (xor:SI (match_operand:SI 1 "register_operand" "")
+                  (const_int -1)))
      (clobber (reg:CC 33))])]
   ""
-  "{ operands[2] = force_const_mem (SImode, constm1_rtx); }")
-
-(define_insn "*one_cmplsi2"
-  [(set (match_operand:SI 0 "r_or_s_operand" "=d,Q")
-        (not:SI (match_operand:SI 1 "r_or_s_operand" "0,0")))
-   (use (match_operand:SI 2 "memory_operand" "m,m"))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   x\\t%0,%2
-   xc\\t%O0(4,%R0),%2"
-  [(set_attr "op_type"  "RR,SS")
-   (set_attr "atype"    "mem")])
-
+  "")
 ;
 ; one_cmplhi2 instruction pattern(s).
 ;
-
 (define_expand "one_cmplhi2"
   [(parallel
-    [(set (match_operand:HI 0 "r_or_s_operand" "=d")
-          (not:HI (match_operand:HI 1 "r_or_s_operand" "0")))
-     (use (match_dup 2))
+    [(set (match_operand:HI 0 "register_operand" "")
+          (xor:HI (match_operand:HI 1 "register_operand" "")
+                  (const_int -1)))
      (clobber (reg:CC 33))])]
   ""
-  "{ operands[2] = force_const_mem (SImode, constm1_rtx); }")
-
-(define_insn "*one_cmplhi2"
-  [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
-        (not:HI (match_operand:HI 1 "r_or_s_operand" "0,0")))
-   (use (match_operand:SI 2 "memory_operand" "m,m"))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   x\\t%0,%2
-   xc\\t%O0(2,%R0),%2"
-  [(set_attr "op_type"  "RX,SS")
-   (set_attr "atype"    "mem")])
-
+  "")
 ;
 ; one_cmplqi2 instruction pattern(s).
 ;
-
-(define_insn "one_cmpqi2"
-  [(set (match_operand:QI 0 "memory_operand" "=Q")
-        (not:QI (match_operand:QI 1 "memory_operand" "0")))
-   (clobber (reg:CC 33))]
+(define_expand "one_cmplqi2"
+  [(parallel
+    [(set (match_operand:QI 0 "register_operand" "")
+          (xor:QI (match_operand:QI 1 "register_operand" "")
+                  (const_int -1)))
+     (clobber (reg:CC 33))])]
   ""
-  "xi\\t%0,255"
-  [(set_attr "op_type"  "SI")])
+  "")
 
 
 ;;
 (define_insn "ashlsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
-                   (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+                   (match_operand:SI 2 "nonmemory_operand" "J,a")))
    (clobber (reg:CC 33))]
   ""
   "@
 (define_insn "ashrsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
-                     (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+                     (match_operand:SI 2 "nonmemory_operand" "J,a")))
    (clobber (reg:CC 33))]
   ""
   "@
    sra\\t%0,0(%2)"
   [(set_attr "op_type"  "RS")])
 
-;
-; ashlhi3 instruction pattern(s).
-;
-
-(define_insn "ashlhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,d")
-        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
-                   (match_operand:SI 2 "r_or_im8_operand" "J,a")))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   sll\\t%0,%c2
-   sll\\t%0,0(%2)"
-  [(set_attr "op_type"  "RS,RS")])
-
-;
-; ashrhi3 instruction pattern(s).
-;
-
-(define_insn "ashrhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,d")
-        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
-                     (match_operand:SI 2 "r_or_im8_operand" "J,a")))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   sll\\t%0,16\;sra\\t%0,16+%c2
-   sll\\t%0,16\;sra\\t%0,16(%2)"
-   [(set_attr "op_type"  "NN,NN")
-    (set_attr "length"   "8,8")])
-
 
 ;;
 ;;- logical shift instructions.
 (define_insn "lshrsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
-                     (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+                     (match_operand:SI 2 "nonmemory_operand" "J,a")))
    (clobber (reg:CC 33))]
   ""
   "@
    srl\\t%0,0(%2)"
   [(set_attr "op_type"  "RS")])
 
-;
-; lshrhi3 instruction pattern(s).
-;
-
-(define_insn "lshrhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,d")
-        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
-                     (match_operand:SI 2 "r_or_im8_operand" "J,a")))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   sll\\t%0,16\;srl\\t%0,16+%c2
-   sll\\t%0,16\;srl\\t%0,16(%2)"
-  [(set_attr "op_type"  "NN,NN")
-   (set_attr "length"   "8,8")])
-
 
 ;;
 ;; Branch instruction patterns.
 (define_insn "blockage"
   [(unspec_volatile [(const_int 0)] 0)]
   ""
-  "")
+  ""
+  [(set_attr "type"    "none")])
+
 
 
 ;
   "TARGET_64BIT"
   "brasl\\t%2,%0"
   [(set_attr "op_type" "RIL")
-   (set_attr "type"   "jsr")])
+   (set_attr "type"    "jsr")])
 
 (define_insn "bras"
   [(call (mem:QI (match_operand:SI 0 "bras_sym_operand" "X"))
   "TARGET_SMALL_EXEC"
   "bras\\t%2,%0"
   [(set_attr "op_type" "RI")
-   (set_attr "type"   "jsr")])
+   (set_attr "type"    "jsr")])
 
 (define_insn "basr_64"
   [(call (mem:QI (match_operand:DI 0 "register_operand" "a"))
     return \"basr\\t13,0\;ahi\\t13,%Y0\";
 }"
   [(set_attr "op_type" "NN")
-   (set_attr "type"    "o2")
+   (set_attr "type"    "la")
    (set_attr "length"  "8")])
 
 (define_insn "ltorg"
    return \"0:\";
 }"
   [(set_attr "op_type" "NN")
-   (set_attr "type"    "branch")
+   (set_attr "type"    "other")
    (set_attr "length"  "4096")])
 
+;;
+;; Insns related to generating the function prologue and epilogue.
+;;
+
+
+(define_expand "prologue"
+  [(use (const_int 0))]
+  ""
+  "
+{
+      s390_emit_prologue ();
+      DONE;
+}")
+
+(define_expand "epilogue"
+  [(use (const_int 1))]
+  ""
+  "
+{
+      s390_emit_epilogue ();
+      DONE;
+}")
+
+
+(define_insn "*return_si"
+  [(return)
+   (use (match_operand:SI 0 "register_operand" "a"))]
+  "!TARGET_64BIT"
+  "br\\t%0"
+  [(set_attr "op_type" "RR")
+   (set_attr "type"    "jsr")          
+   (set_attr "atype"   "mem")])
+
+(define_insn "*return_di"
+  [(return)
+   (use (match_operand:DI 0 "register_operand" "a"))]
+  "TARGET_64BIT"
+  "br\\t%0"
+  [(set_attr "op_type" "RR")
+   (set_attr "type"    "jsr")          
+   (set_attr "atype"   "mem")])
+
+
+(define_insn "lit"
+  [(set (reg 13) (pc))
+   (unspec_volatile [(const_int 0)] 200)]
+  ""
+  "*
+{
+   s390_output_constant_pool (asm_out_file);
+   return \"\";
+}"
+  [(set_attr "op_type" "NN")
+   (set_attr "type"    "integer")])
+
 
 ;;
 ;; Peephole optimization patterns.
index 91585b77b3f99992f96b2393fa1e6662a7cc20a7..bc8d519b2d12625987098af5a2e18c146ec7314b 100644 (file)
@@ -1,5 +1,6 @@
 # The crtbegin and crtend must not depend on a small GOT
 CRTSTUFF_T_CFLAGS = -O2 -fPIC
+CRTSTUFF_T_CFLAGS_S = -O2 -fPIC
 
 # Compile libgcc2.a with pic.
 TARGET_LIBGCC2_CFLAGS = -fPIC -include $(srcdir)/config/s390/fixdfdi.h