| Copyright (C) 2002 |
| Free Software Foundation, Inc. |
| |
| Implementation Notes |
| ==================== |
| |
| IEEE floating point comparisons |
| |
| Ian Dall <ian@beware.dropbear.id.au> |
| ------------------------------------ |
| |
| 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. |
| |