1 /*-
2  * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: releng/10.1/sys/sys/endian.h 208331 2010-05-20 06:16:13Z phk $
27  */
28 
29 #ifndef _SYS_ENDIAN_H_
30 #define _SYS_ENDIAN_H_
31 
32 #include <rtthread.h>
33 #include "sunxi_hal_common.h"
34 
35 #ifdef CONFIG_RTTKERNEL
36 
37 #ifndef _LITTLE_ENDIAN
38 #define _LITTLE_ENDIAN 1
39 #endif
40 
41 #define _BYTE_ORDER _LITTLE_ENDIAN
42 
43 #ifndef __bswap32
44 
45 #if ((defined(__GNUC__) && !defined(__CC_ARM)))
46 
47 #define __bswap16(x) ((uint16_t)__builtin_bswap16(x))
48 #define __bswap32(x) ((uint32_t)__builtin_bswap32(x))
49 #define __bswap64(x) ((uint64_t)__builtin_bswap64(x))
50 
51 #else /* ((defined(__GNUC__) && !defined(__CC_ARM))) */
52 
53 #define __bswap16(x) ((uint16_t)(                   \
54     (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) |    \
55     (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
56 
57 #define __bswap32(x) ((uint32_t)(                       \
58     (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) |  \
59     (((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) |  \
60     (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) |  \
61     (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
62 
63 #define __bswap64(x) ((uint64_t)(                               \
64     (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
65     (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
66     (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
67     (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
68     (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
69     (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
70     (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
71     (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
72 
73 #endif /* ((defined(__GNUC__) && !defined(__CC_ARM))) */
74 
75 #else /* __bswap32 */
76 
77 #undef __bswap32
78 #define __bswap32(x) (uint32_t)__builtin_bswap32(x)
79 
80 #endif /* __bswap32 */
81 
82 /*
83  * General byte order swapping functions.
84  */
85 #define bswap16(x)  __bswap16(x)
86 #define bswap32(x)  __bswap32(x)
87 #define bswap64(x)  __bswap64(x)
88 
89 /*
90  * Host to big endian, host to little endian, big endian to host, and little
91  * endian to host byte order functions as detailed in byteorder(9).
92  */
93 #if _BYTE_ORDER == _LITTLE_ENDIAN
94 #define htobe16(x)  bswap16((x))
95 #define htobe32(x)  bswap32((x))
96 #define htobe64(x)  bswap64((x))
97 #define htole16(x)  ((uint16_t)(x))
98 #define htole32(x)  ((uint32_t)(x))
99 #define htole64(x)  ((uint64_t)(x))
100 
101 #define be16toh(x)  bswap16((x))
102 #define be32toh(x)  bswap32((x))
103 #define be64toh(x)  bswap64((x))
104 #define le16toh(x)  ((uint16_t)(x))
105 #define le32toh(x)  ((uint32_t)(x))
106 #define le64toh(x)  ((uint64_t)(x))
107 #elif (_BYTE_ORDER == _BIG_ENDIAN)
108 #define htobe16(x)  ((uint16_t)(x))
109 #define htobe32(x)  ((uint32_t)(x))
110 #define htobe64(x)  ((uint64_t)(x))
111 #define htole16(x)  bswap16((x))
112 #define htole32(x)  bswap32((x))
113 #define htole64(x)  bswap64((x))
114 
115 #define be16toh(x)  ((uint16_t)(x))
116 #define be32toh(x)  ((uint32_t)(x))
117 #define be64toh(x)  ((uint64_t)(x))
118 #define le16toh(x)  bswap16((x))
119 #define le32toh(x)  bswap32((x))
120 #define le64toh(x)  bswap64((x))
121 #else
122 #error "Endian not defined!"
123 #endif /* _BYTE_ORDER == _LITTLE_ENDIAN */
124 #endif
125 
126 #define __cpu_to_le64(x) htole64(x)
127 #define __le64_to_cpu(x) le64toh(x)
128 #define __cpu_to_le32(x) htole32(x)
129 #define __le32_to_cpu(x) le32toh(x)
130 #define __cpu_to_le16(x) htole16(x)
131 #define __le16_to_cpu(x) le16toh(x)
132 #define __cpu_to_be64(x) htobe64(x)
133 #define __be64_to_cpu(x) be64toh(x)
134 #define __cpu_to_be32(x) htobe32(x)
135 #define __be32_to_cpu(x) be32toh(x)
136 #define __cpu_to_be16(x) htobe16(x)
137 #define __be16_to_cpu(x) be16toh(x)
138 
139 #define cpu_to_le64 __cpu_to_le64
140 #define le64_to_cpu __le64_to_cpu
141 #define cpu_to_le32 __cpu_to_le32
142 #define le32_to_cpu __le32_to_cpu
143 #define cpu_to_le16 __cpu_to_le16
144 #define le16_to_cpu __le16_to_cpu
145 #define cpu_to_be64 __cpu_to_be64
146 #define be64_to_cpu __be64_to_cpu
147 #define cpu_to_be32 __cpu_to_be32
148 #define be32_to_cpu __be32_to_cpu
149 #define cpu_to_be16 __cpu_to_be16
150 #define be16_to_cpu __be16_to_cpu
151 
152 
153 /* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
154 
155 static __inline uint16_t
be16dec(const void * pp)156 be16dec(const void *pp)
157 {
158     uint8_t const *p = (uint8_t const *)pp;
159 
160     return ((p[0] << 8) | p[1]);
161 }
162 
163 static __inline uint32_t
be32dec(const void * pp)164 be32dec(const void *pp)
165 {
166     uint8_t const *p = (uint8_t const *)pp;
167 
168     return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
169 }
170 
171 static __inline uint64_t
be64dec(const void * pp)172 be64dec(const void *pp)
173 {
174     uint8_t const *p = (uint8_t const *)pp;
175 
176     return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
177 }
178 
179 static __inline uint16_t
le16dec(const void * pp)180 le16dec(const void *pp)
181 {
182     uint8_t const *p = (uint8_t const *)pp;
183 
184     return ((p[1] << 8) | p[0]);
185 }
186 
187 static __inline uint32_t
le32dec(const void * pp)188 le32dec(const void *pp)
189 {
190     uint8_t const *p = (uint8_t const *)pp;
191 
192     return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
193 }
194 
195 static __inline uint64_t
le64dec(const void * pp)196 le64dec(const void *pp)
197 {
198     uint8_t const *p = (uint8_t const *)pp;
199 
200     return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
201 }
202 
203 static __inline void
be16enc(void * pp,uint16_t u)204 be16enc(void *pp, uint16_t u)
205 {
206     uint8_t *p = (uint8_t *)pp;
207 
208     p[0] = (u >> 8) & 0xff;
209     p[1] = u & 0xff;
210 }
211 
212 static __inline void
be32enc(void * pp,uint32_t u)213 be32enc(void *pp, uint32_t u)
214 {
215     uint8_t *p = (uint8_t *)pp;
216 
217     p[0] = (u >> 24) & 0xff;
218     p[1] = (u >> 16) & 0xff;
219     p[2] = (u >> 8) & 0xff;
220     p[3] = u & 0xff;
221 }
222 
223 static __inline void
be64enc(void * pp,uint64_t u)224 be64enc(void *pp, uint64_t u)
225 {
226     uint8_t *p = (uint8_t *)pp;
227 
228     be32enc(p, (uint32_t)(u >> 32));
229     be32enc(p + 4, (uint32_t)(u & 0xffffffffU));
230 }
231 
232 static __inline void
le16enc(void * pp,uint16_t u)233 le16enc(void *pp, uint16_t u)
234 {
235     uint8_t *p = (uint8_t *)pp;
236 
237     p[0] = u & 0xff;
238     p[1] = (u >> 8) & 0xff;
239 }
240 
241 static __inline void
le32enc(void * pp,uint32_t u)242 le32enc(void *pp, uint32_t u)
243 {
244     uint8_t *p = (uint8_t *)pp;
245 
246     p[0] = u & 0xff;
247     p[1] = (u >> 8) & 0xff;
248     p[2] = (u >> 16) & 0xff;
249     p[3] = (u >> 24) & 0xff;
250 }
251 
252 static __inline void
le64enc(void * pp,uint64_t u)253 le64enc(void *pp, uint64_t u)
254 {
255     uint8_t *p = (uint8_t *)pp;
256 
257     le32enc(p, (uint32_t)(u & 0xffffffffU));
258     le32enc(p + 4, (uint32_t)(u >> 32));
259 }
260 
261 #endif  /* _SYS_ENDIAN_H_ */
262