|
@@ -165,3 +165,85 @@ static unsigned int PerformComparison(const unsigned int opcode)
|
|
|
/* Check for unordered condition and convert all operands to 80-bit
|
|
|
format.
|
|
|
?? Might be some mileage in avoiding this conversion if possible.
|
|
|
+ Eg, if both operands are 32-bit, detect this and do a 32-bit
|
|
|
+ comparison (cheaper than an 80-bit one). */
|
|
|
+ switch (fpa11->fType[Fn]) {
|
|
|
+ case typeSingle:
|
|
|
+ //printk("single.\n");
|
|
|
+ if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
|
|
|
+ goto unordered;
|
|
|
+ rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case typeDouble:
|
|
|
+ //printk("double.\n");
|
|
|
+ if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
|
|
|
+ goto unordered;
|
|
|
+ rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case typeExtended:
|
|
|
+ //printk("extended.\n");
|
|
|
+ if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
|
|
|
+ goto unordered;
|
|
|
+ rFn = fpa11->fpreg[Fn].fExtended;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CONSTANT_FM(opcode)) {
|
|
|
+ //printk("Fm is a constant: #%d.\n",Fm);
|
|
|
+ rFm = getExtendedConstant(Fm);
|
|
|
+ if (floatx80_is_nan(rFm))
|
|
|
+ goto unordered;
|
|
|
+ } else {
|
|
|
+ //printk("Fm = r%d which contains a ",Fm);
|
|
|
+ switch (fpa11->fType[Fm]) {
|
|
|
+ case typeSingle:
|
|
|
+ //printk("single.\n");
|
|
|
+ if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
|
|
|
+ goto unordered;
|
|
|
+ rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case typeDouble:
|
|
|
+ //printk("double.\n");
|
|
|
+ if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
|
|
|
+ goto unordered;
|
|
|
+ rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case typeExtended:
|
|
|
+ //printk("extended.\n");
|
|
|
+ if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
|
|
|
+ goto unordered;
|
|
|
+ rFm = fpa11->fpreg[Fm].fExtended;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (n_flag)
|
|
|
+ rFm.high ^= 0x8000;
|
|
|
+
|
|
|
+ /* test for less than condition */
|
|
|
+ if (floatx80_lt(rFn, rFm))
|
|
|
+ flags |= CC_NEGATIVE;
|
|
|
+
|
|
|
+ /* test for equal condition */
|
|
|
+ if (floatx80_eq(rFn, rFm))
|
|
|
+ flags |= CC_ZERO;
|
|
|
+
|
|
|
+ /* test for greater than or equal condition */
|
|
|
+ if (floatx80_lt(rFm, rFn))
|
|
|
+ flags |= CC_CARRY;
|
|
|
+
|
|
|
+#else
|
|
|
+ if (CONSTANT_FM(opcode)) {
|
|
|
+ /* Fm is a constant. Do the comparison in whatever precision
|
|
|
+ Fn happens to be stored in. */
|
|
|
+ if (fpa11->fType[Fn] == typeSingle) {
|