Mercurial > spc_convert
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