Browse Source

[libc] Add flsll()

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
d36e814b8a

+ 50
- 0
src/arch/i386/include/bits/strings.h View File

1
+#ifndef _BITS_STRINGS_H
2
+#define _BITS_STRINGS_H
3
+
4
+FILE_LICENCE ( GPL2_OR_LATER );
5
+
6
+/**
7
+ * Find last (i.e. most significant) set bit
8
+ *
9
+ * @v value		Value
10
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
11
+ */
12
+static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
13
+	long msb_minus_one;
14
+
15
+	/* If the input value is zero, the BSR instruction returns
16
+	 * ZF=1 and leaves an undefined value in the output register.
17
+	 * Perform this check in C rather than asm so that it can be
18
+	 * omitted in cases where the compiler is able to prove that
19
+	 * the input is non-zero.
20
+	 */
21
+	if ( value ) {
22
+		__asm__ ( "bsrl %1, %0"
23
+			  : "=r" ( msb_minus_one )
24
+			  : "rm" ( value ) );
25
+		return ( msb_minus_one + 1 );
26
+	} else {
27
+		return 0;
28
+	}
29
+}
30
+
31
+/**
32
+ * Find last (i.e. most significant) set bit
33
+ *
34
+ * @v value		Value
35
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
36
+ */
37
+static inline __attribute__ (( always_inline )) int __flsll ( long long value ){
38
+	unsigned long high = ( value >> 32 );
39
+	unsigned long low = ( value >> 0 );
40
+
41
+	if ( high ) {
42
+		return ( 32 + __flsl ( high ) );
43
+	} else if ( low ) {
44
+		return ( __flsl ( low ) );
45
+	} else {
46
+		return 0;
47
+	}
48
+}
49
+
50
+#endif /* _BITS_STRINGS_H */

src/arch/x86/include/bits/strings.h → src/arch/x86_64/include/bits/strings.h View File

9
  * @v value		Value
9
  * @v value		Value
10
  * @ret msb		Most significant bit set in value (LSB=1), or zero
10
  * @ret msb		Most significant bit set in value (LSB=1), or zero
11
  */
11
  */
12
-static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
13
-	long msb_minus_one;
12
+static inline __attribute__ (( always_inline )) int __flsll ( long long value ){
13
+	long long msb_minus_one;
14
 
14
 
15
 	/* If the input value is zero, the BSR instruction returns
15
 	/* If the input value is zero, the BSR instruction returns
16
 	 * ZF=1 and leaves an undefined value in the output register.
16
 	 * ZF=1 and leaves an undefined value in the output register.
19
 	 * the input is non-zero.
19
 	 * the input is non-zero.
20
 	 */
20
 	 */
21
 	if ( value ) {
21
 	if ( value ) {
22
-		__asm__ ( "bsr %1, %0"
22
+		__asm__ ( "bsrq %1, %0"
23
 			  : "=r" ( msb_minus_one )
23
 			  : "=r" ( msb_minus_one )
24
 			  : "rm" ( value ) );
24
 			  : "rm" ( value ) );
25
 		return ( msb_minus_one + 1 );
25
 		return ( msb_minus_one + 1 );
28
 	}
28
 	}
29
 }
29
 }
30
 
30
 
31
+/**
32
+ * Find last (i.e. most significant) set bit
33
+ *
34
+ * @v value		Value
35
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
36
+ */
37
+static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
38
+
39
+	return __flsll ( value );
40
+}
41
+
31
 #endif /* _BITS_STRINGS_H */
42
 #endif /* _BITS_STRINGS_H */

+ 11
- 4
src/include/strings.h View File

8
 #include <bits/strings.h>
8
 #include <bits/strings.h>
9
 
9
 
10
 static inline __attribute__ (( always_inline )) int
10
 static inline __attribute__ (( always_inline )) int
