]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[libc] Add inline assembly implementation of flsl() using BSR instruction
authorMichael Brown <mcb30@ipxe.org>
Thu, 24 Apr 2014 13:49:08 +0000 (14:49 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 24 Apr 2014 13:49:08 +0000 (14:49 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/include/bits/strings.h [new file with mode: 0644]
src/core/bitops.c [deleted file]
src/include/strings.h

diff --git a/src/arch/x86/include/bits/strings.h b/src/arch/x86/include/bits/strings.h
new file mode 100644 (file)
index 0000000..62e0fbf
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _BITS_STRINGS_H
+#define _BITS_STRINGS_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Find last (i.e. most significant) set bit
+ *
+ * @v value            Value
+ * @ret msb            Most significant bit set in value (LSB=1), or zero
+ */
+static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
+       long msb_minus_one;
+
+       /* If the input value is zero, the BSR instruction returns
+        * ZF=1 and leaves an undefined value in the output register.
+        * Perform this check in C rather than asm so that it can be
+        * omitted in cases where the compiler is able to prove that
+        * the input is non-zero.
+        */
+       if ( value ) {
+               __asm__ ( "bsr %1, %0"
+                         : "=r" ( msb_minus_one )
+                         : "rm" ( value ) );
+               return ( msb_minus_one + 1 );
+       } else {
+               return 0;
+       }
+}
+
+#endif /* _BITS_STRINGS_H */
diff --git a/src/core/bitops.c b/src/core/bitops.c
deleted file mode 100644 (file)
index 1bca9e4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <strings.h>
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-int __flsl ( long x ) {
-       unsigned long value = x;
-       int ls = 0;
-
-       for ( ls = 0 ; value ; ls++ ) {
-               value >>= 1;
-       }
-       return ls;
-}
index c7063d68292e59dbb41613f1a95630e8dd797516..924a084fc398174dbb5d43d5df1bc706a67a00d8 100644 (file)
@@ -5,6 +5,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #include <limits.h>
 #include <string.h>
+#include <bits/strings.h>
 
 static inline __attribute__ (( always_inline )) int
 __constant_flsl ( unsigned long x ) {
@@ -42,8 +43,7 @@ __constant_flsl ( unsigned long x ) {
        return r;
 }
 
-/* We don't actually have these functions yet */
-extern int __flsl ( long x );
+int __flsl ( long x );
 
 #define flsl( x ) \
        ( __builtin_constant_p ( x ) ? __constant_flsl ( x ) : __flsl ( x ) )