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.

