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