[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 08/30] softfloat: Support halving the result of mulad
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 08/30] softfloat: Support halving the result of muladd operation |
Date: |
Thu, 20 Feb 2014 11:17:12 +0000 |
The ARMv8 instruction set includes a fused floating point
reciprocal square root step instruction which demands an
"(x * y + z) / 2" fused operation. Support this by adding
a flag to the softfloat muladd operations which requests
that the result is halved before rounding.
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
---
fpu/softfloat.c | 38 ++++++++++++++++++++++++++++++++++++++
include/fpu/softfloat.h | 3 +++
2 files changed, 41 insertions(+)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e0ea599..fc0b179 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2372,6 +2372,17 @@ float32 float32_muladd(float32 a, float32 b, float32 c,
int flags STATUS_PARAM)
}
}
/* Zero plus something non-zero : just return the something */
+ if (flags & float_muladd_halve_result) {
+ if (cExp == 0) {
+ normalizeFloat32Subnormal(cSig, &cExp, &cSig);
+ }
+ /* Subtract one to halve, and one again because roundAndPackFloat32
+ * wants one less than the true exponent.
+ */
+ cExp -= 2;
+ cSig = (cSig | 0x00800000) << 7;
+ return roundAndPackFloat32(cSign ^ signflip, cExp, cSig
STATUS_VAR);
+ }
return packFloat32(cSign ^ signflip, cExp, cSig);
}
@@ -2408,6 +2419,9 @@ float32 float32_muladd(float32 a, float32 b, float32 c,
int flags STATUS_PARAM)
/* Throw out the special case of c being an exact zero now */
shift64RightJamming(pSig64, 32, &pSig64);
pSig = pSig64;
+ if (flags & float_muladd_halve_result) {
+ pExp--;
+ }
return roundAndPackFloat32(zSign, pExp - 1,
pSig STATUS_VAR);
}
@@ -2472,6 +2486,10 @@ float32 float32_muladd(float32 a, float32 b, float32 c,
int flags STATUS_PARAM)
zSig64 <<= shiftcount;
zExp -= shiftcount;
}
+ if (flags & float_muladd_halve_result) {
+ zExp--;
+ }
+
shift64RightJamming(zSig64, 32, &zSig64);
return roundAndPackFloat32(zSign, zExp, zSig64 STATUS_VAR);
}
@@ -4088,6 +4106,17 @@ float64 float64_muladd(float64 a, float64 b, float64 c,
int flags STATUS_PARAM)
}
}
/* Zero plus something non-zero : just return the something */
+ if (flags & float_muladd_halve_result) {
+ if (cExp == 0) {
+ normalizeFloat64Subnormal(cSig, &cExp, &cSig);
+ }
+ /* Subtract one to halve, and one again because roundAndPackFloat64
+ * wants one less than the true exponent.
+ */
+ cExp -= 2;
+ cSig = (cSig | 0x0010000000000000ULL) << 10;
+ return roundAndPackFloat64(cSign ^ signflip, cExp, cSig
STATUS_VAR);
+ }
return packFloat64(cSign ^ signflip, cExp, cSig);
}
@@ -4123,6 +4152,9 @@ float64 float64_muladd(float64 a, float64 b, float64 c,
int flags STATUS_PARAM)
if (!cSig) {
/* Throw out the special case of c being an exact zero now */
shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1);
+ if (flags & float_muladd_halve_result) {
+ pExp--;
+ }
return roundAndPackFloat64(zSign, pExp - 1,
pSig1 STATUS_VAR);
}
@@ -4159,6 +4191,9 @@ float64 float64_muladd(float64 a, float64 b, float64 c,
int flags STATUS_PARAM)
zExp--;
}
shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1);
+ if (flags & float_muladd_halve_result) {
+ zExp--;
+ }
return roundAndPackFloat64(zSign, zExp, zSig1 STATUS_VAR);
} else {
/* Subtraction */
@@ -4209,6 +4244,9 @@ float64 float64_muladd(float64 a, float64 b, float64 c,
int flags STATUS_PARAM)
zExp -= (shiftcount + 64);
}
}
+ if (flags & float_muladd_halve_result) {
+ zExp--;
+ }
return roundAndPackFloat64(zSign, zExp, zSig0 STATUS_VAR);
}
}
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 806ae13..4b4df88 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -249,11 +249,14 @@ void float_raise( int8 flags STATUS_PARAM);
| Using these differs from negating an input or output before calling
| the muladd function in that this means that a NaN doesn't have its
| sign bit inverted before it is propagated.
+| We also support halving the result before rounding, as a special
+| case to support the ARM fused-sqrt-step instruction FRSQRTS.
*----------------------------------------------------------------------------*/
enum {
float_muladd_negate_c = 1,
float_muladd_negate_product = 2,
float_muladd_negate_result = 4,
+ float_muladd_halve_result = 8,
};
/*----------------------------------------------------------------------------
--
1.8.5
- [Qemu-devel] [PULL 27/30] target-arm: A64: Implement the wide 3-reg-different operations, (continued)
- [Qemu-devel] [PULL 27/30] target-arm: A64: Implement the wide 3-reg-different operations, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 07/30] target-arm: A64: Implement floating point pairwise insns, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 26/30] target-arm: A64: Add most remaining three-reg-diff widening ops, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 25/30] target-arm: A64: Add opcode comments to disas_simd_three_reg_diff, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 24/30] target-arm: A64: Implement store-exclusive for system mode, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 23/30] target-arm: Fix incorrect type for value argument to write_raw_cp_reg, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 22/30] target-arm: Remove failure status return from read/write_raw_cp_reg, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 20/30] target-arm: Drop success/fail return from cpreg read and write functions, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 21/30] target-arm: Remove unnecessary code now read/write fns can't fail, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 19/30] target-arm: Convert miscellaneous reginfo structs to accessfn, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 08/30] softfloat: Support halving the result of muladd operation,
Peter Maydell <=
- [Qemu-devel] [PULL 01/30] hw/intc/arm_gic: Fix NVIC assertion failure, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 04/30] target-arm: A64: Implement SIMD scalar indexed instructions, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 02/30] target-arm: A64: Implement plain vector SIMD indexed element insns, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 14/30] target-arm: Log bad system register accesses with LOG_UNIMP, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 17/30] target-arm: Convert performance monitor reginfo to accessfn, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 15/30] target-arm: Stop underdecoding ARM946 PRBS registers, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 12/30] target-arm: Restrict check_ap() use of S and R bits to v6 and earlier, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 18/30] target-arm: Convert generic timer reginfo to accessfn, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 11/30] target-arm: Define names for SCTLR bits, Peter Maydell, 2014/02/20
- [Qemu-devel] [PULL 03/30] target-arm: A64: Implement long vector x indexed insns, Peter Maydell, 2014/02/20