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.2.4/gcc/config/arm/arm.opt =================================================================== --- gcc-4.2.4.orig/gcc/config/arm/arm.opt 2009-08-09 16:08:54.000000000 +0100 +++ gcc-4.2.4/gcc/config/arm/arm.opt 2009-08-09 16:08:55.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.2.4/gcc/config/arm/arm.c =================================================================== --- gcc-4.2.4.orig/gcc/config/arm/arm.c 2009-08-09 16:08:54.000000000 +0100 +++ gcc-4.2.4/gcc/config/arm/arm.c 2009-08-09 16:08:55.000000000 +0100 @@ -12030,7 +12030,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.2.4/gcc/config/arm/arm.md =================================================================== --- gcc-4.2.4.orig/gcc/config/arm/arm.md 2009-08-09 16:08:51.000000000 +0100 +++ gcc-4.2.4/gcc/config/arm/arm.md 2009-08-09 16:08:55.000000000 +0100 @@ -356,7 +356,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]); @@ -392,7 +392,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_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" + "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)" "#" "TARGET_ARM && reload_completed" [(parallel [(set (reg:CC_C CC_REGNUM) @@ -420,7 +420,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_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" + "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)" "#" "TARGET_ARM && reload_completed" [(parallel [(set (reg:CC_C CC_REGNUM) @@ -449,7 +449,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_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" + "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI)" "#" "TARGET_ARM && reload_completed" [(parallel [(set (reg:CC_C CC_REGNUM) @@ -834,7 +834,7 @@ (clobber (reg:CC CC_REGNUM))])] "TARGET_EITHER" " - if (TARGET_HARD_FLOAT && TARGET_MAVERICK + if (TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI && TARGET_ARM && cirrus_fp_register (operands[0], DImode) && cirrus_fp_register (operands[1], DImode)) @@ -2659,7 +2659,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; " ) @@ -4166,7 +4167,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))" @@ -4286,7 +4288,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_THUMB - && !(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.2.4/gcc/config/arm/cirrus.md =================================================================== --- gcc-4.2.4.orig/gcc/config/arm/cirrus.md 2009-08-09 16:08:52.000000000 +0100 +++ gcc-4.2.4/gcc/config/arm/cirrus.md 2009-08-16 22:32:00.000000000 +0100 @@ -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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && 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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && 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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI" "cfmul64%?\\t%V0, %V1, %V2" [(set_attr "type" "fmul") (set_attr "cirrus" "normal")] @@ -230,7 +230,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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0" "cfsh32%?\\t%V0, %V1, #%s2" [(set_attr "type" "farith") @@ -240,7 +240,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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0" "cfsh32%?\\t%V0, %V1, #-%s2" [(set_attr "type" "farith") @@ -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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI" "cfrshl64%?\\t%V1, %V0, %s2" [(set_attr "type" "farith") (set_attr "cirrus" "normal")] @@ -270,8 +270,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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + (match_operand:SI 2 "const_cirrus_shift_operand" "")))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && TARGET_CIRRUS_DI" "cfsh64%?\\t%V0, %V1, #%s2" [(set_attr "type" "farith") (set_attr "cirrus" "normal")] @@ -280,8 +280,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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + (match_operand:SI 2 "const_cirrus_shiftrt_operand" "")))] + "TARGET_ARM && 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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && 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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && 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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && 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_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "TARGET_ARM && 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) Index: gcc-4.2.4/gcc/doc/invoke.texi =================================================================== --- gcc-4.2.4.orig/gcc/doc/invoke.texi 2009-08-09 16:08:54.000000000 +0100 +++ gcc-4.2.4/gcc/doc/invoke.texi 2009-08-09 16:08:55.000000000 +0100 @@ -417,6 +417,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 @@ -7770,6 +7771,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.2.4/gcc/config/arm/predicates.md =================================================================== --- gcc-4.2.4.orig/gcc/config/arm/predicates.md 2009-08-16 22:27:01.000000000 +0100 +++ gcc-4.2.4/gcc/config/arm/predicates.md 2009-08-16 22:29:15.000000000 +0100 @@ -460,8 +460,12 @@ || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS)); }) -(define_predicate "cirrus_shift_const" +(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")))