Преглед на файлове

[libc] Add flsll()

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown преди 10 години
родител
ревизия
d36e814b8a
променени са 4 файла, в които са добавени 112 реда и са изтрити 7 реда
  1. 50
    0
      src/arch/i386/include/bits/strings.h
  2. 14
    3
      src/arch/x86_64/include/bits/strings.h
  3. 11
    4
      src/include/strings.h
  4. 37
    0
      src/tests/math_test.c

+ 50
- 0
src/arch/i386/include/bits/strings.h Целия файл

@@ -0,0 +1,50 @@
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 Целия файл

@@ -9,8 +9,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
9 9
  * @v value		Value
10 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 15
 	/* If the input value is zero, the BSR instruction returns
16 16
 	 * ZF=1 and leaves an undefined value in the output register.
@@ -19,7 +19,7 @@ static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
19 19
 	 * the input is non-zero.
20 20
 	 */
21 21
 	if ( value ) {
22
-		__asm__ ( "bsr %1, %0"
22
+		__asm__ ( "bsrq %1, %0"
23 23
 			  : "=r" ( msb_minus_one )
24 24
 			  : "rm" ( value ) );
25 25
 		return ( msb_minus_one + 1 );
@@ -28,4 +28,15 @@ static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
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 42
 #endif /* _BITS_STRINGS_H */

+ 11
- 4
src/include/strings.h Целия файл

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

+ 37
- 0
src/tests/math_test.c Целия файл

@@ -44,6 +44,16 @@ __attribute__ (( noinline )) int flsl_var ( long value ) {
44 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 58
  * Check current stack pointer
49 59
  *
@@ -181,6 +191,25 @@ flsl_okx ( long value, int msb, const char *file, unsigned int line ) {
181 191
 }
182 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 214
  * Report a 64-bit unsigned integer division test result
186 215
  *
@@ -251,6 +280,14 @@ static void math_test_exec ( void ) {
251 280
 	flsl_ok ( -1U, ( 8 * sizeof ( int ) ) );
252 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 291
 	/* Test 64-bit arithmetic
255 292
 	 *
256 293
 	 * On a 64-bit machine, these tests are fairly meaningless.

Loading…
Отказ
Запис