1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2024 Oxide Computer Company 14 */ 15 16 #ifndef _SYS_STDBIT_H 17 #define _SYS_STDBIT_H 18 19 /* 20 * This header implements all of the different aspects of the C23 stdbit.h 21 * functionality. We attempt to make this header useful to all C versions other 22 * than the type generic interfaces, for which we require the asked for version 23 * of C to be at least C23. The functions that are present here are allowed to 24 * be inline or not. To provide wider ranging compiler support we declare extern 25 * versions of all of these symbols which are provided in both libc and the 26 * kernel. This also avoids cases where a compiler builtin relies on external 27 * runtime library support. 28 * 29 * In the future, we should provide inline versions with compilers that support 30 * common builtins. 31 */ 32 33 #include <sys/feature_tests.h> 34 #include <sys/isa_defs.h> 35 36 /* 37 * This header is required specifically to make the size_t, uintXX_t, and the 38 * _least_ variants available. The generic values are allowed to leverage the 39 * 'bool' type. In C23, bool became a keyword as opposed to a definition to 40 * _Bool. We therefore include it so we can attempt to be consistent and 41 * generally useful. 42 */ 43 #include <sys/int_types.h> 44 #include <sys/stdbool.h> 45 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 50 /* 51 * Declare our version. 52 */ 53 #define __STDC_VERSION_STDBIT_H__ 202311L 54 55 #if !defined(_SIZE_T) || __cplusplus >= 199711L 56 #define _SIZE_T 57 #if defined(_LP64) || defined(_I32LPx) 58 typedef unsigned long size_t; /* size of something in bytes */ 59 #else 60 typedef unsigned int size_t; /* (historical version) */ 61 #endif 62 #endif /* _SIZE_T */ 63 64 /* 65 * Endian values and detection. 66 */ 67 #define __STDC_ENDIAN_LITTLE__ 1234 68 #define __STDC_ENDIAN_BIG__ 4321 69 #if defined(_LITTLE_ENDIAN) 70 #define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__ 71 #elif defined(_BIG_ENDIAN) 72 #define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_BIG__ 73 #else 74 #error "Unknown byte order" 75 #endif /* _LITTLE_ENDIAN */ 76 77 /* 78 * Count Leading Zeros 79 */ 80 extern unsigned int stdc_leading_zeros_uc(unsigned char) _C23_UNSEQ_ATTR; 81 extern unsigned int stdc_leading_zeros_us(unsigned short) _C23_UNSEQ_ATTR; 82 extern unsigned int stdc_leading_zeros_ui(unsigned int) _C23_UNSEQ_ATTR; 83 extern unsigned int stdc_leading_zeros_ul(unsigned long) _C23_UNSEQ_ATTR; 84 85 /* 86 * Count Leading Ones 87 */ 88 extern unsigned int stdc_leading_ones_uc(unsigned char) _C23_UNSEQ_ATTR; 89 extern unsigned int stdc_leading_ones_us(unsigned short) _C23_UNSEQ_ATTR; 90 extern unsigned int stdc_leading_ones_ui(unsigned int) _C23_UNSEQ_ATTR; 91 extern unsigned int stdc_leading_ones_ul(unsigned long) _C23_UNSEQ_ATTR; 92 93 /* 94 * Count Trailing Zeros 95 */ 96 extern unsigned int stdc_trailing_zeros_uc(unsigned char) _C23_UNSEQ_ATTR; 97 extern unsigned int stdc_trailing_zeros_us(unsigned short) _C23_UNSEQ_ATTR; 98 extern unsigned int stdc_trailing_zeros_ui(unsigned int) _C23_UNSEQ_ATTR; 99 extern unsigned int stdc_trailing_zeros_ul(unsigned long) _C23_UNSEQ_ATTR; 100 101 /* 102 * Count Trailing Ones 103 */ 104 extern unsigned int stdc_trailing_ones_uc(unsigned char) _C23_UNSEQ_ATTR; 105 extern unsigned int stdc_trailing_ones_us(unsigned short) _C23_UNSEQ_ATTR; 106 extern unsigned int stdc_trailing_ones_ui(unsigned int) _C23_UNSEQ_ATTR; 107 extern unsigned int stdc_trailing_ones_ul(unsigned long) _C23_UNSEQ_ATTR; 108 109 /* 110 * First Leading Zero 111 */ 112 extern unsigned int stdc_first_leading_zero_uc(unsigned char) _C23_UNSEQ_ATTR; 113 extern unsigned int stdc_first_leading_zero_us(unsigned short) _C23_UNSEQ_ATTR; 114 extern unsigned int stdc_first_leading_zero_ui(unsigned int) _C23_UNSEQ_ATTR; 115 extern unsigned int stdc_first_leading_zero_ul(unsigned long) _C23_UNSEQ_ATTR; 116 117 /* 118 * First Leading One 119 */ 120 extern unsigned int stdc_first_leading_one_uc(unsigned char) _C23_UNSEQ_ATTR; 121 extern unsigned int stdc_first_leading_one_us(unsigned short) _C23_UNSEQ_ATTR; 122 extern unsigned int stdc_first_leading_one_ui(unsigned int) _C23_UNSEQ_ATTR; 123 extern unsigned int stdc_first_leading_one_ul(unsigned long) _C23_UNSEQ_ATTR; 124 125 /* 126 * First Trailing Zero 127 */ 128 extern unsigned int stdc_first_trailing_zero_uc(unsigned char) _C23_UNSEQ_ATTR; 129 extern unsigned int stdc_first_trailing_zero_us(unsigned short) _C23_UNSEQ_ATTR; 130 extern unsigned int stdc_first_trailing_zero_ui(unsigned int) _C23_UNSEQ_ATTR; 131 extern unsigned int stdc_first_trailing_zero_ul(unsigned long) _C23_UNSEQ_ATTR; 132 133 /* 134 * First Trailing One 135 */ 136 extern unsigned int stdc_first_trailing_one_uc(unsigned char) _C23_UNSEQ_ATTR; 137 extern unsigned int stdc_first_trailing_one_us(unsigned short) _C23_UNSEQ_ATTR; 138 extern unsigned int stdc_first_trailing_one_ui(unsigned int) _C23_UNSEQ_ATTR; 139 extern unsigned int stdc_first_trailing_one_ul(unsigned long) _C23_UNSEQ_ATTR; 140 141 /* 142 * Count Zeros 143 */ 144 extern unsigned int stdc_count_zeros_uc(unsigned char) _C23_UNSEQ_ATTR; 145 extern unsigned int stdc_count_zeros_us(unsigned short) _C23_UNSEQ_ATTR; 146 extern unsigned int stdc_count_zeros_ui(unsigned int) _C23_UNSEQ_ATTR; 147 extern unsigned int stdc_count_zeros_ul(unsigned long) _C23_UNSEQ_ATTR; 148 149 /* 150 * Count Ones 151 */ 152 extern unsigned int stdc_count_ones_uc(unsigned char) _C23_UNSEQ_ATTR; 153 extern unsigned int stdc_count_ones_us(unsigned short) _C23_UNSEQ_ATTR; 154 extern unsigned int stdc_count_ones_ui(unsigned int) _C23_UNSEQ_ATTR; 155 extern unsigned int stdc_count_ones_ul(unsigned long) _C23_UNSEQ_ATTR; 156 157 /* 158 * Single-bit Check 159 */ 160 extern bool stdc_has_single_bit_uc(unsigned char) _C23_UNSEQ_ATTR; 161 extern bool stdc_has_single_bit_us(unsigned short) _C23_UNSEQ_ATTR; 162 extern bool stdc_has_single_bit_ui(unsigned int) _C23_UNSEQ_ATTR; 163 extern bool stdc_has_single_bit_ul(unsigned long) _C23_UNSEQ_ATTR; 164 165 /* 166 * Bit Width 167 */ 168 extern unsigned int stdc_bit_width_uc(unsigned char) _C23_UNSEQ_ATTR; 169 extern unsigned int stdc_bit_width_us(unsigned short) _C23_UNSEQ_ATTR; 170 extern unsigned int stdc_bit_width_ui(unsigned int) _C23_UNSEQ_ATTR; 171 extern unsigned int stdc_bit_width_ul(unsigned long) _C23_UNSEQ_ATTR; 172 173 /* 174 * Bit Floor 175 */ 176 extern unsigned char stdc_bit_floor_uc(unsigned char) _C23_UNSEQ_ATTR; 177 extern unsigned short stdc_bit_floor_us(unsigned short) _C23_UNSEQ_ATTR; 178 extern unsigned int stdc_bit_floor_ui(unsigned int) _C23_UNSEQ_ATTR; 179 extern unsigned long stdc_bit_floor_ul(unsigned long) _C23_UNSEQ_ATTR; 180 181 /* 182 * Bit Ceiling 183 */ 184 extern unsigned char stdc_bit_ceil_uc(unsigned char) _C23_UNSEQ_ATTR; 185 extern unsigned short stdc_bit_ceil_us(unsigned short) _C23_UNSEQ_ATTR; 186 extern unsigned int stdc_bit_ceil_ui(unsigned int) _C23_UNSEQ_ATTR; 187 extern unsigned long stdc_bit_ceil_ul(unsigned long) _C23_UNSEQ_ATTR; 188 189 /* 190 * long long variants of functions. This check is just for some non-C23 191 * environments out of courtesy. 192 */ 193 #if defined(_LONGLONG_TYPE) 194 extern unsigned int stdc_leading_zeros_ull(unsigned long long) _C23_UNSEQ_ATTR; 195 extern unsigned int stdc_leading_ones_ull(unsigned long long) _C23_UNSEQ_ATTR; 196 extern unsigned int stdc_trailing_zeros_ull(unsigned long long) _C23_UNSEQ_ATTR; 197 extern unsigned int stdc_trailing_ones_ull(unsigned long long) _C23_UNSEQ_ATTR; 198 extern unsigned int stdc_first_leading_zero_ull(unsigned long long) 199 _C23_UNSEQ_ATTR; 200 extern unsigned int stdc_first_leading_one_ull(unsigned long long) 201 _C23_UNSEQ_ATTR; 202 extern unsigned int stdc_first_trailing_zero_ull(unsigned long long) 203 _C23_UNSEQ_ATTR; 204 extern unsigned int stdc_first_trailing_one_ull(unsigned long long) 205 _C23_UNSEQ_ATTR; 206 extern unsigned int stdc_count_zeros_ull(unsigned long long) _C23_UNSEQ_ATTR; 207 extern unsigned int stdc_count_ones_ull(unsigned long long) _C23_UNSEQ_ATTR; 208 extern bool stdc_has_single_bit_ull(unsigned long long) _C23_UNSEQ_ATTR; 209 extern unsigned int stdc_bit_width_ull(unsigned long long) _C23_UNSEQ_ATTR; 210 extern unsigned long long stdc_bit_floor_ull(unsigned long long) 211 _C23_UNSEQ_ATTR; 212 extern unsigned long long stdc_bit_ceil_ull(unsigned long long) _C23_UNSEQ_ATTR; 213 #endif /* _LONGLONG_TYPE */ 214 215 /* 216 * Type Generic functions. The standard requires that these be a generic return 217 * type that operates on the following types of values: 218 * 219 * - Standard unsigned integer types (excluding bool) i.e. 'unsigned int'. 220 * - Extended unsigned integer types i.e. 'uint128_t' which is not something 221 * currently supported and up to the platform. 222 * - Bit-precise integers that match standard or extended integers. This means 223 * that _BitInt(32) is accepted, but a value that basically doesn't match a 224 * uint8_t, uint16_t, uint32_t, or uint64_t like _BitInt(48) is not valid. 225 * 226 * There currently is no way to match ranges of _BitInt in the _Generic macro so 227 * we end up focusing on the size of the type that was passed. _Generic matches 228 * on the type of the first expression, so rather than just the base type of the 229 * value, we instead use a suggestion to transform it into a fixed-length array. 230 * This works for signed and unsigned integers, implicitly doing a cast to the 231 * unsigned value for signed integers. Similarly, this incidentally works for 232 * signed and unsigned _BitInt() values that are able to be translated into 233 * standard sizes. We always use the ull versions for 64-bit values as that is 234 * always 64-bit regardless if we're in an ILP32 or LP64 environment. 235 */ 236 #if defined(_STDC_C23) 237 /* CSTYLED */ 238 #define stdc_leading_zeros(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 239 char(*)[1]: stdc_leading_zeros_uc(val), \ 240 char(*)[2]: stdc_leading_zeros_us(val), \ 241 char(*)[4]: stdc_leading_zeros_ui(val), \ 242 char(*)[8]: stdc_leading_zeros_ull(val)) 243 244 /* CSTYLED */ 245 #define stdc_leading_ones(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 246 char(*)[1]: stdc_leading_ones_uc(val), \ 247 char(*)[2]: stdc_leading_ones_us(val), \ 248 char(*)[4]: stdc_leading_ones_ui(val), \ 249 char(*)[8]: stdc_leading_ones_ull(val)) 250 251 /* CSTYLED */ 252 #define stdc_trailing_zeros(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 253 char(*)[1]: stdc_trailing_zeros_uc(val), \ 254 char(*)[2]: stdc_trailing_zeros_us(val), \ 255 char(*)[4]: stdc_trailing_zeros_ui(val), \ 256 char(*)[8]: stdc_trailing_zeros_ull(val)) 257 258 /* CSTYLED */ 259 #define stdc_trailing_ones(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 260 char(*)[1]: stdc_trailing_ones_uc(val), \ 261 char(*)[2]: stdc_trailing_ones_us(val), \ 262 char(*)[4]: stdc_trailing_ones_ui(val), \ 263 char(*)[8]: stdc_trailing_ones_ull(val)) 264 265 /* CSTYLED */ 266 #define stdc_first_leading_zero(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 267 char(*)[1]: stdc_first_leading_zero_uc(val), \ 268 char(*)[2]: stdc_first_leading_zero_us(val), \ 269 char(*)[4]: stdc_first_leading_zero_ui(val), \ 270 char(*)[8]: stdc_first_leading_zero_ull(val)) 271 272 /* CSTYLED */ 273 #define stdc_first_leading_one(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 274 char(*)[1]: stdc_first_leading_one_uc(val), \ 275 char(*)[2]: stdc_first_leading_one_us(val), \ 276 char(*)[4]: stdc_first_leading_one_ui(val), \ 277 char(*)[8]: stdc_first_leading_one_ull(val)) 278 279 /* CSTYLED */ 280 #define stdc_first_trailing_zero(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 281 char(*)[1]: stdc_first_trailing_zero_uc(val), \ 282 char(*)[2]: stdc_first_trailing_zero_us(val), \ 283 char(*)[4]: stdc_first_trailing_zero_ui(val), \ 284 char(*)[8]: stdc_first_trailing_zero_ull(val)) 285 286 /* CSTYLED */ 287 #define stdc_first_trailing_one(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 288 char(*)[1]: stdc_first_trailing_one_uc(val), \ 289 char(*)[2]: stdc_first_trailing_one_us(val), \ 290 char(*)[4]: stdc_first_trailing_one_ui(val), \ 291 char(*)[8]: stdc_first_trailing_one_ull(val)) 292 293 /* CSTYLED */ 294 #define stdc_count_zeros(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 295 char(*)[1]: stdc_count_zeros_uc(val), \ 296 char(*)[2]: stdc_count_zeros_us(val), \ 297 char(*)[4]: stdc_count_zeros_ui(val), \ 298 char(*)[8]: stdc_count_zeros_ull(val)) 299 300 /* CSTYLED */ 301 #define stdc_count_ones(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 302 char(*)[1]: stdc_count_ones_uc(val), \ 303 char(*)[2]: stdc_count_ones_us(val), \ 304 char(*)[4]: stdc_count_ones_ui(val), \ 305 char(*)[8]: stdc_count_ones_ull(val)) 306 307 /* CSTYLED */ 308 #define stdc_has_single_bit(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 309 char(*)[1]: stdc_has_single_bit_uc(val), \ 310 char(*)[2]: stdc_has_single_bit_us(val), \ 311 char(*)[4]: stdc_has_single_bit_ui(val), \ 312 char(*)[8]: stdc_has_single_bit_ull(val)) 313 314 /* CSTYLED */ 315 #define stdc_bit_width(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 316 char(*)[1]: stdc_bit_width_uc(val), \ 317 char(*)[2]: stdc_bit_width_us(val), \ 318 char(*)[4]: stdc_bit_width_ui(val), \ 319 char(*)[8]: stdc_bit_width_ull(val)) 320 321 /* CSTYLED */ 322 #define stdc_bit_floor(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 323 char(*)[1]: stdc_bit_floor_uc(val), \ 324 char(*)[2]: stdc_bit_floor_us(val), \ 325 char(*)[4]: stdc_bit_floor_ui(val), \ 326 char(*)[8]: stdc_bit_floor_ull(val)) 327 328 /* CSTYLED */ 329 #define stdc_bit_ceil(val) _Generic((char(*)[sizeof (val)]){ 0 }, \ 330 char(*)[1]: stdc_bit_ceil_uc(val), \ 331 char(*)[2]: stdc_bit_ceil_us(val), \ 332 char(*)[4]: stdc_bit_ceil_ui(val), \ 333 char(*)[8]: stdc_bit_ceil_ull(val)) 334 #endif /* STDC_C23 */ 335 336 #ifdef __cplusplus 337 } 338 #endif 339 340 #endif /* _SYS_STDBIT_H */ 341