forked from cxd4/rsp
-
Notifications
You must be signed in to change notification settings - Fork 24
/
my_types.h
507 lines (463 loc) · 14.8 KB
/
my_types.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
/*
* minimum data types for MIPS and the Ultra64 RCP
*
* No copyright is intended on this file. :)
*
* To work with features of the RCP hardware, we need at the very least:
* 1. a 64-bit type or a type which can encompass 64-bit operations
* 2. signed and unsigned 32-or-more-bit types (s32, u32)
* 3. signed and unsigned 16-or-more-bit types (s16, u16)
* 4. signed and unsigned 8-or-more-bit types (s8, u8)
*
* This tends to coincide with the regulations of <stdint.h> and even most of
* what is guaranteed by simple preprocessor logic and the C89 standard, so
* the deduction of RCP hardware types will have the following priority:
* 1. compiler implementation of the <stdint.h> extension
* 2. 64-bit ABI detection by the preprocessor with help from <limits.h>
* 3. preprocessor derivation of literal integer interpretation
* 4. the presumption of C89 conformance for 8-, 16-, and 32-bit types
* and the presumption of `long long` support for 64-bit types
*/
/*
* Rather than call it "n64_types.h" or "my_stdint.h", the idea is that this
* header should be maintainable to any independent implementation's needs,
* especially in the event that one decides that type requirements should be
* mandated by the user and not permanently merged into the C specifications.
*
* Custom, collision-free type definitions are also useful in that they can
* be tested for cross-ABI portability by changing a custom type like `u32`
* from `unsigned long` to `unsigned short` or vice-versa.
*/
#ifndef _MY_TYPES_H_
#define _MY_TYPES_H_
#if defined(USE_SSE2NEON) && defined(__ARM_NEON__)
#include "sse2neon/SSE2NEON.h"
#define ARCH_MIN_SSE2
#endif
/*
* This is the only method we really need to care about for defining types.
*
* All concerns of absolute plausibility are addressed with minimum-width
* types; we do not require fixed-width types or any C99 dependency.
*/
#include <limits.h>
/*
* Until proven otherwise, there are no standard integer types.
*/
#undef HAVE_STANDARD_INTEGER_TYPES
/*
* an optional facility which could be used as an external alternative to
* deducing minimum-width types (if the compiler agrees to rely on this level
* of the language specifications to have it)
*
* Because no standard system is required to have any exact-width type, the
* C99 enforcement of <stdint.h> is more of an early initiative (as in,
* "better early than late" or "better early than never at all") rather than
* a fully portable resource available or even possible all of the time.
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#include <stdint.h>
#endif
/*
* Even with -std=c89 or -ansi, modern GCC will tend to supply <stdint.h>.
* That isn't needed--here--for LP64 ABI, however, so why assume it exists?
*/
#if defined(__GNUC__) && !defined(__LP64__)
#include <stdint.h>
#endif
/*
* With or without external or internal support for <stdint.h>, we need to
* confirm the level of support for RCP data types on the Nintendo 64.
*
* We only need minimum-width data types, not exact-width types.
* Systems on which there is no 16- or 32-bit type, for example, can easily
* be accounted for by the code itself using optimizable AND bit-masks.
*/
#if defined(INT8_MIN) && defined(INT8_MAX)
#define HAVE_INT8_EXACT
#endif
#if defined(INT_FAST8_MIN) && defined(INT_FAST8_MAX)
#define HAVE_INT8_FAST
#endif
#if defined(INT_LEAST8_MIN) && defined(INT_LEAST8_MAX)
#define HAVE_INT8_MINIMUM
#endif
#if defined(INT16_MIN) && defined(INT16_MAX)
#define HAVE_INT16_EXACT
#endif
#if defined(INT_FAST16_MIN) && defined(INT_FAST16_MAX)
#define HAVE_INT16_FAST
#endif
#if defined(INT_LEAST16_MIN) && defined(INT_LEAST16_MAX)
#define HAVE_INT16_MINIMUM
#endif
#if defined(INT32_MIN) && defined(INT32_MAX)
#define HAVE_INT32_EXACT
#endif
#if defined(INT_FAST32_MIN) && defined(INT_FAST32_MAX)
#define HAVE_INT32_FAST
#endif
#if defined(INT_LEAST32_MIN) && defined(INT_LEAST32_MAX)
#define HAVE_INT32_MINIMUM
#endif
#if defined(INT64_MIN) && defined(INT64_MAX)
#define HAVE_INT64_EXACT
#endif
#if defined(INT_FAST64_MIN) && defined(INT_FAST64_MAX)
#define HAVE_INT64_FAST
#endif
#if defined(INT_LEAST64_MIN) && defined(INT_LEAST64_MAX)
#define HAVE_INT64_MINIMUM
#endif
#if defined(HAVE_INT8_EXACT)\
|| defined(HAVE_INT8_FAST) \
|| defined(HAVE_INT8_MINIMUM)
#define HAVE_INT8
#endif
#if defined(HAVE_INT16_EXACT)\
|| defined(HAVE_INT16_FAST) \
|| defined(HAVE_INT16_MINIMUM)
#define HAVE_INT16
#endif
#if defined(HAVE_INT32_EXACT)\
|| defined(HAVE_INT32_FAST) \
|| defined(HAVE_INT32_MINIMUM)
#define HAVE_INT32
#endif
#if defined(HAVE_INT64_EXACT)\
|| defined(HAVE_INT64_FAST) \
|| defined(HAVE_INT64_MINIMUM)
#define HAVE_INT64
#endif
/*
* This determines whether or not it is possible to use the evolution of the
* C standards for compiler advice on how to define the types or whether we
* will instead rely on preprocessor logic and ABI detection or C89 rules to
* define each of the types.
*/
#if defined(HAVE_INT8) \
&& defined(HAVE_INT16)\
&& defined(HAVE_INT32)\
&& defined(HAVE_INT64)
#define HAVE_STANDARD_INTEGER_TYPES
#endif
/*
* Since the Microsoft Windows API frequently uses `long` instead of `int` to
* guarantee 32-bit DWORD types, they were forced to propose a "LLP64" ABI.
*/
#if defined(_MSC_VER)
#define MICROSOFT_ABI
#endif
#if defined(HAVE_INT8_EXACT)
typedef int8_t s8;
typedef uint8_t u8;
typedef s8 i8;
#elif defined(HAVE_INT8_FAST)
typedef int_fast8_t s8;
typedef uint_fast8_t u8;
typedef s8 i8;
#elif defined(HAVE_INT8_MINIMUM)
typedef int_least8_t s8;
typedef uint_least8_t u8;
typedef s8 i8;
#elif defined(MICROSOFT_ABI)
typedef signed __int8 s8;
typedef unsigned __int8 u8;
typedef __int8 i8;
#elif (SCHAR_MIN < -127 && SCHAR_MAX >= +127)
typedef signed char s8;
typedef unsigned char u8;
typedef char i8;
#else
#error Non-ANSI-conformant `char` size.
#endif
#if defined(HAVE_INT16_EXACT)
typedef int16_t s16;
typedef uint16_t u16;
#elif defined(HAVE_INT16_FAST)
typedef int_fast16_t s16;
typedef uint_fast16_t u16;
#elif defined(HAVE_INT16_MINIMUM)
typedef int_least16_t s16;
typedef uint_least16_t u16;
#elif defined(MICROSOFT_ABI)
typedef signed __int16 s16;
typedef unsigned __int16 u16;
#elif (SCHAR_MIN < -32767 && SCHAR_MAX >= +32767)
typedef signed char s16;
typedef unsigned char u16;
#else
typedef signed short s16;
typedef unsigned short u16;
#endif
#if defined(HAVE_INT32_EXACT)
typedef int32_t s32;
typedef uint32_t u32;
#elif defined(HAVE_INT32_FAST)
typedef int_fast32_t s32;
typedef uint_fast32_t u32;
#elif defined(HAVE_INT32_MINIMUM)
typedef int_least32_t s32;
typedef uint_least32_t u32;
#elif defined(MICROSOFT_ABI)
typedef signed __int32 s32;
typedef unsigned __int32 u32;
#elif (SCHAR_MIN < -2147483647L && SCHAR_MAX >= +2147483647L)
typedef signed char s32;
typedef unsigned char u32;
#elif (SHRT_MIN < -2147483647L && SHRT_MAX >= +2147483647L)
typedef signed short s32;
typedef unsigned short u32;
#elif (INT_MIN < -2147483647L && INT_MAX >= +2147483647L)
typedef signed int s32;
typedef unsigned int u32;
#else
typedef signed long s32;
typedef unsigned long u32;
#endif
#if defined(HAVE_INT64_EXACT)
typedef int64_t s64;
typedef uint64_t u64;
#elif defined(HAVE_INT64_FAST)
typedef int_fast64_t s64;
typedef uint_fast64_t u64;
#elif defined(HAVE_INT64_MINIMUM)
typedef int_least64_t s64;
typedef uint_least64_t u64;
#elif defined(MICROSOFT_ABI)
typedef signed __int64 s64;
typedef unsigned __int64 u64;
#elif defined(__LP64__) && (0x00000000FFFFFFFFUL < ~0UL)
typedef signed long s64;
typedef unsigned long u64;
#elif (LONG_MIN < -9223372036854775807L && LONG_MAX >= +9223372036854775807L)
typedef signed long s64;
typedef unsigned long u64;
#else
typedef signed long long s64;
typedef unsigned long long u64;
#endif
/*
* Although most types are signed by default, using `int' instead of `signed
* int' and `i32' instead of `s32' can be preferable to denote cases where
* the signedness of something operated on is irrelevant to the algorithm.
*/
typedef s16 i16;
typedef s32 i32;
typedef s64 i64;
/*
* If <stdint.h> was unavailable or not included (should be included before
* "my_types.h" if it is ever to be included), then perhaps this is the
* right opportunity to try defining the <stdint.h> types ourselves.
*
* Due to sole popularity, code can sometimes be easier to read when saying
* things like "int8_t" instead of "i8", just because more people are more
* likely to understand the <stdint.h> type names in generic C code. To be
* as neutral as possible, people will have every right to sometimes prefer
* saying "uint32_t" instead of "u32" for the sake of modern standards.
*
* The below macro just means whether or not we had access to <stdint.h>
* material to deduce any of our 8-, 16-, 32-, or 64-bit type definitions.
*/
#ifndef HAVE_STANDARD_INTEGER_TYPES
typedef s8 int8_t;
typedef u8 uint8_t;
typedef s16 int16_t;
typedef u16 uint16_t;
typedef s32 int32_t;
typedef u32 uint32_t;
typedef s64 int64_t;
typedef u64 uint64_t;
#define HAVE_STANDARD_INTEGER_TYPES
#endif
/*
* MIPS-native types are `float' for f32, `double' for f64.
* These type requirements are based on the MIPS manuals on the FPU.
*/
#include <float.h>
#if (FLT_MANT_DIG >= 24) && (FLT_MAX_EXP > 127)
typedef float f32;
#elif (DBL_MANT_DIG >= 24) && (DBL_MAX_EXP > 127)
typedef double f32;
#elif (LDBL_MANT_DIG >= 24) && (LDBL_MAX_EXP > 127)
typedef long double f32;
#else
typedef struct {
#if (UINT_MAX >= (0x00000001UL << 23) - 1UL)
unsigned f: 23; /* mantissa fraction */
#else
unsigned long f;
#endif
unsigned e: 8; /* biased exponent, from -126 to +127 for generic values */
unsigned s: 1; /* mantissa sign bit */
} f32;
#endif
#if (DBL_MANT_DIG >= 53) && (DBL_MAX_EXP > 1023)
typedef double f64;
#elif (LDBL_MANT_DIG >= 53) && (LDBL_MAX_EXP > 1023)
typedef long double f64;
#else
typedef struct {
uint64_t f/*: 52*/;
unsigned e: 11;
unsigned s: 1;
} f64;
#endif
/*
* Pointer types, serving as the memory reference address to the actual type.
* I thought this was useful to have due to the various reasons for declaring
* or using variable pointers in various styles and complex scenarios.
* ex) i32* pointer;
* ex) i32 * pointer;
* ex) i32 *a, *b, *c;
* neutral: `pi32 pointer;' or `pi32 a, b, c;'
*/
typedef i8* pi8;
typedef i16* pi16;
typedef i32* pi32;
typedef i64* pi64;
typedef s8* ps8;
typedef s16* ps16;
typedef s32* ps32;
typedef s64* ps64;
typedef u8* pu8;
typedef u16* pu16;
typedef u32* pu32;
typedef u64* pu64;
typedef f32* pf32;
typedef f64* pf64;
typedef void* p_void;
typedef void(*p_func)(void);
/*
* helper macros with exporting functions for shared objects or dynamically
* loaded libraries
*/
#if defined(M64P_PLUGIN_API)
#define M64P_PLUGIN_PROTOTYPES 1
#include "m64p_common.h"
#include "m64p_config.h"
#include "m64p_plugin.h"
#include "m64p_types.h"
#include "osal_dynamiclib.h"
#else
#if defined(_WIN32)
#define EXPORT __declspec(dllexport)
#define CALL __cdecl
#else
#define EXPORT __attribute__((visibility("default")))
#define CALL
#endif
#endif
/*
* Commonly, Ultra64 will refer to these common symbols.
* They seem to be fairly widely used outside of just <windows.h>.
*/
#if !defined(TRUE) && !defined(FALSE)
#define FALSE 0
#define TRUE 1
#endif
/*
* Optimizing compilers aren't necessarily perfect compilers, but they do
* have that extra chance of supporting explicit [anti-]inline instructions.
*/
#ifdef _MSC_VER
#define INLINE __inline
#define NOINLINE __declspec(noinline)
#define ALIGNED _declspec(align(16))
#elif defined(__GNUC__)
#define INLINE inline
#define NOINLINE __attribute__((noinline))
#define ALIGNED __attribute__((aligned(16)))
#else
#define INLINE
#define NOINLINE
#define ALIGNED
#endif
/*
* aliasing helpers
* Strictly put, this may be unspecified behavior, but it's nice to have!
*/
typedef union {
u8 B[2];
s8 SB[2];
i16 W;
u16 UW;
s16 SW; /* Here, again, explicitly writing "signed" may help clarity. */
} word_16;
typedef union {
u8 B[4];
s8 SB[4];
i16 H[2];
u16 UH[2];
s16 SH[2];
i32 W;
u32 UW;
s32 SW;
} word_32;
typedef union {
u8 B[8];
s8 SB[8];
i16 Q[4];
u16 UQ[4];
s16 SQ[4];
i32 H[2];
u32 UH[2];
s32 SH[2];
i64 W;
u64 UW;
s64 SW;
} word_64;
/*
* helper macros for indexing memory in the above unions
* EEP! Currently concentrates mostly on 32-bit endianness.
*/
#ifndef ENDIAN_M
#if defined(__BIG_ENDIAN__)
#define ENDIAN_M ( 0U)
#else
#define ENDIAN_M (~0U)
#endif
#endif
#define ENDIAN_SWAP_BYTE (ENDIAN_M & 7U & 3U)
#define ENDIAN_SWAP_HALF (ENDIAN_M & 6U & 2U)
#define ENDIAN_SWAP_BIMI (ENDIAN_M & 5U & 1U)
#define ENDIAN_SWAP_WORD (ENDIAN_M & 4U & 0U)
#define BES(address) ((address) ^ ENDIAN_SWAP_BYTE)
#define HES(address) ((address) ^ ENDIAN_SWAP_HALF)
#define MES(address) ((address) ^ ENDIAN_SWAP_BIMI)
#define WES(address) ((address) ^ ENDIAN_SWAP_WORD)
/*
* extra types of encoding for the well-known MIPS RISC architecture
* Possibly implement other machine types in future versions of this header.
*/
typedef struct {
unsigned opcode : 6;
unsigned rs : 5;
unsigned rt : 5;
unsigned rd : 5;
unsigned sa : 5;
unsigned function : 6;
} MIPS_type_R;
typedef struct {
unsigned opcode : 6;
unsigned rs : 5;
unsigned rt : 5;
unsigned immediate: 16;
} MIPS_type_I;
#if (UINT_MAX >= (0x00000001UL << 26) - 1UL)
typedef struct {
unsigned opcode : 6;
unsigned target : 26;
} MIPS_type_J;
#else
typedef struct {
unsigned opcode : 6;
unsigned long target; /* If `int' can't store 26 bits, `long' can. */
} MIPS_type_J;
#endif
#if defined(__arm__) && (defined(__GNUC__) || defined(__clang__))
#define COMPILER_FENCE() __asm__ __volatile__("":::"memory")
#else
#define COMPILER_FENCE()
#endif
#endif