1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2018 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 | /** |
34 | * \name The two types of endianness |
35 | */ |
36 | /* @{ */ |
37 | #define SDL_LIL_ENDIAN 1234 |
38 | #define SDL_BIG_ENDIAN 4321 |
39 | /* @} */ |
40 | |
41 | #ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */ |
42 | #ifdef __linux__ |
43 | #include <endian.h> |
44 | #define SDL_BYTEORDER __BYTE_ORDER |
45 | #else /* __linux__ */ |
46 | #if defined(__hppa__) || \ |
47 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ |
48 | (defined(__MIPS__) && defined(__MISPEB__)) || \ |
49 | defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ |
50 | defined(__sparc__) |
51 | #define SDL_BYTEORDER SDL_BIG_ENDIAN |
52 | #else |
53 | #define SDL_BYTEORDER SDL_LIL_ENDIAN |
54 | #endif |
55 | #endif /* __linux__ */ |
56 | #endif /* !SDL_BYTEORDER */ |
57 | |
58 | |
59 | #include "begin_code.h" |
60 | /* Set up for C function definitions, even when using C++ */ |
61 | #ifdef __cplusplus |
62 | extern "C" { |
63 | #endif |
64 | |
65 | /** |
66 | * \file SDL_endian.h |
67 | */ |
68 | #if defined(__GNUC__) && defined(__i386__) && \ |
69 | !(__GNUC__ == 2 && __GNUC_MINOR__ == 95 /* broken gcc version */) |
70 | SDL_FORCE_INLINE Uint16 |
71 | SDL_Swap16(Uint16 x) |
72 | { |
73 | __asm__("xchgb %b0,%h0" : "=q" (x):"0" (x)); |
74 | return x; |
75 | } |
76 | #elif defined(__GNUC__) && defined(__x86_64__) |
77 | SDL_FORCE_INLINE Uint16 |
78 | SDL_Swap16(Uint16 x) |
79 | { |
80 | __asm__("xchgb %b0,%h0" : "=Q" (x):"0" (x)); |
81 | return x; |
82 | } |
83 | #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) |
84 | SDL_FORCE_INLINE Uint16 |
85 | SDL_Swap16(Uint16 x) |
86 | { |
87 | int result; |
88 | |
89 | __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result):"0" (x >> 8), "r" (x)); |
90 | return (Uint16)result; |
91 | } |
92 | #elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__)) && !defined(__mcoldfire__) |
93 | SDL_FORCE_INLINE Uint16 |
94 | SDL_Swap16(Uint16 x) |
95 | { |
96 | __asm__("rorw #8,%0" : "=d" (x): "0" (x):"cc" ); |
97 | return x; |
98 | } |
99 | #elif defined(__WATCOMC__) && defined(__386__) |
100 | extern _inline Uint16 SDL_Swap16(Uint16); |
101 | #pragma aux SDL_Swap16 = \ |
102 | "xchg al, ah" \ |
103 | parm [ax] \ |
104 | modify [ax]; |
105 | #else |
106 | SDL_FORCE_INLINE Uint16 |
107 | SDL_Swap16(Uint16 x) |
108 | { |
109 | return SDL_static_cast(Uint16, ((x << 8) | (x >> 8))); |
110 | } |
111 | #endif |
112 | |
113 | #if defined(__GNUC__) && defined(__i386__) |
114 | SDL_FORCE_INLINE Uint32 |
115 | SDL_Swap32(Uint32 x) |
116 | { |
117 | __asm__("bswap %0" : "=r" (x):"0" (x)); |
118 | return x; |
119 | } |
120 | #elif defined(__GNUC__) && defined(__x86_64__) |
121 | SDL_FORCE_INLINE Uint32 |
122 | SDL_Swap32(Uint32 x) |
123 | { |
124 | __asm__("bswapl %0" : "=r" (x):"0" (x)); |
125 | return x; |
126 | } |
127 | #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) |
128 | SDL_FORCE_INLINE Uint32 |
129 | SDL_Swap32(Uint32 x) |
130 | { |
131 | Uint32 result; |
132 | |
133 | __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result):"0" (x >> 24), "r" (x)); |
134 | __asm__("rlwimi %0,%2,8,8,15" : "=&r" (result):"0" (result), "r" (x)); |
135 | __asm__("rlwimi %0,%2,24,0,7" : "=&r" (result):"0" (result), "r" (x)); |
136 | return result; |
137 | } |
138 | #elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__)) && !defined(__mcoldfire__) |
139 | SDL_FORCE_INLINE Uint32 |
140 | SDL_Swap32(Uint32 x) |
141 | { |
142 | __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0" : "=d" (x): "0" (x):"cc" ); |
143 | return x; |
144 | } |
145 | #elif defined(__WATCOMC__) && defined(__386__) |
146 | extern _inline Uint32 SDL_Swap32(Uint32); |
147 | #ifndef __SW_3 /* 486+ */ |
148 | #pragma aux SDL_Swap32 = \ |
149 | "bswap eax" \ |
150 | parm [eax] \ |
151 | modify [eax]; |
152 | #else /* 386-only */ |
153 | #pragma aux SDL_Swap32 = \ |
154 | "xchg al, ah" \ |
155 | "ror eax, 16" \ |
156 | "xchg al, ah" \ |
157 | parm [eax] \ |
158 | modify [eax]; |
159 | #endif |
160 | #else |
161 | SDL_FORCE_INLINE Uint32 |
162 | SDL_Swap32(Uint32 x) |
163 | { |
164 | return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) | |
165 | ((x >> 8) & 0x0000FF00) | (x >> 24))); |
166 | } |
167 | #endif |
168 | |
169 | #if defined(__GNUC__) && defined(__i386__) |
170 | SDL_FORCE_INLINE Uint64 |
171 | SDL_Swap64(Uint64 x) |
172 | { |
173 | union |
174 | { |
175 | struct |
176 | { |
177 | Uint32 a, b; |
178 | } s; |
179 | Uint64 u; |
180 | } v; |
181 | v.u = x; |
182 | __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b):"0" (v.s.a), |
183 | "1" (v.s. |
184 | b)); |
185 | return v.u; |
186 | } |
187 | #elif defined(__GNUC__) && defined(__x86_64__) |
188 | SDL_FORCE_INLINE Uint64 |
189 | SDL_Swap64(Uint64 x) |
190 | { |
191 | __asm__("bswapq %0" : "=r" (x):"0" (x)); |
192 | return x; |
193 | } |
194 | #else |
195 | SDL_FORCE_INLINE Uint64 |
196 | SDL_Swap64(Uint64 x) |
197 | { |
198 | Uint32 hi, lo; |
199 | |
200 | /* Separate into high and low 32-bit values and swap them */ |
201 | lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
202 | x >>= 32; |
203 | hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
204 | x = SDL_Swap32(lo); |
205 | x <<= 32; |
206 | x |= SDL_Swap32(hi); |
207 | return (x); |
208 | } |
209 | #endif |
210 | |
211 | |
212 | SDL_FORCE_INLINE float |
213 | SDL_SwapFloat(float x) |
214 | { |
215 | union |
216 | { |
217 | float f; |
218 | Uint32 ui32; |
219 | } swapper; |
220 | swapper.f = x; |
221 | swapper.ui32 = SDL_Swap32(swapper.ui32); |
222 | return swapper.f; |
223 | } |
224 | |
225 | |
226 | /** |
227 | * \name Swap to native |
228 | * Byteswap item from the specified endianness to the native endianness. |
229 | */ |
230 | /* @{ */ |
231 | #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
232 | #define SDL_SwapLE16(X) (X) |
233 | #define SDL_SwapLE32(X) (X) |
234 | #define SDL_SwapLE64(X) (X) |
235 | #define SDL_SwapFloatLE(X) (X) |
236 | #define SDL_SwapBE16(X) SDL_Swap16(X) |
237 | #define SDL_SwapBE32(X) SDL_Swap32(X) |
238 | #define SDL_SwapBE64(X) SDL_Swap64(X) |
239 | #define SDL_SwapFloatBE(X) SDL_SwapFloat(X) |
240 | #else |
241 | #define SDL_SwapLE16(X) SDL_Swap16(X) |
242 | #define SDL_SwapLE32(X) SDL_Swap32(X) |
243 | #define SDL_SwapLE64(X) SDL_Swap64(X) |
244 | #define SDL_SwapFloatLE(X) SDL_SwapFloat(X) |
245 | #define SDL_SwapBE16(X) (X) |
246 | #define SDL_SwapBE32(X) (X) |
247 | #define SDL_SwapBE64(X) (X) |
248 | #define SDL_SwapFloatBE(X) (X) |
249 | #endif |
250 | /* @} *//* Swap to native */ |
251 | |
252 | /* Ends C function definitions when using C++ */ |
253 | #ifdef __cplusplus |
254 | } |
255 | #endif |
256 | #include "close_code.h" |
257 | |
258 | #endif /* SDL_endian_h_ */ |
259 | |
260 | /* vi: set ts=4 sw=4 expandtab: */ |
261 | |