This patch disables all 64-bit integer operations of the MaverickCrunch unit
unless the new flag -mcirrus-di is supplied (as well as -mcpu-ep9312
-mfpu=maverick -mfloat-abi=softfp).

The 64-bit instructions (or their GCC support) are known to be buggy, as shown
for example by openssl-0.9.8g's testsuite:
In the unpacked openssl source directory:
 $ ./config
 $ vi Makefile
 > /^CC= /s/$/-4.3-crunch/
 > /^CFLAG= /s/$/ -mcpu=ep9312 -mfpu=maverick -mfloat-abi=softfp -mcirrus-di/
 > :wq
 $ make
 $ make test
fails if either of the two files: */sha/sha512.c and */bn/bn_asm.c are compiled
with cirrus 64-bit support enabled. If you disable cfmul64, sha512.c works ok,
but I've disabled everything down to cfadd64, cfsub64 and 64-bit load and store
and bn_asm still fails, which suggests another hardware timing bug.

Index: gcc-4.3.4/gcc/config/arm/arm.opt
===================================================================
--- gcc-4.3.4.orig/gcc/config/arm/arm.opt	2009-08-16 22:23:22.000000000 +0100
+++ gcc-4.3.4/gcc/config/arm/arm.opt	2009-08-16 22:23:29.000000000 +0100
@@ -63,6 +63,10 @@
 Target Report Mask(CALLER_INTERWORKING)
 Thumb: Assume function pointers may go to non-Thumb aware code
 
+mcirrus-di
+Target Report Mask(CIRRUS_DI)
+Cirrus: Enable processing of 64-bit integers in the MaverickCrunch unit (buggy)
+
 mcpu=
 Target RejectNegative Joined
 Specify the name of the target CPU
Index: gcc-4.3.4/gcc/config/arm/arm.c
===================================================================
--- gcc-4.3.4.orig/gcc/config/arm/arm.c	2009-08-16 22:23:22.000000000 +0100
+++ gcc-4.3.4/gcc/config/arm/arm.c	2009-08-16 22:23:30.000000000 +0100
@@ -13913,7 +13913,8 @@
        upper 32 bits.  This causes gcc all sorts of grief.  We can't
        even split the registers into pairs because Cirrus SI values
        get sign extended to 64bits-- aldyh.  */
-    return (GET_MODE_CLASS (mode) == MODE_FLOAT) || (mode == DImode);
+    return (GET_MODE_CLASS (mode) == MODE_FLOAT)
+	    || (mode == DImode && TARGET_CIRRUS_DI);
 
   if (TARGET_HARD_FLOAT && TARGET_VFP
       && IS_VFP_REGNUM (regno))
Index: gcc-4.3.4/gcc/config/arm/arm.md
===================================================================
--- gcc-4.3.4.orig/gcc/config/arm/arm.md	2009-08-16 22:23:22.000000000 +0100
+++ gcc-4.3.4/gcc/config/arm/arm.md	2009-08-16 22:23:30.000000000 +0100
@@ -369,7 +369,7 @@
     (clobber (reg:CC CC_REGNUM))])]
   "TARGET_EITHER"
   "
