Mercurial > spc_convert
comparison snes_spc/blargg_endian.h @ 0:e38dacceb958
initial import
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 21 Oct 2011 05:53:11 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e38dacceb958 |
---|---|
1 // CPU Byte Order Utilities | |
2 | |
3 // snes_spc 0.9.0 | |
4 #ifndef BLARGG_ENDIAN | |
5 #define BLARGG_ENDIAN | |
6 | |
7 #include "blargg_common.h" | |
8 | |
9 // BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) | |
10 #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ | |
11 defined (__x86_64__) || defined (__ia64__) || defined (__i386__) | |
12 #define BLARGG_CPU_X86 1 | |
13 #define BLARGG_CPU_CISC 1 | |
14 #endif | |
15 | |
16 #if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) | |
17 #define BLARGG_CPU_POWERPC 1 | |
18 #define BLARGG_CPU_RISC 1 | |
19 #endif | |
20 | |
21 // BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only | |
22 // one may be #defined to 1. Only needed if something actually depends on byte order. | |
23 #if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) | |
24 #ifdef __GLIBC__ | |
25 // GCC handles this for us | |
26 #include <endian.h> | |
27 #if __BYTE_ORDER == __LITTLE_ENDIAN | |
28 #define BLARGG_LITTLE_ENDIAN 1 | |
29 #elif __BYTE_ORDER == __BIG_ENDIAN | |
30 #define BLARGG_BIG_ENDIAN 1 | |
31 #endif | |
32 #else | |
33 | |
34 #if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ | |
35 (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) | |
36 #define BLARGG_LITTLE_ENDIAN 1 | |
37 #endif | |
38 | |
39 #if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ | |
40 defined (__sparc__) || BLARGG_CPU_POWERPC || \ | |
41 (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) | |
42 #define BLARGG_BIG_ENDIAN 1 | |
43 #elif !defined (__mips__) | |
44 // No endian specified; assume little-endian, since it's most common | |
45 #define BLARGG_LITTLE_ENDIAN 1 | |
46 #endif | |
47 #endif | |
48 #endif | |
49 | |
50 #if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN | |
51 #undef BLARGG_LITTLE_ENDIAN | |
52 #undef BLARGG_BIG_ENDIAN | |
53 #endif | |
54 | |
55 inline void blargg_verify_byte_order() | |
56 { | |
57 #ifndef NDEBUG | |
58 #if BLARGG_BIG_ENDIAN | |
59 volatile int i = 1; | |
60 assert( *(volatile char*) &i == 0 ); | |
61 #elif BLARGG_LITTLE_ENDIAN | |
62 volatile int i = 1; | |
63 assert( *(volatile char*) &i != 0 ); | |
64 #endif | |
65 #endif | |
66 } | |
67 | |
68 inline unsigned get_le16( void const* p ) | |
69 { | |
70 return (unsigned) ((unsigned char const*) p) [1] << 8 | | |
71 (unsigned) ((unsigned char const*) p) [0]; | |
72 } | |
73 | |
74 inline unsigned get_be16( void const* p ) | |
75 { | |
76 return (unsigned) ((unsigned char const*) p) [0] << 8 | | |
77 (unsigned) ((unsigned char const*) p) [1]; | |
78 } | |
79 | |
80 inline blargg_ulong get_le32( void const* p ) | |
81 { | |
82 return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | | |
83 (blargg_ulong) ((unsigned char const*) p) [2] << 16 | | |
84 (blargg_ulong) ((unsigned char const*) p) [1] << 8 | | |
85 (blargg_ulong) ((unsigned char const*) p) [0]; | |
86 } | |
87 | |
88 inline blargg_ulong get_be32( void const* p ) | |
89 { | |
90 return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | | |
91 (blargg_ulong) ((unsigned char const*) p) [1] << 16 | | |
92 (blargg_ulong) ((unsigned char const*) p) [2] << 8 | | |
93 (blargg_ulong) ((unsigned char const*) p) [3]; | |
94 } | |
95 | |
96 inline void set_le16( void* p, unsigned n ) | |
97 { | |
98 ((unsigned char*) p) [1] = (unsigned char) (n >> 8); | |
99 ((unsigned char*) p) [0] = (unsigned char) n; | |
100 } | |
101 | |
102 inline void set_be16( void* p, unsigned n ) | |
103 { | |
104 ((unsigned char*) p) [0] = (unsigned char) (n >> 8); | |
105 ((unsigned char*) p) [1] = (unsigned char) n; | |
106 } | |
107 | |
108 inline void set_le32( void* p, blargg_ulong n ) | |
109 { | |
110 ((unsigned char*) p) [0] = (unsigned char) n; | |
111 ((unsigned char*) p) [1] = (unsigned char) (n >> 8); | |
112 ((unsigned char*) p) [2] = (unsigned char) (n >> 16); | |
113 ((unsigned char*) p) [3] = (unsigned char) (n >> 24); | |
114 } | |
115 | |
116 inline void set_be32( void* p, blargg_ulong n ) | |
117 { | |
118 ((unsigned char*) p) [3] = (unsigned char) n; | |
119 ((unsigned char*) p) [2] = (unsigned char) (n >> 8); | |
120 ((unsigned char*) p) [1] = (unsigned char) (n >> 16); | |
121 ((unsigned char*) p) [0] = (unsigned char) (n >> 24); | |
122 } | |
123 | |
124 #if BLARGG_NONPORTABLE | |
125 // Optimized implementation if byte order is known | |
126 #if BLARGG_LITTLE_ENDIAN | |
127 #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) | |
128 #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) | |
129 #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) | |
130 #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) | |
131 #elif BLARGG_BIG_ENDIAN | |
132 #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) | |
133 #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) | |
134 #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) | |
135 #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) | |
136 | |
137 #if BLARGG_CPU_POWERPC | |
138 // PowerPC has special byte-reversed instructions | |
139 #if defined (__MWERKS__) | |
140 #define GET_LE16( addr ) (__lhbrx( addr, 0 )) | |
141 #define GET_LE32( addr ) (__lwbrx( addr, 0 )) | |
142 #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) | |
143 #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) | |
144 #elif defined (__GNUC__) | |
145 #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) | |
146 #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) | |
147 #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) | |
148 #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) | |
149 #endif | |
150 #endif | |
151 #endif | |
152 #endif | |
153 | |
154 #ifndef GET_LE16 | |
155 #define GET_LE16( addr ) get_le16( addr ) | |
156 #define SET_LE16( addr, data ) set_le16( addr, data ) | |
157 #endif | |
158 | |
159 #ifndef GET_LE32 | |
160 #define GET_LE32( addr ) get_le32( addr ) | |
161 #define SET_LE32( addr, data ) set_le32( addr, data ) | |
162 #endif | |
163 | |
164 #ifndef GET_BE16 | |
165 #define GET_BE16( addr ) get_be16( addr ) | |
166 #define SET_BE16( addr, data ) set_be16( addr, data ) | |
167 #endif | |
168 | |
169 #ifndef GET_BE32 | |
170 #define GET_BE32( addr ) get_be32( addr ) | |
171 #define SET_BE32( addr, data ) set_be32( addr, data ) | |
172 #endif | |
173 | |
174 // auto-selecting versions | |
175 | |
176 inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } | |
177 inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } | |
178 inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } | |
179 inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } | |
180 inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } | |
181 inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } | |
182 inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } | |
183 inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } | |
184 | |
185 #endif |