summaryrefslogtreecommitdiffstats
path: root/src/arch
diff options
context:
space:
mode:
authorMichael Brown2012-03-04 16:06:45 +0100
committerMichael Brown2012-03-04 16:14:47 +0100
commitaf96c4151ce96d04f960a79e5cf317353410bb1e (patch)
treee9e60f0fb1faf73099628a961e7c3223608e55f1 /src/arch
parent[tls] Add missing #include <stdlib.h> (diff)
downloadipxe-af96c4151ce96d04f960a79e5cf317353410bb1e.tar.gz
ipxe-af96c4151ce96d04f960a79e5cf317353410bb1e.tar.xz
ipxe-af96c4151ce96d04f960a79e5cf317353410bb1e.zip
[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>
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/i386/include/bits/byteswap.h88
1 files changed, 56 insertions, 32 deletions
diff --git a/src/arch/i386/include/bits/byteswap.h b/src/arch/i386/include/bits/byteswap.h
index ddbd40edb..381e695fb 100644
--- a/src/arch/i386/include/bits/byteswap.h
+++ b/src/arch/i386/include/bits/byteswap.h
@@ -1,43 +1,67 @@
-#ifndef ETHERBOOT_BITS_BYTESWAP_H
-#define ETHERBOOT_BITS_BYTESWAP_H
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H
+
+/** @file
+ *
+ * Byte-order swapping functions
+ *
+ */
+
+#include <stdint.h>
FILE_LICENCE ( GPL2_OR_LATER );
-static inline __attribute__ ((always_inline, const)) uint16_t
-__bswap_variable_16(uint16_t x)
-{
- __asm__("xchgb %b0,%h0\n\t"
- : "=q" (x)
- : "0" (x));
+static inline __attribute__ (( always_inline, const )) uint16_t
+__bswap_variable_16 ( uint16_t x ) {
+ __asm__ ( "xchgb %b0,%h0" : "=q" ( x ) : "0" ( x ) );
return x;
}
-static inline __attribute__ ((always_inline, const)) uint32_t
-__bswap_variable_32(uint32_t x)
-{
- __asm__("xchgb %b0,%h0\n\t"
- "rorl $16,%0\n\t"
- "xchgb %b0,%h0"
- : "=q" (x)
- : "0" (x));
+static inline __attribute__ (( always_inline )) void
+__bswap_16s ( uint16_t *x ) {
+ __asm__ ( "rorw $8, %0" : "=g" ( *x ) : "0" ( *x ) );
+}
+
+static inline __attribute__ (( always_inline, const )) uint32_t
+__bswap_variable_32 ( uint32_t x ) {
+ __asm__ ( "bswapl %0" : "=r" ( x ) : "0" ( x ) );
return x;
}
-static inline __attribute__ ((always_inline, const)) uint64_t
-__bswap_variable_64(uint64_t x)
-{
- union {
- uint64_t qword;
- uint32_t dword[2];
- } u;
-
- u.qword = x;
- u.dword[0] = __bswap_variable_32(u.dword[0]);
- u.dword[1] = __bswap_variable_32(u.dword[1]);
- __asm__("xchgl %0,%1"
- : "=r" ( u.dword[0] ), "=r" ( u.dword[1] )
- : "0" ( u.dword[0] ), "1" ( u.dword[1] ) );
- return u.qword;
+static inline __attribute__ (( always_inline )) void
+__bswap_32s ( uint32_t *x ) {
+ __asm__ ( "bswapl %0" : "=r" ( *x ) : "0" ( *x ) );
+}
+
+static inline __attribute__ (( always_inline, const )) uint64_t
+__bswap_variable_64 ( uint64_t x ) {
+ uint32_t in_high = ( x >> 32 );
+ uint32_t in_low = ( x & 0xffffffffUL );
+ uint32_t out_high;
+ uint32_t out_low;
+
+ __asm__ ( "bswapl %0\n\t"
+ "bswapl %1\n\t"
+ "xchgl %0,%1\n\t"
+ : "=r" ( out_high ), "=r" ( out_low )
+ : "0" ( in_high ), "1" ( in_low ) );
+
+ return ( ( ( ( uint64_t ) out_high ) << 32 ) |
+ ( ( uint64_t ) out_low ) );
+}
+
+static inline __attribute__ (( always_inline )) void
+__bswap_64s ( uint64_t *x ) {
+ uint32_t __attribute__ (( may_alias )) *dwords = ( ( void * ) x );
+ uint32_t discard;
+
+ __asm__ ( "movl %0,%2\n\t"
+ "bswapl %2\n\t"
+ "xchgl %2,%1\n\t"
+ "bswapl %2\n\t"
+ "movl %2,%0\n\t"
+ : "=g" ( dwords[0] ), "=g" ( dwords[1] ), "=r" ( discard )
+ : "0" ( dwords[0] ), "1" ( dwords[1] ) );
}
-#endif /* ETHERBOOT_BITS_BYTESWAP_H */
+#endif /* _BITS_BYTESWAP_H */