summaryrefslogtreecommitdiff
path: root/firmware/include/rbendian.h
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 /firmware/include/rbendian.h
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
Diffstat (limited to 'firmware/include/rbendian.h')
-rw-r--r--firmware/include/rbendian.h168
1 files changed, 168 insertions, 0 deletions
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_ */