11
-__constant_flsl ( unsigned long x ) {
11
+__constant_flsll ( unsigned long long x ) {
12
 	int r = 0;
12
 	int r = 0;
13
 
13
 
14
-#if ULONG_MAX > 0xffffffff
15
-	if ( x & 0xffffffff00000000UL ) {
14
+	if ( x & 0xffffffff00000000ULL ) {
16
 		x >>= 32;
15
 		x >>= 32;
17
 		r += 32;
16
 		r += 32;
18
 	}
17
 	}
19
-#endif
20
 	if ( x & 0xffff0000UL ) {
18
 	if ( x & 0xffff0000UL ) {
21
 		x >>= 16;
19
 		x >>= 16;
22
 		r += 16;
20
 		r += 16;
43
 	return r;
41
 	return r;
44
 }
42
 }
45
 
43
 
44
+static inline __attribute__ (( always_inline )) int
45
+__constant_flsl ( unsigned long x ) {
46
+	return __constant_flsll ( x );
47
+}
48
+
49
+int __flsll ( long long x );
46
 int __flsl ( long x );
50
 int __flsl ( long x );
47
 
51
 
52
+#define flsll( x ) \
53
+	( __builtin_constant_p ( x ) ? __constant_flsll ( x ) : __flsll ( x ) )
54
+
48
 #define flsl( x ) \
55
 #define flsl( x ) \
49
 	( __builtin_constant_p ( x ) ? __constant_flsl ( x ) : __flsl ( x ) )
56
 	( __builtin_constant_p ( x ) ? __constant_flsl ( x ) : __flsl ( x ) )
50
 
57
 

+ 37
- 0
src/tests/math_test.c View File

44
 	return flsl ( value );
44
 	return flsl ( value );
45
 }
45
 }
46
 
46
 
47
+/**
48
+ * Force a call to the non-constant implementation of flsll()
49
+ *
50
+ * @v value		Value
51
+ * @ret msb		Most significant bit set in value (LSB=1), or zero
52
+ */
53
+__attribute__ (( noinline )) int flsll_var ( long long value ) {
54
+	return flsll ( value );
55
+}
56
+
47
 /**
57
 /**
48
  * Check current stack pointer
58
  * Check current stack pointer
49
  *
59
  *
181
 }
191
 }
182
 #define flsl_ok( value, msb ) flsl_okx ( value, msb, __FILE__, __LINE__ )
192
 #define flsl_ok( value, msb ) flsl_okx ( value, msb, __FILE__, __LINE__ )
183
 
193
 
194
+/**
195
+ * Report a flsll() test result
196
+ *
197
+ * @v value		Value
198
+ * @v msb		Expected MSB
199
+ * @v file		Test code file
200
+ * @v line		Test code line
201
+ */
202
+static inline __attribute__ (( always_inline )) void
203
+flsll_okx ( long long value, int msb, const char *file, unsigned int line ) {
204
+
205
+	/* Verify as a constant (requires to be inlined) */
206
+	okx ( flsll ( value ) == msb, file, line );
207
+
208
+	/* Verify as a non-constant */
209
+	okx ( flsll_var ( value ) == msb, file, line );
210
+}
211
+#define flsll_ok( value, msb ) flsll_okx ( value, msb, __FILE__, __LINE__ )
212
+
184
 /**
213
 /**
185
  * Report a 64-bit unsigned integer division test result
214
  * Report a 64-bit unsigned integer division test result
186
  *
215
  *
251
 	flsl_ok ( -1U, ( 8 * sizeof ( int ) ) );
280
 	flsl_ok ( -1U, ( 8 * sizeof ( int ) ) );
252
 	flsl_ok ( -1UL, ( 8 * sizeof ( long ) ) );
281
 	flsl_ok ( -1UL, ( 8 * sizeof ( long ) ) );
253
 
282
 
283
+	/* Test flsll() */
284
+	flsll_ok ( 0, 0 );
285
+	flsll_ok ( 1, 1 );
286
+	flsll_ok ( 0x6d63623330ULL, 39 );
287
+	flsll_ok ( -1U, ( 8 * sizeof ( int ) ) );
288
+	flsll_ok ( -1UL, ( 8 * sizeof ( long ) ) );
289
+	flsll_ok ( -1ULL, ( 8 * sizeof ( long long ) ) );
290
+
254
 	/* Test 64-bit arithmetic
291
 	/* Test 64-bit arithmetic
255
 	 *
292
 	 *
256
 	 * On a 64-bit machine, these tests are fairly meaningless.
293
 	 * On a 64-bit machine, these tests are fairly meaningless.

Loading…
Cancel
Save