Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | Simple DirectMedia Layer |
||
3 | Copyright (C) 1997-2023 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 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) |
||
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 | #ifdef __clang__ |
||
37 | #ifndef __PRFCHWINTRIN_H |
||
38 | #define __PRFCHWINTRIN_H |
||
39 | static __inline__ void __attribute__((__always_inline__, __nodebug__)) |
||
40 | _m_prefetch(void *__P) |
||
41 | { |
||
42 | __builtin_prefetch(__P, 0, 3 /* _MM_HINT_T0 */); |
||
43 | } |
||
44 | #endif /* __PRFCHWINTRIN_H */ |
||
45 | #endif /* __clang__ */ |
||
46 | |||
47 | #include <intrin.h> |
||
48 | #endif |
||
49 | |||
50 | /** |
||
51 | * \name The two types of endianness |
||
52 | */ |
||
53 | /* @{ */ |
||
54 | #define SDL_LIL_ENDIAN 1234 |
||
55 | #define SDL_BIG_ENDIAN 4321 |
||
56 | /* @} */ |
||
57 | |||
58 | #ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */ |
||
59 | #ifdef __linux__ |
||
60 | #include <endian.h> |
||
61 | #define SDL_BYTEORDER __BYTE_ORDER |
||
62 | #elif defined(__OpenBSD__) || defined(__DragonFly__) |
||
63 | #include <endian.h> |
||
64 | #define SDL_BYTEORDER BYTE_ORDER |
||
65 | #elif defined(__FreeBSD__) || defined(__NetBSD__) |
||
66 | #include <sys/endian.h> |
||
67 | #define SDL_BYTEORDER BYTE_ORDER |
||
68 | /* predefs from newer gcc and clang versions: */ |
||
69 | #elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__) |
||
70 | #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) |
||
71 | #define SDL_BYTEORDER SDL_LIL_ENDIAN |
||
72 | #elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) |
||
73 | #define SDL_BYTEORDER SDL_BIG_ENDIAN |
||
74 | #else |
||
75 | #error Unsupported endianness |
||
76 | #endif /**/ |
||
77 | #else |
||
78 | #if defined(__hppa__) || \ |
||
79 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ |
||
80 | (defined(__MIPS__) && defined(__MIPSEB__)) || \ |
||
81 | defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \ |
||
82 | defined(__sparc__) |
||
83 | #define SDL_BYTEORDER SDL_BIG_ENDIAN |
||
84 | #else |
||
85 | #define SDL_BYTEORDER SDL_LIL_ENDIAN |
||
86 | #endif |
||
87 | #endif /* __linux__ */ |
||
88 | #endif /* !SDL_BYTEORDER */ |
||
89 | |||
90 | #ifndef SDL_FLOATWORDORDER /* Not defined in SDL_config.h? */ |
||
91 | /* predefs from newer gcc versions: */ |
||
92 | #if defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__FLOAT_WORD_ORDER__) |
||
93 | #if (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__) |
||
94 | #define SDL_FLOATWORDORDER SDL_LIL_ENDIAN |
||
95 | #elif (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__) |
||
96 | #define SDL_FLOATWORDORDER SDL_BIG_ENDIAN |
||
97 | #else |
||
98 | #error Unsupported endianness |
||
99 | #endif /**/ |
||
100 | #elif defined(__MAVERICK__) |
||
101 | /* For Maverick, float words are always little-endian. */ |
||
102 | #define SDL_FLOATWORDORDER SDL_LIL_ENDIAN |
||
103 | #elif (defined(__arm__) || defined(__thumb__)) && !defined(__VFP_FP__) && !defined(__ARM_EABI__) |
||
104 | /* For FPA, float words are always big-endian. */ |
||
105 | #define SDL_FLOATWORDORDER SDL_BIG_ENDIAN |
||
106 | #else |
||
107 | /* By default, assume that floats words follow the memory system mode. */ |
||
108 | #define SDL_FLOATWORDORDER SDL_BYTEORDER |
||
109 | #endif /* __FLOAT_WORD_ORDER__ */ |
||
110 | #endif /* !SDL_FLOATWORDORDER */ |
||
111 | |||
112 | |||
113 | #include "begin_code.h" |
||
114 | /* Set up for C function definitions, even when using C++ */ |
||
115 | #ifdef __cplusplus |
||
116 | extern "C" { |
||
117 | #endif |
||
118 | |||
119 | /** |
||
120 | * \file SDL_endian.h |
||
121 | */ |
||
122 | |||
123 | /* various modern compilers may have builtin swap */ |
||
124 | #if defined(__GNUC__) || defined(__clang__) |
||
125 | # define HAS_BUILTIN_BSWAP16 (_SDL_HAS_BUILTIN(__builtin_bswap16)) || \ |
||
126 | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) |
||
127 | # define HAS_BUILTIN_BSWAP32 (_SDL_HAS_BUILTIN(__builtin_bswap32)) || \ |
||
128 | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) |
||
129 | # define HAS_BUILTIN_BSWAP64 (_SDL_HAS_BUILTIN(__builtin_bswap64)) || \ |
||
130 | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) |
||
131 | |||
132 | /* this one is broken */ |
||
133 | # define HAS_BROKEN_BSWAP (__GNUC__ == 2 && __GNUC_MINOR__ <= 95) |
||
134 | #else |
||
135 | # define HAS_BUILTIN_BSWAP16 0 |
||
136 | # define HAS_BUILTIN_BSWAP32 0 |
||
137 | # define HAS_BUILTIN_BSWAP64 0 |
||
138 | # define HAS_BROKEN_BSWAP 0 |
||
139 | #endif |
||
140 | |||
141 | #if HAS_BUILTIN_BSWAP16 |
||
142 | #define SDL_Swap16(x) __builtin_bswap16(x) |
||
143 | #elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL) |
||
144 | #pragma intrinsic(_byteswap_ushort) |
||
145 | #define SDL_Swap16(x) _byteswap_ushort(x) |
||
146 | #elif defined(__i386__) && !HAS_BROKEN_BSWAP |
||
147 | SDL_FORCE_INLINE Uint16 |
||
148 | SDL_Swap16(Uint16 x) |
||
149 | { |
||
150 | __asm__("xchgb %b0,%h0": "=q"(x):"0"(x)); |
||
151 | return x; |
||
152 | } |
||
153 | #elif defined(__x86_64__) |
||
154 | SDL_FORCE_INLINE Uint16 |
||
155 | SDL_Swap16(Uint16 x) |
||
156 | { |
||
157 | __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x)); |
||
158 | return x; |
||
159 | } |
||
160 | #elif (defined(__powerpc__) || defined(__ppc__)) |
||
161 | SDL_FORCE_INLINE Uint16 |
||
162 | SDL_Swap16(Uint16 x) |
||
163 | { |
||
164 | int result; |
||
165 | |||
166 | __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x)); |
||
167 | return (Uint16)result; |
||
168 | } |
||
169 | #elif (defined(__m68k__) && !defined(__mcoldfire__)) |
||
170 | SDL_FORCE_INLINE Uint16 |
||
171 | SDL_Swap16(Uint16 x) |
||
172 | { |
||
173 | __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc"); |
||
174 | return x; |
||
175 | } |
||
176 | #elif defined(__WATCOMC__) && defined(__386__) |
||
177 | extern __inline Uint16 SDL_Swap16(Uint16); |
||
178 | #pragma aux SDL_Swap16 = \ |
||
179 | "xchg al, ah" \ |
||
180 | parm [ax] \ |
||
181 | modify [ax]; |
||
182 | #else |
||
183 | SDL_FORCE_INLINE Uint16 |
||
184 | SDL_Swap16(Uint16 x) |
||
185 | { |
||
186 | return SDL_static_cast(Uint16, ((x << 8) | (x >> 8))); |
||
187 | } |
||
188 | #endif |
||
189 | |||
190 | #if HAS_BUILTIN_BSWAP32 |
||
191 | #define SDL_Swap32(x) __builtin_bswap32(x) |
||
192 | #elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL) |
||
193 | #pragma intrinsic(_byteswap_ulong) |
||
194 | #define SDL_Swap32(x) _byteswap_ulong(x) |
||
195 | #elif defined(__i386__) && !HAS_BROKEN_BSWAP |
||
196 | SDL_FORCE_INLINE Uint32 |
||
197 | SDL_Swap32(Uint32 x) |
||
198 | { |
||
199 | __asm__("bswap %0": "=r"(x):"0"(x)); |
||
200 | return x; |
||
201 | } |
||
202 | #elif defined(__x86_64__) |
||
203 | SDL_FORCE_INLINE Uint32 |
||
204 | SDL_Swap32(Uint32 x) |
||
205 | { |
||
206 | __asm__("bswapl %0": "=r"(x):"0"(x)); |
||
207 | return x; |
||
208 | } |
||
209 | #elif (defined(__powerpc__) || defined(__ppc__)) |
||
210 | SDL_FORCE_INLINE Uint32 |
||
211 | SDL_Swap32(Uint32 x) |
||
212 | { |
||
213 | Uint32 result; |
||
214 | |||
215 | __asm__("rlwimi %0,%2,24,16,23": "=&r"(result): "0" (x>>24), "r"(x)); |
||
216 | __asm__("rlwimi %0,%2,8,8,15" : "=&r"(result): "0" (result), "r"(x)); |
||
217 | __asm__("rlwimi %0,%2,24,0,7" : "=&r"(result): "0" (result), "r"(x)); |
||
218 | return result; |
||
219 | } |
||
220 | #elif (defined(__m68k__) && !defined(__mcoldfire__)) |
||
221 | SDL_FORCE_INLINE Uint32 |
||
222 | SDL_Swap32(Uint32 x) |
||
223 | { |
||
224 | __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc"); |
||
225 | return x; |
||
226 | } |
||
227 | #elif defined(__WATCOMC__) && defined(__386__) |
||
228 | extern __inline Uint32 SDL_Swap32(Uint32); |
||
229 | #pragma aux SDL_Swap32 = \ |
||
230 | "bswap eax" \ |
||
231 | parm [eax] \ |
||
232 | modify [eax]; |
||
233 | #else |
||
234 | SDL_FORCE_INLINE Uint32 |
||
235 | SDL_Swap32(Uint32 x) |
||
236 | { |
||
237 | return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) | |
||
238 | ((x >> 8) & 0x0000FF00) | (x >> 24))); |
||
239 | } |
||
240 | #endif |
||
241 | |||
242 | #if HAS_BUILTIN_BSWAP64 |
||
243 | #define SDL_Swap64(x) __builtin_bswap64(x) |
||
244 | #elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL) |
||
245 | #pragma intrinsic(_byteswap_uint64) |
||
246 | #define SDL_Swap64(x) _byteswap_uint64(x) |
||
247 | #elif defined(__i386__) && !HAS_BROKEN_BSWAP |
||
248 | SDL_FORCE_INLINE Uint64 |
||
249 | SDL_Swap64(Uint64 x) |
||
250 | { |
||
251 | union { |
||
252 | struct { |
||
253 | Uint32 a, b; |
||
254 | } s; |
||
255 | Uint64 u; |
||
256 | } v; |
||
257 | v.u = x; |
||
258 | __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1" |
||
259 | : "=r"(v.s.a), "=r"(v.s.b) |
||
260 | : "0" (v.s.a), "1"(v.s.b)); |
||
261 | return v.u; |
||
262 | } |
||
263 | #elif defined(__x86_64__) |
||
264 | SDL_FORCE_INLINE Uint64 |
||
265 | SDL_Swap64(Uint64 x) |
||
266 | { |
||
267 | __asm__("bswapq %0": "=r"(x):"0"(x)); |
||
268 | return x; |
||
269 | } |
||
270 | #elif defined(__WATCOMC__) && defined(__386__) |
||
271 | extern __inline Uint64 SDL_Swap64(Uint64); |
||
272 | #pragma aux SDL_Swap64 = \ |
||
273 | "bswap eax" \ |
||
274 | "bswap edx" \ |
||
275 | "xchg eax,edx" \ |
||
276 | parm [eax edx] \ |
||
277 | modify [eax edx]; |
||
278 | #else |
||
279 | SDL_FORCE_INLINE Uint64 |
||
280 | SDL_Swap64(Uint64 x) |
||
281 | { |
||
282 | Uint32 hi, lo; |
||
283 | |||
284 | /* Separate into high and low 32-bit values and swap them */ |
||
285 | lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
||
286 | x >>= 32; |
||
287 | hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
||
288 | x = SDL_Swap32(lo); |
||
289 | x <<= 32; |
||
290 | x |= SDL_Swap32(hi); |
||
291 | return (x); |
||
292 | } |
||
293 | #endif |
||
294 | |||
295 | |||
296 | SDL_FORCE_INLINE float |
||
297 | SDL_SwapFloat(float x) |
||
298 | { |
||
299 | union { |
||
300 | float f; |
||
301 | Uint32 ui32; |
||
302 | } swapper; |
||
303 | swapper.f = x; |
||
304 | swapper.ui32 = SDL_Swap32(swapper.ui32); |
||
305 | return swapper.f; |
||
306 | } |
||
307 | |||
308 | /* remove extra macros */ |
||
309 | #undef HAS_BROKEN_BSWAP |
||
310 | #undef HAS_BUILTIN_BSWAP16 |
||
311 | #undef HAS_BUILTIN_BSWAP32 |
||
312 | #undef HAS_BUILTIN_BSWAP64 |
||
313 | |||
314 | /** |
||
315 | * \name Swap to native |
||
316 | * Byteswap item from the specified endianness to the native endianness. |
||
317 | */ |
||
318 | /* @{ */ |
||
319 | #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
||
320 | #define SDL_SwapLE16(X) (X) |
||
321 | #define SDL_SwapLE32(X) (X) |
||
322 | #define SDL_SwapLE64(X) (X) |
||
323 | #define SDL_SwapFloatLE(X) (X) |
||
324 | #define SDL_SwapBE16(X) SDL_Swap16(X) |
||
325 | #define SDL_SwapBE32(X) SDL_Swap32(X) |
||
326 | #define SDL_SwapBE64(X) SDL_Swap64(X) |
||
327 | #define SDL_SwapFloatBE(X) SDL_SwapFloat(X) |
||
328 | #else |
||
329 | #define SDL_SwapLE16(X) SDL_Swap16(X) |
||
330 | #define SDL_SwapLE32(X) SDL_Swap32(X) |
||
331 | #define SDL_SwapLE64(X) SDL_Swap64(X) |
||
332 | #define SDL_SwapFloatLE(X) SDL_SwapFloat(X) |
||
333 | #define SDL_SwapBE16(X) (X) |
||
334 | #define SDL_SwapBE32(X) (X) |
||
335 | #define SDL_SwapBE64(X) (X) |
||
336 | #define SDL_SwapFloatBE(X) (X) |
||
337 | #endif |
||
338 | /* @} *//* Swap to native */ |
||
339 | |||
340 | /* Ends C function definitions when using C++ */ |
||
341 | #ifdef __cplusplus |
||
342 | } |
||
343 | #endif |
||
344 | #include "close_code.h" |
||
345 | |||
346 | #endif /* SDL_endian_h_ */ |
||
347 | |||
348 | /* vi: set ts=4 sw=4 expandtab: */ |