VirtualC64 v5.0 beta
Commodore 64 Emulator
Loading...
Searching...
No Matches
Macros.h
1// -----------------------------------------------------------------------------
2// This file is part of VirtualC64
3//
4// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
5// This FILE is dual-licensed. You are free to choose between:
6//
7// - The GNU General Public License v3 (or any later version)
8// - The Mozilla Public License v2
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR MPL-2.0
11// -----------------------------------------------------------------------------
12
13#pragma once
14
15#include "Types.h"
16
17//
18// Optimizing code
19//
20
21#ifdef _MSC_VER
22
23#define unreachable __assume(false)
24#define likely(x) (x)
25#define unlikely(x) (x)
26
27#else
28
29#define unreachable __builtin_unreachable()
30#define likely(x) __builtin_expect(!!(x), 1)
31#define unlikely(x) __builtin_expect(!!(x), 0)
32
33#endif
34
35#define fatalError assert(false); unreachable
36
37
38//
39// Accessing bits and bytes
40//
41
42// Returns the low nibble or the high nibble of a 8 bit value
43#define LO_NIBBLE(x) (u8)((x) & 0xF)
44#define HI_NIBBLE(x) (u8)(((x) >> 4) & 0xF)
45
46// Returns the low byte or the high byte of a 16 bit value
47#define LO_BYTE(x) (u8)((x) & 0xFF)
48#define HI_BYTE(x) (u8)((x) >> 8)
49
50// Returns the low word or the high word of a 32 bit value
51#define LO_WORD(x) (u16)((x) & 0xFFFF)
52#define HI_WORD(x) (u16)((x) >> 16)
53
54// Constructs a larger integer in little endian byte format
55#define LO_HI(x,y) (u16)((y) << 8 | (x))
56#define LO_LO_HI(x,y,z) (u32)((z) << 16 | (y) << 8 | (x))
57#define LO_LO_HI_HI(x,y,z,w) (u32)((w) << 24 | (z) << 16 | (y) << 8 | (x))
58#define LO_W_HI_W(x,y) (u32)((y) << 16 | (x))
59
60// Constructs a larger integer in big endian byte format
61#define HI_LO(x,y) (u16)((x) << 8 | (y))
62#define HI_HI_LO(x,y,z) (u32)((x) << 16 | (y) << 8 | (z))
63#define HI_HI_LO_LO(x,y,z,w) (u32)((x) << 24 | (y) << 16 | (z) << 8 | (w))
64#define HI_W_LO_W(x,y) (u32)((x) << 16 | (y))
65
66// Returns a certain byte of a larger integer
67#define BYTE0(x) LO_BYTE(x)
68#define BYTE1(x) LO_BYTE((x) >> 8)
69#define BYTE2(x) LO_BYTE((x) >> 16)
70#define BYTE3(x) LO_BYTE((x) >> 24)
71#define GET_BYTE(x,nr) LO_BYTE((x) >> (8 * (nr)))
72
73// Returns a non-zero value if the n-th bit is set in x
74#define GET_BIT(x,nr) ((x) & (1 << (nr)))
75
76// Sets, clears, or toggles single bits
77#define SET_BIT(x,nr) ((x) |= (1 << (nr)))
78#define CLR_BIT(x,nr) ((x) &= ~(1 << (nr)))
79#define TOGGLE_BIT(x,nr) ((x) ^= (1 << (nr)))
80
81// Replaces bits, bytes, and words
82#define REPLACE_BIT(x,nr,v) ((v) ? SET_BIT(x, nr) : CLR_BIT(x, nr))
83#define REPLACE_LO(x,y) (((x) & ~0x00FF) | (y))
84#define REPLACE_HI(x,y) (((x) & ~0xFF00) | ((y) << 8))
85#define REPLACE_LO_WORD(x,y) (((x) & ~0xFFFF) | (y))
86#define REPLACE_HI_WORD(x,y) (((x) & ~0xFFFF0000) | ((y) << 16))
87
88// Checks if none or all bits of a bitmask are set
89#define ALL_CLR(x,m) (((x) & (m)) == 0)
90#define ALL_SET(x,m) (((x) & (m)) == m)
91
92// Checks for a rising or a falling edge
93#define RISING_EDGE(x,y) (!(x) && (y))
94#define RISING_EDGE_BIT(x,y,n) (!((x) & (1 << (n))) && ((y) & (1 << (n))))
95#define FALLING_EDGE(x,y) ((x) && !(y))
96#define FALLING_EDGE_BIT(x,y,n) (((x) & (1 << (n))) && !((y) & (1 << (n))))
97
98// Checks is a number is even or odd
99#define IS_EVEN(x) (!IS_ODD(x))
100#define IS_ODD(x) ((x) & 1)
101
102// Rounds a number up or down to the next even or odd number
103#define UP_TO_NEXT_EVEN(x) ((x) + ((x) & 1))
104#define DOWN_TO_NEXT_EVEN(x) ((x) & (~1))
105#define UP_TO_NEXT_ODD(x) ((x) | 1)
106#define DOWN_TO_NEXT_ODD(x) ((x) - !((x) & 1))
107
108
109//
110// Converting data types
111//
112
113// Signed alternative for the sizeof keyword
114#define isizeof(x) (isize)(sizeof(x))
115
116
117//
118// Converting units
119//
120
121// Converts kilo and mega bytes to bytes
122#define KB(x) ((x) << 10)
123#define MB(x) ((x) << 20)
124#define GB(x) ((x) << 30)
125
126// Converts kilo and mega Hertz to Hertz
127#define KHz(x) ((x) * 1000)
128#define MHz(x) ((x) * 1000000)
129
130
131//
132// Performing overflow-prone arithmetic
133//
134
135// Sanitizer friendly macros for adding signed offsets to integer values
136#define U8_ADD(x,y) (u8)((i64)(x) + (i64)(y))
137#define U8_SUB(x,y) (u8)((i64)(x) - (i64)(y))
138#define U8_ADD3(x,y,z) (u8)((i64)(x) + (i64)(y) + (i64)(z))
139#define U8_SUB3(x,y,z) (u8)((i64)(x) - (i64)(y) - (i64)(z))
140#define U8_INC(x,y) x = U8_ADD(x,y)
141#define U8_DEC(x,y) x = U8_SUB(x,y)
142
143#define U16_ADD(x,y) (u16)((i64)(x) + (i64)(y))
144#define U16_SUB(x,y) (u16)((i64)(x) - (i64)(y))
145#define U16_ADD3(x,y,z) (u16)((i64)(x) + (i64)(y) + (i64)(z))
146#define U16_SUB3(x,y,z) (u16)((i64)(x) - (i64)(y) - (i64)(z))
147#define U16_INC(x,y) x = U16_ADD(x,y)
148#define U16_DEC(x,y) x = U16_SUB(x,y)
149
150#define U32_ADD(x,y) (u32)((i64)(x) + (i64)(y))
151#define U32_SUB(x,y) (u32)((i64)(x) - (i64)(y))
152#define U32_ADD3(x,y,z) (u32)((i64)(x) + (i64)(y) + (i64)(z))
153#define U32_SUB3(x,y,z) (u32)((i64)(x) - (i64)(y) - (i64)(z))
154#define U32_INC(x,y) x = U32_ADD(x,y)
155#define U32_DEC(x,y) x = U32_SUB(x,y)
156
157#define U64_ADD(x,y) (u64)((i64)(x) + (i64)(y))
158#define U64_SUB(x,y) (u64)((i64)(x) - (i64)(y))
159#define U64_ADD3(x,y,z) (u64)((i64)(x) + (i64)(y) + (i64)(z))
160#define U64_SUB3(x,y,z) (u64)((i64)(x) - (i64)(y) - (i64)(z))
161#define U64_INC(x,y) x = U64_ADD(x,y)
162#define U64_DEC(x,y) x = U64_SUB(x,y)
163
164/* The following macro can be used to disable clang sanitizer checks. It has
165 * been added to make the code compatible with gcc which doesn't recognize
166 * the 'no_sanitize' keyword.
167 */
168#if defined(__clang__)
169#define NO_SANITIZE(x) __attribute__((no_sanitize(x)))
170#else
171#define NO_SANITIZE(x)
172#endif