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
14static 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
28static 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
49static 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
102typedef struct { uint16_t x; } __attribute__((packed)) __ua_uint16_t;
103typedef struct { uint32_t x; } __attribute__((packed)) __ua_uint32_t;
104typedef struct { uint64_t x; } __attribute__((packed)) __ua_uint64_t;
105
106/* These are guaranteed to support unaligned accesses */
107static 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
113static 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
119static 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
125static 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
131static 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
137static 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
143static 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
149static 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
155static 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
161static 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
167static 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
173static 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