1 /*
2  * OpenBOR - http://www.chronocrash.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2014 OpenBOR Team
7  */
8 
9 #ifndef BOR_ENDIAN_H
10 #define BOR_ENDIAN_H
11 
12 /*
13 	This wrapper is largely based of SDL_endian.h
14 	from the http://www.libsdl.org  However, it is
15 	now compatible with all platforms and does not
16 	require SDL to be installed on that platform.
17 	Thank You to the group of developers who created SDL!
18 */
19 
20 #include "types.h"
21 
22 typedef s8	                SInt8;
23 typedef u8                  UInt8;
24 typedef s16                 SInt16;
25 typedef u16                 UInt16;
26 typedef s32                 SInt32;
27 typedef u32                 UInt32;
28 #ifdef __x86_64__
29 typedef signed long         SInt64;
30 typedef unsigned long       UInt64;
31 #else
32 typedef signed long long    SInt64;
33 typedef unsigned long long  UInt64;
34 #endif
35 
36 #ifndef __inline__
37 #define __inline__ __inline
38 #endif
39 
40 /* Use inline functions for compilers that support them, and static
41    functions for those that do not.  Because these functions become
42    static for compilers that do not support inline functions, this
43    header should only be included in files that actually use them.
44 */
45 #if defined(__GNUC__) && (defined(__i386__) || defined(__i586__) || defined(__i686__))&& \
46    !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
Swap16(UInt16 x)47 static __inline__ UInt16 Swap16(UInt16 x)
48 {
49     __asm__("xchgb %b0,%h0" : "=q" (x) :  "0" (x));
50     return x;
51 }
52 #elif defined(__GNUC__) && defined(__x86_64__)
Swap16(UInt16 x)53 static __inline__ UInt16 Swap16(UInt16 x)
54 {
55     __asm__("xchgb %b0,%h0" : "=Q" (x) :  "0" (x));
56     return x;
57 }
58 #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
Swap16(UInt16 x)59 static __inline__ UInt16 Swap16(UInt16 x)
60 {
61     UInt32 result;
62 
63     __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result) : "0" (x >> 8), "r" (x));
64     return (UInt16)result;
65 }
66 #elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__))
Swap16(UInt16 x)67 static __inline__ UInt16 Swap16(UInt16 x)
68 {
69     __asm__("rorw #8,%0" : "=d" (x) :  "0" (x) : "cc");
70     return x;
71 }
72 #else
Swap16(UInt16 x)73 static __inline__ UInt16 Swap16(UInt16 x)
74 {
75     return((x << 8) | (x >> 8));
76 }
77 #endif
78 
Swap32(UInt32 D)79 static __inline__ UInt32 Swap32(UInt32 D)
80 {
81     return((D << 24) | ((D << 8) & 0x00FF0000) | ((D >> 8) & 0x0000FF00) | (D >> 24));
82 }
83 
Swap64(UInt64 val)84 static __inline__ UInt64 Swap64(UInt64 val)
85 {
86     UInt32 hi, lo;
87     /* Separate into high and low 32-bit values and swap them */
88     lo = (UInt32)(val & 0xFFFFFFFF);
89     val >>= 32;
90     hi = (UInt32)(val & 0xFFFFFFFF);
91     val = Swap32(lo);
92     val <<= 32;
93     val |= Swap32(hi);
94     return(val);
95 }
96 
97 /* Byteswap item from the specified endianness to the native endianness */
98 #if (defined(__powerpc__) || defined(__ppc__) || defined(__M68000__) || defined(__M68020__))
99 #ifndef BOR_BIG_ENDIAN
100 #define BOR_BIG_ENDIAN
101 #endif
102 #endif
103 
104 #ifdef BOR_BIG_ENDIAN
105 #define SwapLSB16(X) Swap16(X)
106 #define SwapLSB32(X) Swap32(X)
107 #define SwapLSB64(X) Swap64(X)
108 #define SwapMSB16(X) (X)
109 #define SwapMSB32(X) (X)
110 #define SwapMSB64(X) (X)
111 #else
112 #define SwapLSB16(X) (X)
113 #define SwapLSB32(X) (X)
114 #define SwapLSB64(X) (X)
115 #define SwapMSB16(X) Swap16(X)
116 #define SwapMSB32(X) Swap32(X)
117 #define SwapMSB64(X) Swap64(X)
118 #endif
119 
120 #endif
121