include/SDL_endian.h
author Ryan C. Gordon <icculus@icculus.org>
Thu, 24 Aug 2006 12:49:59 +0000
changeset 1984 b910bcabec26
parent 1895 c121d94672cb
child 1985 8055185ae4ed
permissions -rw-r--r--
Added SDL_SwapFloat* function/macros. Reference Bugzilla #293.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 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@libsdl.org
    21 */
    22 
    23 /**
    24  * \file SDL_endian.h
    25  *
    26  * Functions for reading and writing endian-specific values
    27  */
    28 
    29 #ifndef _SDL_endian_h
    30 #define _SDL_endian_h
    31 
    32 #include "SDL_stdinc.h"
    33 
    34 /* The two types of endianness */
    35 #define SDL_LIL_ENDIAN	1234
    36 #define SDL_BIG_ENDIAN	4321
    37 
    38 #ifndef SDL_BYTEORDER           /* Not defined in SDL_config.h? */
    39 #if defined(__hppa__) || \
    40     defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
    41     (defined(__MIPS__) && defined(__MISPEB__)) || \
    42     defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
    43     defined(__sparc__)
    44 #define SDL_BYTEORDER	SDL_BIG_ENDIAN
    45 #else
    46 #define SDL_BYTEORDER	SDL_LIL_ENDIAN
    47 #endif
    48 #endif /* !SDL_BYTEORDER */
    49 
    50 
    51 #include "begin_code.h"
    52 /* Set up for C function definitions, even when using C++ */
    53 #ifdef __cplusplus
    54 /* *INDENT-OFF* */
    55 extern "C" {
    56 /* *INDENT-ON* */
    57 #endif
    58 
    59 /* Use inline functions for compilers that support them, and static
    60    functions for those that do not.  Because these functions become
    61    static for compilers that do not support inline functions, this
    62    header should only be included in files that actually use them.
    63 */
    64 #if defined(__GNUC__) && defined(__i386__) && \
    65    !(__GNUC__ == 2 && __GNUC_MINOR__ == 95 /* broken gcc version */)
    66 static __inline__ Uint16
    67 SDL_Swap16(Uint16 x)
    68 {
    69   __asm__("xchgb %b0,%h0": "=q"(x):"0"(x));
    70     return x;
    71 }
    72 #elif defined(__GNUC__) && defined(__x86_64__)
    73 static __inline__ Uint16
    74 SDL_Swap16(Uint16 x)
    75 {
    76   __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x));
    77     return x;
    78 }
    79 #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
    80 static __inline__ Uint16
    81 SDL_Swap16(Uint16 x)
    82 {
    83     Uint16 result;
    84 
    85   __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x));
    86     return result;
    87 }
    88 #elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__))
    89 static __inline__ Uint16
    90 SDL_Swap16(Uint16 x)
    91 {
    92   __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc");
    93     return x;
    94 }
    95 #else
    96 static __inline__ Uint16
    97 SDL_Swap16(Uint16 x)
    98 {
    99     return ((x << 8) | (x >> 8));
   100 }
   101 #endif
   102 
   103 #if defined(__GNUC__) && defined(__i386__)
   104 static __inline__ Uint32
   105 SDL_Swap32(Uint32 x)
   106 {
   107   __asm__("bswap %0": "=r"(x):"0"(x));
   108     return x;
   109 }
   110 #elif defined(__GNUC__) && defined(__x86_64__)
   111 static __inline__ Uint32
   112 SDL_Swap32(Uint32 x)
   113 {
   114   __asm__("bswapl %0": "=r"(x):"0"(x));
   115     return x;
   116 }
   117 #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
   118 static __inline__ Uint32
   119 SDL_Swap32(Uint32 x)
   120 {
   121     Uint32 result;
   122 
   123   __asm__("rlwimi %0,%2,24,16,23": "=&r"(result):"0"(x >> 24), "r"(x));
   124   __asm__("rlwimi %0,%2,8,8,15": "=&r"(result):"0"(result), "r"(x));
   125   __asm__("rlwimi %0,%2,24,0,7": "=&r"(result):"0"(result), "r"(x));
   126     return result;
   127 }
   128 #elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__))
   129 static __inline__ Uint32
   130 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
   137 SDL_Swap32(Uint32 x)
   138 {
   139     return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) |
   140             (x >> 24));
   141 }
   142 #endif
   143 
   144 #ifdef SDL_HAS_64BIT_TYPE
   145 #if defined(__GNUC__) && defined(__i386__)
   146 static __inline__ Uint64
   147 SDL_Swap64(Uint64 x)
   148 {
   149     union
   150     {
   151         struct
   152         {
   153             Uint32 a, b;
   154         } s;
   155         Uint64 u;
   156     } v;
   157     v.u = x;
   158   __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1": "=r"(v.s.a), "=r"(v.s.b):"0"(v.s.a),
   159             "1"(v.s.
   160                 b));
   161     return v.u;
   162 }
   163 #elif defined(__GNUC__) && defined(__x86_64__)
   164 static __inline__ Uint64
   165 SDL_Swap64(Uint64 x)
   166 {
   167   __asm__("bswapq %0": "=r"(x):"0"(x));
   168     return x;
   169 }
   170 #else
   171 static __inline__ Uint64
   172 SDL_Swap64(Uint64 x)
   173 {
   174     Uint32 hi, lo;
   175 
   176     /* Separate into high and low 32-bit values and swap them */
   177     lo = (Uint32) (x & 0xFFFFFFFF);
   178     x >>= 32;
   179     hi = (Uint32) (x & 0xFFFFFFFF);
   180     x = SDL_Swap32(lo);
   181     x <<= 32;
   182     x |= SDL_Swap32(hi);
   183     return (x);
   184 }
   185 #endif
   186 #else
   187 /* This is mainly to keep compilers from complaining in SDL code.
   188    If there is no real 64-bit datatype, then compilers will complain about
   189    the fake 64-bit datatype that SDL provides when it compiles user code.
   190 */
   191 #define SDL_Swap64(X)	(X)
   192 #endif /* SDL_HAS_64BIT_TYPE */
   193 
   194 
   195 static __inline__ float
   196 SDL_SwapFloat(float x)
   197 {
   198     union { float f; Uint32 ui32; } swapper;
   199     swapper.f = x;
   200     swapper.ui32 = SDL_Swap32(swapper.ui32);
   201     return swapper.f;
   202 }
   203 
   204 
   205 /* Byteswap item from the specified endianness to the native endianness */
   206 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   207 #define SDL_SwapLE16(X)	(X)
   208 #define SDL_SwapLE32(X)	(X)
   209 #define SDL_SwapLE64(X)	(X)
   210 #define SDL_SwapFloatLE(X)	(X)
   211 #define SDL_SwapBE16(X)	SDL_Swap16(X)
   212 #define SDL_SwapBE32(X)	SDL_Swap32(X)
   213 #define SDL_SwapBE64(X)	SDL_Swap64(X)
   214 #define SDL_SwapFloatBE(X)	SDL_SwapFloat(X)
   215 #else
   216 #define SDL_SwapLE16(X)	SDL_Swap16(X)
   217 #define SDL_SwapLE32(X)	SDL_Swap32(X)
   218 #define SDL_SwapLE64(X)	SDL_Swap64(X)
   219 #define SDL_SwapFloatLE(X)	SDL_SwapFloat(X)
   220 #define SDL_SwapBE16(X)	(X)
   221 #define SDL_SwapBE32(X)	(X)
   222 #define SDL_SwapBE64(X)	(X)
   223 #define SDL_SwapFloatBE(X)	(X)
   224 #endif
   225 
   226 /* Ends C function definitions when using C++ */
   227 #ifdef __cplusplus
   228 /* *INDENT-OFF* */
   229 }
   230 /* *INDENT-ON* */
   231 #endif
   232 #include "close_code.h"
   233 
   234 #endif /* _SDL_endian_h */
   235 
   236 /* vi: set ts=4 sw=4 expandtab: */