Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RishiRecon
GitHub Repository: RishiRecon/exploits
Path: blob/main/misc/emulator/xnes/snes9x/apu/blargg_endian.h
28798 views
1
// CPU Byte Order Utilities
2
3
// snes_spc 0.9.0
4
#ifndef BLARGG_ENDIAN
5
#define BLARGG_ENDIAN
6
7
#include "blargg_common.h"
8
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 1
13
#define BLARGG_CPU_CISC 1
14
#endif
15
16
#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
17
#define BLARGG_CPU_POWERPC 1
18
#define BLARGG_CPU_RISC 1
19
#endif
20
21
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
22
// 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 us
26
#include <endian.h>
27
#if __BYTE_ORDER == __LITTLE_ENDIAN
28
#define BLARGG_LITTLE_ENDIAN 1
29
#elif __BYTE_ORDER == __BIG_ENDIAN
30
#define BLARGG_BIG_ENDIAN 1
31
#endif
32
#else
33
34
#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
35
(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
36
#define BLARGG_LITTLE_ENDIAN 1
37
#endif
38
39
#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 1
43
#elif !defined (__mips__)
44
// No endian specified; assume little-endian, since it's most common
45
#define BLARGG_LITTLE_ENDIAN 1
46
#endif
47
#endif
48
#endif
49
50
#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
51
#undef BLARGG_LITTLE_ENDIAN
52
#undef BLARGG_BIG_ENDIAN
53
#endif
54
55
inline void blargg_verify_byte_order()
56
{
57
#ifndef NDEBUG
58
#if BLARGG_BIG_ENDIAN
59
volatile int i = 1;
60
assert( *(volatile char*) &i == 0 );
61
#elif BLARGG_LITTLE_ENDIAN
62
volatile int i = 1;
63
assert( *(volatile char*) &i != 0 );
64
#endif
65
#endif
66
}
67
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
}
73
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
}
79
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
}
87
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
}
95
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
}
101
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
}
107
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
}
115
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
}
123
124
#if BLARGG_NONPORTABLE
125
// Optimized implementation if byte order is known
126
#if BLARGG_LITTLE_ENDIAN
127
#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_ENDIAN
132
#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))
136
137
#if BLARGG_CPU_POWERPC
138
// PowerPC has special byte-reversed instructions
139
#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
#endif
150
#endif
151
#endif
152
#endif
153
154
#ifndef GET_LE16
155
#define GET_LE16( addr ) get_le16( addr )
156
#define SET_LE16( addr, data ) set_le16( addr, data )
157
#endif
158
159
#ifndef GET_LE32
160
#define GET_LE32( addr ) get_le32( addr )
161
#define SET_LE32( addr, data ) set_le32( addr, data )
162
#endif
163
164
#ifndef GET_BE16
165
#define GET_BE16( addr ) get_be16( addr )
166
#define SET_BE16( addr, data ) set_be16( addr, data )
167
#endif
168
169
#ifndef GET_BE32
170
#define GET_BE32( addr ) get_be32( addr )
171
#define SET_BE32( addr, data ) set_be32( addr, data )
172
#endif
173
174
// auto-selecting versions
175
176
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 ); }
184
185
#endif
186
187