Testing infrastructure for softfpu (not run by default).

Drop countLeadingZeros.
 Fix div_floats.
 Add udiv_qrnnd specializations for x86_64, s390x, ppc64 hosts.
 -----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJbt6apAAoJEGTfOOivfiFfv7IH/2pFUMKB8aaFA6p4xlMCufYg
 usYvyXqul2D6/ZFwirsxOmFrVs0Vx8/E2BHMvW7fx+XVfMUa7bUNYKeYwTtvKgI1
 hsm1hKEedVl+hOLZZBfiPEbMnm5Epg2L2NbLpMo1RWWqqKjlOMMU0RZH/lBpuoT3
 OUDQEQaMvTC91xqhWDgwkedNGRl57kXNDYLQAvfhYtcKHj8vYgwbzA46/y1p1xVd
 E37ym5jL6DHhzIoU7ty9u74PxkM2qBKGhVlRqLQ0YO6gStKoW0ZBVZSlQx9NPG7J
 OjYYmZwWs5T61ai0e3N0sqP5QJyhs7g/FfmKDgzhPMFkeGh8kwihjdJwPaKzJ88=
 =iTHi
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/rth/tags/pull-fpu-20181005' into staging

Testing infrastructure for softfpu (not run by default).
Drop countLeadingZeros.
Fix div_floats.
Add udiv_qrnnd specializations for x86_64, s390x, ppc64 hosts.

# gpg: Signature made Fri 05 Oct 2018 19:00:09 BST
# gpg:                using RSA key 64DF38E8AF7E215F
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>"
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* remotes/rth/tags/pull-fpu-20181005:
  softfloat: Specialize udiv_qrnnd for ppc64
  softfloat: Specialize udiv_qrnnd for s390x
  softfloat: Specialize udiv_qrnnd for x86_64
  softfloat: Fix division
  softfloat: Replace countLeadingZeros32/64 with clz32/64
  tests/fp/fp-test: add floating point tests
  gitmodules: add berkeley's softfloat + testfloat version 3
  softfloat: remove float64_trunc_to_int

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-10-08 12:44:35 +01:00
commit 079911cb6e
13 changed files with 2392 additions and 125 deletions

View file

@ -79,17 +79,6 @@ this code that are retained.
* version 2 or later. See the COPYING file in the top-level directory.
*/
/*----------------------------------------------------------------------------
| This macro tests for minimum version of the GNU C compiler.
*----------------------------------------------------------------------------*/
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define SOFTFLOAT_GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
# define SOFTFLOAT_GNUC_PREREQ(maj, min) 0
#endif
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
@ -340,15 +329,30 @@ static inline void
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
static inline void
shortShift128Left(
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
static inline void shortShift128Left(uint64_t a0, uint64_t a1, int count,
uint64_t *z0Ptr, uint64_t *z1Ptr)
{
*z1Ptr = a1 << count;
*z0Ptr = count == 0 ? a0 : (a0 << count) | (a1 >> (-count & 63));
}
*z1Ptr = a1<<count;
*z0Ptr =
( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
| number of bits given in `count'. Any bits shifted off are lost. The value
| of `count' may be greater than 64. The result is broken into two 64-bit
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
static inline void shift128Left(uint64_t a0, uint64_t a1, int count,
uint64_t *z0Ptr, uint64_t *z1Ptr)
{
if (count < 64) {
*z1Ptr = a1 << count;
*z0Ptr = count == 0 ? a0 : (a0 << count) | (a1 >> (-count & 63));
} else {
*z1Ptr = 0;
*z0Ptr = a1 << (count - 64);
}
}
/*----------------------------------------------------------------------------
@ -630,8 +634,36 @@ static inline uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b)
*
* Licensed under the GPLv2/LGPLv3
*/
static inline uint64_t div128To64(uint64_t n0, uint64_t n1, uint64_t d)
static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1,
uint64_t n0, uint64_t d)
{
#if defined(__x86_64__)
uint64_t q;
asm("divq %4" : "=a"(q), "=d"(*r) : "0"(n0), "1"(n1), "rm"(d));
return q;
#elif defined(__s390x__)
/* Need to use a TImode type to get an even register pair for DLGR. */
unsigned __int128 n = (unsigned __int128)n1 << 64 | n0;
asm("dlgr %0, %1" : "+r"(n) : "r"(d));
*r = n >> 64;
return n;
#elif defined(_ARCH_PPC64)
/* From Power ISA 3.0B, programming note for divdeu. */
uint64_t q1, q2, Q, r1, r2, R;
asm("divdeu %0,%2,%4; divdu %1,%3,%4"
: "=&r"(q1), "=r"(q2)
: "r"(n1), "r"(n0), "r"(d));
r1 = -(q1 * d); /* low part of (n1<<64) - (q1 * d) */
r2 = n0 - (q2 * d);
Q = q1 + q2;
R = r1 + r2;
if (R >= d || R < r2) { /* overflow implies R > d */
Q += 1;
R -= d;
}
*r = R;
return Q;
#else
uint64_t d0, d1, q0, q1, r1, r0, m;
d0 = (uint32_t)d;
@ -669,8 +701,9 @@ static inline uint64_t div128To64(uint64_t n0, uint64_t n1, uint64_t d)
}
r0 -= m;
/* Return remainder in LSB */
return (q1 << 32) | q0 | (r0 != 0);
*r = r0;
return (q1 << 32) | q0;
#endif
}
/*----------------------------------------------------------------------------
@ -712,82 +745,6 @@ static inline uint32_t estimateSqrt32(int aExp, uint32_t a)
}
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 32 is returned.
*----------------------------------------------------------------------------*/
static inline int8_t countLeadingZeros32(uint32_t a)
{
#if SOFTFLOAT_GNUC_PREREQ(3, 4)
if (a) {
return __builtin_clz(a);
} else {
return 32;
}
#else
static const int8_t countLeadingZerosHigh[] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int8_t shiftCount;
shiftCount = 0;
if ( a < 0x10000 ) {
shiftCount += 16;
a <<= 16;
}
if ( a < 0x1000000 ) {
shiftCount += 8;
a <<= 8;
}
shiftCount += countLeadingZerosHigh[ a>>24 ];
return shiftCount;
#endif
}
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 64 is returned.
*----------------------------------------------------------------------------*/
static inline int8_t countLeadingZeros64(uint64_t a)
{
#if SOFTFLOAT_GNUC_PREREQ(3, 4)
if (a) {
return __builtin_clzll(a);
} else {
return 64;
}
#else
int8_t shiftCount;
shiftCount = 0;
if ( a < ( (uint64_t) 1 )<<32 ) {
shiftCount += 32;
}
else {
a >>= 32;
}
shiftCount += countLeadingZeros32( a );
return shiftCount;
#endif
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
| is equal to the 128-bit value formed by concatenating `b0' and `b1'.

View file

@ -535,7 +535,6 @@ float128 float64_to_float128(float64, float_status *status);
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int(float64, float_status *status);
float64 float64_trunc_to_int(float64, float_status *status);
float64 float64_add(float64, float64, float_status *status);
float64 float64_sub(float64, float64, float_status *status);
float64 float64_mul(float64, float64, float_status *status);