diff options
author | Michael Brown <mcb30@ipxe.org> | 2014-04-24 14:49:08 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2014-04-24 14:49:08 +0100 |
commit | dce7107fc087092dc95b420504b26261933d5f73 (patch) | |
tree | 19f2d2d874fcaede9cfe98a52d362cd1b21e2822 /src/arch/x86/include | |
parent | 8f0e0e135670f19ee2b2f6e4ab2ab997ebd543a3 (diff) | |
download | ipxe-dce7107fc087092dc95b420504b26261933d5f73.tar.gz |
[libc] Add inline assembly implementation of flsl() using BSR instruction
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/x86/include')
-rw-r--r-- | src/arch/x86/include/bits/strings.h | 31 |
1 files changed, 31 insertions, 0 deletions
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 */ |