diff 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
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/snes_spc/blargg_endian.h	Fri Oct 21 05:53:11 2011 -0700
     1.3 @@ -0,0 +1,185 @@
     1.4 +// CPU Byte Order Utilities
     1.5 +
     1.6 +// snes_spc 0.9.0
     1.7 +#ifndef BLARGG_ENDIAN
     1.8 +#define BLARGG_ENDIAN
     1.9 +
    1.10 +#include "blargg_common.h"
    1.11 +
    1.12 +// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
    1.13 +#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
    1.14 +		defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
    1.15 +	#define BLARGG_CPU_X86 1
    1.16 +	#define BLARGG_CPU_CISC 1
    1.17 +#endif
    1.18 +
    1.19 +#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
    1.20 +	#define BLARGG_CPU_POWERPC 1
    1.21 +	#define BLARGG_CPU_RISC 1
    1.22 +#endif
    1.23 +
    1.24 +// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
    1.25 +// one may be #defined to 1. Only needed if something actually depends on byte order.
    1.26 +#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
    1.27 +#ifdef __GLIBC__
    1.28 +	// GCC handles this for us
    1.29 +	#include <endian.h>
    1.30 +	#if __BYTE_ORDER == __LITTLE_ENDIAN
    1.31 +		#define BLARGG_LITTLE_ENDIAN 1
    1.32 +	#elif __BYTE_ORDER == __BIG_ENDIAN
    1.33 +		#define BLARGG_BIG_ENDIAN 1
    1.34 +	#endif
    1.35 +#else
    1.36 +
    1.37 +#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
    1.38 +		(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
    1.39 +	#define BLARGG_LITTLE_ENDIAN 1
    1.40 +#endif
    1.41 +
    1.42 +#if defined (MSB_FIRST)     || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
    1.43 +	defined (__sparc__)     ||  BLARGG_CPU_POWERPC || \
    1.44 +	(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
    1.45 +	#define BLARGG_BIG_ENDIAN 1
    1.46 +#elif !defined (__mips__)
    1.47 +	// No endian specified; assume little-endian, since it's most common
    1.48 +	#define BLARGG_LITTLE_ENDIAN 1
    1.49 +#endif
    1.50 +#endif
    1.51 +#endif
    1.52 +
    1.53 +#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
    1.54 +	#undef BLARGG_LITTLE_ENDIAN
    1.55 +	#undef BLARGG_BIG_ENDIAN
    1.56 +#endif
    1.57 +
    1.58 +inline void blargg_verify_byte_order()
    1.59 +{
    1.60 +	#ifndef NDEBUG
    1.61 +		#if BLARGG_BIG_ENDIAN
    1.62 +			volatile int i = 1;
    1.63 +			assert( *(volatile char*) &i == 0 );
    1.64 +		#elif BLARGG_LITTLE_ENDIAN
    1.65 +			volatile int i = 1;
    1.66 +			assert( *(volatile char*) &i != 0 );
    1.67 +		#endif
    1.68 +	#endif
    1.69 +}
    1.70 +
    1.71 +inline unsigned get_le16( void const* p )
    1.72 +{
    1.73 +	return  (unsigned) ((unsigned char const*) p) [1] << 8 |
    1.74 +			(unsigned) ((unsigned char const*) p) [0];
    1.75 +}
    1.76 +
    1.77 +inline unsigned get_be16( void const* p )
    1.78 +{
    1.79 +	return  (unsigned) ((unsigned char const*) p) [0] << 8 |
    1.80 +			(unsigned) ((unsigned char const*) p) [1];
    1.81 +}
    1.82 +
    1.83 +inline blargg_ulong get_le32( void const* p )
    1.84 +{
    1.85 +	return  (blargg_ulong) ((unsigned char const*) p) [3] << 24 |
    1.86 +			(blargg_ulong) ((unsigned char const*) p) [2] << 16 |
    1.87 +			(blargg_ulong) ((unsigned char const*) p) [1] <<  8 |
    1.88 +			(blargg_ulong) ((unsigned char const*) p) [0];
    1.89 +}
    1.90 +
    1.91 +inline blargg_ulong get_be32( void const* p )
    1.92 +{
    1.93 +	return  (blargg_ulong) ((unsigned char const*) p) [0] << 24 |
    1.94 +			(blargg_ulong) ((unsigned char const*) p) [1] << 16 |
    1.95 +			(blargg_ulong) ((unsigned char const*) p) [2] <<  8 |
    1.96 +			(blargg_ulong) ((unsigned char const*) p) [3];
    1.97 +}
    1.98 +
    1.99 +inline void set_le16( void* p, unsigned n )
   1.100 +{
   1.101 +	((unsigned char*) p) [1] = (unsigned char) (n >> 8);
   1.102 +	((unsigned char*) p) [0] = (unsigned char) n;
   1.103 +}
   1.104 +
   1.105 +inline void set_be16( void* p, unsigned n )
   1.106 +{
   1.107 +	((unsigned char*) p) [0] = (unsigned char) (n >> 8);
   1.108 +	((unsigned char*) p) [1] = (unsigned char) n;
   1.109 +}
   1.110 +
   1.111 +inline void set_le32( void* p, blargg_ulong n )
   1.112 +{
   1.113 +	((unsigned char*) p) [0] = (unsigned char) n;
   1.114 +	((unsigned char*) p) [1] = (unsigned char) (n >> 8);
   1.115 +	((unsigned char*) p) [2] = (unsigned char) (n >> 16);
   1.116 +	((unsigned char*) p) [3] = (unsigned char) (n >> 24);
   1.117 +}
   1.118 +
   1.119 +inline void set_be32( void* p, blargg_ulong n )
   1.120 +{
   1.121 +	((unsigned char*) p) [3] = (unsigned char) n;
   1.122 +	((unsigned char*) p) [2] = (unsigned char) (n >> 8);
   1.123 +	((unsigned char*) p) [1] = (unsigned char) (n >> 16);
   1.124 +	((unsigned char*) p) [0] = (unsigned char) (n >> 24);
   1.125 +}
   1.126 +
   1.127 +#if BLARGG_NONPORTABLE
   1.128 +	// Optimized implementation if byte order is known
   1.129 +	#if BLARGG_LITTLE_ENDIAN
   1.130 +		#define GET_LE16( addr )        (*(BOOST::uint16_t*) (addr))
   1.131 +		#define GET_LE32( addr )        (*(BOOST::uint32_t*) (addr))
   1.132 +		#define SET_LE16( addr, data )  (void) (*(BOOST::uint16_t*) (addr) = (data))
   1.133 +		#define SET_LE32( addr, data )  (void) (*(BOOST::uint32_t*) (addr) = (data))
   1.134 +	#elif BLARGG_BIG_ENDIAN
   1.135 +		#define GET_BE16( addr )        (*(BOOST::uint16_t*) (addr))
   1.136 +		#define GET_BE32( addr )        (*(BOOST::uint32_t*) (addr))
   1.137 +		#define SET_BE16( addr, data )  (void) (*(BOOST::uint16_t*) (addr) = (data))
   1.138 +		#define SET_BE32( addr, data )  (void) (*(BOOST::uint32_t*) (addr) = (data))
   1.139 +		
   1.140 +		#if BLARGG_CPU_POWERPC
   1.141 +			// PowerPC has special byte-reversed instructions
   1.142 +			#if defined (__MWERKS__)
   1.143 +				#define GET_LE16( addr )        (__lhbrx( addr, 0 ))
   1.144 +				#define GET_LE32( addr )        (__lwbrx( addr, 0 ))
   1.145 +				#define SET_LE16( addr, in )    (__sthbrx( in, addr, 0 ))
   1.146 +				#define SET_LE32( addr, in )    (__stwbrx( in, addr, 0 ))
   1.147 +			#elif defined (__GNUC__)
   1.148 +				#define GET_LE16( addr )        ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;})
   1.149 +				#define GET_LE32( addr )        ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;})
   1.150 +				#define SET_LE16( addr, in )    ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );})
   1.151 +				#define SET_LE32( addr, in )    ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );})
   1.152 +			#endif
   1.153 +		#endif
   1.154 +	#endif
   1.155 +#endif
   1.156 +
   1.157 +#ifndef GET_LE16
   1.158 +	#define GET_LE16( addr )        get_le16( addr )
   1.159 +	#define SET_LE16( addr, data )  set_le16( addr, data )
   1.160 +#endif
   1.161 +
   1.162 +#ifndef GET_LE32
   1.163 +	#define GET_LE32( addr )        get_le32( addr )
   1.164 +	#define SET_LE32( addr, data )  set_le32( addr, data )
   1.165 +#endif
   1.166 +
   1.167 +#ifndef GET_BE16
   1.168 +	#define GET_BE16( addr )        get_be16( addr )
   1.169 +	#define SET_BE16( addr, data )  set_be16( addr, data )
   1.170 +#endif
   1.171 +
   1.172 +#ifndef GET_BE32
   1.173 +	#define GET_BE32( addr )        get_be32( addr )
   1.174 +	#define SET_BE32( addr, data )  set_be32( addr, data )
   1.175 +#endif
   1.176 +
   1.177 +// auto-selecting versions
   1.178 +
   1.179 +inline void set_le( BOOST::uint16_t* p, unsigned     n ) { SET_LE16( p, n ); }
   1.180 +inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); }
   1.181 +inline void set_be( BOOST::uint16_t* p, unsigned     n ) { SET_BE16( p, n ); }
   1.182 +inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); }
   1.183 +inline unsigned     get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); }
   1.184 +inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); }
   1.185 +inline unsigned     get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); }
   1.186 +inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); }
   1.187 +
   1.188 +#endif