aboutsummaryrefslogtreecommitdiff
path: root/fpu
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2011-04-14 00:49:29 +0200
committerAurelien Jarno <aurelien@aurel32.net>2011-04-17 20:32:14 +0200
commitb3b4c7f33fc8e51db75bf4abaf4a631c2f1fb23b (patch)
treeb2ae2e51d576be0a351cc65cb84848e3093f14e6 /fpu
parenta0102082de4026833afbd2525e8a6320d1f92885 (diff)
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.h29
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
}
/*----------------------------------------------------------------------------