From b3b4c7f33fc8e51db75bf4abaf4a631c2f1fb23b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 14 Apr 2011 00:49:29 +0200 Subject: 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 Signed-off-by: Aurelien Jarno --- fpu/softfloat-macros.h | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'fpu') 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 @@ -35,6 +35,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 @@ -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 } /*---------------------------------------------------------------------------- -- cgit v1.2.1