1 #ifndef _BYTESWAP_H 2 #define _BYTESWAP_H 3 4 #include <stdint.h> 5 #include <klibc/endian.h> 6 #include <klibc/compiler.h> 7 8 /* This assumes an i386 platform */ 9 10 #define __bswap_16_macro(v) ((uint16_t) \ 11 (((uint16_t)(v) << 8) | \ 12 ((uint16_t)(v) >> 8))) 13 14 static inline __constfunc uint16_t __bswap_16(uint16_t v) 15 { 16 return __bswap_16_macro(v); 17 } 18 19 #define bswap_16(x) (__builtin_constant_p(x) ? \ 20 __bswap_16_macro(x) : __bswap_16(x)) 21 22 #define __bswap_32_macro(v) ((uint32_t) \ 23 ((((uint32_t)(v) & 0x000000ff) << 24) | \ 24 (((uint32_t)(v) & 0x0000ff00) << 8) | \ 25 (((uint32_t)(v) & 0x00ff0000) >> 8) | \ 26 (((uint32_t)(v) & 0xff000000) >> 24))) 27 28 static inline __constfunc uint32_t __bswap_32(uint32_t v) 29 { 30 #if defined(__x86_64__) 31 asm("bswap %0" : "+r" (v)); 32 #elif defined(__i386__) 33 asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0" 34 : "+q" (v)); 35 #else 36 v = __bswap_32_macro(v); 37 #endif 38 return v; 39 } 40 41 #define bswap_32(x) (__builtin_constant_p(x) ? \ 42 __bswap_32_macro(x) : __bswap_32(x)) 43 44 45 #define __bswap_64_macro(v) ((uint64_t) \ 46 (((uint64_t)__bswap_32_macro((uint32_t)(v)) << 32) | \ 47 (__bswap_32_macro((uint32_t)((uint64_t)(v) >> 32))))) 48 49 static inline __constfunc uint64_t __bswap_64(uint64_t v) 50 { 51 #if defined(__x86_64__) 52 asm("bswap %0" : "+r" (v)); 53 #else 54 v = ((uint64_t)__bswap_32(v) << 32) | __bswap_32(v >> 32); 55 #endif 56 return v; 57 } 58 59 #define bswap_64(x) (__builtin_constant_p(x) ? \ 60 __bswap_64_macro(x) : __bswap_64(x)) 61 62 /* This is generic */ 63 64 #if __BYTE_ORDER == __LITTLE_ENDIAN 65 66 #define be16_to_cpu(x) bswap_16(x) 67 #define cpu_to_be16(x) bswap_16(x) 68 #define be32_to_cpu(x) bswap_32(x) 69 #define cpu_to_be32(x) bswap_32(x) 70 #define be64_to_cpu(x) bswap_64(x) 71 #define cpu_to_be64(x) bswap_64(x) 72 73 #define le16_to_cpu(x) (x) 74 #define cpu_to_le16(x) (x) 75 #define le32_to_cpu(x) (x) 76 #define cpu_to_le32(x) (x) 77 #define le64_to_cpu(x) (x) 78 #define cpu_to_le64(x) (x) 79 80 #elif __BYTE_ORDER == __BIG_ENDIAN 81 82 #define le16_to_cpu(x) bswap_16(x) 83 #define cpu_to_le16(x) bswap_16(x) 84 #define le32_to_cpu(x) bswap_32(x) 85 #define cpu_to_le32(x) bswap_32(x) 86 #define le64_to_cpu(x) bswap_64(x) 87 #define cpu_to_le64(x) bswap_64(x) 88 89 #define be16_to_cpu(x) (x) 90 #define cpu_to_be16(x) (x) 91 #define be32_to_cpu(x) (x) 92 #define cpu_to_be32(x) (x) 93 #define be64_to_cpu(x) (x) 94 #define cpu_to_be64(x) (x) 95 96 #else 97 98 #error "Unknown byte order!" 99 100 #endif 101 102 typedef struct { uint16_t x; } __attribute__((packed)) __ua_uint16_t; 103 typedef struct { uint32_t x; } __attribute__((packed)) __ua_uint32_t; 104 typedef struct { uint64_t x; } __attribute__((packed)) __ua_uint64_t; 105 106 /* These are guaranteed to support unaligned accesses */ 107 static inline uint16_t get_le16(const uint16_t *p) 108 { 109 const __ua_uint16_t *up = (const __ua_uint16_t *)p; 110 return le16_to_cpu(up->x); 111 } 112 113 static inline uint32_t get_le32(const uint32_t *p) 114 { 115 const __ua_uint32_t *up = (const __ua_uint32_t *)p; 116 return le32_to_cpu(up->x); 117 } 118 119 static inline uint64_t get_le64(const uint64_t *p) 120 { 121 const __ua_uint64_t *up = (const __ua_uint64_t *)p; 122 return le64_to_cpu(up->x); 123 } 124 125 static inline uint16_t get_be16(const uint16_t *p) 126 { 127 const __ua_uint16_t *up = (const __ua_uint16_t *)p; 128 return be16_to_cpu(up->x); 129 } 130 131 static inline uint32_t get_be32(const uint32_t *p) 132 { 133 const __ua_uint32_t *up = (const __ua_uint32_t *)p; 134 return be32_to_cpu(up->x); 135 } 136 137 static inline uint64_t get_be64(const uint64_t *p) 138 { 139 const __ua_uint64_t *up = (const __ua_uint64_t *)p; 140 return be64_to_cpu(up->x); 141 } 142 143 static inline void put_le16(uint16_t v, uint16_t *p) 144 { 145 __ua_uint16_t *up = (__ua_uint16_t *)p; 146 up->x = cpu_to_le16(v); 147 } 148 149 static inline void put_le32(uint32_t v, uint32_t *p) 150 { 151 __ua_uint32_t *up = (__ua_uint32_t *)p; 152 up->x = cpu_to_le32(v); 153 } 154 155 static inline void put_le64(uint64_t v, uint64_t *p) 156 { 157 __ua_uint64_t *up = (__ua_uint64_t *)p; 158 up->x = cpu_to_le64(v); 159 } 160 161 static inline void put_be16(uint16_t v, uint16_t *p) 162 { 163 __ua_uint16_t *up = (__ua_uint16_t *)p; 164 up->x = cpu_to_be16(v); 165 } 166 167 static inline void put_be32(uint32_t v, uint32_t *p) 168 { 169 __ua_uint32_t *up = (__ua_uint32_t *)p; 170 up->x = cpu_to_be32(v); 171 } 172 173 static inline void put_be64(uint64_t v, uint64_t *p) 174 { 175 __ua_uint64_t *up = (__ua_uint64_t *)p; 176 up->x = cpu_to_be64(v); 177 } 178 179 #endif /* _BYTESWAP_H */ 180 181