mirror of
https://github.com/ipxe/ipxe
synced 2025-12-29 19:38:37 +03:00
[libc] Add ffs(), ffsl(), and ffsll()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -3,6 +3,50 @@
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/**
|
||||
* Find first (i.e. least significant) set bit
|
||||
*
|
||||
* @v value Value
|
||||
* @ret lsb Least significant bit set in value (LSB=1), or zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int __ffsl ( long value ) {
|
||||
long lsb_minus_one;
|
||||
|
||||
/* If the input value is zero, the BSF instruction returns
|
||||
* ZF=0 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__ ( "bsfl %1, %0"
|
||||
: "=r" ( lsb_minus_one )
|
||||
: "rm" ( value ) );
|
||||
return ( lsb_minus_one + 1 );
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find first (i.e. least significant) set bit
|
||||
*
|
||||
* @v value Value
|
||||
* @ret lsb Least significant bit set in value (LSB=1), or zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int __ffsll ( long long value ){
|
||||
unsigned long high = ( value >> 32 );
|
||||
unsigned long low = ( value >> 0 );
|
||||
|
||||
if ( low ) {
|
||||
return ( __ffsl ( low ) );
|
||||
} else if ( high ) {
|
||||
return ( 32 + __ffsl ( high ) );
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find last (i.e. most significant) set bit
|
||||
*
|
||||
@@ -13,7 +57,7 @@ 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.
|
||||
* ZF=0 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.
|
||||
|
||||
Reference in New Issue
Block a user