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
Emulator
Utilities
Macros.h
Generated by
1.10.0