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 /* These headers are from sdl12-compat, and are intended to give just enough
23 functionality to let you build an SDL-1.2-based project without having the
24 real SDL-1.2 available to you. */
25 
26 #ifndef _SDL_endian_h
27 #define _SDL_endian_h
28 
29 #include "SDL_stdinc.h"
30 
31 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
32 #include <intrin.h>
33 #endif
34 
35 /* This is all lifted out of SDL2's zlib-licensed headers. */
36 
37 #define SDL_LIL_ENDIAN  1234
38 #define SDL_BIG_ENDIAN  4321
39 
40 #ifndef SDL_BYTEORDER           /* Not defined in SDL_config.h? */
41 #ifdef __linux__
42 #include <endian.h>
43 #define SDL_BYTEORDER  __BYTE_ORDER
44 #elif defined(__OpenBSD__)
45 #include <endian.h>
46 #define SDL_BYTEORDER  BYTE_ORDER
47 #elif defined(__FreeBSD__) || defined(__NetBSD__)
48 #include <sys/endian.h>
49 #define SDL_BYTEORDER  BYTE_ORDER
50 #else
51 #if defined(__hppa__) || \
52     defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
53     (defined(__MIPS__) && defined(__MIPSEB__)) || \
54     defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
55     defined(__sparc__)
56 #define SDL_BYTEORDER   SDL_BIG_ENDIAN
57 #else
58 #define SDL_BYTEORDER   SDL_LIL_ENDIAN
59 #endif
60 #endif /* __linux__ */
61 #endif /* !SDL_BYTEORDER */
62 
63 
64 #include "begin_code.h"
65 
66 /* various modern compilers may have builtin swap */
67 #if defined (__has_builtin)
68 #define _SDL_HAS_BUILTIN(x) __has_builtin(x)
69 #else
70 #define _SDL_HAS_BUILTIN(x) 0
71 #endif
72 
73 #if defined(__GNUC__) || defined(__clang__)
74 #   define HAS_BUILTIN_BSWAP16 (_SDL_HAS_BUILTIN(__builtin_bswap16)) || \
75         (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
76 #   define HAS_BUILTIN_BSWAP32 (_SDL_HAS_BUILTIN(__builtin_bswap32)) || \
77         (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
78 #   define HAS_BUILTIN_BSWAP64 (_SDL_HAS_BUILTIN(__builtin_bswap64)) || \
79         (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
80 
81     /* this one is broken */
82 #   define HAS_BROKEN_BSWAP (__GNUC__ == 2 && __GNUC_MINOR__ <= 95)
83 #else
84 #   define HAS_BUILTIN_BSWAP16 0
85 #   define HAS_BUILTIN_BSWAP32 0
86 #   define HAS_BUILTIN_BSWAP64 0
87 #   define HAS_BROKEN_BSWAP 0
88 #endif
89 
90 #if HAS_BUILTIN_BSWAP16
91 #define SDL_Swap16(x) __builtin_bswap16(x)
92 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
93 #pragma intrinsic(_byteswap_ushort)
94 #define SDL_Swap16(x) _byteswap_ushort(x)
95 #elif defined(__i386__) && !HAS_BROKEN_BSWAP
96 static __inline__ Uint16
SDL_Swap16(Uint16 x)97 SDL_Swap16(Uint16 x)
98 {
99   __asm__("xchgb %b0,%h0": "=q"(x):"0"(x));
100     return x;
101 }
102 #elif defined(__x86_64__)
103 static __inline__ Uint16
SDL_Swap16(Uint16 x)104 SDL_Swap16(Uint16 x)
105 {
106   __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x));
107     return x;
108 }
109 #elif (defined(__powerpc__) || defined(__ppc__))
110 static __inline__ Uint16
SDL_Swap16(Uint16 x)111 SDL_Swap16(Uint16 x)
112 {
113     int result;
114 
115   __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x));
116     return (Uint16)result;
117 }
118 #elif (defined(__m68k__) && !defined(__mcoldfire__))
119 static __inline__ Uint16
SDL_Swap16(Uint16 x)120 SDL_Swap16(Uint16 x)
121 {
122   __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc");
123     return x;
124 }
125 #elif defined(__WATCOMC__) && defined(__386__)
126 extern __inline Uint16 SDL_Swap16(Uint16);
127 #pragma aux SDL_Swap16 = \
128   "xchg al, ah" \
129   parm   [ax]   \
130   modify [ax];
131 #else
132 static __inline__ Uint16
SDL_Swap16(Uint16 x)133 SDL_Swap16(Uint16 x)
134 {
135     return SDL_static_cast(Uint16, ((x << 8) | (x >> 8)));
136 }
137 #endif
138 
139 #if HAS_BUILTIN_BSWAP32
140 #define SDL_Swap32(x) __builtin_bswap32(x)
141 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
142 #pragma intrinsic(_byteswap_ulong)
143 #define SDL_Swap32(x) _byteswap_ulong(x)
144 #elif defined(__i386__) && !HAS_BROKEN_BSWAP
145 static __inline__ Uint32
SDL_Swap32(Uint32 x)146 SDL_Swap32(Uint32 x)
147 {
148   __asm__("bswap %0": "=r"(x):"0"(x));
149     return x;
150 }
151 #elif defined(__x86_64__)
152 static __inline__ Uint32
SDL_Swap32(Uint32 x)153 SDL_Swap32(Uint32 x)
154 {
155   __asm__("bswapl %0": "=r"(x):"0"(x));
156     return x;
157 }
158 #elif (defined(__powerpc__) || defined(__ppc__))
159 static __inline__ Uint32
SDL_Swap32(Uint32 x)160 SDL_Swap32(Uint32 x)
161 {
162     Uint32 result;
163 
164   __asm__("rlwimi %0,%2,24,16,23": "=&r"(result): "0" (x>>24),  "r"(x));
165   __asm__("rlwimi %0,%2,8,8,15"  : "=&r"(result): "0" (result), "r"(x));
166   __asm__("rlwimi %0,%2,24,0,7"  : "=&r"(result): "0" (result), "r"(x));
167     return result;
168 }
169 #elif (defined(__m68k__) && !defined(__mcoldfire__))
170 static __inline__ Uint32
SDL_Swap32(Uint32 x)171 SDL_Swap32(Uint32 x)
172 {
173   __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc");
174     return x;
175 }
176 #elif defined(__WATCOMC__) && defined(__386__)
177 extern __inline Uint32 SDL_Swap32(Uint32);
178 #pragma aux SDL_Swap32 = \
179   "bswap eax"  \
180   parm   [eax] \
181   modify [eax];
182 #else
183 static __inline__ Uint32
SDL_Swap32(Uint32 x)184 SDL_Swap32(Uint32 x)
185 {
186     return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) |
187                                     ((x >> 8) & 0x0000FF00) | (x >> 24)));
188 }
189 #endif
190 
191 #if HAS_BUILTIN_BSWAP64
192 #define SDL_Swap64(x) __builtin_bswap64(x)
193 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
194 #pragma intrinsic(_byteswap_uint64)
195 #define SDL_Swap64(x) _byteswap_uint64(x)
196 #elif defined(__i386__) && !HAS_BROKEN_BSWAP
197 static __inline__ Uint64
SDL_Swap64(Uint64 x)198 SDL_Swap64(Uint64 x)
199 {
200     union {
201         struct {
202             Uint32 a, b;
203         } s;
204         Uint64 u;
205     } v;
206     v.u = x;
207   __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
208           : "=r"(v.s.a), "=r"(v.s.b)
209           : "0" (v.s.a),  "1"(v.s.b));
210     return v.u;
211 }
212 #elif defined(__x86_64__)
213 static __inline__ Uint64
SDL_Swap64(Uint64 x)214 SDL_Swap64(Uint64 x)
215 {
216   __asm__("bswapq %0": "=r"(x):"0"(x));
217     return x;
218 }
219 #elif defined(__WATCOMC__) && defined(__386__)
220 extern __inline Uint64 SDL_Swap64(Uint64);
221 #pragma aux SDL_Swap64 = \
222   "bswap eax"     \
223   "bswap edx"     \
224   "xchg eax,edx"  \
225   parm [eax edx]  \
226   modify [eax edx];
227 #else
228 static __inline__ Uint64
SDL_Swap64(Uint64 x)229 SDL_Swap64(Uint64 x)
230 {
231     Uint32 hi, lo;
232 
233     /* Separate into high and low 32-bit values and swap them */
234     lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
235     x >>= 32;
236     hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
237     x = SDL_Swap32(lo);
238     x <<= 32;
239     x |= SDL_Swap32(hi);
240     return (x);
241 }
242 #endif
243 
244 
245 /* remove extra macros */
246 #undef HAS_BROKEN_BSWAP
247 #undef HAS_BUILTIN_BSWAP16
248 #undef HAS_BUILTIN_BSWAP32
249 #undef HAS_BUILTIN_BSWAP64
250 #undef _SDL_HAS_BUILTIN
251 
252 /**
253  *  \name Swap to native
254  *  Byteswap item from the specified endianness to the native endianness.
255  */
256 /* @{ */
257 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
258 #define SDL_SwapLE16(X)     (X)
259 #define SDL_SwapLE32(X)     (X)
260 #define SDL_SwapLE64(X)     (X)
261 #define SDL_SwapBE16(X)     SDL_Swap16(X)
262 #define SDL_SwapBE32(X)     SDL_Swap32(X)
263 #define SDL_SwapBE64(X)     SDL_Swap64(X)
264 #else
265 #define SDL_SwapLE16(X)     SDL_Swap16(X)
266 #define SDL_SwapLE32(X)     SDL_Swap32(X)
267 #define SDL_SwapLE64(X)     SDL_Swap64(X)
268 #define SDL_SwapBE16(X)     (X)
269 #define SDL_SwapBE32(X)     (X)
270 #define SDL_SwapBE64(X)     (X)
271 #endif
272 /* @} *//* Swap to native */
273 
274 #include "close_code.h"
275 
276 #endif /* _SDL_endian_h */
277