-  if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
+  if (TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)
     {
       if (!cirrus_fp_register (operands[0], DImode))
         operands[0] = force_reg (DImode, operands[0]);
@@ -405,7 +405,7 @@
 	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
 		 (match_operand:DI 2 "s_register_operand" "r,  0")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
+  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)"
   "#"
   "TARGET_32BIT && reload_completed"
   [(parallel [(set (reg:CC_C CC_REGNUM)
@@ -433,7 +433,7 @@
 		  (match_operand:SI 2 "s_register_operand" "r,r"))
 		 (match_operand:DI 1 "s_register_operand" "r,0")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
+  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)"
   "#"
   "TARGET_32BIT && reload_completed"
   [(parallel [(set (reg:CC_C CC_REGNUM)
@@ -462,7 +462,7 @@
 		  (match_operand:SI 2 "s_register_operand" "r,r"))
 		 (match_operand:DI 1 "s_register_operand" "r,0")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
+  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)"
   "#"
   "TARGET_32BIT && reload_completed"
   [(parallel [(set (reg:CC_C CC_REGNUM)
@@ -857,7 +857,7 @@
     (clobber (reg:CC CC_REGNUM))])]
   "TARGET_EITHER"
   "
-  if (TARGET_HARD_FLOAT && TARGET_MAVERICK
+  if (TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI
       && TARGET_32BIT
       && cirrus_fp_register (operands[0], DImode)
       && cirrus_fp_register (operands[1], DImode))
@@ -2979,7 +2979,8 @@
            values to iwmmxt regs and back.  */
         FAIL;
     }
-  else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
+  else if (!TARGET_REALLY_IWMMXT
+	   && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI))
     FAIL;
   "
 )
@@ -4544,7 +4545,8 @@
   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
 	(match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
   "TARGET_ARM
-   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
+   && !(TARGET_HARD_FLOAT
+	&& ((TARGET_MAVERICK && TARGET_CIRRUS_DI) || TARGET_VFP))
    && !TARGET_IWMMXT
    && (   register_operand (operands[0], DImode)
        || register_operand (operands[1], DImode))"
@@ -4664,7 +4666,7 @@
   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
 	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
   "TARGET_THUMB1
-   && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
+   && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)
    && (   register_operand (operands[0], DImode)
        || register_operand (operands[1], DImode))"
   "*
Index: gcc-4.3.4/gcc/config/arm/cirrus.md
===================================================================
--- gcc-4.3.4.orig/gcc/config/arm/cirrus.md	2009-08-16 22:23:22.000000000 +0100
+++ gcc-4.3.4/gcc/config/arm/cirrus.md	2009-08-16 22:23:30.000000000 +0100
@@ -79,7 +79,7 @@
   [(set (match_operand:DI          0 "cirrus_fp_register" "=v")
 	(plus:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
 		 (match_operand:DI 2 "cirrus_fp_register"  "v")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfadd64%?\\t%V0, %V1, %V2"
   [(set_attr "type" "farith")
    (set_attr "cirrus" "normal")]
@@ -120,7 +120,7 @@
   [(set (match_operand:DI           0 "cirrus_fp_register" "=v")
 	(minus:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
 		  (match_operand:DI 2 "cirrus_fp_register"  "v")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfsub64%?\\t%V0, %V1, %V2"
   [(set_attr "type" "farith")
    (set_attr "cirrus" "normal")]
@@ -170,7 +170,7 @@
   [(set (match_operand:DI          0 "cirrus_fp_register" "=v")
 	(mult:DI (match_operand:DI 2 "cirrus_fp_register"  "v")
 		 (match_operand:DI 1 "cirrus_fp_register"  "v")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfmul64%?\\t%V0, %V1, %V2"
   [(set_attr "type" "fmul")
    (set_attr "cirrus" "normal")]
@@ -224,7 +224,7 @@
 (define_insn "cirrus_ashl_const"
   [(set (match_operand:SI            0 "cirrus_fp_register" "=v")
 	(ashift:SI (match_operand:SI 1 "cirrus_fp_register"  "v")
-		   (match_operand:SI 2 "cirrus_shift_const"  "")))]
+		   (match_operand:SI 2 "const_cirrus_shift_operand"  "")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
   "cfsh32%?\\t%V0, %V1, #%s2"
   [(set_attr "type" "farith")
@@ -234,7 +234,7 @@
 (define_insn "cirrus_ashiftrt_const"
   [(set (match_operand:SI	       0 "cirrus_fp_register" "=v")
 	(ashiftrt:SI (match_operand:SI 1 "cirrus_fp_register"  "v")
-		     (match_operand:SI 2 "cirrus_shift_const"  "")))]
+		     (match_operand:SI 2 "const_cirrus_shiftrt_operand"  "")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
   "cfsh32%?\\t%V0, %V1, #-%s2"
   [(set_attr "type" "farith")
@@ -251,11 +251,11 @@
    (set_attr "cirrus" "normal")]
 )
 
-(define_insn "ashldi3_cirrus"
+(define_insn "cirrus_ashldi3"
   [(set (match_operand:DI            0 "cirrus_fp_register" "=v")
 	(ashift:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
 		   (match_operand:SI 2 "register_operand"    "r")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfrshl64%?\\t%V1, %V0, %s2"
   [(set_attr "type" "farith")
    (set_attr "cirrus" "normal")]
@@ -264,8 +264,8 @@
 (define_insn "cirrus_ashldi_const"
   [(set (match_operand:DI            0 "cirrus_fp_register" "=v")
 	(ashift:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
-		   (match_operand:SI 2 "cirrus_shift_const"  "")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+		   (match_operand:SI 2 "const_cirrus_shift_operand"  "")))]
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfsh64%?\\t%V0, %V1, #%s2"
   [(set_attr "type" "farith")
    (set_attr "cirrus" "normal")]
@@ -274,8 +274,8 @@
 (define_insn "cirrus_ashiftrtdi_const"
   [(set (match_operand:DI            0 "cirrus_fp_register" "=v")
 	(ashiftrt:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
-		     (match_operand:SI 2 "cirrus_shift_const"  "")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+		     (match_operand:SI 2 "const_cirrus_shiftrt_operand"  "")))]
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfsh64%?\\t%V0, %V1, #-%s2"
   [(set_attr "type" "farith")
    (set_attr "cirrus" "normal")]
@@ -284,18 +284,16 @@
 (define_insn "*cirrus_absdi2"
   [(set (match_operand:DI         0 "cirrus_fp_register" "=v")
 	(abs:DI (match_operand:DI 1 "cirrus_fp_register"  "v")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfabs64%?\\t%V0, %V1"
   [(set_attr "type" "farith")
    (set_attr "cirrus" "normal")]
 )
 
-;; This doesn't really clobber ``cc''.  Fixme: aldyh.  
 (define_insn "*cirrus_negdi2"
   [(set (match_operand:DI         0 "cirrus_fp_register" "=v")
-	(neg:DI (match_operand:DI 1 "cirrus_fp_register"  "v")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+	(neg:DI (match_operand:DI 1 "cirrus_fp_register"  "v")))]
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfneg64%?\\t%V0, %V1"
   [(set_attr "type" "farith")
    (set_attr "cirrus" "normal")]
@@ -332,11 +330,9 @@
    (set_attr "cirrus" "normal")]
 )
 
-;; This doesn't really clobber the condition codes either.  
 (define_insn "*cirrus_abssi2"
   [(set (match_operand:SI         0 "cirrus_fp_register" "=v")
-        (abs:SI (match_operand:SI 1 "cirrus_fp_register"  "v")))
-   (clobber (reg:CC CC_REGNUM))]
+        (abs:SI (match_operand:SI 1 "cirrus_fp_register"  "v")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
   "cfabs32%?\\t%V0, %V1"
   [(set_attr "type" "farith")
@@ -386,7 +382,7 @@
 (define_insn "floatdisf2"
   [(set (match_operand:SF           0 "cirrus_fp_register" "=v")
 	(float:SF (match_operand:DI 1 "cirrus_fp_register" "v")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfcvt64s%?\\t%V0, %V1"
   [(set_attr "type" "f_cvt")
    (set_attr "cirrus" "normal")]
@@ -395,7 +391,7 @@
 (define_insn "floatdidf2"
   [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
 	(float:DF (match_operand:DI 1 "cirrus_fp_register" "v")))]
-  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "cfcvt64d%?\\t%V0, %V1"
   [(set_attr "type" "f_cvt")
    (set_attr "cirrus" "normal")]
@@ -448,7 +444,7 @@
 (define_insn "*cirrus_arm_movdi"
   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,o<>,v,r,v,m,v")
 	(match_operand:DI 1 "di_operand"              "rIK,mi,r,r,v,mi,v,v"))]
-  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI"
   "*
   {
   switch (which_alternative)
Index: gcc-4.3.4/gcc/doc/invoke.texi
===================================================================
--- gcc-4.3.4.orig/gcc/doc/invoke.texi	2009-08-16 22:23:21.000000000 +0100
+++ gcc-4.3.4/gcc/doc/invoke.texi	2009-08-16 22:23:30.000000000 +0100
@@ -429,6 +429,7 @@
 -msingle-pic-base  -mno-single-pic-base @gol
 -mpic-register=@var{reg} @gol
 -mnop-fun-dllimport @gol
+-mirrus-di @gol
 -mieee @gol
 -mpoke-function-name @gol
 -mthumb  -marm @gol
@@ -8672,6 +8673,16 @@
 Specify the register to be used for PIC addressing.  The default is R10
 unless stack-checking is enabled, when R9 is used.
 
+@item -mcirrus-di
+When compiling for the Maverick FPU, enable handling of 64-bit integers
+in the FPU (add, subtract, multiply, arithmetic shifts and conversions).
+Normally they are disabled because some instruction sequences can give
+erroneous results.
+This option only has any effect if the
+@option{-mcpu=ep9312} @option{-mfpu=maverick} options have been used and is
+disabled by default.
+The default can be re-enabled by use of the @option{-mno-cirrus-di} switch.
+
 @item -mieee
 When compiling for the Maverick FPU, disable the instructions that fail
 to honor denormalized values. As these include floating point add, sub,
Index: gcc-4.3.4/gcc/config/arm/predicates.md
===================================================================
--- gcc-4.3.4.orig/gcc/config/arm/predicates.md	2009-08-16 22:24:32.000000000 +0100
+++ gcc-4.3.4/gcc/config/arm/predicates.md	2009-08-16 22:24:38.000000000 +0100
@@ -474,9 +474,14 @@
 	      || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
 })
 
-(define_predicate "cirrus_shift_const"
+; Crunch shifts only work up to 31 places left or 32 right
+(define_predicate "const_cirrus_shift_operand"
   (and (match_code "const_int")
-       (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 64")))
+       (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) <= 31")))
+
+(define_predicate "const_cirrus_shiftrt_operand"
+  (and (match_code "const_int")
+       (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) <= 32")))
 
 
 ;; Neon predicates
