diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2011-04-14 00:49:29 +0200 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2011-04-17 20:32:14 +0200 |
commit | b3b4c7f33fc8e51db75bf4abaf4a631c2f1fb23b (patch) | |
tree | b2ae2e51d576be0a351cc65cb84848e3093f14e6 /fpu | |
parent | a0102082de4026833afbd2525e8a6320d1f92885 (diff) | |
download | qemu-b3b4c7f33fc8e51db75bf4abaf4a631c2f1fb23b.tar.gz qemu-b3b4c7f33fc8e51db75bf4abaf4a631c2f1fb23b.tar.bz2 qemu-b3b4c7f33fc8e51db75bf4abaf4a631c2f1fb23b.zip |
softfloat: use GCC builtins to count the leading zeros
Softfloat has its own implementation to count the leading zeros. However
a lot of architectures have either a dedicated instruction or an
optimized to do that. When using GCC >= 3.4, this patch uses GCC builtins
instead of the handcoded implementation.
Note that I amware that QEMU_GNUC_PREREQ is defined in osdep.h and that
clz32() and clz64() are defined in host-utils.h, but I think it is better
to keep the softfloat implementation self contained.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'fpu')
-rw-r--r-- | fpu/softfloat-macros.h | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h index 3128e60cbf..e82ce2332d 100644 --- a/fpu/softfloat-macros.h +++ b/fpu/softfloat-macros.h @@ -36,6 +36,17 @@ these four paragraphs for those parts of this code that are retained. =============================================================================*/ /*---------------------------------------------------------------------------- +| 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 | the result by setting the least significant bit to 1. The value of `count' @@ -616,6 +627,13 @@ static uint32_t estimateSqrt32( int16 aExp, uint32_t a ) static int8 countLeadingZeros32( uint32_t a ) { +#if SOFTFLOAT_GNUC_PREREQ(3, 4) + if (a) { + return __builtin_clz(a); + } else { + return 32; + } +#else static const int8 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, @@ -647,7 +665,7 @@ static int8 countLeadingZeros32( uint32_t a ) } shiftCount += countLeadingZerosHigh[ a>>24 ]; return shiftCount; - +#endif } /*---------------------------------------------------------------------------- @@ -657,6 +675,13 @@ static int8 countLeadingZeros32( uint32_t a ) static int8 countLeadingZeros64( uint64_t a ) { +#if SOFTFLOAT_GNUC_PREREQ(3, 4) + if (a) { + return __builtin_clzll(a); + } else { + return 64; + } +#else int8 shiftCount; shiftCount = 0; @@ -668,7 +693,7 @@ static int8 countLeadingZeros64( uint64_t a ) } shiftCount += countLeadingZeros32( a ); return shiftCount; - +#endif } /*---------------------------------------------------------------------------- |