aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Schmidt <bernds_cb1@t-online.de>2019-11-25 12:31:16 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2019-11-25 12:31:16 +0000
commit6cebc6cbbb801183090dbb2752aa6b698331a31c (patch)
treefca756e8522b7361502d0dc0728102c258745712 /gcc
parente9daced36d53a316bb8ddeb1e0edcb7982bebeb9 (diff)
downloadgcc-6cebc6cbbb801183090dbb2752aa6b698331a31c.zip
gcc-6cebc6cbbb801183090dbb2752aa6b698331a31c.tar.gz
gcc-6cebc6cbbb801183090dbb2752aa6b698331a31c.tar.bz2
Convert m68k to not use cc0
* config/m68k/m68k.c (output_move_himode, output_move_qimode): Replace code for non-CONST_INT constants with gcc_unreachable. * config/m68k/m68k.md (cbranchdi): Don't generate individual compare and test. (CMPMODE): New mode_iterator. (cbranchsi4, cbranchqi4, cbranchhi4): Replace expanders with cbranch<mode>4. (cstoresi4, cstoreqi4, cstorehi4): Replace expanders with cstore<mode>4. (cmp<mode>_68881): Remove 'F' constraint from first comparison operand. (bit test insns patterns): Use nonimmediate_operand, not register_operand, for source operands that allow memory in their constraints. (divmodsi4, udivmodsi4, divmodhi4 and related unnamed patterns): Use register_operand, not nonimmediate_operand, for the destinations. (DBCC): New mode_iterator. (dbcc peepholes): Use it to reduce duplication. (trap): Use const_true_rtx, not const1_rtx. * config/m68k/predicates.md (m68k_comparison_operand): Renamed from m68k_subword_comparison_operand and changed to handle SImode. PR target/91851 * config/m68k/m68k-protos.h (output-dbcc_and_branch): Adjust declaration. (m68k_init_cc): New declaration. (m68k_output_compare_di, m68k_output_compare_si) (m68k_output_compare_hi, m68k_output_compare_qi) (m68k_output_compare_fp, m68k_output_btst, m68k_output_bftst) (m68k_find_flags_value, m68k_output_scc, m68k_output_scc_float) (m68k_output_branch_integer, m68k_output_branch_integer_rev. m68k_output_branch_float, m68k_output_branch_float_rev): Likewise. (valid_dbcc_comparison_p_2, flags_in_68881) (output_btst): Remove declaration. * config/m68k/m68k.c (INCLDUE_STRING): Define. (TARGET_ASM_FINAL_POSTSCAN_INSN): Define. (valid_dbcc_comparison_p_2, flags_in_68881): Delete functions. (flags_compare_op0, flags_compare_op1, flags_operand1, flags_operand2, flags_valid): New static variables. (m68k_find_flags_value, m68k_init_cc): New functions. (handle_flags_for_move, m68k_asm_final_postscan_insn, remember_compare_flags): New static functions. (output_dbcc_and_branch): New argument CODE. Use it, and add PLUS and MINUS to the possible codes. All callers changed. (m68k_output_btst): Renamed from output_btst. Remove OPERANDS and INSN arguments, add CODE arg. Return the comparison code to use. All callers changed. Use CODE instead of next_insn_tests_no_inequality, and replace cc_status management with changing the return code. (m68k_rtx_costs): Instead of testing for COMPARE, test for RTX_COMPARE or RTX_COMM_COMPARE. (output_move_simode, output_move_qimode): Call handle_flags_for_move. (notice_update_cc): Delete function. (m68k_output_bftst, m68k_output_compare_di, m68k_output_compare_si, m68k_output_compare_hi, m68k_output_compare_qi, m68k_output_compare_fp, m68k_output_branch_integer, m68k_output_branch_integer_rev, m68k_output_scc, m68k_output_branch_float, m68k_output_branch_float_rev, m68k_output_scc_float): New functions. (output_andsi3, output_iorsi3, output_xorsi3): Call CC_STATUS_INIT once at the start, and set flags_valid and flags_operand1 if the flags are usable. * config/m68k/m68k.h (CC_IN_68881, NOTICE_UPDATE_CC, CC_OVERFLOW_UNUSABLE, CC_NO_CARRY, OUTPUT_JUMP): Remove definitions. (CC_STATUS_INIT): Define. * config/m68k/m68k.md (flags_valid): New define_attr. (tstdi, tstsi_internal_68020_cf, tstsi_internal, tsthi_internal, tstqi_internal, tst<mode>_68881, tst<mode>_cf, cmpdi_internal, cmpdi, unnamed cmpsi/cmphi/cmpqi patterns, cmpsi_cf, cmp<mode>_68881, cmp<mode>_cf, unnamed btst patterns, tst_bftst_reg, tst_bftst_reg, unnamed scc patterns, scc, sls, sordered_1, sunordered_1, suneq_1, sunge_1, sungt_1, sunle_1, sunlt_1, sltgt_1, fsogt_1, fsoge_1, fsolt_1, fsole_1, bge0_di, blt0_di, beq, bne, bgt, bgtu, blt, bltu, bge, bgeu, ble, bleu, bordered, bunordered, buneq, bunge, bungt, bunle, bunlt, bltgt, beq_rev, bne_rev, bgt_rev, bgtu_rev, blt_rev, bltu_rev, bge_rev, bgeu_rev, ble_rev, bleu_rev, bordered_rev, bunordered_rev, buneq_rev, bunge_rv, bungt_rev, bunle_rev, bunlt_rev, bltgt_rev, ctrapdi4, ctrapsi4, ctraphi4, ctrapqi4, conditional_trap): Delete patterns. (cbranchdi4_insn): New pattern. (cbranchdi4): Don't generate cc0 patterns. When testing LT or GE, test high part only. When testing EQ or NE, generate beq0_di and bne0_di patterns directly. (cstoredi4): When testing LT or GE, test high part only. (both sets of cbranch<mode>4, cstore<mode>4): Don't generate cc0 patterns. (scc0_constraints, cmp1_constraints, cmp2_constraints, scc0_cf_constraints, cmp1_cf_constraints, cmp2_cf_constraints, cmp2_cf_predicate): New define_mode_attrs. (cbranch<mode>4_insn, cbranch<mode>4_insn_rev, cbranch<mode>4_insn_cf, cbranch<mode>4_insn_cf_rev, cstore<mode>4_insn, cstore<mode>4_insn_cf for integer modes) New patterns. (cbranch<mode>4_insn_68881, cbranch<mode>4_insn_rev_68881): (cbranch<mode>4_insn_cf, cbranch<mode>4_insn_rev_cf, cstore<mode>4_insn_68881, cstore<mode>4_insn_cf for FP): New patterns. (cbranchsi4_btst_mem_insn, cbranchsi4_btst_reg_insn, cbranchsi4_btst_mem_insn_1, cbranchsi4_btst_reg_insn_1): Likewise. (BTST): New define_mode_iterator. (btst_predicate, btst_constraint, btst_range): New define_mode_attrs. (cbranch_bftst<mode>_insn, cstore_bftst<mode>_insn): New patterns. (movsi_m68k_movsi_m68k2, movsi_cf, unnamed movstrict patterns, unnamed movhi and movqi patterns, unnamed movsf, movdf and movxf patterns): Set attr "flags_valid". (truncsiqi2, trunchiqi2, truncsihi2): Remove manual CC_STATUS management. Set attr "flags_valid". (extendsidi2, extendplussidi, unnamed float_extendsfdf pattern, extendsfdf2_cf, fix_truncdfsi2, fix_truncdfhi2, fix_truncdfqi2, addi_sexthishl32, adddi_dilshr32, adddi_dilshr32_cf, addi_dishl32, subdi_sexthishl32, subdi_dishl32, subdi3): Remove manual CC_STATUS management. (addsi3_internal, addhi3, addqi3, subsi3, subhi3, subqi3, unnamed strict_lowpart subhi and subqi patterns): Set attr "flags_valid". (unnamed strict_lowpart addhi3 and addqi3 patterns): Likewise. Remove code to operate on address regs and assert the case does not occur. (unnamed mulsidi patterns, divmodhi4, udivmodhi4): Remove manual CC_STATUS_INIT. (andsi3_internal, andhi3, andqi3, iorsi3_internal, iorhi3, iorqi3, xorsi3_internal, xorhi3, xorqi3, negsi2_internal, negsi2_5200, neghi2, negqi2, one_cmplsi2_internal, one_cmplhi2, one_cmplqi2, unnamed strict_lowpart patterns for andhi, andqi, iorhi, iorqi, xorhi, xorqi, neghi, negqi, one_cmplhi and one_cmplqi): Set attr "flags_valid". (iorsi_zext_ashl16, iorsi_zext): Remove manual CC_STATUS_INIT. (ashldi_sexthi, ashlsi_16, ashlsi_17_24): Remove manual CC_STATUS_INIT. (ashlsi3, ashlhi3, ashlqi3, ashrsi3, ashrhi3, ashrqi3, lshrsi3, lshrhi3, shrqi3, rotlsi3, rotlhi3, rotlhi3_lowpart, rotlqi3, rotlqi3_lowpart, rotrsi3, rotrhi3, rotrhi_lowpart, rotrqi3, unnamed strict_low_part patterns for HI and QI versions): Set attr "flags_valid". (bsetmemqi, bsetmemqi_ext, bsetdreg, bchgdreg, bclrdreg, bclrmemqi, extzv_8_16_reg, extzv_bfextu_mem, insv_bfchg_mem, insv_bfclr_mem, insv_bfset_mem, extv_bfextu_reg, insv_bfclr_reg, insv_bfset_reg, dbne_hi, dbne_si, dbge_hi, dbge_si, extendsfxf2, extenddfxf2, ): Remove manual cc_status management. (various unnamed peepholes): Adjust compare/branch sequences for new cbranch patterns. (dbcc peepholes): Likewise, and output the comparison here as well. * config/m68k/predicates.md (valid_dbcc_comparison_p): Delete. (fp_src_operand): Allow constant zero. (address_reg_operand): New predicate. * rtl.h (inequality_comparisons_p): Remove declaration. * recog.h (next_insn_tests_no_inequality): Likewise. * rtlanal.c (inequality_comparisons_p): Delete function. * recog.c (next_insn_tests_no_inequality): Likewise. From-SVN: r278681
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog163
-rw-r--r--gcc/config/m68k/m68k-protos.h19
-rw-r--r--gcc/config/m68k/m68k.c889
-rw-r--r--gcc/config/m68k/m68k.h32
-rw-r--r--gcc/config/m68k/m68k.md2515
-rw-r--r--gcc/config/m68k/predicates.md32
-rw-r--r--gcc/recog.c17
-rw-r--r--gcc/recog.h1
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/rtlanal.c58
10 files changed, 1657 insertions, 2070 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6dee39e..b0957b0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,166 @@
+2019-11-25 Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * config/m68k/m68k.c (output_move_himode, output_move_qimode):
+ Replace code for non-CONST_INT constants with gcc_unreachable.
+ * config/m68k/m68k.md (cbranchdi): Don't generate individual
+ compare and test.
+ (CMPMODE): New mode_iterator.
+ (cbranchsi4, cbranchqi4, cbranchhi4): Replace expanders with
+ cbranch<mode>4.
+ (cstoresi4, cstoreqi4, cstorehi4): Replace expanders with
+ cstore<mode>4.
+ (cmp<mode>_68881): Remove 'F' constraint from first comparison
+ operand.
+ (bit test insns patterns): Use nonimmediate_operand, not
+ register_operand, for source operands that allow memory in
+ their constraints.
+ (divmodsi4, udivmodsi4, divmodhi4 and related unnamed patterns):
+ Use register_operand, not nonimmediate_operand, for the
+ destinations.
+ (DBCC): New mode_iterator.
+ (dbcc peepholes): Use it to reduce duplication.
+ (trap): Use const_true_rtx, not const1_rtx.
+ * config/m68k/predicates.md (m68k_comparison_operand): Renamed
+ from m68k_subword_comparison_operand and changed to handle
+ SImode.
+
+ PR target/91851
+ * config/m68k/m68k-protos.h (output-dbcc_and_branch): Adjust
+ declaration.
+ (m68k_init_cc): New declaration.
+ (m68k_output_compare_di, m68k_output_compare_si)
+ (m68k_output_compare_hi, m68k_output_compare_qi)
+ (m68k_output_compare_fp, m68k_output_btst, m68k_output_bftst)
+ (m68k_find_flags_value, m68k_output_scc, m68k_output_scc_float)
+ (m68k_output_branch_integer, m68k_output_branch_integer_rev.
+ m68k_output_branch_float, m68k_output_branch_float_rev):
+ Likewise.
+ (valid_dbcc_comparison_p_2, flags_in_68881)
+ (output_btst): Remove declaration.
+ * config/m68k/m68k.c (INCLDUE_STRING): Define.
+ (TARGET_ASM_FINAL_POSTSCAN_INSN): Define.
+ (valid_dbcc_comparison_p_2, flags_in_68881): Delete functions.
+ (flags_compare_op0, flags_compare_op1, flags_operand1,
+ flags_operand2, flags_valid): New static variables.
+ (m68k_find_flags_value, m68k_init_cc): New functions.
+ (handle_flags_for_move, m68k_asm_final_postscan_insn,
+ remember_compare_flags): New static functions.
+ (output_dbcc_and_branch): New argument CODE. Use it, and add
+ PLUS and MINUS to the possible codes. All callers changed.
+ (m68k_output_btst): Renamed from output_btst. Remove OPERANDS
+ and INSN arguments, add CODE arg. Return the comparison code
+ to use. All callers changed. Use CODE instead of
+ next_insn_tests_no_inequality, and replace cc_status management
+ with changing the return code.
+ (m68k_rtx_costs): Instead of testing for COMPARE, test for
+ RTX_COMPARE or RTX_COMM_COMPARE.
+ (output_move_simode, output_move_qimode): Call
+ handle_flags_for_move.
+ (notice_update_cc): Delete function.
+ (m68k_output_bftst, m68k_output_compare_di, m68k_output_compare_si,
+ m68k_output_compare_hi, m68k_output_compare_qi,
+ m68k_output_compare_fp, m68k_output_branch_integer,
+ m68k_output_branch_integer_rev, m68k_output_scc,
+ m68k_output_branch_float, m68k_output_branch_float_rev,
+ m68k_output_scc_float): New functions.
+ (output_andsi3, output_iorsi3, output_xorsi3): Call CC_STATUS_INIT
+ once at the start, and set flags_valid and flags_operand1 if the
+ flags are usable.
+ * config/m68k/m68k.h (CC_IN_68881, NOTICE_UPDATE_CC,
+ CC_OVERFLOW_UNUSABLE, CC_NO_CARRY, OUTPUT_JUMP): Remove
+ definitions.
+ (CC_STATUS_INIT): Define.
+ * config/m68k/m68k.md (flags_valid): New define_attr.
+ (tstdi, tstsi_internal_68020_cf, tstsi_internal, tsthi_internal,
+ tstqi_internal, tst<mode>_68881, tst<mode>_cf, cmpdi_internal,
+ cmpdi, unnamed cmpsi/cmphi/cmpqi patterns, cmpsi_cf,
+ cmp<mode>_68881, cmp<mode>_cf, unnamed btst patterns,
+ tst_bftst_reg, tst_bftst_reg, unnamed scc patterns, scc,
+ sls, sordered_1, sunordered_1, suneq_1, sunge_1, sungt_1,
+ sunle_1, sunlt_1, sltgt_1, fsogt_1, fsoge_1, fsolt_1, fsole_1,
+ bge0_di, blt0_di, beq, bne, bgt, bgtu, blt, bltu, bge, bgeu,
+ ble, bleu, bordered, bunordered, buneq, bunge, bungt, bunle,
+ bunlt, bltgt, beq_rev, bne_rev, bgt_rev, bgtu_rev,
+ blt_rev, bltu_rev, bge_rev, bgeu_rev, ble_rev, bleu_rev,
+ bordered_rev, bunordered_rev, buneq_rev, bunge_rv, bungt_rev,
+ bunle_rev, bunlt_rev, bltgt_rev, ctrapdi4, ctrapsi4, ctraphi4,
+ ctrapqi4, conditional_trap): Delete patterns.
+ (cbranchdi4_insn): New pattern.
+ (cbranchdi4): Don't generate cc0 patterns. When testing LT or GE,
+ test high part only. When testing EQ or NE, generate beq0_di
+ and bne0_di patterns directly.
+ (cstoredi4): When testing LT or GE, test high part only.
+ (both sets of cbranch<mode>4, cstore<mode>4): Don't generate cc0
+ patterns.
+ (scc0_constraints, cmp1_constraints, cmp2_constraints,
+ scc0_cf_constraints, cmp1_cf_constraints, cmp2_cf_constraints,
+ cmp2_cf_predicate): New define_mode_attrs.
+ (cbranch<mode>4_insn, cbranch<mode>4_insn_rev,
+ cbranch<mode>4_insn_cf, cbranch<mode>4_insn_cf_rev,
+ cstore<mode>4_insn, cstore<mode>4_insn_cf for integer modes)
+ New patterns.
+ (cbranch<mode>4_insn_68881, cbranch<mode>4_insn_rev_68881):
+ (cbranch<mode>4_insn_cf, cbranch<mode>4_insn_rev_cf,
+ cstore<mode>4_insn_68881, cstore<mode>4_insn_cf for FP):
+ New patterns.
+ (cbranchsi4_btst_mem_insn, cbranchsi4_btst_reg_insn,
+ cbranchsi4_btst_mem_insn_1, cbranchsi4_btst_reg_insn_1):
+ Likewise.
+ (BTST): New define_mode_iterator.
+ (btst_predicate, btst_constraint, btst_range): New
+ define_mode_attrs.
+ (cbranch_bftst<mode>_insn, cstore_bftst<mode>_insn): New
+ patterns.
+ (movsi_m68k_movsi_m68k2, movsi_cf, unnamed movstrict patterns,
+ unnamed movhi and movqi patterns, unnamed movsf, movdf and movxf
+ patterns): Set attr "flags_valid".
+ (truncsiqi2, trunchiqi2, truncsihi2): Remove manual CC_STATUS
+ management. Set attr "flags_valid".
+ (extendsidi2, extendplussidi, unnamed float_extendsfdf pattern,
+ extendsfdf2_cf, fix_truncdfsi2, fix_truncdfhi2, fix_truncdfqi2,
+ addi_sexthishl32, adddi_dilshr32, adddi_dilshr32_cf,
+ addi_dishl32, subdi_sexthishl32, subdi_dishl32, subdi3): Remove
+ manual CC_STATUS management.
+ (addsi3_internal, addhi3, addqi3, subsi3, subhi3, subqi3,
+ unnamed strict_lowpart subhi and subqi patterns): Set attr
+ "flags_valid".
+ (unnamed strict_lowpart addhi3 and addqi3 patterns): Likewise.
+ Remove code to operate on address regs and assert the case
+ does not occur.
+ (unnamed mulsidi patterns, divmodhi4, udivmodhi4): Remove
+ manual CC_STATUS_INIT.
+ (andsi3_internal, andhi3, andqi3, iorsi3_internal, iorhi3, iorqi3,
+ xorsi3_internal, xorhi3, xorqi3, negsi2_internal,
+ negsi2_5200, neghi2, negqi2, one_cmplsi2_internal, one_cmplhi2,
+ one_cmplqi2, unnamed strict_lowpart patterns
+ for andhi, andqi, iorhi, iorqi, xorhi, xorqi, neghi, negqi,
+ one_cmplhi and one_cmplqi): Set attr "flags_valid".
+ (iorsi_zext_ashl16, iorsi_zext): Remove manual CC_STATUS_INIT.
+ (ashldi_sexthi, ashlsi_16, ashlsi_17_24): Remove manual
+ CC_STATUS_INIT.
+ (ashlsi3, ashlhi3, ashlqi3, ashrsi3, ashrhi3, ashrqi3, lshrsi3,
+ lshrhi3, shrqi3, rotlsi3, rotlhi3, rotlhi3_lowpart, rotlqi3,
+ rotlqi3_lowpart, rotrsi3, rotrhi3, rotrhi_lowpart, rotrqi3,
+ unnamed strict_low_part patterns for HI and
+ QI versions): Set attr "flags_valid".
+ (bsetmemqi, bsetmemqi_ext, bsetdreg, bchgdreg, bclrdreg,
+ bclrmemqi, extzv_8_16_reg, extzv_bfextu_mem, insv_bfchg_mem,
+ insv_bfclr_mem, insv_bfset_mem, extv_bfextu_reg,
+ insv_bfclr_reg, insv_bfset_reg, dbne_hi, dbne_si, dbge_hi,
+ dbge_si, extendsfxf2, extenddfxf2, ): Remove manual cc_status management.
+ (various unnamed peepholes): Adjust compare/branch sequences
+ for new cbranch patterns.
+ (dbcc peepholes): Likewise, and output the comparison here
+ as well.
+ * config/m68k/predicates.md (valid_dbcc_comparison_p): Delete.
+ (fp_src_operand): Allow constant zero.
+ (address_reg_operand): New predicate.
+
+ * rtl.h (inequality_comparisons_p): Remove declaration.
+ * recog.h (next_insn_tests_no_inequality): Likewise.
+ * rtlanal.c (inequality_comparisons_p): Delete function.
+ * recog.c (next_insn_tests_no_inequality): Likewise.
+
2019-11-25 Richard Biener <rguenther@suse.de>
* tree-vect-slp.c (vect_detect_hybrid_slp_stmts): Add assertion.
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index abd920e..a88d903 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -42,7 +42,23 @@ extern const char *output_iorsi3 (rtx *);
extern const char *output_xorsi3 (rtx *);
extern const char *output_call (rtx);
extern const char *output_sibcall (rtx);
-extern void output_dbcc_and_branch (rtx *);
+extern void m68k_init_cc ();
+extern void output_dbcc_and_branch (rtx *, rtx_code);
+extern rtx_code m68k_output_compare_di (rtx, rtx, rtx, rtx, rtx_insn *, rtx_code);
+extern rtx_code m68k_output_compare_si (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_compare_hi (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_compare_qi (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_compare_fp (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_btst (rtx, rtx, rtx_code, int);
+extern rtx_code m68k_output_bftst (rtx, rtx, rtx, rtx_code);
+extern rtx_code m68k_find_flags_value (rtx, rtx, rtx_code);
+
+extern const char *m68k_output_scc (rtx_code);
+extern const char *m68k_output_scc_float (rtx_code);
+extern const char *m68k_output_branch_integer (rtx_code);
+extern const char *m68k_output_branch_integer_rev (rtx_code);
+extern const char *m68k_output_branch_float (rtx_code);
+extern const char *m68k_output_branch_float_rev (rtx_code);
extern int floating_exact_log2 (rtx);
extern bool strict_low_part_peephole_ok (machine_mode mode,
rtx_insn *first_insn, rtx target);
@@ -88,7 +104,6 @@ extern enum attr_op_mem m68k_sched_attr_op_mem (rtx_insn *);
extern enum reg_class m68k_secondary_reload_class (enum reg_class,
machine_mode, rtx);
extern enum reg_class m68k_preferred_reload_class (rtx, enum reg_class);
-extern int flags_in_68881 (void);
extern void m68k_expand_prologue (void);
extern bool m68k_use_return_insn (void);
extern void m68k_expand_epilogue (bool);
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 1030dfa..8d010eb 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#define IN_TARGET_CODE 1
#include "config.h"
+#define INCLUDE_STRING
#include "system.h"
#include "coretypes.h"
#include "backend.h"
@@ -194,6 +195,7 @@ static bool m68k_hard_regno_mode_ok (unsigned int, machine_mode);
static bool m68k_modes_tieable_p (machine_mode, machine_mode);
static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
int *, const_tree, int);
+static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
/* Initialize the GCC target structure. */
@@ -355,6 +357,9 @@ static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+#undef TARGET_ASM_FINAL_POSTSCAN_INSN
+#define TARGET_ASM_FINAL_POSTSCAN_INSN m68k_asm_final_postscan_insn
+
static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
@@ -1356,40 +1361,6 @@ m68k_expand_epilogue (bool sibcall_p)
emit_jump_insn (ret_rtx);
}
-/* Return true if X is a valid comparison operator for the dbcc
- instruction.
-
- Note it rejects floating point comparison operators.
- (In the future we could use Fdbcc).
-
- It also rejects some comparisons when CC_NO_OVERFLOW is set. */
-
-int
-valid_dbcc_comparison_p_2 (rtx x, machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (x))
- {
- case EQ: case NE: case GTU: case LTU:
- case GEU: case LEU:
- return 1;
-
- /* Reject some when CC_NO_OVERFLOW is set. This may be over
- conservative */
- case GT: case LT: case GE: case LE:
- return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
- default:
- return 0;
- }
-}
-
-/* Return nonzero if flags are currently in the 68881 flag register. */
-int
-flags_in_68881 (void)
-{
- /* We could add support for these in the future */
- return cc_status.flags & CC_IN_68881;
-}
-
/* Return true if PARALLEL contains register REGNO. */
static bool
m68k_reg_present_p (const_rtx parallel, unsigned int regno)
@@ -1580,18 +1551,186 @@ m68k_legitimize_address (rtx x, rtx oldx, machine_mode mode)
return x;
}
+
+/* For eliding comparisons, we remember how the flags were set.
+ FLAGS_COMPARE_OP0 and FLAGS_COMPARE_OP1 are remembered for a direct
+ comparison, they take priority. FLAGS_OPERAND1 and FLAGS_OPERAND2
+ are used in more cases, they are a fallback for comparisons against
+ zero after a move or arithmetic insn.
+ FLAGS_VALID is set to FLAGS_VALID_NO if we should not use any of
+ these values. */
+
+static rtx flags_compare_op0, flags_compare_op1;
+static rtx flags_operand1, flags_operand2;
+static attr_flags_valid flags_valid = FLAGS_VALID_NO;
+
+/* Return a code other than UNKNOWN if we can elide a CODE comparison of
+ OP0 with OP1. */
+
+rtx_code
+m68k_find_flags_value (rtx op0, rtx op1, rtx_code code)
+{
+ if (flags_compare_op0 != NULL_RTX)
+ {
+ if (rtx_equal_p (op0, flags_compare_op0)
+ && rtx_equal_p (op1, flags_compare_op1))
+ return code;
+ if (rtx_equal_p (op0, flags_compare_op1)
+ && rtx_equal_p (op1, flags_compare_op0))
+ return swap_condition (code);
+ return UNKNOWN;
+ }
+
+ machine_mode mode = GET_MODE (op0);
+ if (op1 != CONST0_RTX (mode))
+ return UNKNOWN;
+ /* Comparisons against 0 with these two should have been optimized out. */
+ gcc_assert (code != LTU && code != GEU);
+ if (flags_valid == FLAGS_VALID_NOOV && (code == GT || code == LE))
+ return UNKNOWN;
+ if (rtx_equal_p (flags_operand1, op0) || rtx_equal_p (flags_operand2, op0))
+ return (FLOAT_MODE_P (mode) ? code
+ : code == GE ? PLUS : code == LT ? MINUS : code);
+ /* See if we are testing whether the high part of a DImode value is
+ positive or negative and we have the full value as a remembered
+ operand. */
+ if (code != GE && code != LT)
+ return UNKNOWN;
+ if (mode == SImode
+ && flags_operand1 != NULL_RTX && GET_MODE (flags_operand1) == DImode
+ && REG_P (flags_operand1) && REG_P (op0)
+ && hard_regno_nregs (REGNO (flags_operand1), DImode) == 2
+ && REGNO (flags_operand1) == REGNO (op0))
+ return code == GE ? PLUS : MINUS;
+ if (mode == SImode
+ && flags_operand2 != NULL_RTX && GET_MODE (flags_operand2) == DImode
+ && REG_P (flags_operand2) && REG_P (op0)
+ && hard_regno_nregs (REGNO (flags_operand2), DImode) == 2
+ && REGNO (flags_operand2) == REGNO (op0))
+ return code == GE ? PLUS : MINUS;
+ return UNKNOWN;
+}
+
+/* Called through CC_STATUS_INIT, which is invoked by final whenever a
+ label is encountered. */
+
+void
+m68k_init_cc ()
+{
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ flags_valid = FLAGS_VALID_NO;
+}
+
+/* Update flags for a move operation with OPERANDS. Called for move
+ operations where attr_flags_valid returns "set". */
+
+static void
+handle_flags_for_move (rtx *operands)
+{
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+ if (!ADDRESS_REG_P (operands[0]))
+ {
+ flags_valid = FLAGS_VALID_MOVE;
+ flags_operand1 = side_effects_p (operands[0]) ? NULL_RTX : operands[0];
+ if (side_effects_p (operands[1])
+ /* ??? For mem->mem moves, this can discard the source as a
+ valid compare operand. If you assume aligned moves, this
+ is unnecessary, but in theory, we could have an unaligned
+ move overwriting parts of its source. */
+ || modified_in_p (operands[1], current_output_insn))
+ flags_operand2 = NULL_RTX;
+ else
+ flags_operand2 = operands[1];
+ return;
+ }
+ if (flags_operand1 != NULL_RTX
+ && modified_in_p (flags_operand1, current_output_insn))
+ flags_operand1 = NULL_RTX;
+ if (flags_operand2 != NULL_RTX
+ && modified_in_p (flags_operand2, current_output_insn))
+ flags_operand2 = NULL_RTX;
+}
+
+/* Process INSN to remember flag operands if possible. */
+
+static void
+m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int)
+{
+ enum attr_flags_valid v = get_attr_flags_valid (insn);
+ if (v == FLAGS_VALID_SET)
+ return;
+ /* Comparisons use FLAGS_VALID_SET, so we can be sure we need to clear these
+ now. */
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+
+ if (v == FLAGS_VALID_NO)
+ {
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ return;
+ }
+ else if (v == FLAGS_VALID_UNCHANGED)
+ {
+ if (flags_operand1 != NULL_RTX && modified_in_p (flags_operand1, insn))
+ flags_operand1 = NULL_RTX;
+ if (flags_operand2 != NULL_RTX && modified_in_p (flags_operand2, insn))
+ flags_operand2 = NULL_RTX;
+ return;
+ }
+
+ flags_valid = v;
+ rtx set = single_set (insn);
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+ if (side_effects_p (dest))
+ dest = NULL_RTX;
+
+ switch (v)
+ {
+ case FLAGS_VALID_YES:
+ case FLAGS_VALID_NOOV:
+ flags_operand1 = dest;
+ flags_operand2 = NULL_RTX;
+ break;
+ case FLAGS_VALID_MOVE:
+ /* fmoves to memory or data registers do not set the condition
+ codes. Normal moves _do_ set the condition codes, but not in
+ a way that is appropriate for comparison with 0, because -0.0
+ would be treated as a negative nonzero number. Note that it
+ isn't appropriate to conditionalize this restriction on
+ HONOR_SIGNED_ZEROS because that macro merely indicates whether
+ we care about the difference between -0.0 and +0.0. */
+ if (dest != NULL_RTX
+ && !FP_REG_P (dest)
+ && (FP_REG_P (src)
+ || GET_CODE (src) == FIX
+ || FLOAT_MODE_P (GET_MODE (dest))))
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ else
+ {
+ flags_operand1 = dest;
+ if (GET_MODE (src) != VOIDmode && !side_effects_p (src)
+ && !modified_in_p (src, insn))
+ flags_operand2 = src;
+ else
+ flags_operand2 = NULL_RTX;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ return;
+}
-
/* Output a dbCC; jCC sequence. Note we do not handle the
- floating point version of this sequence (Fdbcc). We also
- do not handle alternative conditions when CC_NO_OVERFLOW is
- set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
- kick those out before we get here. */
+ floating point version of this sequence (Fdbcc).
+ OPERANDS are as in the two peepholes. CODE is the code
+ returned by m68k_output_branch_<mode>. */
void
-output_dbcc_and_branch (rtx *operands)
+output_dbcc_and_branch (rtx *operands, rtx_code code)
{
- switch (GET_CODE (operands[3]))
+ switch (code)
{
case EQ:
output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
@@ -1633,6 +1772,14 @@ output_dbcc_and_branch (rtx *operands)
output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
break;
+ case PLUS:
+ output_asm_insn ("dbpl %0,%l1\n\tjle %l2", operands);
+ break;
+
+ case MINUS:
+ output_asm_insn ("dbmi %0,%l1\n\tjle %l2", operands);
+ break;
+
default:
gcc_unreachable ();
}
@@ -1790,11 +1937,12 @@ output_scc_di (rtx op, rtx operand1, rtx operand2, rtx dest)
return "";
}
-const char *
-output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos)
+rtx_code
+m68k_output_btst (rtx countop, rtx dataop, rtx_code code, int signpos)
{
- operands[0] = countop;
- operands[1] = dataop;
+ rtx ops[2];
+ ops[0] = countop;
+ ops[1] = dataop;
if (GET_CODE (countop) == CONST_INT)
{
@@ -1805,40 +1953,41 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos
{
int offset = (count & ~signpos) / 8;
count = count & signpos;
- operands[1] = dataop = adjust_address (dataop, QImode, offset);
+ ops[1] = dataop = adjust_address (dataop, QImode, offset);
+ }
+
+ if (code == EQ || code == NE)
+ {
+ if (count == 31)
+ {
+ output_asm_insn ("tst%.l %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
+ if (count == 15)
+ {
+ output_asm_insn ("tst%.w %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
+ if (count == 7)
+ {
+ output_asm_insn ("tst%.b %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
}
- if (count == signpos)
- cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
- else
- cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
-
- /* These three statements used to use next_insns_test_no...
- but it appears that this should do the same job. */
- if (count == 31
- && next_insn_tests_no_inequality (insn))
- return "tst%.l %1";
- if (count == 15
- && next_insn_tests_no_inequality (insn))
- return "tst%.w %1";
- if (count == 7
- && next_insn_tests_no_inequality (insn))
- return "tst%.b %1";
/* Try to use `movew to ccr' followed by the appropriate branch insn.
On some m68k variants unfortunately that's slower than btst.
On 68000 and higher, that should also work for all HImode operands. */
if (TUNE_CPU32 || TARGET_COLDFIRE || optimize_size)
{
- if (count == 3 && DATA_REG_P (operands[1])
- && next_insn_tests_no_inequality (insn))
+ if (count == 3 && DATA_REG_P (ops[1]) && (code == EQ || code == NE))
{
- cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N | CC_NO_OVERFLOW;
- return "move%.w %1,%%ccr";
+ output_asm_insn ("move%.w %1,%%ccr", ops);
+ return code == EQ ? PLUS : MINUS;
}
- if (count == 2 && DATA_REG_P (operands[1])
- && next_insn_tests_no_inequality (insn))
+ if (count == 2 && DATA_REG_P (ops[1]) && (code == EQ || code == NE))
{
- cc_status.flags = CC_NOT_NEGATIVE | CC_INVERTED | CC_NO_OVERFLOW;
- return "move%.w %1,%%ccr";
+ output_asm_insn ("move%.w %1,%%ccr", ops);
+ return code == EQ ? NE : EQ;
}
/* count == 1 followed by bvc/bvs and
count == 0 followed by bcc/bcs are also possible, but need
@@ -1847,7 +1996,28 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos
cc_status.flags = CC_NOT_NEGATIVE;
}
- return "btst %0,%1";
+ output_asm_insn ("btst %0,%1", ops);
+ return code;
+}
+
+/* Output a bftst instruction for a zero_extract with ZXOP0, ZXOP1 and ZXOP2
+ operands. CODE is the code of the comparison, and we return the code to
+ be actually used in the jump. */
+
+rtx_code
+m68k_output_bftst (rtx zxop0, rtx zxop1, rtx zxop2, rtx_code code)
+{
+ if (zxop1 == const1_rtx && GET_CODE (zxop2) == CONST_INT)
+ {
+ int width = GET_CODE (zxop0) == REG ? 31 : 7;
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ return m68k_output_btst (GEN_INT (width - INTVAL (zxop2)), zxop0, code, 1000);
+ }
+ rtx ops[3] = { zxop0, zxop1, zxop2 };
+ output_asm_insn ("bftst %0{%b2:%b1}", ops);
+ return code;
}
/* Return true if X is a legitimate base register. STRICT_P says
@@ -2839,7 +3009,8 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
case CONST_DOUBLE:
/* Make 0.0 cheaper than other floating constants to
encourage creating tstsf and tstdf insns. */
- if (outer_code == COMPARE
+ if ((GET_RTX_CLASS (outer_code) == RTX_COMPARE
+ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
&& (x == CONST0_RTX (SFmode) || x == CONST0_RTX (DFmode)))
*total = 4;
else
@@ -2953,7 +3124,8 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
return true;
case ZERO_EXTRACT:
- if (outer_code == COMPARE)
+ if (GET_RTX_CLASS (outer_code) == RTX_COMPARE
+ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
*total = 0;
return false;
@@ -3056,6 +3228,8 @@ output_move_simode_const (rtx *operands)
const char *
output_move_simode (rtx *operands)
{
+ handle_flags_for_move (operands);
+
if (GET_CODE (operands[1]) == CONST_INT)
return output_move_simode_const (operands);
else if ((GET_CODE (operands[1]) == SYMBOL_REF
@@ -3072,7 +3246,7 @@ output_move_simode (rtx *operands)
const char *
output_move_himode (rtx *operands)
{
- if (GET_CODE (operands[1]) == CONST_INT)
+ if (GET_CODE (operands[1]) == CONST_INT)
{
if (operands[1] == const0_rtx
&& (DATA_REG_P (operands[0])
@@ -3094,16 +3268,18 @@ output_move_himode (rtx *operands)
return "move%.w %1,%0";
}
else if (CONSTANT_P (operands[1]))
- return "move%.l %1,%0";
+ gcc_unreachable ();
return "move%.w %1,%0";
}
const char *
output_move_qimode (rtx *operands)
{
+ handle_flags_for_move (operands);
+
/* 68k family always modifies the stack pointer by at least 2, even for
byte pushes. The 5200 (ColdFire) does not do this. */
-
+
/* This case is generated by pushqi1 pattern now. */
gcc_assert (!(GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
@@ -3134,11 +3310,15 @@ output_move_qimode (rtx *operands)
if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
return "sub%.l %0,%0";
if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
- return "move%.l %1,%0";
+ gcc_unreachable ();
/* 68k family (including the 5200 ColdFire) does not support byte moves to
from address registers. */
if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
- return "move%.w %1,%0";
+ {
+ if (ADDRESS_REG_P (operands[1]))
+ CC_STATUS_INIT;
+ return "move%.w %1,%0";
+ }
return "move%.b %1,%0";
}
@@ -4136,125 +4316,440 @@ output_addsi3 (rtx *operands)
}
return "add%.l %2,%0";
}
-
-/* Store in cc_status the expressions that the condition codes will
- describe after execution of an instruction whose pattern is EXP.
- Do not alter them if the instruction would not alter the cc's. */
-
-/* On the 68000, all the insns to store in an address register fail to
- set the cc's. However, in some cases these instructions can make it
- possibly invalid to use the saved cc's. In those cases we clear out
- some or all of the saved cc's so they won't be used. */
-void
-notice_update_cc (rtx exp, rtx insn)
+/* Emit a comparison between OP0 and OP1. Return true iff the comparison
+ was reversed. SC1 is an SImode scratch reg, and SC2 a DImode scratch reg,
+ as needed. CODE is the code of the comparison, we return it unchanged or
+ swapped, as necessary. */
+rtx_code
+m68k_output_compare_di (rtx op0, rtx op1, rtx sc1, rtx sc2, rtx_insn *insn,
+ rtx_code code)
{
- if (GET_CODE (exp) == SET)
+ rtx ops[4];
+ ops[0] = op0;
+ ops[1] = op1;
+ ops[2] = sc1;
+ ops[3] = sc2;
+ if (op1 == const0_rtx)
{
- if (GET_CODE (SET_SRC (exp)) == CALL)
- CC_STATUS_INIT;
- else if (ADDRESS_REG_P (SET_DEST (exp)))
+ if (!REG_P (op0) || ADDRESS_REG_P (op0))
{
- if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
- cc_status.value1 = 0;
- if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
- cc_status.value2 = 0;
+ rtx xoperands[2];
+
+ xoperands[0] = sc2;
+ xoperands[1] = op0;
+ output_move_double (xoperands);
+ output_asm_insn ("neg%.l %R0\n\tnegx%.l %0", xoperands);
+ return swap_condition (code);
}
- /* fmoves to memory or data registers do not set the condition
- codes. Normal moves _do_ set the condition codes, but not in
- a way that is appropriate for comparison with 0, because -0.0
- would be treated as a negative nonzero number. Note that it
- isn't appropriate to conditionalize this restriction on
- HONOR_SIGNED_ZEROS because that macro merely indicates whether
- we care about the difference between -0.0 and +0.0. */
- else if (!FP_REG_P (SET_DEST (exp))
- && SET_DEST (exp) != cc0_rtx
- && (FP_REG_P (SET_SRC (exp))
- || GET_CODE (SET_SRC (exp)) == FIX
- || FLOAT_MODE_P (GET_MODE (SET_DEST (exp)))))
- CC_STATUS_INIT;
- /* A pair of move insns doesn't produce a useful overall cc. */
- else if (!FP_REG_P (SET_DEST (exp))
- && !FP_REG_P (SET_SRC (exp))
- && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
- && (GET_CODE (SET_SRC (exp)) == REG
- || GET_CODE (SET_SRC (exp)) == MEM
- || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
- CC_STATUS_INIT;
- else if (SET_DEST (exp) != pc_rtx)
+ if (find_reg_note (insn, REG_DEAD, op0))
{
- cc_status.flags = 0;
- cc_status.value1 = SET_DEST (exp);
- cc_status.value2 = SET_SRC (exp);
+ output_asm_insn ("neg%.l %R0\n\tnegx%.l %0", ops);
+ return swap_condition (code);
}
- }
- else if (GET_CODE (exp) == PARALLEL
- && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
- {
- rtx dest = SET_DEST (XVECEXP (exp, 0, 0));
- rtx src = SET_SRC (XVECEXP (exp, 0, 0));
-
- if (ADDRESS_REG_P (dest))
- CC_STATUS_INIT;
- else if (dest != pc_rtx)
+ else
{
- cc_status.flags = 0;
- cc_status.value1 = dest;
- cc_status.value2 = src;
+ /* 'sub' clears %1, and also clears the X cc bit.
+ 'tst' sets the Z cc bit according to the low part of the DImode
+ operand.
+ 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high
+ part. */
+ output_asm_insn ("sub%.l %2,%2\n\ttst%.l %R0\n\tsubx%.l %2,%0", ops);
+ return code;
}
}
+
+ if (rtx_equal_p (sc2, op0))
+ {
+ output_asm_insn ("sub%.l %R1,%R3\n\tsubx%.l %1,%3", ops);
+ return code;
+ }
else
+ {
+ output_asm_insn ("sub%.l %R0,%R3\n\tsubx%.l %0,%3", ops);
+ return swap_condition (code);
+ }
+}
+
+static void
+remember_compare_flags (rtx op0, rtx op1)
+{
+ if (side_effects_p (op0) || side_effects_p (op1))
CC_STATUS_INIT;
- if (cc_status.value2 != 0
- && ADDRESS_REG_P (cc_status.value2)
- && GET_MODE (cc_status.value2) == QImode)
- CC_STATUS_INIT;
- if (cc_status.value2 != 0)
- switch (GET_CODE (cc_status.value2))
- {
- case ASHIFT: case ASHIFTRT: case LSHIFTRT:
- case ROTATE: case ROTATERT:
- /* These instructions always clear the overflow bit, and set
- the carry to the bit shifted out. */
- cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
- break;
+ else
+ {
+ flags_compare_op0 = op0;
+ flags_compare_op1 = op1;
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ flags_valid = FLAGS_VALID_SET;
+ }
+}
- case PLUS: case MINUS: case MULT:
- case DIV: case UDIV: case MOD: case UMOD: case NEG:
- if (GET_MODE (cc_status.value2) != VOIDmode)
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
- case ZERO_EXTEND:
- /* (SET r1 (ZERO_EXTEND r2)) on this machine
- ends with a move insn moving r2 in r2's mode.
- Thus, the cc's are set for r2.
- This can set N bit spuriously. */
- cc_status.flags |= CC_NOT_NEGATIVE;
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_si (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
- default:
- break;
- }
- if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
- && cc_status.value2
- && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
- cc_status.value2 = 0;
- /* Check for PRE_DEC in dest modifying a register used in src. */
- if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
- && GET_CODE (XEXP (cc_status.value1, 0)) == PRE_DEC
- && cc_status.value2
- && reg_overlap_mentioned_p (XEXP (XEXP (cc_status.value1, 0), 0),
- cc_status.value2))
- cc_status.value2 = 0;
- if (((cc_status.value1 && FP_REG_P (cc_status.value1))
- || (cc_status.value2 && FP_REG_P (cc_status.value2))))
- cc_status.flags = CC_IN_68881;
- if (cc_status.value2 && GET_CODE (cc_status.value2) == COMPARE
- && GET_MODE_CLASS (GET_MODE (XEXP (cc_status.value2, 0))) == MODE_FLOAT)
- {
- cc_status.flags = CC_IN_68881;
- if (!FP_REG_P (XEXP (cc_status.value2, 0))
- && FP_REG_P (XEXP (cc_status.value2, 1)))
- cc_status.flags |= CC_REVERSED;
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx && (TARGET_68020 || TARGET_COLDFIRE || !ADDRESS_REG_P (op0)))
+ output_asm_insn ("tst%.l %0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.l %1,%0", ops);
+ else if (REG_P (op1)
+ || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.l %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else if (!TARGET_COLDFIRE
+ && ADDRESS_REG_P (op0)
+ && GET_CODE (op1) == CONST_INT
+ && INTVAL (op1) < 0x8000
+ && INTVAL (op1) >= -0x8000)
+ output_asm_insn ("cmp%.w %1,%0", ops);
+ else
+ output_asm_insn ("cmp%.l %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_hi (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx)
+ output_asm_insn ("tst%.w %d0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.w %1,%0", ops);
+ else if ((REG_P (op1) && !ADDRESS_REG_P (op1))
+ || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.w %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else
+ output_asm_insn ("cmp%.w %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_qi (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx)
+ output_asm_insn ("tst%.b %d0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.b %1,%0", ops);
+ else if (REG_P (op1) || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.b %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else
+ output_asm_insn ("cmp%.b %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_fp (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+
+ remember_compare_flags (op0, op1);
+
+ machine_mode mode = GET_MODE (op0);
+ std::string prec = mode == SFmode ? "s" : mode == DFmode ? "d" : "x";
+
+ if (op1 == CONST0_RTX (GET_MODE (op0)))
+ {
+ if (FP_REG_P (op0))
+ output_asm_insn ("ftst%.x %0", ops);
+ else
+ output_asm_insn (("ftst%." + prec + " %0").c_str (), ops);
+ return code;
+ }
+
+ switch (which_alternative)
+ {
+ case 0:
+ output_asm_insn ("fcmp%.x %1,%0", ops);
+ break;
+ case 1:
+ output_asm_insn (("fcmp%." + prec + " %f1,%0").c_str (), ops);
+ break;
+ case 2:
+ output_asm_insn (("fcmp%." + prec + " %0,%f1").c_str (), ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ case 3:
+ /* This is the ftst case, handled earlier. */
+ gcc_unreachable ();
+ }
+ return code;
+}
+
+/* Return an output template for a branch with CODE. */
+const char *
+m68k_output_branch_integer (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "jeq %l3";
+ case NE:
+ return "jne %l3";
+ case GT:
+ return "jgt %l3";
+ case GTU:
+ return "jhi %l3";
+ case LT:
+ return "jlt %l3";
+ case LTU:
+ return "jcs %l3";
+ case GE:
+ return "jge %l3";
+ case GEU:
+ return "jcc %l3";
+ case LE:
+ return "jle %l3";
+ case LEU:
+ return "jls %l3";
+ case PLUS:
+ return "jpl %l3";
+ case MINUS:
+ return "jmi %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a reversed branch with CODE. */
+const char *
+m68k_output_branch_integer_rev (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "jne %l3";
+ case NE:
+ return "jeq %l3";
+ case GT:
+ return "jle %l3";
+ case GTU:
+ return "jls %l3";
+ case LT:
+ return "jge %l3";
+ case LTU:
+ return "jcc %l3";
+ case GE:
+ return "jlt %l3";
+ case GEU:
+ return "jcs %l3";
+ case LE:
+ return "jgt %l3";
+ case LEU:
+ return "jhi %l3";
+ case PLUS:
+ return "jmi %l3";
+ case MINUS:
+ return "jpl %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a scc instruction with CODE. */
+const char *
+m68k_output_scc (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "seq %0";
+ case NE:
+ return "sne %0";
+ case GT:
+ return "sgt %0";
+ case GTU:
+ return "shi %0";
+ case LT:
+ return "slt %0";
+ case LTU:
+ return "scs %0";
+ case GE:
+ return "sge %0";
+ case GEU:
+ return "scc %0";
+ case LE:
+ return "sle %0";
+ case LEU:
+ return "sls %0";
+ case PLUS:
+ return "spl %0";
+ case MINUS:
+ return "smi %0";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a floating point branch
+ instruction with CODE. */
+const char *
+m68k_output_branch_float (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fjeq %l3";
+ case NE:
+ return "fjne %l3";
+ case GT:
+ return "fjgt %l3";
+ case LT:
+ return "fjlt %l3";
+ case GE:
+ return "fjge %l3";
+ case LE:
+ return "fjle %l3";
+ case ORDERED:
+ return "fjor %l3";
+ case UNORDERED:
+ return "fjun %l3";
+ case UNEQ:
+ return "fjueq %l3";
+ case UNGE:
+ return "fjuge %l3";
+ case UNGT:
+ return "fjugt %l3";
+ case UNLE:
+ return "fjule %l3";
+ case UNLT:
+ return "fjult %l3";
+ case LTGT:
+ return "fjogl %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a reversed floating point branch
+ instruction with CODE. */
+const char *
+m68k_output_branch_float_rev (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fjne %l3";
+ case NE:
+ return "fjeq %l3";
+ case GT:
+ return "fjngt %l3";
+ case LT:
+ return "fjnlt %l3";
+ case GE:
+ return "fjnge %l3";
+ case LE:
+ return "fjnle %l3";
+ case ORDERED:
+ return "fjun %l3";
+ case UNORDERED:
+ return "fjor %l3";
+ case UNEQ:
+ return "fjogl %l3";
+ case UNGE:
+ return "fjolt %l3";
+ case UNGT:
+ return "fjole %l3";
+ case UNLE:
+ return "fjogt %l3";
+ case UNLT:
+ return "fjoge %l3";
+ case LTGT:
+ return "fjueq %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a floating point scc
+ instruction with CODE. */
+const char *
+m68k_output_scc_float (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fseq %0";
+ case NE:
+ return "fsne %0";
+ case GT:
+ return "fsgt %0";
+ case GTU:
+ return "fshi %0";
+ case LT:
+ return "fslt %0";
+ case GE:
+ return "fsge %0";
+ case LE:
+ return "fsle %0";
+ case ORDERED:
+ return "fsor %0";
+ case UNORDERED:
+ return "fsun %0";
+ case UNEQ:
+ return "fsueq %0";
+ case UNGE:
+ return "fsuge %0";
+ case UNGT:
+ return "fsugt %0";
+ case UNLE:
+ return "fsule %0";
+ case UNLT:
+ return "fsult %0";
+ case LTGT:
+ return "fsogl %0";
+ default:
+ gcc_unreachable ();
}
}
@@ -4932,6 +5427,7 @@ const char *
output_andsi3 (rtx *operands)
{
int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) | 0xffff) == -1
&& (DATA_REG_P (operands[0])
@@ -4941,8 +5437,6 @@ output_andsi3 (rtx *operands)
if (GET_CODE (operands[0]) != REG)
operands[0] = adjust_address (operands[0], HImode, 2);
operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (operands[2] == const0_rtx)
return "clr%.w %0";
return "and%.w %2,%0";
@@ -4959,10 +5453,13 @@ output_andsi3 (rtx *operands)
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- /* This does not set condition codes in a standard way. */
- CC_STATUS_INIT;
return "bclr %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "and%.l %2,%0";
}
@@ -4970,6 +5467,7 @@ const char *
output_iorsi3 (rtx *operands)
{
register int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >> 16 == 0
&& (DATA_REG_P (operands[0])
@@ -4978,8 +5476,6 @@ output_iorsi3 (rtx *operands)
{
if (GET_CODE (operands[0]) != REG)
operands[0] = adjust_address (operands[0], HImode, 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 0xffff)
return "mov%.w %2,%0";
return "or%.w %2,%0";
@@ -4996,9 +5492,13 @@ output_iorsi3 (rtx *operands)
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- CC_STATUS_INIT;
return "bset %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "or%.l %2,%0";
}
@@ -5006,6 +5506,7 @@ const char *
output_xorsi3 (rtx *operands)
{
register int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >> 16 == 0
&& (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
@@ -5013,8 +5514,6 @@ output_xorsi3 (rtx *operands)
{
if (! DATA_REG_P (operands[0]))
operands[0] = adjust_address (operands[0], HImode, 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 0xffff)
return "not%.w %0";
return "eor%.w %2,%0";
@@ -5031,9 +5530,13 @@ output_xorsi3 (rtx *operands)
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- CC_STATUS_INIT;
return "bchg %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "eor%.l %2,%0";
}
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index fc65e52..39955b0 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -671,36 +671,6 @@ __transfer_from_trampoline () \
#define FUNCTION_MODE QImode
-/* Tell final.c how to eliminate redundant test instructions. */
-
-/* Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). */
-
-/* Set if the cc value is actually in the 68881, so a floating point
- conditional branch must be output. */
-#define CC_IN_68881 04000
-
-/* On the 68000, all the insns to store in an address register fail to
- set the cc's. However, in some cases these instructions can make it
- possibly invalid to use the saved cc's. In those cases we clear out
- some or all of the saved cc's so they won't be used. */
-#define NOTICE_UPDATE_CC(EXP,INSN) notice_update_cc (EXP, INSN)
-
-/* The shift instructions always clear the overflow bit. */
-#define CC_OVERFLOW_UNUSABLE 01000
-
-/* The shift instructions use the carry bit in a way not compatible with
- conditional branches. conditions.h uses CC_NO_OVERFLOW for this purpose.
- Rename it to something more understandable. */
-#define CC_NO_CARRY CC_NO_OVERFLOW
-
-#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
-do { if (cc_prev_status.flags & CC_IN_68881) \
- return FLOAT; \
- if (cc_prev_status.flags & CC_NO_OVERFLOW) \
- return NO_OV; \
- return NORMAL; } while (0)
-
/* Control the assembler format that we output. */
#define ASM_APP_ON "#APP\n"
@@ -900,6 +870,8 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+#define CC_STATUS_INIT m68k_init_cc ()
+
#include "config/m68k/m68k-opts.h"
enum fpu_type
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 31e8767..25e0b73 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -250,6 +250,18 @@
;; Alternative is OK for ColdFire.
(define_attr "ok_for_coldfire" "yes,no" (const_string "yes"))
+;; Instruction sets flags predictably to allow a following comparison to be
+;; elided.
+;; "no" means we should clear all flag state. "yes" means the destination
+;; register is valid. "noov" is similar but does not allow tests that rely
+;; on the overflow flag. "unchanged" means the instruction does not set the
+;; flags (but we should still verify none of the remembered operands are
+;; clobbered). "move" is a special case for which we remember both the
+;; destination and the source. "set" is another special case where the
+;; instruction pattern already performs the update and no more work is
+;; required in postscan_insn.
+(define_attr "flags_valid" "no,yes,set,noov,move,unchanged" (const_string "no"))
+
;; Define 'enabled' attribute.
(define_attr "enabled" ""
(cond [(and (match_test "TARGET_COLDFIRE")
@@ -303,150 +315,129 @@
DONE;
})
-;; We don't want to allow a constant operand for test insns because
-;; (set (cc0) (const_int foo)) has no mode information. Such insns will
-;; be folded while optimizing anyway.
-
-(define_insn "tstdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand" "am,d")
- (const_int 0)))
- (clobber (match_scratch:SI 1 "=X,d"))
- (clobber (match_scratch:DI 2 "=d,X"))]
+;; Compare instructions, combined with jumps or scc operations.
+
+(define_insn "beq0_di"
+ [(set (pc)
+ (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ",,"))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,&d,d"))]
""
{
- if (which_alternative == 0)
- {
- rtx xoperands[2];
-
- xoperands[0] = operands[2];
- xoperands[1] = operands[0];
- output_move_double (xoperands);
- cc_status.flags |= CC_REVERSED; /*|*/
- return "neg%.l %R2\;negx%.l %2";
- }
- if (find_reg_note (insn, REG_DEAD, operands[0]))
+ rtx_code code = m68k_find_flags_value (operands[0], const0_rtx, EQ);
+ if (code == EQ)
+ return "jeq %l1";
+ if (which_alternative == 2)
+ return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[3] = adjust_address (operands[0], SImode, 4);
+ if (! ADDRESS_REG_P (operands[0]))
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "neg%.l %R0\;negx%.l %0";
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ return "or%.l %0,%2\;jeq %l1";
+ else
+ return "or%.l %3,%2\;jeq %l1";
+ }
+ return "move%.l %0,%2\;or%.l %3,%2\;jeq %l1";
}
+ operands[4] = gen_label_rtx();
+ if (TARGET_68020 || TARGET_COLDFIRE)
+ output_asm_insn ("tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1", operands);
else
- /*
- 'sub' clears %1, and also clears the X cc bit
- 'tst' sets the Z cc bit according to the low part of the DImode operand
- 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part.
- */
- return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0";
-})
-
-;; If you think that the 68020 does not support tstl a0,
-;; reread page B-167 of the 68020 manual more carefully.
-(define_insn "*tstsi_internal_68020_cf"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
- (const_int 0)))]
- "TARGET_68020 || TARGET_COLDFIRE"
- "tst%.l %0"
- [(set_attr "type" "tst_l")])
-
-;; On an address reg, cmpw may replace cmpl.
-(define_insn "*tstsi_internal"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "dm,r")
- (const_int 0)))]
- "!(TARGET_68020 || TARGET_COLDFIRE)"
- "@
- tst%.l %0
- cmp%.w #0,%0"
- [(set_attr "type" "tst_l,cmp")])
-
-;; This can't use an address register, because comparisons
-;; with address registers as second operand always test the whole word.
-(define_insn "*tsthi_internal"
- [(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_operand" "dm")
- (const_int 0)))]
- ""
- "tst%.w %0"
- [(set_attr "type" "tst")])
-
-(define_insn "*tstqi_internal"
- [(set (cc0)
- (compare (match_operand:QI 0 "nonimmediate_operand" "dm")
- (const_int 0)))]
- ""
- "tst%.b %0"
- [(set_attr "type" "tst")])
-
-(define_insn "tst<mode>_68881"
- [(set (cc0)
- (compare (match_operand:FP 0 "general_operand" "f<FP:dreg>m")
- (match_operand:FP 1 "const0_operand" "H")))]
- "TARGET_68881"
-{
- cc_status.flags = CC_IN_68881;
- if (FP_REG_P (operands[0]))
- return "ftst%.x %0";
- return "ftst%.<FP:prec> %0";
-}
- [(set_attr "type" "ftst")])
-
-(define_insn "tst<mode>_cf"
- [(set (cc0)
- (compare (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U")
- (match_operand:FP 1 "const0_operand" "H")))]
- "TARGET_COLDFIRE_FPU"
-{
- cc_status.flags = CC_IN_68881;
- if (FP_REG_P (operands[0]))
- return "ftst%.d %0";
- return "ftst%.<FP:prec> %0";
-}
- [(set_attr "type" "ftst")])
-
-
-;; compare instructions.
+ output_asm_insn ("cmp%.w #0,%0\;jne %l4\;cmp%.w #0,%3\;jeq %l1", operands);
+ (*targetm.asm_out.internal_label) (asm_out_file, "L",
+ CODE_LABEL_NUMBER (operands[4]));
+ return "";
+})
-(define_insn "*cmpdi_internal"
- [(set (cc0)
- (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
- (match_operand:DI 2 "general_operand" "d,0")))
- (clobber (match_scratch:DI 0 "=d,d"))]
+(define_insn "bne0_di"
+ [(set (pc)
+ (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ",,"))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,&d,X"))]
""
{
- if (rtx_equal_p (operands[0], operands[1]))
- return "sub%.l %R2,%R0\;subx%.l %2,%0";
+ rtx_code code = m68k_find_flags_value (operands[0], const0_rtx, NE);
+ if (code == NE)
+ return "jne %l1";
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
+ operands[3] = adjust_address (operands[0], SImode, 4);
+ if (!ADDRESS_REG_P (operands[0]))
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "sub%.l %R1,%R0\;subx%.l %1,%0";
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ return "or%.l %0,%2\;jne %l1";
+ else
+ return "or%.l %3,%2\;jne %l1";
+ }
+ return "move%.l %0,%2\;or%.l %3,%2\;jne %l1";
}
+ if (TARGET_68020 || TARGET_COLDFIRE)
+ return "tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1";
+ else
+ return "cmp%.w #0,%0\;jne %l1\;cmp%.w #0,%3\;jne %l1";
})
-(define_insn "cmpdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand")
- (match_operand:DI 1 "general_operand")))
- (clobber (match_scratch:DI 2))]
+(define_insn "cbranchdi4_insn"
+ [(set (pc)
+ (if_then_else (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "nonimmediate_operand" "0,d,am,d")
+ (match_operand:DI 3 "general_operand" "d,0,C0,C0")])
+ (label_ref (match_operand 4 ""))
+ (pc)))
+ (clobber (match_scratch:DI 0 "=d,d,d,X"))
+ (clobber (match_scratch:SI 5 "=X,X,X,d"))]
""
- "")
-
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_di (operands[2], operands[3], operands[5], operands[0], insn, code);
+ operands[3] = operands[4];
+ return m68k_output_branch_integer (code);
+})
(define_expand "cbranchdi4"
- [(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:DI 1 "nonimmediate_operand")
- (match_operand:DI 2 "general_operand")])
- (label_ref (match_operand 3 ""))
- (pc)))]
+ [(parallel
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DI 1 "nonimmediate_operand")
+ (match_operand:DI 2 "general_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))
+ (clobber (match_scratch:DI 4 ""))
+ (clobber (match_scratch:SI 5 ""))])]
""
{
- if (operands[2] == const0_rtx)
- emit_insn (gen_tstdi (operands[1]));
- else
- emit_insn (gen_cmpdi (operands[1], operands[2]));
- operands[1] = cc0_rtx;
- operands[2] = const0_rtx;
+ rtx_code code = GET_CODE (operands[0]);
+ if ((code == GE || code == LT) && operands[2] == const0_rtx)
+ {
+ rtx xop1 = operand_subword_force (operands[1], 0, DImode);
+ rtx xop2 = operand_subword_force (operands[2], 0, DImode);
+ /* gen_cbranchsi4 won't use anything from operands[0] other than the
+ code. */
+ emit_jump_insn (gen_cbranchsi4 (operands[0], xop1, xop2, operands[3]));
+ DONE;
+ }
+ if (code == EQ && operands[2] == const0_rtx)
+ {
+ emit_jump_insn (gen_beq0_di (operands[1], operands[3]));
+ DONE;
+ }
+ if (code == NE && operands[2] == const0_rtx)
+ {
+ emit_jump_insn (gen_bne0_di (operands[1], operands[3]));
+ DONE;
+ }
})
(define_expand "cstoredi4"
@@ -456,40 +447,38 @@
(match_operand:DI 3 "general_operand")]))]
""
{
- if (operands[3] == const0_rtx)
- emit_insn (gen_tstdi (operands[2]));
- else
- emit_insn (gen_cmpdi (operands[2], operands[3]));
- operands[2] = cc0_rtx;
- operands[3] = const0_rtx;
+ rtx_code code = GET_CODE (operands[1]);
+ if ((code == GE || code == LT) && operands[3] == const0_rtx)
+ {
+ rtx xop2 = operand_subword_force (operands[2], 0, DImode);
+ rtx xop3 = operand_subword_force (operands[3], 0, DImode);
+ /* gen_cstoresi4 won't use anything from operands[1] other than the
+ code. */
+ emit_jump_insn (gen_cstoresi4 (operands[0], operands[1], xop2, xop3));
+ DONE;
+ }
})
+(define_mode_iterator CMPMODE [QI HI SI])
-(define_expand "cbranchsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (set (pc)
+(define_expand "cbranch<mode>4"
+ [(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 2 "m68k_comparison_operand" "")])
(label_ref (match_operand 3 ""))
(pc)))]
""
"")
-(define_expand "cstoresi4"
- [(set (cc0)
- (compare (match_operand:SI 2 "nonimmediate_operand" "")
- (match_operand:SI 3 "general_operand" "")))
- (set (match_operand:QI 0 "register_operand")
+(define_expand "cstore<mode>4"
+ [(set (match_operand:QI 0 "register_operand")
(match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 3 "m68k_comparison_operand" "")]))]
""
"")
-
-;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
-;;
;; In theory we ought to be able to use some 'S' constraints and
;; operand predicates that allow PC-rel addressing modes in the
;; comparison patterns and expanders below. But we would have to be
@@ -497,315 +486,357 @@
;; both operands and determining whether or not we emit the operands in
;; order or reversed is not trivial to do just based on the constraints
;; and operand predicates. So to be safe, just don't allow the PC-rel
-;; versions in the various comparison expanders, patterns, for comparisons.
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>")
- (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))]
+
+(define_mode_attr scc0_constraints [(QI "=d,d,d") (HI "=d,d,d,d,d") (SI "=d,d,d,d,d,d")])
+(define_mode_attr cmp1_constraints [(QI "dn,dm,>") (HI "rnm,d,n,m,>") (SI "r,r,r,mr,ma,>")])
+(define_mode_attr cmp2_constraints [(QI "dm,nd,>") (HI "d,rnm,m,n,>") (SI "mrC0,mr,ma,KTrC0,Ksr,>")])
+
+;; Note that operand 0 of an SCC insn is supported in the hardware as
+;; memory, but we cannot allow it to be in memory in case the address
+;; needs to be reloaded.
+
+(define_mode_attr scc0_cf_constraints [(QI "=d") (HI "=d") (SI "=d,d,d")])
+(define_mode_attr cmp1_cf_constraints [(QI "dm") (HI "dm") (SI "mrKs,r,rm")])
+(define_mode_attr cmp2_cf_constraints [(QI "C0") (HI "C0") (SI "r,mrKs,C0")])
+(define_mode_attr cmp2_cf_predicate [(QI "const0_operand") (HI "const0_operand") (SI "general_operand")])
+
+(define_insn "cbranch<mode>4_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
"!TARGET_COLDFIRE"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.l %1,%0";
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.l %d0,%d1";
- }
- if (ADDRESS_REG_P (operands[0])
- && GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) < 0x8000
- && INTVAL (operands[1]) >= -0x8000)
- return "cmp%.w %1,%0";
- return "cmp%.l %d1,%d0";
-})
-
-(define_insn "*cmpsi_cf"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
- (match_operand:SI 1 "general_operand" "r,mrKs")))]
- "TARGET_COLDFIRE"
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "flags_valid" "set")])
+
+(define_insn "cbranch<mode>4_insn_rev"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "!TARGET_COLDFIRE"
{
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.l %d0,%d1";
- }
- return "cmp%.l %d1,%d0";
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer_rev (code);
}
- [(set_attr "type" "cmp_l")])
+ [(set_attr "flags_valid" "set")])
-(define_expand "cbranchhi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "nonimmediate_operand" "")
- (match_operand:HI 2 "m68k_subword_comparison_operand" "")))
- (set (pc)
+(define_insn "cbranch<mode>4_insn_cf"
+ [(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")])
(label_ref (match_operand 3 ""))
(pc)))]
- ""
- "")
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_expand "cstorehi4"
- [(set (cc0)
- (compare (match_operand:HI 2 "nonimmediate_operand" "")
- (match_operand:HI 3 "m68k_subword_comparison_operand" "")))
- (set (match_operand:QI 0 "register_operand")
- (match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
- ""
- "")
+(define_insn "cbranch<mode>4_insn_cf_rev"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
- (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
+(define_insn "cstore<mode>4_insn"
+ [(set (match_operand:QI 0 "register_operand" "<scc0_constraints>")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 3 "general_operand" "<cmp2_constraints>")]))]
"!TARGET_COLDFIRE"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.w %1,%0";
- if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.w %d0,%d1";
- }
- return "cmp%.w %d1,%d0";
-})
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_<mode> (operands[2], operands[3], code);
+ return m68k_output_scc (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_expand "cbranchqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "m68k_subword_comparison_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+(define_insn "cstore<mode>4_insn_cf"
+ [(set (match_operand:QI 0 "register_operand" "<scc0_cf_constraints>")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 3 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")]))]
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_<mode> (operands[2], operands[3], code);
+ return m68k_output_scc (code);
+}
+ [(set_attr "flags_valid" "set")])
+
+;; ColdFire/5200 only allows "<Q>" type addresses when the bit position is
+;; specified as a constant, so we must disable all patterns that may extract
+;; from a MEM at a constant bit position if we can't use this as a constraint.
+
+(define_insn "cbranchsi4_btst_mem_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS,o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 2 "general_operand" "di,d")))
+ (const_int 0)])
(label_ref (match_operand 3 ""))
(pc)))]
""
- "")
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "ok_for_coldfire" "no,yes")])
-(define_expand "cstoreqi4"
- [(set (cc0)
- (compare (match_operand:QI 2 "nonimmediate_operand" "")
- (match_operand:QI 3 "m68k_subword_comparison_operand" "")))
- (set (match_operand:QI 0 "register_operand")
- (match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
- ""
- "")
+(define_insn "cbranchsi4_btst_reg_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (match_operand:SI 2 "general_operand" "di")))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_btst (operands[2], operands[1], code, 31);
+ return m68k_output_branch_integer (code);
+})
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:QI 0 "nonimmediate_operand" "dn,dm,>")
- (match_operand:QI 1 "general_operand" "dm,nd,>")))]
- "!TARGET_COLDFIRE"
+;; Nonoffsettable mem refs are ok in this one pattern
+;; since we don't try to adjust them.
+(define_insn "cbranchsi4_btst_mem_insn_1"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!TARGET_COLDFIRE && (unsigned) INTVAL (operands[2]) < 8"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.b %1,%0";
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ rtx_code code = GET_CODE (operands[0]);
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]));
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
+ return m68k_output_branch_integer (code);
+})
+
+(define_insn "cbranchsi4_btst_reg_insn_1"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do,dQ")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "n,n"))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!(REG_P (operands[1]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ if (GET_CODE (operands[1]) == MEM)
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.b %d0,%d1";
+ operands[1] = adjust_address (operands[1], QImode,
+ INTVAL (operands[2]) / 8);
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]) % 8);
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
}
- return "cmp%.b %d1,%d0";
+ else
+ {
+ operands[2] = GEN_INT (31 - INTVAL (operands[2]));
+ code = m68k_output_btst (operands[2], operands[1], code, 31);
+ }
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "ok_for_coldfire" "no,yes")])
+
+(define_mode_iterator BTST [QI SI])
+(define_mode_attr btst_predicate [(QI "memory_operand") (SI "register_operand")])
+(define_mode_attr btst_constraint [(QI "o") (SI "d")])
+(define_mode_attr btst_range [(QI "7") (SI "31")])
+
+;; Special patterns for optimizing bit-field instructions.
+(define_insn "cbranch_bftst<mode>_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(zero_extract:SI (match_operand:BTST 1 "<btst_predicate>" "<btst_constraint>")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "general_operand" "dn"))
+ (const_int 0)])
+ (label_ref (match_operand 4 ""))
+ (pc)))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (!REG_P (operands[1]) || !CONST_INT_P (operands[3])
+ || IN_RANGE (INTVAL (operands[3]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_bftst (operands[1], operands[2], operands[3], code);
+ operands[3] = operands[4];
+ return m68k_output_branch_integer (code);
})
+(define_insn "cstore_bftst<mode>_insn"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(zero_extract:SI (match_operand:BTST 2 "<btst_predicate>" "<btst_constraint>")
+ (match_operand:SI 3 "const_int_operand" "n")
+ (match_operand:SI 4 "general_operand" "dn"))
+ (const_int 0)]))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (!REG_P (operands[2]) || !CONST_INT_P (operands[4])
+ || IN_RANGE (INTVAL (operands[4]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_bftst (operands[2], operands[3], operands[4], code);
+ return m68k_output_scc (code);
+})
+
+;; Floating point comparison patterns
(define_expand "cbranch<mode>4"
- [(set (cc0)
- (compare (match_operand:FP 1 "register_operand" "")
- (match_operand:FP 2 "fp_src_operand" "")))
- (set (pc)
+ [(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:FP 1 "register_operand" "")
+ (match_operand:FP 2 "fp_src_operand" "")])
(label_ref (match_operand 3 ""))
(pc)))]
"TARGET_HARD_FLOAT"
"")
+;; ??? This presumably tries to allow tests against zero for coldfire, but
+;; it would have to test operands[3] and use CONST0_RTX (mode).
(define_expand "cstore<mode>4"
- [(set (cc0)
- (compare (match_operand:FP 2 "register_operand" "")
- (match_operand:FP 3 "fp_src_operand" "")))
- (set (match_operand:QI 0 "register_operand")
+ [(set (match_operand:QI 0 "register_operand")
(match_operator:QI 1 "m68k_cstore_comparison_operator"
- [(cc0) (const_int 0)]))]
+ [(match_operand:FP 2 "register_operand" "")
+ (match_operand:FP 3 "fp_src_operand" "")]))]
"TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)"
"if (TARGET_COLDFIRE && operands[2] != const0_rtx)
FAIL;")
-(define_insn "*cmp<mode>_68881"
- [(set (cc0)
- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg>mF")
- (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg>mF,f")))]
+(define_insn "cbranch<mode>4_insn_68881"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg>mF,f,H")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
"TARGET_68881
- && (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
- "@
- fcmp%.x %1,%0
- fcmp%.<FP:prec> %f1,%0
- fcmp%.<FP:prec> %0,%f1"
- [(set_attr "type" "fcmp")])
-
-(define_insn "*cmp<mode>_cf"
- [(set (cc0)
- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg><Q>U")
- (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg><Q>U,f")))]
- "TARGET_COLDFIRE_FPU
- && (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
- "@
- fcmp%.d %1,%0
- fcmp%.<FP:prec> %f1,%0
- fcmp%.<FP:prec> %0,%f1"
- [(set_attr "type" "fcmp")])
-
-;; Recognizers for btst instructions.
-
-;; ColdFire/5200 only allows "<Q>" type addresses when the bit position is
-;; specified as a constant, so we must disable all patterns that may extract
-;; from a MEM at a constant bit position if we can't use this as a constraint.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_src_operand" "oS")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "di")))
- (const_int 0)))]
- "!TARGET_COLDFIRE"
-{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
-
-;; This is the same as the above pattern except for the constraints. The 'i'
-;; has been deleted.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "d")))
- (const_int 0)))]
- "TARGET_COLDFIRE"
-{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (match_operand:SI 1 "general_operand" "di")))
- (const_int 0)))]
- "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
-
-;; The following two patterns are like the previous two
-;; except that they use the fact that bit-number operands
-;; are automatically masked to 3 or 5 bits.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 7))))
- (const_int 0)))]
- ""
-{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 31))))
- (const_int 0)))]
- ""
+(define_insn "cbranch<mode>4_insn_cf"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg><Q>U,f<FP:dreg><Q>U")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg><Q>U,f,H")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "TARGET_COLDFIRE_FPU
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-;; Nonoffsettable mem refs are ok in this one pattern
-;; since we don't try to adjust them.
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_COLDFIRE"
+(define_insn "cbranch<mode>4_insn_rev_68881"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg>mF,f,H")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_68881
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- operands[1] = GEN_INT (7 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "!TARGET_COLDFIRE
- && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+(define_insn "cbranch<mode>4_insn_rev_cf"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg><Q>U,f<FP:dreg><Q>U")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg><Q>U,f,H")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_COLDFIRE_FPU
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- if (GET_CODE (operands[0]) == MEM)
- {
- operands[0] = adjust_address (operands[0], QImode,
- INTVAL (operands[1]) / 8);
- operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
- return output_btst (operands, operands[1], operands[0], insn, 7);
- }
- operands[1] = GEN_INT (31 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-;; This is the same as the above pattern except for the constraints.
-;; The 'o' has been replaced with 'Q'.
+(define_insn "cstore<mode>4_insn_68881"
+ [(set (match_operand:QI 0 "register_operand" "=d,d,d,d")
+ (match_operator:QI 1 "m68k_cstore_comparison_operator"
+ [(match_operand:FP 2 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 3 "fp_src_operand" "f,<FP:dreg>mF,f,H")]))]
+ "TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)
+ && (register_operand (operands[2], <MODE>mode)
+ || register_operand (operands[3], <MODE>mode)
+ || const0_operand (operands[3], <MODE>mode))"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_fp (operands[2], operands[3], code);
+ return m68k_output_scc_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "TARGET_COLDFIRE
- && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+;; Test against zero only for coldfire floating point cstore.
+(define_insn "cstore<mode>4_insn_cf"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (match_operator:QI 1 "m68k_cstore_comparison_operator"
+ [(match_operand:FP 2 "fp_src_operand" "f<FP:dreg><Q>U")
+ (match_operand:FP 3 "const0_operand" "H")]))]
+ "TARGET_HARD_FLOAT && TARGET_COLDFIRE_FPU"
{
- if (GET_CODE (operands[0]) == MEM)
- {
- operands[0] = adjust_address (operands[0], QImode,
- INTVAL (operands[1]) / 8);
- operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
- return output_btst (operands, operands[1], operands[0], insn, 7);
- }
- operands[1] = GEN_INT (31 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_fp (operands[2], operands[3], code);
+ return m68k_output_scc_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-
;; move instructions
;; A special case in which it is not desirable
@@ -964,7 +995,8 @@
"!TARGET_COLDFIRE && reload_completed"
{
return output_move_simode (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
;; Before reload is completed the register constraints
;; force integer constants in range for a moveq to be reloaded
@@ -976,7 +1008,8 @@
"!TARGET_COLDFIRE"
{
return output_move_simode (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
;; ColdFire move instructions can have at most one operand of mode >= 6.
(define_insn "*movsi_cf"
@@ -1052,13 +1085,21 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(match_operand:HI 1 "general_src_operand" "gS"))]
"!TARGET_COLDFIRE"
- "* return output_move_himode (operands);")
+ "* return output_move_himode (operands);"
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "move")))])
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=r<Q>,g,U")
(match_operand:HI 1 "general_operand" "g,r<Q>,U"))]
"TARGET_COLDFIRE"
- "* return output_move_himode (operands);")
+ "* return output_move_himode (operands);"
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "move")))])
(define_expand "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
@@ -1070,13 +1111,15 @@
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(match_operand:HI 1 "general_src_operand" "rmSn"))]
"!TARGET_COLDFIRE"
- "* return output_move_stricthi (operands);")
+ "* return output_move_stricthi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+d,m"))
(match_operand:HI 1 "general_src_operand" "rmn,r"))]
"TARGET_COLDFIRE"
- "* return output_move_stricthi (operands);")
+ "* return output_move_stricthi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_expand "movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
@@ -1088,13 +1131,15 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,*a,m")
(match_operand:QI 1 "general_src_operand" "dmSi*a,di*a,dmSi"))]
"!TARGET_COLDFIRE"
- "* return output_move_qimode (operands);")
+ "* return output_move_qimode (operands);"
+ [(set_attr "flags_valid" "set")])
(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>,dm,U,d*a")
(match_operand:QI 1 "general_src_operand" "dmi,d<Q>,U,di*a"))]
"TARGET_COLDFIRE"
- "* return output_move_qimode (operands);")
+ "* return output_move_qimode (operands);"
+ [(set_attr "flags_valid" "set")])
(define_expand "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
@@ -1106,7 +1151,8 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(match_operand:QI 1 "general_src_operand" "dmSn"))]
"!TARGET_COLDFIRE"
- "* return output_move_strictqi (operands);")
+ "* return output_move_strictqi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_insn "*movstrictqi_cf"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d, Ac, d,m"))
@@ -1200,7 +1246,8 @@
return "clr%.l %0";
}
return "move%.l %1,%0";
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn "movsf_cf_soft"
[(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>,g,U")
@@ -1340,7 +1387,8 @@
return "fmove%.d %f1,%0";
}
return output_move_double (operands);
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn_and_split "movdf_cf_soft"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,g")
@@ -1461,7 +1509,8 @@
return "fmove%.x %f1,%0";
}
return output_move_double (operands);
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn ""
[(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
@@ -1582,16 +1631,16 @@
"!TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 3);
return "move%.b %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm,d")
@@ -1602,23 +1651,19 @@
if (GET_CODE (operands[0]) == REG
&& (GET_CODE (operands[1]) == MEM
|| GET_CODE (operands[1]) == CONST_INT))
- {
- /* Must clear condition codes, since the move.w bases them on
- the entire 16 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.w %1,%0";
- }
+ return "move%.w %1,%0";
+
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 1);
return "move%.b %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "truncsihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm,d")
@@ -1627,16 +1672,16 @@
"!TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 2);
return "move%.w %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
;; zero extension instructions
@@ -1804,7 +1849,6 @@
(sign_extend:DI (match_operand:QI 1 "general_src_operand" "rmS")))]
""
{
- CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (ISA_HAS_MVS_MVZ)
return "mvs%.b %1,%2\;smi %0\;extb%.l %0";
@@ -1830,7 +1874,6 @@
(match_operand:HI 1 "general_src_operand" "rmS")))]
""
{
- CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (ISA_HAS_MVS_MVZ)
return "mvs%.w %1,%2\;smi %0\;extb%.l %0";
@@ -1847,8 +1890,6 @@
(clobber (match_scratch:SI 2 "=X,d,d,d"))]
""
{
- CC_STATUS_INIT;
-
if (which_alternative == 0)
/* Handle alternative 0. */
{
@@ -1883,7 +1924,6 @@
(match_operand:SI 2 "general_operand" "rmn"))))]
""
{
- CC_STATUS_INIT;
operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (GET_CODE (operands[1]) == CONST_INT
&& (unsigned) INTVAL (operands[1]) > 8)
@@ -1975,10 +2015,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "f%&move%.x %1,%0";
@@ -2004,10 +2041,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "fdmove%.d %1,%0";
@@ -2137,7 +2171,6 @@
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!";
})
@@ -2148,7 +2181,6 @@
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!";
})
@@ -2159,7 +2191,6 @@
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.b %1,%0\;fmovem%.l %2,%!";
})
@@ -2301,7 +2332,6 @@
(clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return "add%.w %1,%0";
else if (ADDRESS_REG_P (operands[3]))
@@ -2317,7 +2347,6 @@
(match_operand:DI 2 "general_operand" "0,0")))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
@@ -2332,7 +2361,6 @@
(match_operand:DI 2 "register_operand" "0")))]
"TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
return "add%.l %1,%R0\;negx%.l %0\;neg%.l %0";
})
@@ -2346,7 +2374,6 @@
(match_operand:DI 2 "general_operand" "0,0")))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
else
@@ -2412,7 +2439,6 @@
else
{
gcc_assert (GET_CODE (operands[0]) == MEM);
- CC_STATUS_INIT;
if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
{
operands[1] = gen_rtx_MEM (SImode,
@@ -2431,7 +2457,11 @@
return "add%.l %R2,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0";
}
}
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "noov")
+ (const_string "no")))])
(define_insn "addsi_lshrsi_31"
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm,dm,d<Q>")
@@ -2476,7 +2506,8 @@
"! TARGET_COLDFIRE"
- "* return output_addsi3 (operands);")
+ "* return output_addsi3 (operands);"
+ [(set_attr "flags_valid" "noov,unchanged,unchanged,noov,unchanged")])
(define_insn_and_split "*addsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,a, m,r, ?a, ?a,?a,?a")
@@ -2561,7 +2592,7 @@
return "subq%.w %2,%0";
}
/* On the CPU32 it is faster to use two addqw instructions to
- add a small integer (8 < N <= 16) to a register.
+ add a small integer (8 < N <= 16) to a register.
Likewise for subqw. */
if (TUNE_CPU32 && REG_P (operands[0]))
{
@@ -2582,7 +2613,11 @@
return MOTOROLA ? "lea (%c2,%0),%0" : "lea %0@(%c2),%0";
}
return "add%.w %2,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "noov")))])
;; These insns must use MATCH_DUP instead of the more expected
;; use of a matching constraint because the "output" here is also
@@ -2596,6 +2631,7 @@
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
{
+ gcc_assert (!ADDRESS_REG_P (operands[0]));
if (GET_CODE (operands[1]) == CONST_INT)
{
/* If the constant would be a negative number when interpreted as
@@ -2633,11 +2669,10 @@
return "subq%.w #8,%0\;subq%.w %1,%0";
}
}
- if (ADDRESS_REG_P (operands[0]) && !TUNE_68040)
- return MOTOROLA ? "lea (%c1,%0),%0" : "lea %0@(%c1),%0";
}
return "add%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
@@ -2645,6 +2680,7 @@
(match_dup 0)))]
"!TARGET_COLDFIRE"
{
+ gcc_assert (!ADDRESS_REG_P (operands[0]));
if (GET_CODE (operands[1]) == CONST_INT)
{
/* If the constant would be a negative number when interpreted as
@@ -2682,11 +2718,10 @@
return "subq%.w #8,%0\;subq%.w %1,%0";
}
}
- if (ADDRESS_REG_P (operands[0]) && !TUNE_68040)
- return MOTOROLA ? "lea (%c1,%0),%0" : "lea %0@(%c1),%0";
}
return "add%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn "addqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
@@ -2709,7 +2744,8 @@
}
}
return "add%.b %2,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
@@ -2827,7 +2863,6 @@
(clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return "sub%.w %2,%0";
else if (ADDRESS_REG_P (operands[3]))
@@ -2843,7 +2878,6 @@
(const_int 32))))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
else
@@ -2911,7 +2945,6 @@
else
{
gcc_assert (GET_CODE (operands[0]) == MEM);
- CC_STATUS_INIT;
if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
{
operands[1]
@@ -2930,20 +2963,26 @@
return "sub%.l %R2,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0";
}
}
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "noov")
+ (const_string "no")))])
(define_insn "subsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=mda,m,d,a")
- (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
- (match_operand:SI 2 "general_src_operand" "I,dT,mSrT,mSrs")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=md,ma,m,d,a")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0,0")
+ (match_operand:SI 2 "general_src_operand" "I,I,dT,mSrT,mSrs")))]
""
"@
subq%.l %2, %0
+ subq%.l %2, %0
sub%.l %2,%0
sub%.l %2,%0
sub%.l %2,%0"
- [(set_attr "type" "aluq_l,alu_l,alu_l,alu_l")
- (set_attr "opy" "2")])
+ [(set_attr "type" "aluq_l,aluq_l,alu_l,alu_l,alu_l")
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "noov,unchanged,noov,noov,unchanged")])
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=a")
@@ -2958,28 +2997,32 @@
(minus:HI (match_operand:HI 1 "general_operand" "0,0")
(match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
- "sub%.w %2,%0")
+ "sub%.w %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(minus:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
- "sub%.w %1,%0")
+ "sub%.w %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "subqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(minus:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "sub%.b %2,%0")
+ "sub%.b %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(minus:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "sub%.b %1,%0")
+ "sub%.b %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_expand "sub<mode>3"
[(set (match_operand:FP 0 "nonimmediate_operand" "")
@@ -3240,10 +3283,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "mulu%.l %3,%0:%1";
-})
+ "mulu%.l %3,%0:%1")
(define_insn "const_umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -3254,10 +3294,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "mulu%.l %3,%0:%1";
-})
+ "mulu%.l %3,%0:%1")
(define_expand "smulsi3_highpart"
[(parallel
@@ -3289,10 +3326,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "muls%.l %3,%0:%1";
-})
+ "muls%.l %3,%0:%1")
(define_insn "const_smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -3303,10 +3337,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "muls%.l %3,%0:%1";
-})
+ "muls%.l %3,%0:%1")
(define_expand "mul<mode>3"
[(set (match_operand:FP 0 "nonimmediate_operand" "")
@@ -3483,19 +3514,19 @@
(define_expand "divmodsi4"
[(parallel
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ [(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_src_operand" "")))
- (set (match_operand:SI 3 "nonimmediate_operand" "")
+ (set (match_operand:SI 3 "register_operand" "")
(mod:SI (match_dup 1) (match_dup 2)))])]
"TARGET_68020 || TARGET_CF_HWDIV"
"")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "d<Q>U")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=&d")
+ (set (match_operand:SI 3 "register_operand" "=&d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_CF_HWDIV"
{
@@ -3510,10 +3541,10 @@
(set_attr "opy" "2")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020"
{
@@ -3525,19 +3556,19 @@
(define_expand "udivmodsi4"
[(parallel
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))])]
"TARGET_68020 || TARGET_CF_HWDIV"
"")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "d<Q>U")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=&d")
+ (set (match_operand:SI 3 "register_operand" "=&d")
(umod:SI (match_dup 1) (match_dup 2)))]
"TARGET_CF_HWDIV"
{
@@ -3552,10 +3583,10 @@
(set_attr "opy" "2")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020 && !TARGET_COLDFIRE"
{
@@ -3566,10 +3597,10 @@
})
(define_insn "divmodhi4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:HI 0 "register_operand" "=d")
(div:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:HI 3 "register_operand" "=d")
(mod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_COLDFIRE || TARGET_CF_HWDIV"
{
@@ -3578,19 +3609,16 @@
"extl %0\;divs %2,%0",
operands);
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
- {
- CC_STATUS_INIT;
- return "move%.l %0,%3\;swap %3";
- }
+ return "move%.l %0,%3\;swap %3";
else
return "";
})
(define_insn "udivmodhi4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:HI 0 "register_operand" "=d")
(udiv:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:HI 3 "register_operand" "=d")
(umod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_COLDFIRE || TARGET_CF_HWDIV"
{
@@ -3606,10 +3634,7 @@
operands);
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
- {
- CC_STATUS_INIT;
- return "move%.l %0,%3\;swap %3";
- }
+ return "move%.l %0,%3\;swap %3";
else
return "";
})
@@ -3644,7 +3669,8 @@
"!TARGET_COLDFIRE"
{
return output_andsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "andsi3_5200"
[(set (match_operand:SI 0 "not_sp_operand" "=m,d")
@@ -3669,35 +3695,40 @@
(and:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.w %2,%0")
+ "and%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.w %1,%0")
+ "and%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "and%.w %1,%0")
+ "and%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "andqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(and:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.b %2,%0")
+ "and%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(and:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.b %1,%0")
+ "and%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
@@ -3716,7 +3747,6 @@
{
int byte_mode;
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
@@ -3747,7 +3777,8 @@
"! TARGET_COLDFIRE"
{
return output_iorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "iorsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,d")
@@ -3756,7 +3787,8 @@
"TARGET_COLDFIRE"
{
return output_iorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "iorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=m,d")
@@ -3777,28 +3809,32 @@
(ior:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "or%.w %1,%0")
+ "or%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "iorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "or%.b %2,%0")
+ "or%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "or%.b %1,%0")
+ "or%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "or%.b %1,%0")
+ "or%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; On all 68k models, this makes faster code in a special case.
;; See also ashlsi_16, ashrsi_16 and lshrsi_16.
@@ -3810,7 +3846,6 @@
(const_int 16))))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[2]) != REG)
operands[2] = adjust_address (operands[2], HImode, 2);
if (GET_CODE (operands[2]) != REG
@@ -3827,7 +3862,6 @@
{
int byte_mode;
- CC_STATUS_INIT;
byte_mode = (GET_MODE (operands[1]) == QImode);
if (GET_CODE (operands[0]) == MEM)
operands[0] = adjust_address (operands[0], byte_mode ? QImode : HImode,
@@ -3855,7 +3889,8 @@
"!TARGET_COLDFIRE"
{
return output_xorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "xorsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm,d")
@@ -3864,49 +3899,56 @@
"TARGET_COLDFIRE"
{
return output_xorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "xorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(xor:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.w %2,%0")
+ "eor%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.w %1,%0")
+ "eor%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_operand:HI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "eor%.w %1,%0")
+ "eor%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "xorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(xor:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.b %2,%0")
+ "eor%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.b %1,%0")
+ "eor%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_operand:QI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "eor%.b %1,%0")
+ "eor%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; negation instructions
@@ -3965,38 +4007,44 @@
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
"neg%.l %0"
- [(set_attr "type" "neg_l")])
+ [(set_attr "type" "neg_l")
+ (set_attr "flags_valid" "noov")])
(define_insn "negsi2_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_COLDFIRE"
"neg%.l %0"
- [(set_attr "type" "neg_l")])
+ [(set_attr "type" "neg_l")
+ (set_attr "flags_valid" "noov")])
(define_insn "neghi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "neg%.w %0")
+ "neg%.w %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(neg:HI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "neg%.w %0")
+ "neg%.w %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "negqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(neg:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "neg%.b %0")
+ "neg%.b %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(neg:QI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "neg%.b %0")
+ "neg%.b %0"
+ [(set_attr "flags_valid" "noov")])
;; If using software floating point, just flip the sign bit.
@@ -4290,20 +4338,14 @@
[(set (match_operand:SI 0 "register_operand" "=d")
(clz:SI (match_operand:SI 1 "general_operand" "do")))]
"TARGET_68020 && TARGET_BITFIELD"
-{
- CC_STATUS_INIT;
- return "bfffo %1{#0:#0},%0";
-})
+ "bfffo %1{#0:#0},%0")
;; ColdFire ff1 instruction implements clz.
(define_insn "*clzsi2_cf"
[(set (match_operand:SI 0 "register_operand" "=d")
(clz:SI (match_operand:SI 1 "register_operand" "0")))]
"ISA_HAS_FF1"
-{
- CC_STATUS_INIT;
- return "ff1 %0";
-}
+ "ff1 %0"
[(set_attr "type" "ext")])
;; one complement instructions
@@ -4324,7 +4366,8 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(not:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.l %0")
+ "not%.l %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "one_cmplsi2_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d")
@@ -4337,25 +4380,29 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(not:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.w %0")
+ "not%.w %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(not:HI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "not%.w %0")
+ "not%.w %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(not:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.b %0")
+ "not%.b %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(not:QI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "not%.b %0")
+ "not%.b %0"
+ [(set_attr "flags_valid" "yes")])
;; arithmetic shift instructions
;; We don't need the shift memory by 1 bit instruction
@@ -4379,7 +4426,6 @@
(clobber (match_scratch:SI 2 "=a,X"))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
@@ -4577,13 +4623,10 @@
(ashift:SI (match_operand:SI 1 "register_operand" "0")
(const_int 16)))]
"!TUNE_68060"
-{
- CC_STATUS_INIT;
- return "swap %0\;clr%.w %0";
-})
+ "swap %0\;clr%.w %0")
;; ashift patterns : use lsl instead of asl, because lsl always clears the
-;; overflow bit, so we must not set CC_NO_OVERFLOW.
+;; overflow bit, allowing more comparisons.
;; On the 68000, this makes faster code in a special case.
@@ -4595,8 +4638,6 @@
&& INTVAL (operands[2]) > 16
&& INTVAL (operands[2]) <= 24"
{
- CC_STATUS_INIT;
-
operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
return "lsl%.w %2,%0\;swap %0\;clr%.w %0";
})
@@ -4608,40 +4649,45 @@
""
{
if (operands[2] == const1_rtx)
- {
- cc_status.flags = CC_NO_OVERFLOW;
- return "add%.l %0,%0";
- }
+ return "add%.l %0,%0";
return "lsl%.l %2,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 2 "const1_operand")
+ (const_string "noov")
+ (const_string "yes")))])
(define_insn "ashlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashift:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.w %2,%0")
+ "lsl%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashift:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.w %1,%0")
+ "lsl%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "ashlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashift:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.b %2,%0")
+ "lsl%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashift:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.b %1,%0")
+ "lsl%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; On most 68k models, this makes faster code in a special case.
@@ -4695,7 +4741,6 @@
"!TARGET_COLDFIRE"
{
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- CC_STATUS_INIT;
return "asr%.l #1,%0\;roxr%.l #1,%1";
})
@@ -4761,7 +4806,6 @@
(const_int 32)))]
""
{
- CC_STATUS_INIT;
if (TARGET_68020)
return "move%.l %1,%R0\;smi %0\;extb%.l %0";
else
@@ -4775,7 +4819,6 @@
(clobber (match_scratch:SI 2 "=d,d"))]
""
{
- CC_STATUS_INIT;
operands[3] = adjust_address (operands[0], SImode,
which_alternative == 0 ? 4 : 0);
operands[0] = adjust_address (operands[0], SImode, 0);
@@ -4808,7 +4851,6 @@
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
{
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 48)
return "swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0";
if (INTVAL (operands[2]) == 31)
@@ -4858,35 +4900,40 @@
""
"asr%.l %2,%0"
[(set_attr "type" "shift")
- (set_attr "opy" "2")])
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "noov")])
(define_insn "ashrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.w %2,%0")
+ "asr%.w %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.w %1,%0")
+ "asr%.w %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "ashrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.b %2,%0")
+ "asr%.b %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.b %1,%0")
+ "asr%.b %1,%0"
+ [(set_attr "flags_valid" "noov")])
;; logical shift instructions
@@ -4933,7 +4980,6 @@
(const_int 1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
return "lsr%.l #1,%0\;roxr%.l #1,%R0";
})
@@ -5131,7 +5177,6 @@
(const_int 16)))]
"!TUNE_68060"
{
- CC_STATUS_INIT;
return "clr%.w %0\;swap %0";
})
@@ -5157,35 +5202,40 @@
""
"lsr%.l %2,%0"
[(set_attr "type" "shift")
- (set_attr "opy" "2")])
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "yes")])
(define_insn "lshrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.w %2,%0")
+ "lsr%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(lshiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.w %1,%0")
+ "lsr%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "lshrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.b %2,%0")
+ "lsr%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(lshiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.b %1,%0")
+ "lsr%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; rotate instructions
@@ -5195,7 +5245,8 @@
(const_int 16)))]
""
"swap %0"
- [(set_attr "type" "shift")])
+ [(set_attr "type" "shift")
+ (set_attr "flags_valid" "yes")])
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -5212,7 +5263,8 @@
}
else
return "rol%.l %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
@@ -5227,7 +5279,8 @@
}
else
return "rol%.w %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "*rotlhi3_lowpart"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
@@ -5242,7 +5295,8 @@
}
else
return "rol%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
@@ -5257,7 +5311,8 @@
}
else
return "rol%.b %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "*rotlqi3_lowpart"
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
@@ -5272,14 +5327,16 @@
}
else
return "rol%.b %1,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotrsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(rotatert:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.l %2,%0")
+ "ror%.l %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
@@ -5300,14 +5357,16 @@
(rotatert:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.b %2,%0")
+ "ror%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(rotatert:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.b %1,%0")
+ "ror%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_expand "bswapsi2"
[(set (match_operand:SI 0 "register_operand")
@@ -5332,10 +5391,7 @@
(match_operand:SI 1 "general_operand" "d")) 3)
(match_dup 0)))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
;; set bit, bit number is (sign/zero)_extended from HImode/QImode
@@ -5346,10 +5402,7 @@
[(match_operand 1 "general_operand" "d")])) 3)
(match_dup 0)))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bsetdreg"
@@ -5359,10 +5412,7 @@
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bchgdreg"
@@ -5372,10 +5422,7 @@
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bchg %1,%0";
-}
+ "bchg %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bclrdreg"
@@ -5385,10 +5432,7 @@
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; clear bit, bit number is int
@@ -5399,10 +5443,7 @@
(match_operand:SI 1 "general_operand" "d")))
(const_int 0))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; clear bit, bit number is (sign/zero)_extended from HImode/QImode
@@ -5414,10 +5455,7 @@
[(match_operand 1 "general_operand" "d")])))
(const_int 0))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; Special cases of bit-field insns which we should
@@ -5500,7 +5538,6 @@
&& (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
{
- cc_status.flags |= CC_NOT_NEGATIVE;
if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
return "bfextu %1{%b3:%b2},%0";
@@ -5586,15 +5623,6 @@
(match_operand:SI 3 "nonmemory_operand" "dn")))]
"TARGET_68020 && TARGET_BITFIELD"
{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) != 32)
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- CC_STATUS_INIT;
- }
return "bfextu %1{%b3:%b2},%0";
})
@@ -5609,7 +5637,6 @@
|| (GET_CODE (operands[1]) == CONST_INT
&& (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
{
- CC_STATUS_INIT;
return "bfchg %0{%b2:%b1}";
})
@@ -5620,7 +5647,6 @@
(const_int 0))]
"TARGET_68020 && TARGET_BITFIELD"
{
- CC_STATUS_INIT;
return "bfclr %0{%b2:%b1}";
})
@@ -5631,7 +5657,6 @@
(const_int -1))]
"TARGET_68020 && TARGET_BITFIELD"
{
- CC_STATUS_INIT;
return "bfset %0{%b2:%b1}";
})
@@ -5680,15 +5705,6 @@
(match_operand:SI 3 "const_int_operand" "n")))]
"TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) != 32)
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- CC_STATUS_INIT;
- }
return "bfextu %1{%b3:%b2},%0";
})
@@ -5699,7 +5715,6 @@
(const_int 0))]
"TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
- CC_STATUS_INIT;
return "bfclr %0{%b2:%b1}";
})
@@ -5710,7 +5725,6 @@
(const_int -1))]
"TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
- CC_STATUS_INIT;
return "bfset %0{%b2:%b1}";
})
@@ -5733,58 +5747,6 @@
return "bfins %3,%0{%b2:%b1}";
})
-;; Special patterns for optimizing bit-field instructions.
-
-(define_insn "*tst_bftst_mem"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn"))
- (const_int 0)))]
- "TARGET_68020 && TARGET_BITFIELD"
-{
- if (operands[1] == const1_rtx
- && GET_CODE (operands[2]) == CONST_INT)
- {
- int width = GET_CODE (operands[0]) == REG ? 31 : 7;
- return output_btst (operands,
- GEN_INT (width - INTVAL (operands[2])),
- operands[0], insn, 1000);
- /* Pass 1000 as SIGNPOS argument so that btst will
- not think we are testing the sign bit for an `and'
- and assume that nonzero implies a negative result. */
- }
- if (INTVAL (operands[1]) != 32)
- cc_status.flags = CC_NOT_NEGATIVE;
- return "bftst %0{%b2:%b1}";
-})
-
-
-;;; now handle the register cases
-(define_insn "*tst_bftst_reg"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn"))
- (const_int 0)))]
- "TARGET_68020 && TARGET_BITFIELD
- && !(CONST_INT_P (operands[2]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
-{
- if (operands[1] == const1_rtx
- && GET_CODE (operands[2]) == CONST_INT)
- {
- int width = GET_CODE (operands[0]) == REG ? 31 : 7;
- return output_btst (operands, GEN_INT (width - INTVAL (operands[2])),
- operands[0], insn, 1000);
- /* Pass 1000 as SIGNPOS argument so that btst will
- not think we are testing the sign bit for an `and'
- and assume that nonzero implies a negative result. */
- }
- if (INTVAL (operands[1]) != 32)
- cc_status.flags = CC_NOT_NEGATIVE;
- return "bftst %0{%b2:%b1}";
-})
-
(define_insn "scc0_di"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(match_operator 1 "ordered_comparison_operator"
@@ -5822,879 +5784,6 @@
{
return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
})
-
-;; Note that operand 0 of an SCC insn is supported in the hardware as
-;; memory, but we cannot allow it to be in memory in case the address
-;; needs to be reloaded.
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (eq:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ne:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (gt:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sgt %0", "fsgt %0", 0);
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (gtu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "shi %0";
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (lt:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("slt %0", "fslt %0", "smi %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ltu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "scs %0";
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ge:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sge %0", "fsge %0", "spl %0");
-})
-
-(define_insn "*scc"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (geu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "scc %0";
-}
- [(set_attr "type" "scc")])
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (le:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sle %0", "fsle %0", 0);
-})
-
-(define_insn "*sls"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (leu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "sls %0";
-}
- [(set_attr "type" "scc")])
-
-(define_insn "*sordered_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsor %0";
-})
-
-(define_insn "*sunordered_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsun %0";
-})
-
-(define_insn "*suneq_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (uneq:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsueq %0";
-})
-
-(define_insn "*sunge_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unge:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsuge %0";
-})
-
-(define_insn "*sungt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ungt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsugt %0";
-})
-
-(define_insn "*sunle_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unle:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsule %0";
-})
-
-(define_insn "*sunlt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unlt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsult %0";
-})
-
-(define_insn "*sltgt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ltgt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsogl %0";
-})
-
-(define_insn "*fsogt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unle:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsogt %0";
-})
-
-(define_insn "*fsoge_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unlt:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsoge %0";
-})
-
-(define_insn "*fsolt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unge:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsolt %0";
-})
-
-(define_insn "*fsole_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (ungt:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsole %0";
-})
-
-;; Basic conditional jump instructions.
-
-(define_insn "beq0_di"
- [(set (pc)
- (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
- (const_int 0))
- (label_ref (match_operand 1 "" ",,"))
- (pc)))
- (clobber (match_scratch:SI 2 "=d,&d,d"))]
- ""
-{
- CC_STATUS_INIT;
- if (which_alternative == 2)
- return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return "jeq %l1";
- }
- if (GET_CODE (operands[0]) == REG)
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else
- operands[3] = adjust_address (operands[0], SImode, 4);
- if (! ADDRESS_REG_P (operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[3]))
- return "or%.l %0,%2\;jeq %l1";
- else
- return "or%.l %3,%2\;jeq %l1";
- }
- return "move%.l %0,%2\;or%.l %3,%2\;jeq %l1";
- }
- operands[4] = gen_label_rtx();
- if (TARGET_68020 || TARGET_COLDFIRE)
- output_asm_insn ("tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1", operands);
- else
- output_asm_insn ("cmp%.w #0,%0\;jne %l4\;cmp%.w #0,%3\;jeq %l1", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[4]));
- return "";
-})
-
-(define_insn "bne0_di"
- [(set (pc)
- (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
- (const_int 0))
- (label_ref (match_operand 1 "" ",,"))
- (pc)))
- (clobber (match_scratch:SI 2 "=d,&d,X"))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return "jne %l1";
- }
- CC_STATUS_INIT;
- if (GET_CODE (operands[0]) == REG)
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else
- operands[3] = adjust_address (operands[0], SImode, 4);
- if (!ADDRESS_REG_P (operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[3]))
- return "or%.l %0,%2\;jne %l1";
- else
- return "or%.l %3,%2\;jne %l1";
- }
- return "move%.l %0,%2\;or%.l %3,%2\;jne %l1";
- }
- if (TARGET_68020 || TARGET_COLDFIRE)
- return "tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1";
- else
- return "cmp%.w #0,%0\;jne %l1\;cmp%.w #0,%3\;jne %l1";
-})
-
-(define_insn "bge0_di"
- [(set (pc)
- (if_then_else (ge (match_operand:DI 0 "general_operand" "ro")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return cc_status.flags & CC_REVERSED ? "jle %l1" : "jpl %l1";
- }
- CC_STATUS_INIT;
- if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0]))
- output_asm_insn("tst%.l %0", operands);
- else
- {
- /* On an address reg, cmpw may replace cmpl. */
- output_asm_insn("cmp%.w #0,%0", operands);
- }
- return "jpl %l1";
-})
-
-(define_insn "blt0_di"
- [(set (pc)
- (if_then_else (lt (match_operand:DI 0 "general_operand" "ro")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return cc_status.flags & CC_REVERSED ? "jgt %l1" : "jmi %l1";
- }
- CC_STATUS_INIT;
- if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0]))
- output_asm_insn("tst%.l %0", operands);
- else
- {
- /* On an address reg, cmpw may replace cmpl. */
- output_asm_insn("cmp%.w #0,%0", operands);
- }
- return "jmi %l1";
-})
-
-(define_insn "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jhi %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jlt %l0", "fjlt %l0", "jmi %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcs %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jge %l0", "fjge %l0", "jpl %l0");
-})
-
-(define_insn "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcc %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jle %l0", "fjle %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jls %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bordered"
- [(set (pc)
- (if_then_else (ordered (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjor %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunordered"
- [(set (pc)
- (if_then_else (unordered (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjun %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "buneq"
- [(set (pc)
- (if_then_else (uneq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjueq %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunge"
- [(set (pc)
- (if_then_else (unge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjuge %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bungt"
- [(set (pc)
- (if_then_else (ungt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjugt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunle"
- [(set (pc)
- (if_then_else (unle (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjule %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunlt"
- [(set (pc)
- (if_then_else (unlt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjult %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bltgt"
- [(set (pc)
- (if_then_else (ltgt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogl %l0";
-}
- [(set_attr "type" "fbcc")])
-
-;; Negated conditional jump instructions.
-
-(define_insn "*beq_rev"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bne_rev"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgt_rev"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jle %l0", "fjngt %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgtu_rev"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jls %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*blt_rev"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jge %l0", "fjnlt %l0", "jpl %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bltu_rev"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcc %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bge_rev"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jlt %l0", "fjnge %l0", "jmi %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgeu_rev"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcs %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*ble_rev"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jgt %l0", "fjnle %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bleu_rev"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jhi %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bordered_rev"
- [(set (pc)
- (if_then_else (ordered (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjun %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunordered_rev"
- [(set (pc)
- (if_then_else (unordered (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjor %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*buneq_rev"
- [(set (pc)
- (if_then_else (uneq (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogl %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunge_rev"
- [(set (pc)
- (if_then_else (unge (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjolt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bungt_rev"
- [(set (pc)
- (if_then_else (ungt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjole %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunle_rev"
- [(set (pc)
- (if_then_else (unle (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunlt_rev"
- [(set (pc)
- (if_then_else (unlt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjoge %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bltgt_rev"
- [(set (pc)
- (if_then_else (ltgt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjueq %l0";
-}
- [(set_attr "type" "fbcc")])
;; Unconditional and other jump instructions
(define_insn "jump"
@@ -6779,7 +5868,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1";
if (GET_CODE (operands[0]) == MEM)
@@ -6799,7 +5887,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1\;clr%.w %0\;subq%.l #1,%0\;jcc %l1";
if (GET_CODE (operands[0]) == MEM)
@@ -6822,7 +5909,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE && find_reg_note (insn, REG_NONNEG, 0)"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1";
if (GET_CODE (operands[0]) == MEM)
@@ -6857,7 +5943,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE && find_reg_note (insn, REG_NONNEG, 0)"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1\;clr%.w %0\;subq%.l #1,%0\;jcc %l1";
if (GET_CODE (operands[0]) == MEM)
@@ -7004,13 +6089,15 @@
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
- "")
+ ""
+ [(set_attr "flags_valid" "unchanged")])
(define_insn "nop"
[(const_int 0)]
""
"nop"
- [(set_attr "type" "nop")])
+ [(set_attr "type" "nop")
+ (set_attr "flags_valid" "unchanged")])
(define_expand "prologue"
[(const_int 0)]
@@ -7379,97 +6466,56 @@
;;
;; Which moves the jCC condition outside the inner loop for free.
;;
+(define_mode_iterator DBCC [HI SI])
(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ne (match_operand:HI 0 "register_operand" "")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
-{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
- return "";
-})
-
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 0 "register_operand" "")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
-{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
- return "";
-})
-
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 3 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 4 "general_operand" "")
+ (match_operand:CMPMODE 5 "general_operand" "")])
(label_ref (match_operand 2 "" ""))
(pc)))
(parallel
[(set (pc)
(if_then_else
- (ge (plus:HI (match_operand:HI 0 "register_operand" "")
- (const_int -1))
+ (ne (match_operand:DBCC 0 "register_operand" "")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_COLDFIRE && DATA_REG_P (operands[0])"
{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
+ rtx_code code = GET_CODE (operands[3]);
+ code = m68k_output_compare_<CMPMODE:mode> (operands[4], operands[5], code);
+ output_dbcc_and_branch (operands, code);
return "";
})
(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 3 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 4 "general_operand" "")
+ (match_operand:CMPMODE 5 "general_operand" "")])
(label_ref (match_operand 2 "" ""))
(pc)))
(parallel
[(set (pc)
(if_then_else
- (ge (plus:SI (match_operand:SI 0 "register_operand" "")
- (const_int -1))
+ (ge (plus:DBCC (match_operand:DBCC 0 "register_operand" "")
+ (const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_COLDFIRE && DATA_REG_P (operands[0])"
{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
+ rtx_code code = GET_CODE (operands[3]);
+ code = m68k_output_compare_<CMPMODE:mode> (operands[4], operands[5], code);
+ output_dbcc_and_branch (operands, code);
return "";
})
-
(define_insn "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f")
@@ -7480,10 +6526,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "f%$move%.x %1,%0";
@@ -7512,10 +6555,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "fmove%.x %1,%0";
@@ -7583,64 +6623,52 @@
return "fcos%.<FP:prec> %1,%0";
})
-;; Unconditional traps are assumed to have (const_int 1) for the condition.
+;; Unconditional traps are assumed to have const_true_rtx for the condition.
(define_insn "trap"
- [(trap_if (const_int 1) (const_int 7))]
+ [(trap_if (const_int -1) (const_int 7))]
""
"trap #7"
[(set_attr "type" "trap")])
-(define_expand "ctrapdi4"
+;; ??? Our trap instruction uses constant 7 for operand 3, which is
+;; also the trap vector used by TRAPcc instruction. By restricting
+;; these patterns to const1_operand, they will not be generated.
+;; Left disabled for now, as enabling it seems to cause issues.
+(define_insn "ctrap<mode>4"
[(trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020 && !TARGET_COLDFIRE"
{
- if (operands[2] == const0_rtx)
- emit_insn (gen_tstdi (operands[1]));
- else
- emit_insn (gen_cmpdi (operands[1], operands[2]));
- operands[1] = cc0_rtx;
- operands[2] = const0_rtx;
-})
-
-(define_expand "ctrapsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
-
-(define_expand "ctraphi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "nonimmediate_src_operand" "")
- (match_operand:HI 2 "general_src_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
-
-(define_expand "ctrapqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "nonimmediate_src_operand" "")
- (match_operand:QI 2 "general_src_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ switch (code)
+ {
+ case EQ: return "trapeq";
+ case NE: return "trapne";
+ case GT: return "trapgt";
+ case GTU: return "traphi";
+ case LT: return "traplt";
+ case LTU: return "trapcs";
+ case GE: return "trapge";
+ case GEU: return "trapcc";
+ case LE: return "traple";
+ case LEU: return "trapls";
+ default: gcc_unreachable ();
+ }
+})
-(define_insn "*conditional_trap"
+(define_insn "ctrap<mode>4_cf"
[(trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 1 "const1_operand" "I"))]
- "TARGET_68020 && ! flags_in_68881 ()"
-{
- switch (GET_CODE (operands[0]))
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_cf_constraints>")])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020 && TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ switch (code)
{
case EQ: return "trapeq";
case NE: return "trapne";
@@ -7735,10 +6763,8 @@
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "addq_subq_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_dup 0)))
(set (pc) (if_then_else (match_operator 5 "equality_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:SI 2 "register_operand" "") (match_dup 0)])
(match_operand 3 "pc_or_label_operand")
(match_operand 4 "pc_or_label_operand")))]
"peep2_reg_dead_p (2, operands[0])
@@ -7747,8 +6773,7 @@
&& DATA_REG_P (operands[2])
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 2) (plus:SI (match_dup 2) (match_dup 6)))
- (set (cc0) (compare (match_dup 2) (const_int 0)))
- (set (pc) (if_then_else (match_op_dup 5 [(cc0) (const_int 0)])
+ (set (pc) (if_then_else (match_op_dup 5 [(match_dup 2) (const_int 0)])
(match_dup 3)
(match_dup 4)))]
"operands[6] = GEN_INT (-INTVAL (operands[1]));")
@@ -7756,9 +6781,8 @@
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "pow2_m1_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "register_operand" "")))
- (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+ (set (pc) (if_then_else (gtu (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" ""))
(match_operand 4 "pc_or_label_operand")
(match_operand 5 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7769,8 +6793,7 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[2])"
[(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
- (set (cc0) (compare (match_dup 7) (const_int 0)))
- (set (pc) (if_then_else (ne (cc0) (const_int 0))
+ (set (pc) (if_then_else (ne (match_dup 7) (const_int 0))
(match_dup 4) (match_dup 5)))]
"
{
@@ -7779,9 +6802,8 @@
}")
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "pow2_m1_operand" "")))
- (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+ [(set (pc) (if_then_else (gtu (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "pow2_m1_operand" ""))
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7790,17 +6812,15 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
- (set (cc0) (compare (match_dup 0) (const_int 0)))
- (set (pc) (if_then_else (ne (cc0) (const_int 0))
+ (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
(match_dup 2) (match_dup 3)))]
"{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "pow2_m1_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "register_operand" "")))
- (set (pc) (if_then_else (leu (cc0) (const_int 0))
+ (set (pc) (if_then_else (leu (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" ""))
(match_operand 4 "pc_or_label_operand")
(match_operand 5 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7811,8 +6831,7 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[2])"
[(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
- (set (cc0) (compare (match_dup 7) (const_int 0)))
- (set (pc) (if_then_else (eq (cc0) (const_int 0))
+ (set (pc) (if_then_else (eq (match_dup 7) (const_int 0))
(match_dup 4) (match_dup 5)))]
"
{
@@ -7820,9 +6839,8 @@
operands[7] = operands[2];
}")
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "pow2_m1_operand" "")))
- (set (pc) (if_then_else (leu (cc0) (const_int 0))
+ [(set (pc) (if_then_else (leu (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "pow2_m1_operand" ""))
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7831,8 +6849,7 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
- (set (cc0) (compare (match_dup 0) (const_int 0)))
- (set (pc) (if_then_else (eq (cc0) (const_int 0))
+ (set (pc) (if_then_else (eq (match_dup 0) (const_int 0))
(match_dup 2) (match_dup 3)))]
"{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
@@ -7841,10 +6858,9 @@
;; internally against 65535).
;; The rotate in the output pattern will turn into a swap.
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (const_int 65535)))
- (set (pc) (if_then_else (match_operator 1 "swap_peephole_relational_operator"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 1 "swap_peephole_relational_operator"
+ [(match_operand:SI 0 "register_operand" "")
+ (const_int 65535)])
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"peep2_reg_dead_p (1, operands[0])
@@ -7852,7 +6868,6 @@
&& (optimize_size || TUNE_68000_10)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (rotate:SI (match_dup 0) (const_int 16)))
- (set (cc0) (compare (subreg:HI (match_dup 0) 2) (const_int 0)))
- (set (pc) (if_then_else (match_op_dup 1 [(cc0) (const_int 0)])
+ (set (pc) (if_then_else (match_op_dup 1 [(subreg:HI (match_dup 0) 2) (const_int 0)])
(match_dup 2) (match_dup 3)))]
"")
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index ad29788..9e4c8ba 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -115,15 +115,6 @@
&& (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
})
-;; Return true if X is a valid comparison operator for the dbcc
-;; instruction. Note it rejects floating point comparison
-;; operators. (In the future we could use Fdbcc). It also rejects
-;; some comparisons when CC_NO_OVERFLOW is set.
-
-(define_predicate "valid_dbcc_comparison_p"
- (and (match_code "eq,ne,gtu,ltu,geu,leu,gt,lt,ge,le")
- (match_test "valid_dbcc_comparison_p_2 (op, mode)")))
-
(define_predicate "m68k_cstore_comparison_operator"
(if_then_else (match_test "TARGET_68881")
(match_operand 0 "comparison_operator")
@@ -210,10 +201,10 @@
(and (match_code "const_int")
(match_test "op == const1_rtx")))
-;; A valid operand for a HImode or QImode conditional operation.
-;; ColdFire has tst patterns, but not cmp patterns.
-(define_predicate "m68k_subword_comparison_operand"
- (if_then_else (match_test "TARGET_COLDFIRE")
+;; A valid operand for a conditional operation.
+;; ColdFire has tst patterns for HImode and QImode, but not cmp patterns.
+(define_predicate "m68k_comparison_operand"
+ (if_then_else (match_test "TARGET_COLDFIRE && mode != SImode")
(and (match_code "const_int")
(match_test "op == const0_rtx"))
(match_operand 0 "general_src_operand")))
@@ -234,15 +225,17 @@
;; Special case of general_src_operand, which rejects a few fp
;; constants (which we prefer in registers) before reload.
+;; Used only in comparisons, and we do want to allow zero.
(define_predicate "fp_src_operand"
(match_operand 0 "general_src_operand")
{
- return !CONSTANT_P (op)
- || (TARGET_68881
- && (!standard_68881_constant_p (op)
- || reload_in_progress
- || reload_completed));
+ return (!CONSTANT_P (op)
+ || op == CONST0_RTX (mode)
+ || (TARGET_68881
+ && (!standard_68881_constant_p (op)
+ || reload_in_progress
+ || reload_completed)));
})
;; Used to detect constants that are valid for addq/subq instructions
@@ -282,3 +275,6 @@
(define_predicate "swap_peephole_relational_operator"
(match_code "gtu,leu,gt,le"))
+
+(define_predicate "address_reg_operand"
+ (match_test ("ADDRESS_REG_P (op)")))
diff --git a/gcc/recog.c b/gcc/recog.c
index 9e9cca7..0482818 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -923,23 +923,6 @@ validate_simplify_insn (rtx_insn *insn)
return ((num_changes_pending () > 0) && (apply_change_group () > 0));
}
-/* Return 1 if the insn using CC0 set by INSN does not contain
- any ordered tests applied to the condition codes.
- EQ and NE tests do not count. */
-
-int
-next_insn_tests_no_inequality (rtx_insn *insn)
-{
- rtx_insn *next = next_cc0_user (insn);
-
- /* If there is no next insn, we have to take the conservative choice. */
- if (next == 0)
- return 0;
-
- return (INSN_P (next)
- && ! inequality_comparisons_p (PATTERN (next)));
-}
-
/* Return 1 if OP is a valid general operand for machine mode MODE.
This is either a register reference, a memory reference,
or a constant. In the case of a memory reference, the address
diff --git a/gcc/recog.h b/gcc/recog.h
index 71d88e3..69238cf 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -112,7 +112,6 @@ extern void validate_replace_rtx_group (rtx, rtx, rtx_insn *);
extern void validate_replace_src_group (rtx, rtx, rtx_insn *);
extern bool validate_simplify_insn (rtx_insn *insn);
extern int num_changes_pending (void);
-extern int next_insn_tests_no_inequality (rtx_insn *);
extern bool reg_fits_class_p (const_rtx, reg_class_t, int, machine_mode);
extern int offsettable_memref_p (rtx);
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 1369e66..be27937 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3514,7 +3514,6 @@ extern bool insn_nothrow_p (const_rtx);
extern bool can_nonlocal_goto (const rtx_insn *);
extern void copy_reg_eh_region_note_forward (rtx, rtx_insn *, rtx);
extern void copy_reg_eh_region_note_backward (rtx, rtx_insn *, rtx);
-extern int inequality_comparisons_p (const_rtx);
extern rtx replace_rtx (rtx, rtx, rtx, bool = false);
extern void replace_label (rtx *, rtx, rtx, bool);
extern void replace_label_in_insn (rtx_insn *, rtx_insn *, rtx_insn *, bool);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 720aa09..241a35b 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3021,64 +3021,6 @@ may_trap_or_fault_p (const_rtx x)
return may_trap_p_1 (x, 1);
}
-/* Return nonzero if X contains a comparison that is not either EQ or NE,
- i.e., an inequality. */
-
-int
-inequality_comparisons_p (const_rtx x)
-{
- const char *fmt;
- int len, i;
- const enum rtx_code code = GET_CODE (x);
-
- switch (code)
- {
- case REG:
- case SCRATCH:
- case PC:
- case CC0:
- CASE_CONST_ANY:
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- return 0;
-
- case LT:
- case LTU:
- case GT:
- case GTU:
- case LE:
- case LEU:
- case GE:
- case GEU:
- return 1;
-
- default:
- break;
- }
-
- len = GET_RTX_LENGTH (code);
- fmt = GET_RTX_FORMAT (code);
-
- for (i = 0; i < len; i++)
- {
- if (fmt[i] == 'e')
- {
- if (inequality_comparisons_p (XEXP (x, i)))
- return 1;
- }
- else if (fmt[i] == 'E')
- {
- int j;
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (inequality_comparisons_p (XVECEXP (x, i, j)))
- return 1;
- }
- }
-
- return 0;
-}
-
/* Replace any occurrence of FROM in X with TO. The function does
not enter into CONST_DOUBLE for the replace.