diff --git a/src/arch/x86/include/bits/strings.h b/src/arch/x86/include/bits/strings.h new file mode 100644 index 00000000..62e0fbfb --- /dev/null +++ b/src/arch/x86/include/bits/strings.h @@ -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 index 1bca9e47..00000000 --- a/src/core/bitops.c +++ /dev/null @@ -1,13 +0,0 @@ -#include - -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; -} diff --git a/src/include/strings.h b/src/include/strings.h index c7063d68..924a084f 100644 --- a/src/include/strings.h +++ b/src/include/strings.h @@ -5,6 +5,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include 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 ) )