1 #ifndef _BURN_ENDIAN_H
2 #define _BURN_ENDIAN_H
3 
4 #ifdef LSB_FIRST
5 typedef union
6 {
7 	struct { UINT8 l,h,h2,h3; } b;
8 	struct { UINT16 l,h; } w;
9 	UINT32 d;
10 } PAIR;
11 
12 #define BURN_ENDIAN_SWAP_INT8(x)				x
13 #define BURN_ENDIAN_SWAP_INT16(x)				x
14 #define BURN_ENDIAN_SWAP_INT32(x)				x
15 #define BURN_ENDIAN_SWAP_INT64(x)				x
16 #else
17 
18 // Xbox 360 has byteswap 64-bit intrinsic
19 #ifndef _XBOX
20 #define NO_64BIT_BYTESWAP
21 #endif
22 
23 // psl1ght uses those intrinsics too
24 #if defined(__PSL1GHT__) && !defined(__CELLOS_LV2__)
25 #define __CELLOS_LV2__
26 #endif
27 
28 typedef union {
29   struct { UINT8 h3,h2,h,l; } b;
30   struct { UINT16 h,l; } w;
31   UINT32 d;
32 } PAIR;
33 
34 #ifdef NO_64BIT_BYTESWAP
35 typedef union {
36    UINT64 ll;
37    struct { UINT32 l, h; } l;
38 } BYTESWAP_INT64;
39 #endif
40 
41 // Libogc doesn't have intrinsics or ASM macros defined for this
42 #if defined(HW_RVL) || defined(GEKKO)
43 #define __sthbrx(base,index,value)      \
44         __asm__ volatile ("sthbrx       %0,%1,%2" : : "r"(value), "b%"(index), "r"(base) : "memory")
45 
46 #define __stwbrx(base,index,value)      \
47         __asm__ volatile ("stwbrx       %0,%1,%2" : : "r"(value), "b%"(index), "r"(base) : "memory")
48 #endif
49 
50 // Xbox 360
51 #if defined(_XBOX)
52 #define BURN_ENDIAN_SWAP_INT8(x)				(x^1)
53 #define BURN_ENDIAN_SWAP_INT16(x)				(_byteswap_ushort(x))
54 #define BURN_ENDIAN_SWAP_INT32(x)				(_byteswap_ulong(x))
55 #define BURN_ENDIAN_SWAP_INT64(x)				(_byteswap_uint64(x))
56 // PS3
57 #elif defined(__CELLOS_LV2__)
58 #include <ppu_intrinsics.h>
59 #include <math.h>
60 #define BURN_ENDIAN_SWAP_INT8(x)				(x^1)
61 #define BURN_ENDIAN_SWAP_INT16(x)				({uint16_t tt; __sthbrx(&tt, x); tt;})
62 #define BURN_ENDIAN_SWAP_INT32(x)				({uint32_t tt; __stwbrx(&tt, x); tt;})
63 // GC/Wii/WiiU
64 #elif defined(HW_RVL)
65 #define BURN_ENDIAN_SWAP_INT8(x)				(x^1)
66 #define BURN_ENDIAN_SWAP_INT16(x)				({uint16_t tt; __sthbrx(&tt, 0, x); tt;})
67 #define BURN_ENDIAN_SWAP_INT32(x)				({uint32_t tt; __stwbrx(&tt, 0, x); tt;})
68 // gcc/clang
69 #elif defined(__GNUC__)
70 #define BURN_ENDIAN_SWAP_INT8(x)				(x^1)
71 #define BURN_ENDIAN_SWAP_INT16(x)				(__builtin_bswap16(x))
72 #define BURN_ENDIAN_SWAP_INT32(x)				(__builtin_bswap32(x))
73 // Anything else (swap16 & swap32 are kinda broken though)
74 #else
75 #define BURN_ENDIAN_SWAP_INT8(x)				(x^1)
76 #define BURN_ENDIAN_SWAP_INT16(x)				((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))
77 #define BURN_ENDIAN_SWAP_INT32(x)				((((x) << 24) & 0xff000000) | (((x) << 8) & 0x00ff0000) | (((x) >> 8) & 0x0000ff00) | (((x) >> 24) & 0x000000ff))
78 #endif
79 
80 #ifdef NO_64BIT_BYTESWAP
BURN_ENDIAN_SWAP_INT64(UINT64 x)81 static inline UINT64 BURN_ENDIAN_SWAP_INT64(UINT64 x)
82 {
83 	BYTESWAP_INT64 r = {0};
84 	r.l.l = BURN_ENDIAN_SWAP_INT32(x);
85 	r.l.h = BURN_ENDIAN_SWAP_INT32(x >> 32);
86 	return r.ll;
87 }
88 #endif
89 
90 #endif
91 
92 #endif
93