Copyright (C) 2002 Free Software Foundation, Inc. Implementation Notes ==================== IEEE floating point comparisons Ian Dall ------------------------------------ The ns32x81 fpu handles most operands in hardware, but traps on NaN, Inf and Denormalized numbers. The correct behavior can be handled by the trap handler. This is mostly transparent to the compiler, but in the case of floating point comparisons, the trap handler and the compiler must co-operate. Comparing a Nan with anything (including another Nan) is an unordered comparison and a NE test should be true and any other test should be false. There is nothing the trap handler can do to the condition codes to make, for example ble and bgt (the machine instructions, not the gcc insn's) both fail. The L flag (normally used for unsigned comparisons) is cleared by a floating point compare. So, it is possible for the trap handler to communicate that it has seen a NaN by setting this flag. This can get confusing so the following documents the reasoning. There are only 3 flags of significance, N, Z and L. In what follows AB is the conjunction of A and B ("and") A+B is the disjunction of A and B ("or"), upper case represents true and lower case represents false. So "Zl" is "Z AND (NOT L)". Also, we can require that the trap handler clears N and Z, whenever it sets L. This means that in many cases, we do not need to test if L is set or clear. The operations we require are: Operator Expression Check L GT Nl No LT znl Yes GE (Z+N)l No LE nl Yes EQ Zl No NE z+L No For example, the emitted code for the case of LT is bhi 0f blt %0 0: which is, in effect, "branch if ordered and less than." We also need insns for the reverse branches. These have the PC and the label ref operands reversed. Thus the reverse bgt has a pattern: (set (pc) (if_then_else (gt (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" "")))) This is identical to a normal branch with the test complimented: (set (pc) (if_then_else (not (gt (cc0) (const_int 0))) (label_ref (match_operand 0 "" "") (pc)))) Thus we need a family of (NOT cond) tests. For integers this is easy, a reverse blt becomes bge. However, the possibility of unordered comparison complicates the floating point case. So, we need to compliment the above expressions, using deMorgan's theorem, for the reverse branch: Operator Expression Check L RGT n+L Yes RLT Z+N+L Yes RGE zn+L Yes RLE N+L Yes REQ z+L No RNE Zl No For example the emitted code for the case of RLT is bge %0 bhi %0 which is, in effect "branch if not less than and not unordered." These extra comparisons are safe if the trap handler doesn't set the L flag, since in that case the additional "bhi" instructions are never taken. Also, these extra branch instructions are controlled by the "-mieee-compare" option.