}
return __packFloat64(zSign, 0x7FF, 0u, 0u);
}
- if (zExp < 0) {
- __shift64ExtraRightJamming(
- zFrac0, zFrac1, zFrac2, -zExp, zFrac0, zFrac1, zFrac2);
- zExp = 0;
- if (roundNearestEven) {
- increment = zFrac2 < 0u;
+ }
+
+ if (zExp < 0) {
+ __shift64ExtraRightJamming(
+ zFrac0, zFrac1, zFrac2, -zExp, zFrac0, zFrac1, zFrac2);
+ zExp = 0;
+ if (roundNearestEven) {
+ increment = zFrac2 < 0u;
+ } else {
+ if (zSign != 0u) {
+ increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) &&
+ (zFrac2 != 0u);
} else {
- if (zSign != 0u) {
- increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) &&
- (zFrac2 != 0u);
- } else {
- increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) &&
- (zFrac2 != 0u);
- }
+ increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) &&
+ (zFrac2 != 0u);
}
}
}
+
if (increment) {
__add64(zFrac0, zFrac1, 0u, 1u, zFrac0, zFrac1);
zFrac1 &= ~((zFrac2 + uint(zFrac2 == 0u)) & uint(roundNearestEven));
#endif
}
+/* If a shader is in the soft-fp64 path, it almost certainly has register
+ * pressure problems. Choose a method to exchange two values that does not
+ * require a temporary.
+ */
+#define EXCHANGE(a, b) \
+ do { \
+ a ^= b; \
+ b ^= a; \
+ a ^= b; \
+ } while (false)
+
/* Returns the result of adding the double-precision floating-point values
* `a' and `b'. The operation is performed according to the IEEE Standard for
* Floating-Point Arithmetic.
uint zFrac1;
uint zFrac2;
int zExp;
- bool orig_exp_diff_is_zero = (expDiff == 0);
- if (orig_exp_diff_is_zero) {
+ if (expDiff == 0) {
if (aExp == 0x7FF) {
bool propagate = ((aFracHi | bFracHi) | (aFracLo| bFracLo)) != 0u;
return mix(a, __propagateFloat64NaN(a, b), propagate);
zExp = aExp;
__shift64ExtraRightJamming(
zFrac0, zFrac1, zFrac2, 1, zFrac0, zFrac1, zFrac2);
- } else if (0 < expDiff) {
+ } else {
+ if (expDiff < 0) {
+ EXCHANGE(aFracHi, bFracHi);
+ EXCHANGE(aFracLo, bFracLo);
+ EXCHANGE(aExp, bExp);
+ }
+
if (aExp == 0x7FF) {
bool propagate = (aFracHi | aFracLo) != 0u;
- return mix(a, __propagateFloat64NaN(a, b), propagate);
+ return mix(__packFloat64(aSign, 0x7ff, 0u, 0u), __propagateFloat64NaN(a, b), propagate);
}
- expDiff = mix(expDiff, expDiff - 1, bExp == 0);
+ expDiff = mix(abs(expDiff), abs(expDiff) - 1, bExp == 0);
bFracHi = mix(bFracHi | 0x00100000u, bFracHi, bExp == 0);
__shift64ExtraRightJamming(
bFracHi, bFracLo, 0u, expDiff, bFracHi, bFracLo, zFrac2);
zExp = aExp;
- } else {
- if (bExp == 0x7FF) {
- bool propagate = (bFracHi | bFracLo) != 0u;
- return mix(__packFloat64(aSign, 0x7ff, 0u, 0u), __propagateFloat64NaN(a, b), propagate);
- }
- expDiff = mix(expDiff, expDiff + 1, aExp == 0);
- aFracHi = mix(aFracHi | 0x00100000u, aFracHi, aExp == 0);
- __shift64ExtraRightJamming(
- aFracHi, aFracLo, 0u, - expDiff, aFracHi, aFracLo, zFrac2);
- zExp = bExp;
- }
- if (!orig_exp_diff_is_zero) {
+
aFracHi |= 0x00100000u;
__add64(aFracHi, aFracLo, bFracHi, bFracLo, zFrac0, zFrac1);
--zExp;
__shortShift64Left(aFracHi, aFracLo, 10, aFracHi, aFracLo);
__shortShift64Left(bFracHi, bFracLo, 10, bFracHi, bFracLo);
- if (0 < expDiff) {
+ if (expDiff != 0) {
uint zFrac0;
uint zFrac1;
+ if (expDiff < 0) {
+ EXCHANGE(aFracHi, bFracHi);
+ EXCHANGE(aFracLo, bFracLo);
+ EXCHANGE(aExp, bExp);
+ aSign ^= 0x80000000u;
+ }
+
if (aExp == 0x7FF) {
bool propagate = (aFracHi | aFracLo) != 0u;
- return mix(a, __propagateFloat64NaN(a, b), propagate);
+ return mix(__packFloat64(aSign, 0x7ff, 0u, 0u), __propagateFloat64NaN(a, b), propagate);
}
- expDiff = mix(expDiff, expDiff - 1, bExp == 0);
+
+ expDiff = mix(abs(expDiff), abs(expDiff) - 1, bExp == 0);
bFracHi = mix(bFracHi | 0x40000000u, bFracHi, bExp == 0);
__shift64RightJamming(bFracHi, bFracLo, expDiff, bFracHi, bFracLo);
aFracHi |= 0x40000000u;
--zExp;
return __normalizeRoundAndPackFloat64(aSign, zExp - 10, zFrac0, zFrac1);
}
- if (expDiff < 0) {
- uint zFrac0;
- uint zFrac1;
-
- if (bExp == 0x7FF) {
- bool propagate = (bFracHi | bFracLo) != 0u;
- return mix(__packFloat64(aSign ^ 0x80000000u, 0x7ff, 0u, 0u), __propagateFloat64NaN(a, b), propagate);
- }
- expDiff = mix(expDiff, expDiff + 1, aExp == 0);
- aFracHi = mix(aFracHi | 0x40000000u, aFracHi, aExp == 0);
- __shift64RightJamming(aFracHi, aFracLo, - expDiff, aFracHi, aFracLo);
- bFracHi |= 0x40000000u;
- __sub64(bFracHi, bFracLo, aFracHi, aFracLo, zFrac0, zFrac1);
- zExp = bExp;
- aSign ^= 0x80000000u;
- --zExp;
- return __normalizeRoundAndPackFloat64(aSign, zExp - 10, zFrac0, zFrac1);
- }
if (aExp == 0x7FF) {
bool propagate = ((aFracHi | bFracHi) | (aFracLo | bFracLo)) != 0u;
return mix(0xFFFFFFFFFFFFFFFFUL, __propagateFloat64NaN(a, b), propagate);