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. --- gcc-4.3.2/gcc/config/arm/arm.opt.old 2009-03-10 22:08:13.000000000 +0000 +++ gcc-4.3.2/gcc/config/arm/arm.opt 2009-03-10 12:47:31.000000000 +0000 @@ -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 --- gcc-4.3.2/gcc/config/arm/arm.c.old 2009-03-10 09:32:31.000000000 +0000 +++ gcc-4.3.2/gcc/config/arm/arm.c 2009-03-10 12:44:48.000000000 +0000 @@ -13917,7 +13917,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)) --- gcc-4.3.2/gcc/config/arm/arm.md.old 2009-03-10 12:14:01.000000000 +0000 +++ gcc-4.3.2/gcc/config/arm/arm.md 2009-03-10 12:42:55.000000000 +0000 @@ -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))" "* --- gcc-4.3.2/gcc/config/arm/cirrus.md.old 2009-03-10 12:13:10.000000000 +0000 +++ gcc-4.3.2/gcc/config/arm/cirrus.md 2009-03-10 12:32:00.000000000 +0000 @@ -85,7 +85,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")] @@ -126,7 +126,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")] @@ -176,7 +176,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")] @@ -261,7 +261,7 @@ [(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")] @@ -271,7 +271,7 @@ [(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" + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI" "cfsh64%?\\t%V0, %V1, #%s2" [(set_attr "type" "farith") (set_attr "cirrus" "normal")] @@ -281,7 +281,7 @@ [(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" + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI" "cfsh64%?\\t%V0, %V1, #-%s2" [(set_attr "type" "farith") (set_attr "cirrus" "normal")] @@ -290,7 +290,7 @@ (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")] @@ -301,7 +301,7 @@ [(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" + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI" "cfneg64%?\\t%V0, %V1" [(set_attr "type" "farith") (set_attr "cirrus" "normal")] @@ -392,7 +392,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")] @@ -401,7 +401,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")] @@ -454,7 +454,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) --- gcc-4.3.2/gcc/doc/invoke.texi.old 2009-03-10 17:17:19.000000000 +0000 +++ gcc-4.3.2/gcc/doc/invoke.texi 2009-03-10 17:24:19.000000000 +0000 @@ -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 @@ -8670,6 +8671,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,