sys/sparc/fpu/fpu_compare.c
/*
 * Perform a compare instruction (with or without unordered exception).
 * This updates the fcc field in the fsr.
 *
 * If either operand is NaN, the result is unordered.  For cmpe, this
 * causes an NV exception.  Everything else is ordered:
 *	|Inf| > |numbers| > |0|.
 * We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0),
 * so we get this directly.  Note, however, that two zeros compare equal
 * regardless of sign, while everything else depends on sign.
 *
 * Incidentally, two Infs of the same sign compare equal (per the 80387
 * manual---it would be nice if the SPARC documentation were more
 * complete).
 */
Perform a compare instruction (with or without unordered exception).
This updates the fcc field in the fsr.

If either operand is NaN, the result is unordered.  For cmpe, this
causes an NV exception.

Incidentally, two Infs of the same sign compare equal (per the 80387
manual---it would be nice if the SPARC documentation were more
complete).
Perform a compare instruction ( with or without unordered exception ) . This updates the fcc field in the fsr . If either operand is NaN the result is unordered . For cmpe this causes an NV exception . Incidentally two Infs of the same sign compare equal ( per the 80387 manual --- it would be nice if the SPARC documentation were more complete ) .
void
fpu_compare(struct fpemu *fe, int cmpe)
{
	register struct fpn *a, *b;
	register int cc, r3, r2, r1, r0;
	FPU_DECL_CARRY
	a = &fe->fe_f1;
	b = &fe->fe_f2;
	if (ISNAN(a) || ISNAN(b)) {
		if (cmpe)
			fe->fe_cx = FSR_NV;
		cc = FSR_CC_UO;
		goto done;
	}
	if (ISZERO(a) && ISZERO(b)) {
		cc = FSR_CC_EQ;
		goto done;
	}
	if (a->fp_sign) {		
		if (!b->fp_sign) {	
			cc = FSR_CC_LT;
			goto done;
		}
	} else {			
		if (b->fp_sign) {	
			cc = FSR_CC_GT;
			goto done;
		}
	}
#define opposite_cc(cc) ((cc) == FSR_CC_LT ? FSR_CC_GT : FSR_CC_LT)
#define	diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) :  (magnitude))
	if (a->fp_class < b->fp_class) {	
		cc = diff(FSR_CC_LT);
		goto done;
	}
	if (a->fp_class > b->fp_class) {	
		cc = diff(FSR_CC_GT);
		goto done;
	}
	if (ISINF(a)) {				
		cc = FSR_CC_EQ;
		goto done;
	}
	FPU_SUBS(r3, a->fp_mant[0], b->fp_mant[0]);
	FPU_SUBCS(r2, a->fp_mant[1], b->fp_mant[1]);
	FPU_SUBCS(r1, a->fp_mant[2], b->fp_mant[2]);
	FPU_SUBC(r0, a->fp_mant[3], b->fp_mant[3]);
	if (r0 < 0)				
		cc = diff(FSR_CC_LT);
	else if ((r0 | r1 | r2 | r3) != 0)	
		cc = diff(FSR_CC_GT);
	else
		cc = FSR_CC_EQ;		
done:
	fe->fe_fsr = (fe->fe_fsr & ~FSR_FCC) | (cc << FSR_FCC_SHIFT);
}
void fpu_compare ( struct fpemu * fe , int cmpe ) { register struct fpn * a , * b ; register int cc , r3 , r2 , r1 , r0 ; FPU_DECL_CARRY a = & fe -> fe_f1 ; b = & fe -> fe_f2 ; if ( ISNAN ( a ) || ISNAN ( b ) ) { if ( cmpe ) fe -> fe_cx = FSR_NV ; cc = FSR_CC_UO ; goto done ; } if ( ISZERO ( a ) && ISZERO ( b ) ) { cc = FSR_CC_EQ ; goto done ; } if ( a -> fp_sign ) { if ( ! b -> fp_sign ) { cc = FSR_CC_LT ; goto done ; } } else { if ( b -> fp_sign ) { cc = FSR_CC_GT ; goto done ; } } #define opposite_cc ( cc )  ((cc) == FSR_CC_LT ? FSR_CC_GT : FSR_CC_LT) #define diff ( magnitude )  (a->fp_sign ? opposite_cc(magnitude) :  (magnitude)) if ( a -> fp_class < b -> fp_class ) { cc = diff ( FSR_CC_LT ) ; goto done ; } if ( a -> fp_class > b -> fp_class ) { cc = diff ( FSR_CC_GT ) ; goto done ; } if ( ISINF ( a ) ) { cc = FSR_CC_EQ ; goto done ; } FPU_SUBS ( r3 , a -> fp_mant [ 0 ] , b -> fp_mant [ 0 ] ) ; FPU_SUBCS ( r2 , a -> fp_mant [ 1 ] , b -> fp_mant [ 1 ] ) ; FPU_SUBCS ( r1 , a -> fp_mant [ 2 ] , b -> fp_mant [ 2 ] ) ; FPU_SUBC ( r0 , a -> fp_mant [ 3 ] , b -> fp_mant [ 3 ] ) ; if ( r0 < 0 ) cc = diff ( FSR_CC_LT ) ; else if ( ( r0 | r1 | r2 | r3 ) != 0 ) cc = diff ( FSR_CC_GT ) ; else cc = FSR_CC_EQ ; done : fe -> fe_fsr = ( fe -> fe_fsr & ~ FSR_FCC ) | ( cc << FSR_FCC_SHIFT ) ; }
Perform a compare instruction (with or without unordered exception).
Perform a compare instruction ( with or without unordered exception ) .
/*
		 * In any case, we already got an exception for signalling
		 * NaNs; here we may replace that one with an identical
		 * exception, but so what?.
		 */ /*
	 * Must handle both-zero early to avoid sign goofs.  Otherwise,
	 * at most one is 0, and if the signs differ we are done.
	 */ /* a < 0 (or -0) */ /* b >= 0 (or if a = -0, b > 0) */ /* a > 0 (or +0) */ /* b <= -0 (or if a = +0, b < 0) */ /*
	 * Now the signs are the same (but may both be negative).  All
	 * we have left are these cases:
	 *
	 *	|a| < |b|		[classes or values differ]
	 *	|a| > |b|		[classes or values differ]
	 *	|a| == |b|		[classes and values identical]
	 *
	 * We define `diff' here to expand these as:
	 *
	 *	|a| < |b|, a,b >= 0: a < b => FSR_CC_LT
	 *	|a| < |b|, a,b < 0:  a > b => FSR_CC_GT
	 *	|a| > |b|, a,b >= 0: a > b => FSR_CC_GT
	 *	|a| > |b|, a,b < 0:  a < b => FSR_CC_LT
	 */ /* |a| < |b| */ /* |a| > |b| */ /* now none can be 0: only Inf and numbers remain */ /* |Inf| = |Inf| */ /*
	 * Only numbers remain.  To compare two numbers in magnitude, we
	 * simply subtract their mantissas.
	 */ /* underflow: |a| < |b| */ /* |a| > |b| */ /* |a| == |b| */