GCC Maverick Crunch bugs Martin Guy , August 2007 Generating code for -mcpu=ep9312 -mfpu-maverick -mfloat-abi={softfp|hard}, the operators < and > between floating point values often do the wrong thing. Example: #include main() { int i; double d; for (i=3, d=3; i<=5; i++, d++) { printf("%g", d); if (d < 4.0) lt(); if (d > 4.0) gt(); if (d <= 4.0) le(); if (d >= 4.0) ge(); putchar('\n'); } } lt(){ printf(" lt");} gt(){ printf(" gt");} le(){ printf(" le");} ge(){ printf(" ge");} Output: 3 lt le 4 le ge 5 lt gt le ge Assembler fragment without -O: cfldrd mvd1, [fp, #-28] cfldrd mvd0, .L18+8 cfcmpd r15, mvd1, mvd0 bmi .L6 b .L4 .L6: bl lt .L4: cfldrd mvd1, [fp, #-28] cfldrd mvd0, .L18+8 cfcmpd r15, mvd1, mvd0 bgt .L9 b .L7 .L9: bl gt .L7: cfldrd mvd1, [fp, #-28] cfldrd mvd0, .L18+8 bls .L12 b .L10 .L12: bl le .L10: cfldrd mvd1, [fp, #-28] cfldrd mvd0, .L18+8 cfcmpd r15, mvd1, mvd0 bge .L15 b .L13 .L15: bl ge .L13: mov r0, #10 bl putchar With -O: cfcmpd r15, mvd4, mvd5 blmi lt .L19: cfcmpd r15, mvd4, mvd5 blgt gt .L22: cfcmpd r15, mvd4, mvd5 blls le .L25: cfcmpd r15, mvd4, mvd5 blge ge .L28: mov r0, #10 Analysis: This turns out to be because the assembly code is using MI and LS conditions for the < and > tests, but the necessary condition code bits are not set by the Maverick FP compare instructions; they only set the CCs up for EQ NE LT GT LE GE. See EP9307 Users Guide, http://www.cirrus.com/en/pubs/manual/EP9307_Users_Guide.pdf chapter 2, table 2-4: "The NZCV flags are not computed exactly as with integer comparisons using the ARM CMP instruction. Hence, when examining the result of Crunch comparisons, the condition codes field of ARM instructions should be interpreted differently, as shown in Table 2-4 on page 41. The same six condition codes should be used whether the comparison operands were signed integers, unsigned integers, or floating point. No other condition codes are meaningful." Table 2-4 extract: Opcode[31:28] Mnemonic 0000 EQ 0001 NE 1010 GE 1011 LT 1100 GT 1101 LE 1110 AL 1111 NV