1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | |
22 | /** |
23 | * \file SDL_endian.h |
24 | * |
25 | * Functions for reading and writing endian-specific values |
26 | */ |
27 | |
28 | #ifndef SDL_endian_h_ |
29 | #define SDL_endian_h_ |
30 | |
31 | #include "SDL_stdinc.h" |
32 | |
33 | #ifdef _MSC_VER |
34 | /* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version, |
35 | so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */ |
36 | |
37 | #ifdef __clang__ |
38 | #ifndef __PRFCHWINTRIN_H |
39 | #define __PRFCHWINTRIN_H |
40 | |
41 | static __inline__ void __attribute__((__always_inline__, __nodebug__)) |
42 | _m_prefetch(void *__P) |
43 | { |
44 | __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */); |
45 | } |
46 | |
47 | #endif /* __PRFCHWINTRIN_H */ |
48 | #endif /* __clang__ */ |
49 | |
50 | #include <intrin.h> |
51 | #endif |
52 | |
53 | /** |
54 | * \name The two types of endianness |
55 | */ |
56 | /* @{ */ |
57 | #define SDL_LIL_ENDIAN 1234 |
58 | #define SDL_BIG_ENDIAN 4321 |
59 | /* @} */ |
60 | |
61 | #ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */ |
62 | #ifdef __linux__ |
63 | #include <endian.h> |
64 | #define SDL_BYTEORDER __BYTE_ORDER |
65 | #elif defined(__OpenBSD__) |
66 | #include <endian.h> |
67 | #define SDL_BYTEORDER BYTE_ORDER |
68 | #elif defined(__FreeBSD__) |
69 | #include <sys/endian.h> |
70 | #define SDL_BYTEORDER BYTE_ORDER |
71 | #else |
72 | #if defined(__hppa__) || \ |
73 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ |
74 | (defined(__MIPS__) && defined(__MIPSEB__)) || \ |
75 | defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ |
76 | defined(__sparc__) |
77 | #define SDL_BYTEORDER SDL_BIG_ENDIAN |
78 | #else |
79 | #define SDL_BYTEORDER SDL_LIL_ENDIAN |
80 | #endif |
81 | #endif /* __linux__ */ |
82 | #endif /* !SDL_BYTEORDER */ |
83 | |
84 | |
85 | #include "begin_code.h" |
86 | /* Set up for C function definitions, even when using C++ */ |
87 | #ifdef __cplusplus |
88 | extern "C" { |
89 | #endif |
90 | |
91 | /** |
92 | * \file SDL_endian.h |
93 | */ |
94 | #if (defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) || \ |
95 | (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) |
96 | #define SDL_Swap16(x) __builtin_bswap16(x) |
97 | #elif defined(__GNUC__) && defined(__i386__) && \ |
98 | !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */) |
99 | SDL_FORCE_INLINE Uint16 |
100 | SDL_Swap16(Uint16 x) |
101 | { |
102 | __asm__("xchgb %b0,%h0" : "=q" (x):"0" (x)); |
103 | return x; |
104 | } |
105 | #elif defined(__GNUC__) && defined(__x86_64__) |
106 | SDL_FORCE_INLINE Uint16 |
107 | SDL_Swap16(Uint16 x) |
108 | { |
109 | __asm__("xchgb %b0,%h0" : "=Q" (x):"0" (x)); |
110 | return x; |
111 | } |
112 | #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) |
113 | SDL_FORCE_INLINE Uint16 |
114 | SDL_Swap16(Uint16 x) |
115 | { |
116 | int result; |
117 | |
118 | __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result):"0" (x >> 8), "r" (x)); |
119 | return (Uint16)result; |
120 | } |
121 | #elif defined(__GNUC__) && defined(__aarch64__) |
122 | SDL_FORCE_INLINE Uint16 |
123 | SDL_Swap16(Uint16 x) |
124 | { |
125 | __asm__("rev16 %w1, %w0" : "=r" (x) : "r" (x)); |
126 | return x; |
127 | } |
128 | #elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) |
129 | SDL_FORCE_INLINE Uint16 |
130 | SDL_Swap16(Uint16 x) |
131 | { |
132 | __asm__("rorw #8,%0" : "=d" (x): "0" (x):"cc" ); |
133 | return x; |
134 | } |
135 | #elif defined(_MSC_VER) |
136 | #pragma intrinsic(_byteswap_ushort) |
137 | #define SDL_Swap16(x) _byteswap_ushort(x) |
138 | #elif defined(__WATCOMC__) && defined(__386__) |
139 | extern _inline Uint16 SDL_Swap16(Uint16); |
140 | #pragma aux SDL_Swap16 = \ |
141 | "xchg al, ah" \ |
142 | parm [ax] \ |
143 | modify [ax]; |
144 | #else |
145 | SDL_FORCE_INLINE Uint16 |
146 | SDL_Swap16(Uint16 x) |
147 | { |
148 | return SDL_static_cast(Uint16, ((x << 8) | (x >> 8))); |
149 | } |
150 | #endif |
151 | |
152 | #if (defined(__clang__) && (__clang_major__ > 2 || (__clang_major__ == 2 && __clang_minor__ >= 6))) || \ |
153 | (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) |
154 | #define SDL_Swap32(x) __builtin_bswap32(x) |
155 | #elif defined(__GNUC__) && defined(__i386__) && \ |
156 | !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */) |
157 | SDL_FORCE_INLINE Uint32 |
158 | SDL_Swap32(Uint32 x) |
159 | { |
160 | __asm__("bswap %0" : "=r" (x):"0" (x)); |
161 | return x; |
162 | } |
163 | #elif defined(__GNUC__) && defined(__x86_64__) |
164 | SDL_FORCE_INLINE Uint32 |
165 | SDL_Swap32(Uint32 x) |
166 | { |
167 | __asm__("bswapl %0" : "=r" (x):"0" (x)); |
168 | return x; |
169 | } |
170 | #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) |
171 | SDL_FORCE_INLINE Uint32 |
172 | SDL_Swap32(Uint32 x) |
173 | { |
174 | Uint32 result; |
175 | |
176 | __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result): "0" (x>>24), "r" (x)); |
177 | __asm__("rlwimi %0,%2,8,8,15" : "=&r" (result): "0" (result), "r" (x)); |
178 | __asm__("rlwimi %0,%2,24,0,7" : "=&r" (result): "0" (result), "r" (x)); |
179 | return result; |
180 | } |
181 | #elif defined(__GNUC__) && defined(__aarch64__) |
182 | SDL_FORCE_INLINE Uint32 |
183 | SDL_Swap32(Uint32 x) |
184 | { |
185 | __asm__("rev %w1, %w0" : "=r" (x):"r" (x)); |
186 | return x; |
187 | } |
188 | #elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) |
189 | SDL_FORCE_INLINE Uint32 |
190 | SDL_Swap32(Uint32 x) |
191 | { |
192 | __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0" : "=d" (x): "0" (x):"cc" ); |
193 | return x; |
194 | } |
195 | #elif defined(__WATCOMC__) && defined(__386__) |
196 | extern _inline Uint32 SDL_Swap32(Uint32); |
197 | #pragma aux SDL_Swap32 = \ |
198 | "bswap eax" \ |
199 | parm [eax] \ |
200 | modify [eax]; |
201 | #elif defined(_MSC_VER) |
202 | #pragma intrinsic(_byteswap_ulong) |
203 | #define SDL_Swap32(x) _byteswap_ulong(x) |
204 | #else |
205 | SDL_FORCE_INLINE Uint32 |
206 | SDL_Swap32(Uint32 x) |
207 | { |
208 | return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) | |
209 | ((x >> 8) & 0x0000FF00) | (x >> 24))); |
210 | } |
211 | #endif |
212 | |
213 | #if (defined(__clang__) && (__clang_major__ > 2 || (__clang_major__ == 2 && __clang_minor__ >= 6))) || \ |
214 | (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) |
215 | #define SDL_Swap64(x) __builtin_bswap64(x) |
216 | #elif defined(__GNUC__) && defined(__i386__) && \ |
217 | !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */) |
218 | SDL_FORCE_INLINE Uint64 |
219 | SDL_Swap64(Uint64 x) |
220 | { |
221 | union { |
222 | struct { |
223 | Uint32 a, b; |
224 | } s; |
225 | Uint64 u; |
226 | } v; |
227 | v.u = x; |
228 | __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1" |
229 | : "=r" (v.s.a), "=r" (v.s.b) |
230 | : "0" (v.s.a), "1" (v.s.b)); |
231 | return v.u; |
232 | } |
233 | #elif defined(__GNUC__) && defined(__x86_64__) |
234 | SDL_FORCE_INLINE Uint64 |
235 | SDL_Swap64(Uint64 x) |
236 | { |
237 | __asm__("bswapq %0" : "=r" (x):"0" (x)); |
238 | return x; |
239 | } |
240 | #elif defined(__WATCOMC__) && defined(__386__) |
241 | extern _inline Uint64 SDL_Swap64(Uint64); |
242 | #pragma aux SDL_Swap64 = \ |
243 | "bswap eax" \ |
244 | "bswap edx" \ |
245 | "xchg eax,edx" \ |
246 | parm [eax edx] \ |
247 | modify [eax edx]; |
248 | #elif defined(_MSC_VER) |
249 | #pragma intrinsic(_byteswap_uint64) |
250 | #define SDL_Swap64(x) _byteswap_uint64(x) |
251 | #else |
252 | SDL_FORCE_INLINE Uint64 |
253 | SDL_Swap64(Uint64 x) |
254 | { |
255 | Uint32 hi, lo; |
256 | |
257 | /* Separate into high and low 32-bit values and swap them */ |
258 | lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
259 | x >>= 32; |
260 | hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
261 | x = SDL_Swap32(lo); |
262 | x <<= 32; |
263 | x |= SDL_Swap32(hi); |
264 | return (x); |
265 | } |
266 | #endif |
267 | |
268 | |
269 | SDL_FORCE_INLINE float |
270 | SDL_SwapFloat(float x) |
271 | { |
272 | union { |
273 | float f; |
274 | Uint32 ui32; |
275 | } swapper; |
276 | swapper.f = x; |
277 | swapper.ui32 = SDL_Swap32(swapper.ui32); |
278 | return swapper.f; |
279 | } |
280 | |
281 | |
282 | /** |
283 | * \name Swap to native |
284 | * Byteswap item from the specified endianness to the native endianness. |
285 | */ |
286 | /* @{ */ |
287 | #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
288 | #define SDL_SwapLE16(X) (X) |
289 | #define SDL_SwapLE32(X) (X) |
290 | #define SDL_SwapLE64(X) (X) |
291 | #define SDL_SwapFloatLE(X) (X) |
292 | #define SDL_SwapBE16(X) SDL_Swap16(X) |
293 | #define SDL_SwapBE32(X) SDL_Swap32(X) |
294 | #define SDL_SwapBE64(X) SDL_Swap64(X) |
295 | #define SDL_SwapFloatBE(X) SDL_SwapFloat(X) |
296 | #else |
297 | #define SDL_SwapLE16(X) SDL_Swap16(X) |
298 | #define SDL_SwapLE32(X) SDL_Swap32(X) |
299 | #define SDL_SwapLE64(X) SDL_Swap64(X) |
300 | #define SDL_SwapFloatLE(X) SDL_SwapFloat(X) |
301 | #define SDL_SwapBE16(X) (X) |
302 | #define SDL_SwapBE32(X) (X) |
303 | #define SDL_SwapBE64(X) (X) |
304 | #define SDL_SwapFloatBE(X) (X) |
305 | #endif |
306 | /* @} *//* Swap to native */ |
307 | |
308 | /* Ends C function definitions when using C++ */ |
309 | #ifdef __cplusplus |
310 | } |
311 | #endif |
312 | #include "close_code.h" |
313 | |
314 | #endif /* SDL_endian_h_ */ |
315 | |
316 | /* vi: set ts=4 sw=4 expandtab: */ |
317 | |