Mercurial > spc_convert
view snes_spc/blargg_endian.h @ 9:477c36226481 tip
added old scripts for historical interest.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 21 Oct 2011 07:46:18 -0700 |
parents | e38dacceb958 |
children |
line wrap: on
line source
1 // CPU Byte Order Utilities3 // snes_spc 0.9.04 #ifndef BLARGG_ENDIAN5 #define BLARGG_ENDIAN7 #include "blargg_common.h"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 113 #define BLARGG_CPU_CISC 114 #endif16 #if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)17 #define BLARGG_CPU_POWERPC 118 #define BLARGG_CPU_RISC 119 #endif21 // BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only22 // 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 us26 #include <endian.h>27 #if __BYTE_ORDER == __LITTLE_ENDIAN28 #define BLARGG_LITTLE_ENDIAN 129 #elif __BYTE_ORDER == __BIG_ENDIAN30 #define BLARGG_BIG_ENDIAN 131 #endif32 #else34 #if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \35 (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)36 #define BLARGG_LITTLE_ENDIAN 137 #endif39 #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 143 #elif !defined (__mips__)44 // No endian specified; assume little-endian, since it's most common45 #define BLARGG_LITTLE_ENDIAN 146 #endif47 #endif48 #endif50 #if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN51 #undef BLARGG_LITTLE_ENDIAN52 #undef BLARGG_BIG_ENDIAN53 #endif55 inline void blargg_verify_byte_order()56 {57 #ifndef NDEBUG58 #if BLARGG_BIG_ENDIAN59 volatile int i = 1;60 assert( *(volatile char*) &i == 0 );61 #elif BLARGG_LITTLE_ENDIAN62 volatile int i = 1;63 assert( *(volatile char*) &i != 0 );64 #endif65 #endif66 }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 }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 }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 }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 }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 }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 }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 }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 }124 #if BLARGG_NONPORTABLE125 // Optimized implementation if byte order is known126 #if BLARGG_LITTLE_ENDIAN127 #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_ENDIAN132 #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))137 #if BLARGG_CPU_POWERPC138 // PowerPC has special byte-reversed instructions139 #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 #endif150 #endif151 #endif152 #endif154 #ifndef GET_LE16155 #define GET_LE16( addr ) get_le16( addr )156 #define SET_LE16( addr, data ) set_le16( addr, data )157 #endif159 #ifndef GET_LE32160 #define GET_LE32( addr ) get_le32( addr )161 #define SET_LE32( addr, data ) set_le32( addr, data )162 #endif164 #ifndef GET_BE16165 #define GET_BE16( addr ) get_be16( addr )166 #define SET_BE16( addr, data ) set_be16( addr, data )167 #endif169 #ifndef GET_BE32170 #define GET_BE32( addr ) get_be32( addr )171 #define SET_BE32( addr, data ) set_be32( addr, data )172 #endif174 // auto-selecting versions176 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 ); }185 #endif