Home | History | Annotate | Download | only in SDL
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 
     23 /**
     24  *  @file SDL_endian.h
     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 /** @name SDL_ENDIANs
     34  *  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  *  @name SDL_Swap Functions
     67  *  Use inline functions for compilers that support them, and static
     68  *  functions for those that do not.  Because these functions become
     69  *  static for compilers that do not support inline functions, this
     70  *  header should only be included in files that actually use them.
     71  */
     72 /*@{*/
     73 #if defined(__GNUC__) && defined(__i386__) && \
     74    !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
     75 static __inline__ Uint16 SDL_Swap16(Uint16 x)
     76 {
     77 	__asm__("xchgb %b0,%h0" : "=q" (x) :  "0" (x));
     78 	return x;
     79 }
     80 #elif defined(__GNUC__) && defined(__x86_64__)
     81 static __inline__ Uint16 SDL_Swap16(Uint16 x)
     82 {
     83 	__asm__("xchgb %b0,%h0" : "=Q" (x) :  "0" (x));
     84 	return x;
     85 }
     86 #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
     87 static __inline__ Uint16 SDL_Swap16(Uint16 x)
     88 {
     89 	int result;
     90 
     91 	__asm__("rlwimi %0,%2,8,16,23" : "=&r" (result) : "0" (x >> 8), "r" (x));
     92 	return (Uint16)result;
     93 }
     94 #elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))
     95 static __inline__ Uint16 SDL_Swap16(Uint16 x)
     96 {
     97 	__asm__("rorw #8,%0" : "=d" (x) :  "0" (x) : "cc");
     98 	return x;
     99 }
    100 #else
    101 static __inline__ Uint16 SDL_Swap16(Uint16 x) {
    102 	return SDL_static_cast(Uint16, ((x<<8)|(x>>8)));
    103 }
    104 #endif
    105 
    106 #if defined(__GNUC__) && defined(__i386__) && \
    107    !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
    108 static __inline__ Uint32 SDL_Swap32(Uint32 x)
    109 {
    110 	__asm__("bswap %0" : "=r" (x) : "0" (x));
    111 	return x;
    112 }
    113 #elif defined(__GNUC__) && defined(__x86_64__)
    114 static __inline__ Uint32 SDL_Swap32(Uint32 x)
    115 {
    116 	__asm__("bswapl %0" : "=r" (x) : "0" (x));
    117 	return x;
    118 }
    119 #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
    120 static __inline__ Uint32 SDL_Swap32(Uint32 x)
    121 {
    122 	Uint32 result;
    123 
    124 	__asm__("rlwimi %0,%2,24,16,23" : "=&r" (result) : "0" (x>>24), "r" (x));
    125 	__asm__("rlwimi %0,%2,8,8,15"   : "=&r" (result) : "0" (result),    "r" (x));
    126 	__asm__("rlwimi %0,%2,24,0,7"   : "=&r" (result) : "0" (result),    "r" (x));
    127 	return result;
    128 }
    129 #elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))
    130 static __inline__ Uint32 SDL_Swap32(Uint32 x)
    131 {
    132 	__asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0" : "=d" (x) :  "0" (x) : "cc");
    133 	return x;
    134 }
    135 #else
    136 static __inline__ Uint32 SDL_Swap32(Uint32 x) {
    137 	return SDL_static_cast(Uint32, ((x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24)));
    138 }
    139 #endif
    140 
    141 #ifdef SDL_HAS_64BIT_TYPE
    142 #if defined(__GNUC__) && defined(__i386__) && \
    143    !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
    144 static __inline__ Uint64 SDL_Swap64(Uint64 x)
    145 {
    146 	union {
    147 		struct { Uint32 a,b; } s;
    148 		Uint64 u;
    149 	} v;
    150 	v.u = x;
    151 	__asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
    152 	        : "=r" (v.s.a), "=r" (v.s.b)
    153 	        : "0" (v.s.a), "1" (v.s.b));
    154 	return v.u;
    155 }
    156 #elif defined(__GNUC__) && defined(__x86_64__)
    157 static __inline__ Uint64 SDL_Swap64(Uint64 x)
    158 {
    159 	__asm__("bswapq %0" : "=r" (x) : "0" (x));
    160 	return x;
    161 }
    162 #else
    163 static __inline__ Uint64 SDL_Swap64(Uint64 x)
    164 {
    165 	Uint32 hi, lo;
    166 
    167 	/* Separate into high and low 32-bit values and swap them */
    168 	lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
    169 	x >>= 32;
    170 	hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
    171 	x = SDL_Swap32(lo);
    172 	x <<= 32;
    173 	x |= SDL_Swap32(hi);
    174 	return (x);
    175 }
    176 #endif
    177 #else
    178 /* This is mainly to keep compilers from complaining in SDL code.
    179  * If there is no real 64-bit datatype, then compilers will complain about
    180  * the fake 64-bit datatype that SDL provides when it compiles user code.
    181  */
    182 #define SDL_Swap64(X)	(X)
    183 #endif /* SDL_HAS_64BIT_TYPE */
    184 /*@}*/
    185 
    186 /**
    187  *  @name SDL_SwapLE and SDL_SwapBE Functions
    188  *  Byteswap item from the specified endianness to the native endianness
    189  */
    190 /*@{*/
    191 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    192 #define SDL_SwapLE16(X)	(X)
    193 #define SDL_SwapLE32(X)	(X)
    194 #define SDL_SwapLE64(X)	(X)
    195 #define SDL_SwapBE16(X)	SDL_Swap16(X)
    196 #define SDL_SwapBE32(X)	SDL_Swap32(X)
    197 #define SDL_SwapBE64(X)	SDL_Swap64(X)
    198 #else
    199 #define SDL_SwapLE16(X)	SDL_Swap16(X)
    200 #define SDL_SwapLE32(X)	SDL_Swap32(X)
    201 #define SDL_SwapLE64(X)	SDL_Swap64(X)
    202 #define SDL_SwapBE16(X)	(X)
    203 #define SDL_SwapBE32(X)	(X)
    204 #define SDL_SwapBE64(X)	(X)
    205 #endif
    206 /*@}*/
    207 
    208 /* Ends C function definitions when using C++ */
    209 #ifdef __cplusplus
    210 }
    211 #endif
    212 #include "close_code.h"
    213 
    214 #endif /* _SDL_endian_h */
    215