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)"
   ""
 )