SH4ZAM! 0.1.0
Fast math library for the Sega Dreamcast's SH4 CPU
Loading...
Searching...
No Matches
shz_cdefs.h
Go to the documentation of this file.
1/*! \file
2 * \brief Preprocessor definitions and macro utilities.
3 *
4 * This file contains commonly used preprocessor definitions used throughout
5 * the project:
6 * - Compiler attributes
7 * - Miscellaneous utilities
8 *
9 * \author 2025, 2026 Falco Girgis
10 * \copyright MIT License
11 */
12
13#ifndef SHZ_CDEFS_H
14#define SHZ_CDEFS_H
15
16#include <stdint.h>
17#include <assert.h>
18
19#ifdef __cplusplus
20# include <type_traits>
21#endif
22
23#define SHZ_SH4 1
24#define SHZ_PPC 2
25#define SHZ_MIPS 3
26#define SHZ_ARM 4
27#define SHZ_X86 5
28#define SHZ_WASM 8
29#define SHZ_SW ~0
30
31#ifndef SHZ_BACKEND
32# ifdef __DREAMCAST__
33# define SHZ_BACKEND SHZ_SH4
34# else
35# define SHZ_BACKEND SHZ_SW
36# endif
37#endif
38
39/*! \name Utilities
40 * \brief Miscellaneous function-like macros
41 * @{
42 */
43//! Stringifies a literal expression.
44#define SHZ_STRINGIFY_LITERAL(a) #a
45 //! Stringifies an expression _after_ preprocessing, supporting macro expansion.
46#define SHZ_STRINGIFY(a) SHZ_STRINGIFY_LITERAL(a)
47//! Returns the number of elements within a statically sized array
48#define SHZ_COUNT_OF(array) (sizeof(array) / sizeof((array)[0]))
49//! Returns the containing structure from a pointer to one of its members
50#define SHZ_CONTAINER_OF(ptr, type, member) ((type*)((char*)(ptr) - offsetof(type, member)))
51//! Macro which swaps the two values held by \p a and \p b.
52#define SHZ_SWAP(a, b) do { typeof(a) tmp = a; a = b; b = tmp; } while(false)
53//! Macro which forward declares a struct and its typedef.
54#define SHZ_DECLARE_STRUCT(n, t) struct n; typedef struct n t
55//! Macro which forward declares a manually aligned struct and its typedef.
56#define SHZ_DECLARE_STRUCT_ALIGNED(n, t, a) struct SHZ_ALIGNAS(a) n; typedef struct n t
57//! @}
58
59//! \cond
60/*! \name Compiler attributes
61 * \brief Defines for commonly-used GCC attributes.
62 * @{
63 */
64//! Forces a function or type to be aligned by \p N bytes.
65#define SHZ_ALIGNAS(N) __attribute__((aligned((N))))
66//! Tells GCC that a scalar type is to be treated as a vector of size \p N.
67#define SHZ_SIMD(N) __attribute__((vector_size((N))))
68//! Tells GCC that a particular function should be optimized for performance.
69#define SHZ_HOT __attribute__((hot))
70//! Tells GCC that a particular function should be optimized for size.
71#define SHZ_COLD __attribute__((cold))
72//! Put this before a function definition to tell GCC to use fast math optimizations on a specific function.
73#define SHZ_FAST_MATH __attribute__((optimize("fast-math")))
74//! Put this before a function definition to tell GCC to NOT use fast math optimizations on a specific function.
75#define SHZ_NO_FAST_MATH __attribute__((optimize("no-fast-math")))
76//! Tells GCC to disable any optimizations when compiling a function.
77#define SHZ_NO_OPTIMIZATION __attribute__((optimize("O0")))
78//! Aligns a function by the size of an icache line (32 bytes).
79#define SHZ_ICACHE_ALIGNED __attribute__((aligned(32)))
80//! Forces GCC to inline the given function.
81#define SHZ_FORCE_INLINE __attribute__((always_inline)) SHZ_INLINE
82//! Prevents GCC from inlining the given function.
83#define SHZ_NO_INLINE __attribute__((noinline))
84//! Forces GCC to inline all calls to other functions made within the tagged function.
85#define SHZ_FLATTEN __attribute__((flatten))
86//! Tells GCC not to introduce any extra padding for the given type.
87#define SHZ_PACKED __attribute__((packed))
88//! Tells GCC the function has no effects other than returning a value that depends on its arguments and global variables.
89#define SHZ_PURE __attribute__((pure))
90//! Tells GCC that the decorated pointer may be breaking strict aliasing rules for C and C++
91#define SHZ_ALIASING __attribute__((__may_alias__))
92//! Tells GCC that the expression is likely to be true (used for conditional and loop optimizations)
93#define SHZ_LIKELY(e) __builtin_expect(!!(e), 1)
94//! Tells GCC that the expression is likely to be false (used for conditional and loop optimizations)
95#define SHZ_UNLIKELY(e) __builtin_expect(!!(e), 0)
96//! Tells GCC to use its builtin intrinsic for prefetching (better instruction scheduling than pure ASM pref)
97#define SHZ_PREFETCH(a) __builtin_prefetch(a)
98//! Tells GCC to issue a prefetch, using inline ASM so that it cannot be reordered
99#define SHZ_PREFETCH_VOLATILE(a) asm volatile("pref @%0" : : "r" (a))
100
101#ifndef __cplusplus
102 //! Dummy define provided for C++ compatibility
103# define SHZ_DECLS_BEGIN
104 //! Dummy define provided for C++ compatibility
105# define SHZ_DECLS_END
106 //! Requests a function or member to be inlined (nonforcibly) OR to have static linkage.
107# define SHZ_INLINE inline static
108 //! Tells GCC the function has no effects other than returning a value that depends only on its arguments.
109# define SHZ_CONST __attribute__((const))
110 //! Tells GCC the pointer paramter is unique and is not aliased by another parameter
111# define SHZ_RESTRICT restrict
112 //! Dummy define provided for C++ compatibility
113# define SHZ_NOEXCEPT
114 //! Conversion macro for zero-overhead conversions, taking the given \p value to a value of the given \p type.
115# define SHZ_CONVERT(type, value)
116 (((struct {
117 union {
118 typeof(value) from;
119 type to;
120 };
121 static_assert(sizeof(type) == sizeof(value), "SHZ_CONVERT: Cannot convert between types of differing sizes.");
122 }){ (value) }).to)
123#else
124 //! Forces functions declared after this directive to use C linkage.
125# define SHZ_DECLS_BEGIN extern "C" {
126 //! Ends forcing functions to use C linkage.
127# define SHZ_DECLS_END }
128 //! Requests a function or member to be inlined (nonforcibly).
129# define SHZ_INLINE inline
130 //! Tells GCC the function has no effects other than returning a value that depends only on its arguments.
131# define SHZ_CONST __attribute__((const)) constexpr
132 //! Tells GCC the pointer paramter is unique and is not aliased by another parameter
133# define SHZ_RESTRICT __restrict__
134 //! Tells the compiler that the function does not throw exceptions
135# define SHZ_NOEXCEPT noexcept
136 //! Conversion macro for zero-overhead conversions that handles pointers/references \p from and \p type.
137# define SHZ_CONVERT(type, from)
138 [&]<typename To, typename V>(V&& value) -> To {
139 using TNR = std::remove_reference_t<To>;
140 using VNR = std::remove_reference_t<V>;
141 if constexpr (std::is_pointer_v<To>) {
142 if constexpr (std::is_pointer_v<VNR>) {
143 return reinterpret_cast<To>(value);
144 } else {
145 return reinterpret_cast<To>(&value);
146 }
147 } else if constexpr (std::is_reference_v<To>) {
148 static_assert(sizeof(VNR) == sizeof(TNR), "SHZ_CONVERT: Cannot convert between types of differing sizes when converting to a reference type.");
149 return reinterpret_cast<To>(value);
150 } else {
151 static_assert(sizeof(VNR) == sizeof(TNR), "SHZ_CONVERT: Cannot convert between types of differing sizes.");
152 return reinterpret_cast<To&>(value);
153 }
154 }.template operator()<type>(from)
155#endif
156//! @}
157//! \endcond
158
159/*! \name Aliasing Types
160 * \brief Types which may break C/C++'s strict aliasing rules
161 * @{
162 */
163//! int16_t type whose value may be aliased as another type.
164typedef SHZ_ALIASING int16_t shz_alias_int16_t;
165//! uint16_t type whose value may be aliased as another type.
166typedef SHZ_ALIASING uint16_t shz_alias_uint16_t;
167//! int32_t type whose value may be aliased as another type.
168typedef SHZ_ALIASING int32_t shz_alias_int32_t;
169//! uint32_t type whose value may be aliased as another type.
170typedef SHZ_ALIASING uint32_t shz_alias_uint32_t;
171//! float type whose value may be aliased as another type.
172typedef SHZ_ALIASING float shz_alias_float_t;
173//! int64_t type whose value may be aliased as another type.
174typedef SHZ_ALIASING int64_t shz_alias_int64_t;
175//! uint64_t type whose value may be aliased as another type.
176typedef SHZ_ALIASING uint64_t shz_alias_uint64_t;
177//! double type whose value may be aliased as another type.
178typedef SHZ_ALIASING double shz_alias_double_t;
179//! @}
180
181#endif // SHZ_CDEFS_H
SHZ_ALIASING int16_t shz_alias_int16_t
int16_t type whose value may be aliased as another type.
Definition shz_cdefs.h:164
SHZ_ALIASING double shz_alias_double_t
double type whose value may be aliased as another type.
Definition shz_cdefs.h:178
SHZ_ALIASING uint32_t shz_alias_uint32_t
uint32_t type whose value may be aliased as another type.
Definition shz_cdefs.h:170
#define SHZ_SW
Definition shz_cdefs.h:29
#define SHZ_STRINGIFY_LITERAL(a)
Stringifies a literal expression.
Definition shz_cdefs.h:44
SHZ_ALIASING int64_t shz_alias_int64_t
int64_t type whose value may be aliased as another type.
Definition shz_cdefs.h:174
SHZ_ALIASING uint16_t shz_alias_uint16_t
uint16_t type whose value may be aliased as another type.
Definition shz_cdefs.h:166
SHZ_ALIASING int32_t shz_alias_int32_t
int32_t type whose value may be aliased as another type.
Definition shz_cdefs.h:168
SHZ_ALIASING uint64_t shz_alias_uint64_t
uint64_t type whose value may be aliased as another type.
Definition shz_cdefs.h:176
SHZ_ALIASING float shz_alias_float_t
float type whose value may be aliased as another type.
Definition shz_cdefs.h:172