summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2014-08-24 19:46:43 -0400
committerMichael Sevakis <jethead71@rockbox.org>2014-08-25 12:16:56 -0400
commit6ffb8ffeeed9aca75c278906785a957d72b3ef57 (patch)
treeabeeb7df67dfaba1d5bfef6d6a29507b16192455
parentd3cf366868500403bbe072bddf44eaf8c7f749d4 (diff)
downloadrockbox-6ffb8ffeeed9aca75c278906785a957d72b3ef57.tar.gz
rockbox-6ffb8ffeeed9aca75c278906785a957d72b3ef57.zip
Do a better endian.h setup that isn't as fragile
We redefine the top-level macros to our own in order to maintain compatibility with compound initializers by wrapping the mid or low level definitions from the OS header. This allows, hopefully optimized, macros from the host OS's headers to be used when building any hosted target obviating the need for NEED_GENERIC_BYTESWAPS unless the target simply doesn't define its own optimized versions (MIPS!). Throw in some 64-bit swaps for completeness' sake; they generate no code if not yet used anyway. Change-Id: I21b384b55fea46833d01ea3cad1ad8952ea01a11
-rw-r--r--firmware/export/system.h120
-rw-r--r--firmware/include/rbendian.h168
-rw-r--r--firmware/libc/include/endian.h59
3 files changed, 228 insertions, 119 deletions
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 5064fcd91d..4442eb96d7 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -133,24 +133,6 @@ int get_cpu_boost_counter(void);
133#define PTR_ADD(ptr, x) ((typeof(ptr))((char*)(ptr) + (x))) 133#define PTR_ADD(ptr, x) ((typeof(ptr))((char*)(ptr) + (x)))
134#define PTR_SUB(ptr, x) ((typeof(ptr))((char*)(ptr) - (x))) 134#define PTR_SUB(ptr, x) ((typeof(ptr))((char*)(ptr) - (x)))
135 135
136/* newer? SDL includes endian.h, So we ignore it */
137#if (CONFIG_PLATFORM & PLATFORM_HOSTED) || defined(__PCTOOL__)
138#undef letoh16
139#undef letoh32
140#undef htole16
141#undef htole32
142#undef betoh16
143#undef betoh32
144#undef htobe16
145#undef htobe32
146#endif
147
148/* Android NDK contains swap16 and swap32, ignore them */
149#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
150#undef swap16
151#undef swap32
152#endif
153
154/* Get the byte offset of a type's member */ 136/* Get the byte offset of a type's member */
155#ifndef offsetof 137#ifndef offsetof
156#define offsetof(type, member) __builtin_offsetof(type, member) 138#define offsetof(type, member) __builtin_offsetof(type, member)
@@ -206,111 +188,11 @@ enum {
206#include "system-target.h" 188#include "system-target.h"
207#elif defined(HAVE_SDL) /* SDL build */ 189#elif defined(HAVE_SDL) /* SDL build */
208#include "system-sdl.h" 190#include "system-sdl.h"
209#define NEED_GENERIC_BYTESWAPS
210#elif defined(__PCTOOL__) 191#elif defined(__PCTOOL__)
211#include "system-sdl.h" 192#include "system-sdl.h"
212#define NEED_GENERIC_BYTESWAPS
213#endif 193#endif
214#include "bitswap.h" 194#include "bitswap.h"
215 195#include "rbendian.h"
216#ifdef NEED_GENERIC_BYTESWAPS
217static inline uint16_t swap16_hw(uint16_t value)
218 /*
219 result[15..8] = value[ 7..0];
220 result[ 7..0] = value[15..8];
221 */
222{
223 return (value >> 8) | (value << 8);
224}
225
226static inline uint32_t swap32_hw(uint32_t value)
227 /*
228 result[31..24] = value[ 7.. 0];
229 result[23..16] = value[15.. 8];
230 result[15.. 8] = value[23..16];
231 result[ 7.. 0] = value[31..24];
232 */
233{
234 uint32_t hi = swap16_hw(value >> 16);
235 uint32_t lo = swap16_hw(value & 0xffff);
236 return (lo << 16) | hi;
237}
238
239static inline uint32_t swap_odd_even32_hw(uint32_t value)
240{
241 /*
242 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
243 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
244 */
245 uint32_t t = value & 0xff00ff00;
246 return (t >> 8) | ((t ^ value) << 8);
247}
248
249static inline uint32_t swaw32_hw(uint32_t value)
250{
251 /*
252 result[31..16] = value[15.. 0];
253 result[15.. 0] = value[31..16];
254 */
255 return (value >> 16) | (value << 16);
256}
257
258#endif /* NEED_GENERIC_BYTESWAPS */
259
260/* static endianness conversion */
261#define SWAP16_CONST(x) \
262 ((typeof(x))( ((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8) ))
263
264#define SWAP32_CONST(x) \
265 ((typeof(x))( ((uint32_t)(x) >> 24) | \
266 (((uint32_t)(x) & 0xff0000) >> 8) | \
267 (((uint32_t)(x) & 0xff00) << 8) | \
268 ((uint32_t)(x) << 24) ))
269
270#define SWAP_ODD_EVEN32_CONST(x) \
271 ((typeof(x))( ((uint32_t)SWAP16_CONST((uint32_t)(x) >> 16) << 16) | \
272 SWAP16_CONST((uint32_t)(x))) )
273
274#define SWAW32_CONST(x) \
275 ((typeof(x))( ((uint32_t)(x) << 16) | ((uint32_t)(x) >> 16) ))
276
277/* Select best method based upon whether x is a constant expression */
278#define swap16(x) \
279 ( __builtin_constant_p(x) ? SWAP16_CONST(x) : (typeof(x))swap16_hw(x) )
280
281#define swap32(x) \
282 ( __builtin_constant_p(x) ? SWAP32_CONST(x) : (typeof(x))swap32_hw(x) )
283
284#define swap_odd_even32(x) \
285 ( __builtin_constant_p(x) ? SWAP_ODD_EVEN32_CONST(x) : (typeof(x))swap_odd_even32_hw(x) )
286
287#define swaw32(x) \
288 ( __builtin_constant_p(x) ? SWAW32_CONST(x) : (typeof(x))swaw32_hw(x) )
289
290
291#ifdef ROCKBOX_LITTLE_ENDIAN
292#define letoh16(x) (x)
293#define letoh32(x) (x)
294#define htole16(x) (x)
295#define htole32(x) (x)
296#define betoh16(x) swap16(x)
297#define betoh32(x) swap32(x)
298#define htobe16(x) swap16(x)
299#define htobe32(x) swap32(x)
300#define swap_odd_even_be32(x) (x)
301#define swap_odd_even_le32(x) swap_odd_even32(x)
302#else
303#define letoh16(x) swap16(x)
304#define letoh32(x) swap32(x)
305#define htole16(x) swap16(x)
306#define htole32(x) swap32(x)
307#define betoh16(x) (x)
308#define betoh32(x) (x)
309#define htobe16(x) (x)
310#define htobe32(x) (x)
311#define swap_odd_even_be32(x) swap_odd_even32(x)
312#define swap_odd_even_le32(x) (x)
313#endif
314 196
315#ifndef BIT_N 197#ifndef BIT_N
316#define BIT_N(n) (1U << (n)) 198#define BIT_N(n) (1U << (n))
diff --git a/firmware/include/rbendian.h b/firmware/include/rbendian.h
new file mode 100644
index 0000000000..21d3cae68d
--- /dev/null
+++ b/firmware/include/rbendian.h
@@ -0,0 +1,168 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _RBENDIAN_H_
22#define _RBENDIAN_H_
23
24#include "config.h"
25#include <endian.h>
26
27/* clear these out since we redefine them to be truely constant compatible */
28#undef swap16
29#undef swap32
30#undef swap64
31
32#undef letoh16
33#undef letoh32
34#undef letoh64
35#undef htole16
36#undef htole32
37#undef htole64
38#undef betoh16
39#undef betoh32
40#undef betoh64
41#undef htobe16
42#undef htobe32
43#undef htobe64
44
45#ifndef __ENDIAN_H_NATIVE_RB
46
47#if defined (__bswap_16)
48 #define __swap16_os(x) __bswap_16(x)
49 #define __swap32_os(x) __bswap_32(x)
50 #define __swap64_os(x) __bswap_64(x)
51#elif defined (__swap16)
52 #define __swap16_os(x) __swap16(x)
53 #define __swap32_os(x) __swap32(x)
54 #define __swap64_os(x) __swap64(x)
55#else
56 #error "Missing OS swap defines."
57#endif
58
59/* wrap these because they aren't compatible with compound initializers */
60static FORCE_INLINE uint16_t swap16_hw(uint16_t x)
61 { return __swap16_os(x); }
62static FORCE_INLINE uint32_t swap32_hw(uint32_t x)
63 { return __swap32_os(x); }
64static FORCE_INLINE uint64_t swap64_hw(uint64_t x)
65 { return __swap64_os(x); }
66
67#endif /* __ENDIAN_H_NATIVE_RB */
68
69#if defined(NEED_GENERIC_BYTESWAPS) || !defined(__ENDIAN_H_NATIVE_RB)
70/* these are uniquely ours it seems */
71static inline uint32_t swap_odd_even32_hw(uint32_t value)
72 /*
73 * result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
74 * result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
75 */
76{
77 uint32_t t = value & 0xff00ff00;
78 return (t >> 8) | ((t ^ value) << 8);
79}
80
81static inline uint32_t swaw32_hw(uint32_t value)
82 /*
83 * result[31..16] = value[15.. 0];
84 * result[15.. 0] = value[31..16];
85 */
86{
87 return (value >> 16) | (value << 16);
88}
89#endif /* Generic */
90
91/* static endianness conversion */
92#define SWAP16_CONST(x) \
93 ((typeof(x))( ((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8) ))
94
95#define SWAP32_CONST(x) \
96 ((typeof(x))( (((uint32_t)(x) & 0xff000000) >> 24) | \
97 (((uint32_t)(x) & 0x00ff0000) >> 8) | \
98 (((uint32_t)(x) & 0x0000ff00) << 8) | \
99 (((uint32_t)(x) & 0x000000ff) << 24) ))
100
101#define SWAP64_CONST(x) \
102 ((typeof(x))( (((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \
103 (((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \
104 (((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \
105 (((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \
106 (((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \
107 (((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \
108 (((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \
109 (((uint64_t)(x) & 0x00000000000000ffull) << 56) ))
110
111#define SWAP_ODD_EVEN32_CONST(x) \
112 ((typeof(x))( ((uint32_t)SWAP16_CONST((uint32_t)(x) >> 16) << 16) | \
113 SWAP16_CONST((uint32_t)(x))) )
114
115#define SWAW32_CONST(x) \
116 ((typeof(x))( ((uint32_t)(x) << 16) | ((uint32_t)(x) >> 16) ))
117
118/* select best method based upon whether x is a constant expression */
119#define swap16(x) \
120 ( __builtin_constant_p(x) ? SWAP16_CONST(x) : (typeof(x))swap16_hw(x) )
121
122#define swap32(x) \
123 ( __builtin_constant_p(x) ? SWAP32_CONST(x) : (typeof(x))swap32_hw(x) )
124
125#define swap64(x) \
126 ( __builtin_constant_p(x) ? SWAP64_CONST(x) : (typeof(x))swap64_hw(x) )
127
128#define swap_odd_even32(x) \
129 ( __builtin_constant_p(x) ? SWAP_ODD_EVEN32_CONST(x) : (typeof(x))swap_odd_even32_hw(x) )
130
131#define swaw32(x) \
132 ( __builtin_constant_p(x) ? SWAW32_CONST(x) : (typeof(x))swaw32_hw(x) )
133
134#if defined(ROCKBOX_LITTLE_ENDIAN)
135 #define letoh16(x) (x)
136 #define letoh32(x) (x)
137 #define letoh64(x) (x)
138 #define htole16(x) (x)
139 #define htole32(x) (x)
140 #define htole64(x) (x)
141 #define betoh16(x) swap16(x)
142 #define betoh32(x) swap32(x)
143 #define betoh64(x) swap64(x)
144 #define htobe16(x) swap16(x)
145 #define htobe32(x) swap32(x)
146 #define htobe64(x) swap64(x)
147 #define swap_odd_even_be32(x) (x)
148 #define swap_odd_even_le32(x) swap_odd_even32(x)
149#elif defined(ROCKBOX_BIG_ENDIAN)
150 #define letoh16(x) swap16(x)
151 #define letoh32(x) swap32(x)
152 #define letoh64(x) swap64(x)
153 #define htole16(x) swap16(x)
154 #define htole32(x) swap32(x)
155 #define htole64(x) swap64(x)
156 #define betoh16(x) (x)
157 #define betoh32(x) (x)
158 #define betoh64(x) (x)
159 #define htobe16(x) (x)
160 #define htobe32(x) (x)
161 #define htobe64(x) (x)
162 #define swap_odd_even_be32(x) swap_odd_even32(x)
163 #define swap_odd_even_le32(x) (x)
164#else
165 #error "Unknown endianness!"
166#endif
167
168#endif /* _RBENDIAN_H_ */
diff --git a/firmware/libc/include/endian.h b/firmware/libc/include/endian.h
new file mode 100644
index 0000000000..de1c508da7
--- /dev/null
+++ b/firmware/libc/include/endian.h
@@ -0,0 +1,59 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _ENDIAN_H_
22#define _ENDIAN_H_
23
24#ifndef _RBENDIAN_H_
25/* this only defines what may be substituted in the native endian.h */
26#error "Include rbendian.h instead."
27#endif
28
29#define __ENDIAN_H_NATIVE_RB
30
31#ifdef NEED_GENERIC_BYTESWAPS
32static inline uint16_t swap16_hw(uint16_t value)
33 /*
34 * result[15..8] = value[ 7..0];
35 * result[ 7..0] = value[15..8];
36 */
37{
38 return (value >> 8) | (value << 8);
39}
40
41static inline uint32_t swap32_hw(uint32_t value)
42 /*
43 * result[31..24] = value[ 7.. 0];
44 * result[23..16] = value[15.. 8];
45 * result[15.. 8] = value[23..16];
46 * result[ 7.. 0] = value[31..24];
47 */
48{
49 uint32_t hi = swap16_hw(value >> 16);
50 uint32_t lo = swap16_hw(value & 0xffff);
51 return (lo << 16) | hi;
52}
53#endif /* NEED_GENERIC_BYTESWAPS */
54
55static FORCE_INLINE uint64_t swap64_hw(uint64_t x)
56 { return swap32_hw((uint32_t)(x >> 32)) |
57 ((uint64_t)swap32_hw((uint32_t)x) << 32); }
58
59#endif /* _ENDIAN_H_ */