Browse Source

[i386] Optimise byte-swapping functions and provide __bswap_{16,32,64}s()

Use the "bswap" instruction to shrink the size of byte-swapping code,
and provide the in-place variants __bswap_{16,32,64}s.

"bswap" is available only on 486 and later processors.  (We already
assume the presence of "cpuid" and "rdtsc", which are available only
on Pentium and later processors.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
af96c4151c
1 changed files with 56 additions and 32 deletions
  1. 56
    32
      src/arch/i386/include/bits/byteswap.h

+ 56
- 32
src/arch/i386/include/bits/byteswap.h View File

@@ -1,43 +1,67 @@
1
-#ifndef ETHERBOOT_BITS_BYTESWAP_H
2
-#define ETHERBOOT_BITS_BYTESWAP_H
1
+#ifndef _BITS_BYTESWAP_H
2
+#define _BITS_BYTESWAP_H
3
+
4
+/** @file
5
+ *
6
+ * Byte-order swapping functions
7
+ *
8
+ */
9
+
10
+#include <stdint.h>
3 11
 
4 12
 FILE_LICENCE ( GPL2_OR_LATER );
5 13
 
6
-static inline __attribute__ ((always_inline, const)) uint16_t
7
-__bswap_variable_16(uint16_t x)
8
-{
9
-	__asm__("xchgb %b0,%h0\n\t"
10
-		: "=q" (x)
11
-		: "0" (x));
14
+static inline __attribute__ (( always_inline, const )) uint16_t
15
+__bswap_variable_16 ( uint16_t x ) {
16
+	__asm__ ( "xchgb %b0,%h0" : "=q" ( x ) : "0" ( x ) );
12 17
 	return x;
13 18
 }
14 19
 
15
-static inline __attribute__ ((always_inline, const)) uint32_t
16
-__bswap_variable_32(uint32_t x)
17
-{
18
-	__asm__("xchgb %b0,%h0\n\t"
19
-		"rorl $16,%0\n\t"
20
-		"xchgb %b0,%h0"
21
-		: "=q" (x)
22
-		: "0" (x));
20
+static inline __attribute__ (( always_inline )) void
21
+__bswap_16s ( uint16_t *x ) {
22
+	__asm__ ( "rorw $8, %0" : "=g" ( *x ) : "0" ( *x ) );
23
+}
24
+
25
+static inline __attribute__ (( always_inline, const )) uint32_t
26
+__bswap_variable_32 ( uint32_t x ) {
27
+	__asm__ ( "bswapl %0" : "=r" ( x ) : "0" ( x ) );
23 28
 	return x;
24 29
 }
25 30
 
26
-static inline __attribute__ ((always_inline, const)) uint64_t
27
-__bswap_variable_64(uint64_t x)
28
-{
29
-	union {
30
-		uint64_t qword;
31
-		uint32_t dword[2]; 
32
-	} u;
33
-
34
-	u.qword = x;
35
-	u.dword[0] = __bswap_variable_32(u.dword[0]);
36
-	u.dword[1] = __bswap_variable_32(u.dword[1]);
37
-	__asm__("xchgl %0,%1"
38
-		: "=r" ( u.dword[0] ), "=r" ( u.dword[1] )
39
-		: "0" ( u.dword[0] ), "1" ( u.dword[1] ) );
40
-	return u.qword;
31
+static inline __attribute__ (( always_inline )) void
32
+__bswap_32s ( uint32_t *x ) {
33
+	__asm__ ( "bswapl %0" : "=r" ( *x ) : "0" ( *x ) );
34
+}
35
+
36
+static inline __attribute__ (( always_inline, const )) uint64_t
37
+__bswap_variable_64 ( uint64_t x ) {
38
+	uint32_t in_high = ( x >> 32 );
39
+	uint32_t in_low = ( x & 0xffffffffUL );
40
+	uint32_t out_high;
41
+	uint32_t out_low;
42
+
43
+	__asm__ ( "bswapl %0\n\t"
44
+		  "bswapl %1\n\t"
45
+		  "xchgl %0,%1\n\t"
46
+		  : "=r" ( out_high ), "=r" ( out_low )
47
+		  : "0" ( in_high ), "1" ( in_low ) );
48
+
49
+	return ( ( ( ( uint64_t ) out_high ) << 32 ) |
50
+		 ( ( uint64_t ) out_low ) );
51
+}
52
+
53
+static inline __attribute__ (( always_inline )) void
54
+__bswap_64s ( uint64_t *x ) {
55
+	uint32_t __attribute__ (( may_alias )) *dwords = ( ( void * ) x );
56
+	uint32_t discard;
57
+
58
+	__asm__ ( "movl %0,%2\n\t"
59
+		  "bswapl %2\n\t"
60
+		  "xchgl %2,%1\n\t"
61
+		  "bswapl %2\n\t"
62
+		  "movl %2,%0\n\t"
63
+		  : "=g" ( dwords[0] ), "=g" ( dwords[1] ), "=r" ( discard )
64
+		  : "0" ( dwords[0] ), "1" ( dwords[1] ) );
41 65
 }
42 66
 
43
-#endif /* ETHERBOOT_BITS_BYTESWAP_H */
67
+#endif /* _BITS_BYTESWAP_H */

Loading…
Cancel
Save