Path: blob/main/misc/emulator/xnes/snes9x/apu/blargg_endian.h
28798 views
// CPU Byte Order Utilities12// snes_spc 0.9.03#ifndef BLARGG_ENDIAN4#define BLARGG_ENDIAN56#include "blargg_common.h"78// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)9#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \10defined (__x86_64__) || defined (__ia64__) || defined (__i386__)11#define BLARGG_CPU_X86 112#define BLARGG_CPU_CISC 113#endif1415#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)16#define BLARGG_CPU_POWERPC 117#define BLARGG_CPU_RISC 118#endif1920// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only21// 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 us25#include <endian.h>26#if __BYTE_ORDER == __LITTLE_ENDIAN27#define BLARGG_LITTLE_ENDIAN 128#elif __BYTE_ORDER == __BIG_ENDIAN29#define BLARGG_BIG_ENDIAN 130#endif31#else3233#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \34(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)35#define BLARGG_LITTLE_ENDIAN 136#endif3738#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \39defined (__sparc__) || BLARGG_CPU_POWERPC || \40(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)41#define BLARGG_BIG_ENDIAN 142#elif !defined (__mips__)43// No endian specified; assume little-endian, since it's most common44#define BLARGG_LITTLE_ENDIAN 145#endif46#endif47#endif4849#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN50#undef BLARGG_LITTLE_ENDIAN51#undef BLARGG_BIG_ENDIAN52#endif5354inline void blargg_verify_byte_order()55{56#ifndef NDEBUG57#if BLARGG_BIG_ENDIAN58volatile int i = 1;59assert( *(volatile char*) &i == 0 );60#elif BLARGG_LITTLE_ENDIAN61volatile int i = 1;62assert( *(volatile char*) &i != 0 );63#endif64#endif65}6667inline unsigned get_le16( void const* p )68{69return (unsigned) ((unsigned char const*) p) [1] << 8 |70(unsigned) ((unsigned char const*) p) [0];71}7273inline unsigned get_be16( void const* p )74{75return (unsigned) ((unsigned char const*) p) [0] << 8 |76(unsigned) ((unsigned char const*) p) [1];77}7879inline blargg_ulong get_le32( void const* p )80{81return (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}8687inline blargg_ulong get_be32( void const* p )88{89return (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}9495inline 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}100101inline 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}106107inline 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}114115inline 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}122123#if BLARGG_NONPORTABLE124// Optimized implementation if byte order is known125#if BLARGG_LITTLE_ENDIAN126#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_ENDIAN131#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))135136#if BLARGG_CPU_POWERPC137// PowerPC has special byte-reversed instructions138#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 ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;})145#define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;})146#define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );})147#define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );})148#endif149#endif150#endif151#endif152153#ifndef GET_LE16154#define GET_LE16( addr ) get_le16( addr )155#define SET_LE16( addr, data ) set_le16( addr, data )156#endif157158#ifndef GET_LE32159#define GET_LE32( addr ) get_le32( addr )160#define SET_LE32( addr, data ) set_le32( addr, data )161#endif162163#ifndef GET_BE16164#define GET_BE16( addr ) get_be16( addr )165#define SET_BE16( addr, data ) set_be16( addr, data )166#endif167168#ifndef GET_BE32169#define GET_BE32( addr ) get_be32( addr )170#define SET_BE32( addr, data ) set_be32( addr, data )171#endif172173// auto-selecting versions174175inline 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 ); }183184#endif185186187