PageRenderTime 18ms CodeModel.GetById 8ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/gme/blargg_endian.h

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