diff options
Diffstat (limited to 'recipes/gcc/gcc-4.3.4/ep93xx/arm-crunch-ccmav-mode.patch')
-rw-r--r-- | recipes/gcc/gcc-4.3.4/ep93xx/arm-crunch-ccmav-mode.patch | 734 |
1 files changed, 734 insertions, 0 deletions
diff --git a/recipes/gcc/gcc-4.3.4/ep93xx/arm-crunch-ccmav-mode.patch b/recipes/gcc/gcc-4.3.4/ep93xx/arm-crunch-ccmav-mode.patch new file mode 100644 index 0000000000..0edb1c0334 --- /dev/null +++ b/recipes/gcc/gcc-4.3.4/ep93xx/arm-crunch-ccmav-mode.patch @@ -0,0 +1,734 @@ +These modifications implement a new condition code mode CCMAV which is used +on floating point comparisons that were performed in the Maverick Crunch FPU. + +This is necessary because the Maverick sets the conditions codes differently +from the ARM/FPA/VFP. Since we do not use the Maverick's 32-bit int modes nor +its 64-bit comparison, these different conditions pertain to all floating point +comparisons when compiling for Maverick hardfloat. + + ARM/FPA/VFP - (cmp*): MaverickCrunch - (cfcmp*): + N Z C V N Z C V + A == B 0 1 1 0 A == B 0 1 0 0 + A < B 1 0 0 0 A < B 1 0 0 0 + A > B 0 0 1 0 A > B 1 0 0 1 + unord 0 0 1 1 unord 0 0 0 0 + +The new mode is set on floating point comparisons instead of the usual +CCFP and CCFPE, then acted upon when the conditional instruction flags +are output. + +Furthermore, the list of conditions that cannot be tested with a single +conditional test is different. On ARM/FPA/VFP it is UNEQ and LTGT while +on Maverick it is GE UNLT ORDERED and UNORDERED. +We handle this with a new predicate "maverick_comparison_operator" that omits +the comparisons that cannot be represented and we split the cond_exec pattern +into for CCMAV mode plus a separate rule for every non-Maverick CC mode. +This prevents generation of conditional instructions that cannot be represented. + +Although Maverick can also represent LTGT and UNEQ with a single test, we do not +include these since it would mean splitting every other rule that uses +"arm_comparison_operator" in a similar way for very little gain. + +A few other tests are added to prevent optimisations that would +generate these unrepresentable conditions. + +None of these changes affect code generation for ARM or for other FPUs. + +One missed optimisation: movsfcc and movdfcc have been +disabled for Maverick because we don't use the Maverick's instructions +conditionally to avoid hardware bugs. But a limited movsfcc and movdfcc +could be included when Maverick, that applies to all modes where the things +to be moved do not involve the Maverick registers, if such a thing is feasible +without the optimizer moving things into registers between the expand and the +instruction generation. + + Martin Guy <martinwguy@yahoo.it>, November 2008 + +--- gcc-4.3.2/gcc/config/arm/arm-modes.def.old 2007-08-02 11:49:31.000000000 +0100 ++++ gcc-4.3.2/gcc/config/arm/arm-modes.def 2008-11-18 14:39:39.000000000 +0000 +@@ -27,6 +27,7 @@ + + /* CCFPEmode should be used with floating inequalities, + CCFPmode should be used with floating equalities. ++ CCMAVmode should be used with comparisons performed in the Maverick FPU + CC_NOOVmode should be used with SImode integer equalities. + CC_Zmode should be used if only the Z flag is set correctly + CC_Nmode should be used if only the N (sign) flag is set correctly +@@ -37,6 +38,7 @@ + CC_MODE (CC_SWP); + CC_MODE (CCFP); + CC_MODE (CCFPE); ++CC_MODE (CCMAV); + CC_MODE (CC_DNE); + CC_MODE (CC_DEQ); + CC_MODE (CC_DLE); +--- gcc-4.3.2/gcc/config/arm/arm.h 2008-11-18 15:32:10.000000000 +0000 ++++ cluster/gcc-4.3.2/gcc/config/arm/arm.h 2008-11-21 19:24:10.000000000 +0000 +@@ -2306,7 +2306,7 @@ + #define REVERSIBLE_CC_MODE(MODE) 1 + + #define REVERSE_CONDITION(CODE,MODE) \ +- (((MODE) == CCFPmode || (MODE) == CCFPEmode) \ ++ (((MODE) == CCFPmode || (MODE) == CCFPEmode || (MODE) == CCMAVmode) \ + ? reverse_condition_maybe_unordered (code) \ + : reverse_condition (code)) + +--- gcc-4.3.2/gcc/config/arm/predicates.md.old 2007-08-02 11:49:31.000000000 +0100 ++++ gcc-4.3.2/gcc/config/arm/predicates.md 2008-11-20 15:05:50.000000000 +0000 +@@ -195,6 +195,16 @@ + (define_special_predicate "arm_comparison_operator" + (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,ordered,unlt,unle,unge,ungt")) + ++;; Comparisons that can be predicated after a Maverick FP comparison, true for ++;; floating point comparisons other than GE, UNLT, UNORDERED or ORDERED ++;; ++;; Maverick can also match LTGT and UNEQ with a single condition ++;; but including these means duplicating every rule containing ++;; arm_comparison_operator including cond_branch and all the *cc rules. ++;; Extra speed when predicating ltgt and uneq is rare enough not to be worth it. ++(define_special_predicate "maverick_comparison_operator" ++(match_code "eq,ne,le,lt,gt,unle,unge,ungt")) ++ + (define_special_predicate "minmax_operator" + (and (match_code "smin,smax,umin,umax") + (match_test "mode == GET_MODE (op)"))) +--- gcc-4.3.2/gcc/config/arm/arm.c.old 2008-11-19 10:01:53.000000000 +0000 ++++ gcc-4.3.2/gcc/config/arm/arm.c 2008-11-21 12:49:48.000000000 +0000 +@@ -1720,6 +1720,14 @@ + return 0; + } + ++ /* Optimisation of __builtin_inunordered at the end of a ++ * function would generate conditional return on (UN)ORDERED, which cannot ++ * be represented by a single condition code test on Maverick. ++ * Since we do not have access to the specific condition used, ++ * we just disable all conditional returns on Maverick. */ ++ if (iscond && TARGET_MAVERICK && TARGET_HARD_FLOAT) ++ return 0; ++ + /* If there are saved registers but the LR isn't saved, then we need + two instructions for the return. */ + if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM))) +@@ -7733,6 +7741,10 @@ + comparison, and CCFPE otherwise. */ + if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) + { ++ /* Comparisons performed in the Maverick FPU set the CCs their own way. */ ++ if (TARGET_HARD_FLOAT && TARGET_MAVERICK) ++ return CCMAVmode; ++ + switch (op) + { + case EQ: +@@ -7751,8 +7763,6 @@ + case LE: + case GT: + case GE: +- if (TARGET_HARD_FLOAT && TARGET_MAVERICK) +- return CCFPmode; + return CCFPEmode; + + default: +@@ -13367,6 +13377,29 @@ + default: gcc_unreachable (); + } + ++ case CCMAVmode: ++ /* Maverick cmp sets the condition codes differently from ARM/FPA/VFP */ ++ switch (comp_code) ++ { ++ case GT: return ARM_VS; ++ case LE: return ARM_LE; ++ case LT: return ARM_LT; ++ case NE: return ARM_NE; ++ case EQ: return ARM_EQ; ++ case UNLE: return ARM_VC; ++ case UNGT: return ARM_GT; ++ case UNGE: return ARM_GE; ++ case UNEQ: return ARM_PL; ++ case LTGT: return ARM_MI; ++ /* These cannot be represented by a single condition code. */ ++ case GE: /* Fall through */ ++ case UNLT:/* Fall through */ ++ case ORDERED:/* Fall through */ ++ case UNORDERED:/* Fall through */ ++ default: ++ gcc_unreachable (); ++ } ++ + case CC_SWPmode: + switch (comp_code) + { +--- gcc-4.3.2/gcc/config/arm/arm.md.old 2008-11-21 19:08:44.000000000 +0000 ++++ gcc-4.3.2/gcc/config/arm/arm.md 2008-11-21 19:09:18.000000000 +0000 +@@ -258,7 +258,9 @@ + ; they are altered at all + ; + ; JUMP_CLOB is used when the condition cannot be represented by a single +-; instruction (UNEQ and LTGT). These cannot be predicated. ++; instruction. This applies to UNEQ and LTGT for ARM/FPA/VFP comparisons, ++; GE UNLT ORDERED and UNORDERED for Maverick comparisons. ++; These cannot be predicated. + ; + ; NOCOND means that the condition codes are neither altered nor affect the + ; output of this insn +@@ -7332,9 +7334,9 @@ + + ;; Cirrus SF compare instruction + (define_insn "*cirrus_cmpsf" +- [(set (reg:CCFP CC_REGNUM) +- (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v") +- (match_operand:SF 1 "cirrus_fp_register" "v")))] ++ [(set (reg:CCMAV CC_REGNUM) ++ (compare:CCMAV (match_operand:SF 0 "cirrus_fp_register" "v") ++ (match_operand:SF 1 "cirrus_fp_register" "v")))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "cfcmps%?\\tr15, %V0, %V1" + [(set_attr "type" "farith") +@@ -7343,9 +7347,9 @@ + + ;; Cirrus DF compare instruction + (define_insn "*cirrus_cmpdf" +- [(set (reg:CCFP CC_REGNUM) +- (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v") +- (match_operand:DF 1 "cirrus_fp_register" "v")))] ++ [(set (reg:CCMAV CC_REGNUM) ++ (compare:CCMAV (match_operand:DF 0 "cirrus_fp_register" "v") ++ (match_operand:DF 1 "cirrus_fp_register" "v")))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "cfcmpd%?\\tr15, %V0, %V1" + [(set_attr "type" "farith") +@@ -7482,12 +7484,18 @@ + "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" + ) + ++;; Some of the following patterns may need two branch instructions, since ++;; there is no single instruction that will handle all cases. Specifically: ++;; ARM/FPA/VFP cannot test UNEQ and LTGT ++;; Maverick cannot test GE on floating point values, UNLT, ORDERED or UNORDERED. ++ + (define_expand "bunordered" + [(set (pc) + (if_then_else (unordered (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, + arm_compare_op1);" + ) +@@ -7497,7 +7505,8 @@ + (if_then_else (ordered (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, + arm_compare_op1);" + ) +@@ -7507,7 +7516,8 @@ + (if_then_else (ungt (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" + ) + +@@ -7516,7 +7526,8 @@ + (if_then_else (unlt (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" + ) + +@@ -7525,7 +7536,8 @@ + (if_then_else (unge (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" + ) + +@@ -7534,18 +7546,18 @@ + (if_then_else (unle (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" + ) + +-;; The following two patterns need two branch instructions, since there is +-;; no single instruction that will handle all cases. + (define_expand "buneq" + [(set (pc) + (if_then_else (uneq (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" + ) + +@@ -7554,7 +7566,8 @@ + (if_then_else (ltgt (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" + ) + +@@ -7562,7 +7575,7 @@ + ;; Patterns to match conditional branch insns. + ;; + +-; Special pattern to match UNEQ. ++; Special pattern to match UNEQ for FPA and VFP. + (define_insn "*arm_buneq" + [(set (pc) + (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) +@@ -7578,7 +7591,7 @@ + (set_attr "length" "8")] + ) + +-; Special pattern to match LTGT. ++; Special pattern to match LTGT for FPA and VFP. + (define_insn "*arm_bltgt" + [(set (pc) + (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) +@@ -7594,6 +7607,101 @@ + (set_attr "length" "8")] + ) + ++; Special pattern to match floating point GE for Maverick. ++(define_insn "*cirrus_bge" ++ [(set (pc) ++ (if_then_else (ge (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (label_ref (match_operand 0 "" "")) ++ (pc)))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t%l0\;bvs\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "8")] ++) ++ ++; Special pattern to match UNORDERED for Maverick. ++(define_insn "*cirrus_bunordered" ++ [(set (pc) ++ (if_then_else (unordered (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (label_ref (match_operand 0 "" "")) ++ (pc)))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t.+12\;bmi\\t.+8\;b\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "12")] ++) ++ ++; Special pattern to match ORDERED for Maverick. ++(define_insn "*cirrus_bordered" ++ [(set (pc) ++ (if_then_else (ordered (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (label_ref (match_operand 0 "" "")) ++ (pc)))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t%l0\;bmi\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "8")] ++) ++ ++; Special pattern to match UNLT for Maverick. ++(define_insn "*cirrus_bunlt" ++ [(set (pc) ++ (if_then_else (unlt (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (label_ref (match_operand 0 "" "")) ++ (pc)))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t.+12\;bvs\\t.+8\;b\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "12")] ++) ++ ++; Special atterns to match UNEQ and LTGT for Maverick, to handle ++; the two cases not covered by generic *arm_cond_branch ++ ++(define_insn "*cirrus_buneq" ++ [(set (pc) ++ (if_then_else (uneq (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (label_ref (match_operand 0 "" "")) ++ (pc)))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"bpl\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob")] ++) ++ ++(define_insn "*cirrus_bltgt" ++ [(set (pc) ++ (if_then_else (ltgt (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (label_ref (match_operand 0 "" "")) ++ (pc)))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"bmi\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob")] ++) ++ + (define_insn "*arm_cond_branch" + [(set (pc) + (if_then_else (match_operator 1 "arm_comparison_operator" +@@ -7613,7 +7721,7 @@ + (set_attr "type" "branch")] + ) + +-; Special pattern to match reversed UNEQ. ++; Special pattern to match reversed UNEQ for FPA and VFP. + (define_insn "*arm_buneq_reversed" + [(set (pc) + (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) +@@ -7629,7 +7737,7 @@ + (set_attr "length" "8")] + ) + +-; Special pattern to match reversed LTGT. ++; Special pattern to match reversed LTGT for FPA and VFP. + (define_insn "*arm_bltgt_reversed" + [(set (pc) + (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) +@@ -7645,6 +7753,101 @@ + (set_attr "length" "8")] + ) + ++; Patterns to match reversed UNEQ and LTGT for Maverick, the two cases ++; not covered by generic "*arm_cond_branch_reversed" ++ ++(define_insn "*cirrus_buneq_reversed" ++ [(set (pc) ++ (if_then_else (uneq (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (pc) ++ (label_ref (match_operand 0 "" ""))))] ++ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"bmi\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob")] ++) ++ ++(define_insn "*cirrus_bltgt_reversed" ++ [(set (pc) ++ (if_then_else (ltgt (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (pc) ++ (label_ref (match_operand 0 "" ""))))] ++ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"bpl\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob")] ++) ++ ++; Special pattern to match reversed floating point GE for Maverick. ++(define_insn "*cirrus_bge_reversed" ++ [(set (pc) ++ (if_then_else (ge (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (pc) ++ (label_ref (match_operand 0 "" ""))))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t.+12\;bvs\\t.+8\;b\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "12")] ++) ++ ++; Special pattern to match reversed UNORDERED for Maverick. ++(define_insn "*cirrus_bunordered_reversed" ++ [(set (pc) ++ (if_then_else (unordered (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (pc) ++ (label_ref (match_operand 0 "" ""))))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t%l0\;bmi\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "8")] ++) ++ ++; Special pattern to match reversed ORDERED for Maverick. ++(define_insn "*cirrus_bordered_reversed" ++ [(set (pc) ++ (if_then_else (ordered (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (pc) ++ (label_ref (match_operand 0 "" ""))))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t.+12\;bmi\\t.+8\;b\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "12")] ++) ++ ++; Special pattern to match reversed UNLT for Maverick. ++(define_insn "*cirrus_bunlt_reversed" ++ [(set (pc) ++ (if_then_else (unlt (match_operand:CCMAV 1 "cc_register" "") (const_int 0)) ++ (pc) ++ (label_ref (match_operand 0 "" ""))))] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "* ++ gcc_assert (!arm_ccfsm_state); ++ ++ return \"beq\\t%l0\;bvs\\t%l0\"; ++ " ++ [(set_attr "conds" "jump_clob") ++ (set_attr "length" "8")] ++) ++ + (define_insn "*arm_cond_branch_reversed" + [(set (pc) + (if_then_else (match_operator 1 "arm_comparison_operator" +@@ -7696,11 +7899,16 @@ + "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" + ) + ++; SGE can only be represented as a single condition code on ARM/VFP/FPA, ++; not with Maverick when the operands are floating point. + (define_expand "sge" + [(set (match_operand:SI 0 "s_register_operand" "") + (ge:SI (match_dup 1) (const_int 0)))] + "TARGET_32BIT" +- "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" ++ "if (TARGET_HARD_FLOAT && TARGET_MAVERICK ++ && GET_MODE_CLASS (GET_MODE (arm_compare_op0)) == MODE_FLOAT) ++ FAIL; ++ operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" + ) + + (define_expand "slt" +@@ -7738,6 +7946,7 @@ + "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" + ) + ++; SORDERED and SUNORDERED cannot be represented on Maverick + (define_expand "sunordered" + [(set (match_operand:SI 0 "s_register_operand" "") + (unordered:SI (match_dup 1) (const_int 0)))] +@@ -7757,7 +7966,8 @@ + (define_expand "sungt" + [(set (match_operand:SI 0 "s_register_operand" "") + (ungt:SI (match_dup 1) (const_int 0)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, + arm_compare_op1);" + ) +@@ -7765,11 +7975,13 @@ + (define_expand "sunge" + [(set (match_operand:SI 0 "s_register_operand" "") + (unge:SI (match_dup 1) (const_int 0)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, + arm_compare_op1);" + ) + ++; SUNLT cannot be represented on Maverick + (define_expand "sunlt" + [(set (match_operand:SI 0 "s_register_operand" "") + (unlt:SI (match_dup 1) (const_int 0)))] +@@ -7781,7 +7993,8 @@ + (define_expand "sunle" + [(set (match_operand:SI 0 "s_register_operand" "") + (unle:SI (match_dup 1) (const_int 0)))] +- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" ++ "TARGET_32BIT && TARGET_HARD_FLOAT ++ && (TARGET_FPA || TARGET_VFP || TARGET_MAVERICK)" + "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, + arm_compare_op1);" + ) +@@ -8039,20 +8252,32 @@ + enum rtx_code code = GET_CODE (operands[1]); + rtx ccreg; + +- if (code == UNEQ || code == LTGT) +- FAIL; ++ /* Reject comparisons not representable by a single condition code */ ++ if (TARGET_HARD_FLOAT && TARGET_MAVERICK ++ && GET_MODE_CLASS (GET_MODE (arm_compare_op0)) == MODE_FLOAT) ++ { ++ if (code == GE || code == UNLT || code == ORDERED || code == UNORDERED) ++ FAIL; ++ } ++ else ++ { ++ if (code == UNEQ || code == LTGT) ++ FAIL; ++ } + + ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); + }" + ) + ++; We do not use Maverick conditional FP instructions to avoid hardware bugs ++ + (define_expand "movsfcc" + [(set (match_operand:SF 0 "s_register_operand" "") + (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") + (match_operand:SF 2 "s_register_operand" "") + (match_operand:SF 3 "nonmemory_operand" "")))] +- "TARGET_32BIT" ++ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" + " + { + enum rtx_code code = GET_CODE (operands[1]); +@@ -10419,7 +10644,7 @@ + + operands[5] = gen_rtx_REG (mode, CC_REGNUM); + operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); +- if (mode == CCFPmode || mode == CCFPEmode) ++ if (mode == CCFPmode || mode == CCFPEmode || mode == CCMAVmode) + rc = reverse_condition_maybe_unordered (rc); + else + rc = reverse_condition (rc); +@@ -10470,7 +10695,7 @@ + + operands[6] = gen_rtx_REG (mode, CC_REGNUM); + operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); +- if (mode == CCFPmode || mode == CCFPEmode) ++ if (mode == CCFPmode || mode == CCFPEmode || mode == CCMAVmode) + rc = reverse_condition_maybe_unordered (rc); + else + rc = reverse_condition (rc); +@@ -10502,7 +10727,7 @@ + + operands[6] = gen_rtx_REG (mode, CC_REGNUM); + operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); +- if (mode == CCFPmode || mode == CCFPEmode) ++ if (mode == CCFPmode || mode == CCFPEmode || mode == CCMAVmode) + rc = reverse_condition_maybe_unordered (rc); + else + rc = reverse_condition (rc); +@@ -10809,13 +11034,75 @@ + "TARGET_32BIT && arm_arch5e" + "pld\\t%a0") + ++;; Special predication patterns for Maverick Crunch floating-point ++;; which has a different set of predicable conditions after a floating ++;; point comparison. ++ ++(define_cond_exec ++ [(match_operator 0 "maverick_comparison_operator" ++ [(match_operand:CCMAV 1 "cc_register" "") ++ (const_int 0)])] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "" ++) ++ ++;; Every else is the same as the general ARM pattern. ++ ++(define_cond_exec ++ [(match_operator 0 "arm_comparison_operator" ++ [(match_operand:CC_NOOV 1 "cc_register" "") ++ (const_int 0)])] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "" ++) ++ ++(define_cond_exec ++ [(match_operator 0 "arm_comparison_operator" ++ [(match_operand:CC_Z 1 "cc_register" "") ++ (const_int 0)])] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "" ++) ++ ++(define_cond_exec ++ [(match_operator 0 "arm_comparison_operator" ++ [(match_operand:CC_SWP 1 "cc_register" "") ++ (const_int 0)])] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "" ++) ++ ++(define_cond_exec ++ [(match_operator 0 "arm_comparison_operator" ++ [(match_operand:CC_C 1 "cc_register" "") ++ (const_int 0)])] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "" ++) ++ ++(define_cond_exec ++ [(match_operator 0 "arm_comparison_operator" ++ [(match_operand:CC_N 1 "cc_register" "") ++ (const_int 0)])] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "" ++) ++ ++(define_cond_exec ++ [(match_operator 0 "arm_comparison_operator" ++ [(match_operand:CC 1 "cc_register" "") ++ (const_int 0)])] ++ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK" ++ "" ++) ++ + ;; General predication pattern + + (define_cond_exec + [(match_operator 0 "arm_comparison_operator" + [(match_operand 1 "cc_register" "") + (const_int 0)])] +- "TARGET_32BIT" ++ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" + "" + ) + |