G'day all, As I wrote previously on gcc-patches ( http://gcc.gnu.org/ml/gcc-patches/2007-06/msg00244.html ), I'm working on code to get the MaverickCrunch Floating-Point Co-processor supported on ARM. I mentioned previously that you can't use the same opcodes for testing GE on the MaverickCrunch, as you use on ARM. See the below table for NZCV values from MaverickCrunch.
MaverickCrunch - (cfcmp*): N Z C V A == B 0 1 0 0 A < B 1 0 0 0 A > B 1 0 0 1 unord 0 0 0 0 ARM/FPA/VFP - (cmp*): N Z C V A == B 0 1 1 0 A < B 1 0 0 0 A > B 0 0 1 0 unord 0 0 1 1 I've added a new "maverick_comparison_operator" similar to "arm_comparison_operator" to predicates.md, and added the right bits to arm.md, as shown below: ;; Special predication pattern for Maverick Crunch floating-point (define_cond_exec [(match_operator 0 "maverick_comparison_operator" [(match_operand:CCFP 1 "cc_register" "") (const_int 0)])] "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" "" ) All the other predicates are fine, since they are only used in floating point comparisons. But "ge" is also used for integer comparisons. Now, my problem is with the following code: ; Special pattern to match GE for MAVERICK. (define_insn "*arm_bge" [(set (pc) (if_then_else (ge (match_operand 1 "cc_register" "") (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" "* gcc_assert (!arm_ccfsm_state); if (get_attr_cirrus (prev_active_insn(insn)) == CIRRUS_COMPARE) return \"beq\\t%l0\;bvs\\t%l0\"; else return \"bge\\t%l0\;nop\"; " [(set_attr "conds" "jump_clob") (set_attr "length" "8")] ) As you can see, I need to replace all bge with a maverick crunch equivalent. However, "bge" is still also used with integer comparisons, e.g: double a, b; if (a>=b) { produces: cfcmpd r15, mvd1, mvd0 beq .L4 bvs .L4 b .L2 .L4: I haven't got a good example for the integer ge, but unsidf makes use of ge (NB, I disabled MaverickCrunch 64-bit support for clarity, and bugfixing): unsigned int e = 9; double e_d = e; produces: mov r3, #9 str r3, [fp, #-32] ldr r0, [fp, #-32] bl __aeabi_i2d str r0, [fp, #-44] str r1, [fp, #-40] ldr r3, [fp, #-32] cmp r3, #0 bge .L2 nop mov r0, r0 @ nop mov r0, r0 @ nop cfldrd mvd0, .L4 mov r0, r0 @ nop cfldrd mvd1, [fp, #-44] mov r0, r0 @ nop cfaddd mvd1, mvd1, mvd0 cfstrd mvd1, [fp, #-44] .L2: This seems to work fine for C code, but when I generate C++ code, I get errors. Can anyone suggest a better way of writing the above code? I'd rather the jump_clob didn't actually happen unless it was definitely a cirrus compare, and not an ARM compare, but I can't seem to write the code correctly. Also, is "(get_attr_cirrus (prev_active_insn(insn)) == CIRRUS_COMPARE)" the best way to find out if the last compare instruction was a cirrus compare, or an ARM compare? Should I add a new routine to find the last compare insn, e.g. prev_compare_insn??? I know that a branch doesn't have to be directly after a comparison. This and invalid coprocessor offset issue are the only two outstanding bugs for MaverickCrunch support on the Cirrus EP93xx.