The branch main has been updated by fuz: URL: https://cgit.FreeBSD.org/src/commit/?id=6296500a85c8474e3ff3fe2f8e4a9d56dd0acd64
commit 6296500a85c8474e3ff3fe2f8e4a9d56dd0acd64 Author: Robert Clausecker <[email protected]> AuthorDate: 2025-11-18 17:32:53 +0000 Commit: Robert Clausecker <[email protected]> CommitDate: 2025-11-30 19:21:52 +0000 libc: implement C23 <stdbit.h> functions This new header complies with ISO/IEC 9899:2024 (C23). Contrary to glibc, we do not provide inline definitions in <stdbit.h> as we expect our system compiler to soon recognise these as builtins anyway. Relnotes: yes MFC after: 1 month Reviewed by: adrian Approved by: markj (mentor) Differential Revision: https://reviews.freebsd.org/D53657 --- include/Makefile | 4 +- include/stdbit.h | 124 +++++++++++++++++++++++++++++ lib/libc/Makefile | 1 + lib/libc/stdbit/Makefile.inc | 19 +++++ lib/libc/stdbit/Symbol.map | 85 ++++++++++++++++++++ lib/libc/stdbit/stdc_bit_ceil.c | 71 +++++++++++++++++ lib/libc/stdbit/stdc_bit_floor.c | 53 ++++++++++++ lib/libc/stdbit/stdc_bit_width.c | 53 ++++++++++++ lib/libc/stdbit/stdc_count_ones.c | 38 +++++++++ lib/libc/stdbit/stdc_count_zeros.c | 38 +++++++++ lib/libc/stdbit/stdc_first_leading_one.c | 57 +++++++++++++ lib/libc/stdbit/stdc_first_leading_zero.c | 57 +++++++++++++ lib/libc/stdbit/stdc_first_trailing_one.c | 52 ++++++++++++ lib/libc/stdbit/stdc_first_trailing_zero.c | 53 ++++++++++++ lib/libc/stdbit/stdc_has_single_bit.c | 38 +++++++++ lib/libc/stdbit/stdc_leading_ones.c | 60 ++++++++++++++ lib/libc/stdbit/stdc_leading_zeros.c | 60 ++++++++++++++ lib/libc/stdbit/stdc_trailing_ones.c | 56 +++++++++++++ lib/libc/stdbit/stdc_trailing_zeros.c | 56 +++++++++++++ 19 files changed, 973 insertions(+), 2 deletions(-) diff --git a/include/Makefile b/include/Makefile index b8cbf0ecc1c2..028e5055cc91 100644 --- a/include/Makefile +++ b/include/Makefile @@ -29,8 +29,8 @@ INCS= a.out.h ar.h assert.h bitstring.h byteswap.h \ pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h \ res_update.h resolv.h runetype.h sched.h \ search.h semaphore.h setjmp.h \ - signal.h spawn.h stab.h stdalign.h stdbool.h stdckdint.h stddef.h \ - stdnoreturn.h stdio.h stdlib.h string.h stringlist.h \ + signal.h spawn.h stab.h stdalign.h stdbit.h stdbool.h stdckdint.h \ + stddef.h stdnoreturn.h stdio.h stdlib.h string.h stringlist.h \ strings.h sysexits.h tar.h termios.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ uchar.h ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h \ diff --git a/include/stdbit.h b/include/stdbit.h new file mode 100644 index 000000000000..a529676bed4b --- /dev/null +++ b/include/stdbit.h @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __STDC_VERSION_STDBIT_H__ +#define __STDC_VERSION_STDBIT_H__ 202311L + +#include <sys/cdefs.h> + +/* byte order */ +#define __STDC_ENDIAN_LITTLE__ __ORDER_LITTLE_ENDIAN__ +#define __STDC_ENDIAN_BIG__ __ORDER_BIG_ENDIAN__ +#define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER__ + +#define __generic_bitfunc(func, x) (_Generic(x, \ + unsigned char: func ## _uc, \ + unsigned short: func ## _us, \ + unsigned int: func ## _ui, \ + unsigned long: func ## _ul, \ + unsigned long long: func ## _ull)(x)) + +__BEGIN_DECLS +unsigned int stdc_leading_zeros_uc(unsigned char) __pure2; +unsigned int stdc_leading_zeros_us(unsigned short) __pure2; +unsigned int stdc_leading_zeros_ui(unsigned int) __pure2; +unsigned int stdc_leading_zeros_ul(unsigned long) __pure2; +unsigned int stdc_leading_zeros_ull(unsigned long long) __pure2; +#define stdc_leading_zeros(x) __generic_bitfunc(stdc_leading_zeros, x) + +unsigned int stdc_leading_ones_uc(unsigned char) __pure2; +unsigned int stdc_leading_ones_us(unsigned short) __pure2; +unsigned int stdc_leading_ones_ui(unsigned int) __pure2; +unsigned int stdc_leading_ones_ul(unsigned long) __pure2; +unsigned int stdc_leading_ones_ull(unsigned long long) __pure2; +#define stdc_leading_ones(x) __generic_bitfunc(stdc_leading_ones, x) + +unsigned int stdc_trailing_zeros_uc(unsigned char) __pure2; +unsigned int stdc_trailing_zeros_us(unsigned short) __pure2; +unsigned int stdc_trailing_zeros_ui(unsigned int) __pure2; +unsigned int stdc_trailing_zeros_ul(unsigned long) __pure2; +unsigned int stdc_trailing_zeros_ull(unsigned long long) __pure2; +#define stdc_trailing_zeros(x) __generic_bitfunc(stdc_trailing_zeros, x) + +unsigned int stdc_trailing_ones_uc(unsigned char) __pure2; +unsigned int stdc_trailing_ones_us(unsigned short) __pure2; +unsigned int stdc_trailing_ones_ui(unsigned int) __pure2; +unsigned int stdc_trailing_ones_ul(unsigned long) __pure2; +unsigned int stdc_trailing_ones_ull(unsigned long long) __pure2; +#define stdc_trailing_ones(x) __generic_bitfunc(stdc_trailing_ones, x) + +unsigned int stdc_first_leading_zero_uc(unsigned char) __pure2; +unsigned int stdc_first_leading_zero_us(unsigned short) __pure2; +unsigned int stdc_first_leading_zero_ui(unsigned int) __pure2; +unsigned int stdc_first_leading_zero_ul(unsigned long) __pure2; +unsigned int stdc_first_leading_zero_ull(unsigned long long) __pure2; +#define stdc_first_leading_zero(x) __generic_bitfunc(stdc_first_leading_zero, x) + +unsigned int stdc_first_leading_one_uc(unsigned char) __pure2; +unsigned int stdc_first_leading_one_us(unsigned short) __pure2; +unsigned int stdc_first_leading_one_ui(unsigned int) __pure2; +unsigned int stdc_first_leading_one_ul(unsigned long) __pure2; +unsigned int stdc_first_leading_one_ull(unsigned long long) __pure2; +#define stdc_first_leading_one(x) __generic_bitfunc(stdc_first_leading_one, x) + +unsigned int stdc_first_trailing_zero_uc(unsigned char) __pure2; +unsigned int stdc_first_trailing_zero_us(unsigned short) __pure2; +unsigned int stdc_first_trailing_zero_ui(unsigned int) __pure2; +unsigned int stdc_first_trailing_zero_ul(unsigned long) __pure2; +unsigned int stdc_first_trailing_zero_ull(unsigned long long) __pure2; +#define stdc_first_trailing_zero(x) __generic_bitfunc(stdc_first_trailing_zero, x) + +unsigned int stdc_first_trailing_one_uc(unsigned char) __pure2; +unsigned int stdc_first_trailing_one_us(unsigned short) __pure2; +unsigned int stdc_first_trailing_one_ui(unsigned int) __pure2; +unsigned int stdc_first_trailing_one_ul(unsigned long) __pure2; +unsigned int stdc_first_trailing_one_ull(unsigned long long) __pure2; +#define stdc_first_trailing_one(x) __generic_bitfunc(stdc_first_trailing_one, x) + +unsigned int stdc_count_zeros_uc(unsigned char) __pure2; +unsigned int stdc_count_zeros_us(unsigned short) __pure2; +unsigned int stdc_count_zeros_ui(unsigned int) __pure2; +unsigned int stdc_count_zeros_ul(unsigned long) __pure2; +unsigned int stdc_count_zeros_ull(unsigned long long) __pure2; +#define stdc_count_zeros(x) __generic_bitfunc(stdc_count_zeros, x) + +unsigned int stdc_count_ones_uc(unsigned char) __pure2; +unsigned int stdc_count_ones_us(unsigned short) __pure2; +unsigned int stdc_count_ones_ui(unsigned int) __pure2; +unsigned int stdc_count_ones_ul(unsigned long) __pure2; +unsigned int stdc_count_ones_ull(unsigned long long) __pure2; +#define stdc_count_ones(x) __generic_bitfunc(stdc_count_ones, x) + +_Bool stdc_has_single_bit_uc(unsigned char) __pure2; +_Bool stdc_has_single_bit_us(unsigned short) __pure2; +_Bool stdc_has_single_bit_ui(unsigned int) __pure2; +_Bool stdc_has_single_bit_ul(unsigned long) __pure2; +_Bool stdc_has_single_bit_ull(unsigned long long) __pure2; +#define stdc_has_single_bit(x) __generic_bitfunc(stdc_has_single_bit, x) + +unsigned int stdc_bit_width_uc(unsigned char) __pure2; +unsigned int stdc_bit_width_us(unsigned short) __pure2; +unsigned int stdc_bit_width_ui(unsigned int) __pure2; +unsigned int stdc_bit_width_ul(unsigned long) __pure2; +unsigned int stdc_bit_width_ull(unsigned long long) __pure2; +#define stdc_bit_width(x) __generic_bitfunc(stdc_bit_width, x) + +unsigned char stdc_bit_floor_uc(unsigned char) __pure2; +unsigned short stdc_bit_floor_us(unsigned short) __pure2; +unsigned stdc_bit_floor_ui(unsigned int) __pure2; +unsigned long stdc_bit_floor_ul(unsigned long) __pure2; +unsigned long long stdc_bit_floor_ull(unsigned long long) __pure2; +#define stdc_bit_floor(x) __generic_bitfunc(stdc_bit_floor, x) + +unsigned char stdc_bit_ceil_uc(unsigned char) __pure2; +unsigned short stdc_bit_ceil_us(unsigned short) __pure2; +unsigned int stdc_bit_ceil_ui(unsigned int) __pure2; +unsigned long stdc_bit_ceil_ul(unsigned long) __pure2; +unsigned long long stdc_bit_ceil_ull(unsigned long long) __pure2; +#define stdc_bit_ceil(x) __generic_bitfunc(stdc_bit_ceil, x) +__END_DECLS + +#endif /* __STDC_VERSION_STDBIT_H__ */ diff --git a/lib/libc/Makefile b/lib/libc/Makefile index 8705568f6d34..34474cfa9fe4 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -118,6 +118,7 @@ NOASM= .endif .include "${LIBC_SRCTOP}/regex/Makefile.inc" .include "${LIBC_SRCTOP}/resolv/Makefile.inc" +.include "${LIBC_SRCTOP}/stdbit/Makefile.inc" .include "${LIBC_SRCTOP}/stdio/Makefile.inc" .include "${LIBC_SRCTOP}/stdlib/Makefile.inc" .include "${LIBC_SRCTOP}/stdtime/Makefile.inc" diff --git a/lib/libc/stdbit/Makefile.inc b/lib/libc/stdbit/Makefile.inc new file mode 100644 index 000000000000..2ea96d2b6dfe --- /dev/null +++ b/lib/libc/stdbit/Makefile.inc @@ -0,0 +1,19 @@ +# sources for <stdbit.h> +.PATH: ${LIBC_SRCTOP}/stdbit + +SRCS+= stdc_bit_ceil.c \ + stdc_bit_floor.c \ + stdc_bit_width.c \ + stdc_count_ones.c \ + stdc_count_zeros.c \ + stdc_first_leading_one.c \ + stdc_first_leading_zero.c \ + stdc_first_trailing_one.c \ + stdc_first_trailing_zero.c \ + stdc_has_single_bit.c \ + stdc_leading_ones.c \ + stdc_leading_zeros.c \ + stdc_trailing_ones.c \ + stdc_trailing_zeros.c + +SYM_MAPS+=${LIBC_SRCTOP}/stdbit/Symbol.map diff --git a/lib/libc/stdbit/Symbol.map b/lib/libc/stdbit/Symbol.map new file mode 100644 index 000000000000..7014d6984c07 --- /dev/null +++ b/lib/libc/stdbit/Symbol.map @@ -0,0 +1,85 @@ +FBSD_1.9 { + stdc_leading_zeros_uc; + stdc_leading_zeros_us; + stdc_leading_zeros_ui; + stdc_leading_zeros_ul; + stdc_leading_zeros_ull; + + stdc_leading_ones_uc; + stdc_leading_ones_us; + stdc_leading_ones_ui; + stdc_leading_ones_ul; + stdc_leading_ones_ull; + + stdc_trailing_zeros_uc; + stdc_trailing_zeros_us; + stdc_trailing_zeros_ui; + stdc_trailing_zeros_ul; + stdc_trailing_zeros_ull; + + stdc_trailing_ones_uc; + stdc_trailing_ones_us; + stdc_trailing_ones_ui; + stdc_trailing_ones_ul; + stdc_trailing_ones_ull; + + stdc_first_leading_zero_uc; + stdc_first_leading_zero_us; + stdc_first_leading_zero_ui; + stdc_first_leading_zero_ul; + stdc_first_leading_zero_ull; + + stdc_first_leading_one_uc; + stdc_first_leading_one_us; + stdc_first_leading_one_ui; + stdc_first_leading_one_ul; + stdc_first_leading_one_ull; + + stdc_first_trailing_zero_uc; + stdc_first_trailing_zero_us; + stdc_first_trailing_zero_ui; + stdc_first_trailing_zero_ul; + stdc_first_trailing_zero_ull; + + stdc_first_trailing_one_uc; + stdc_first_trailing_one_us; + stdc_first_trailing_one_ui; + stdc_first_trailing_one_ul; + stdc_first_trailing_one_ull; + + stdc_count_zeros_uc; + stdc_count_zeros_us; + stdc_count_zeros_ui; + stdc_count_zeros_ul; + stdc_count_zeros_ull; + + stdc_count_ones_uc; + stdc_count_ones_us; + stdc_count_ones_ui; + stdc_count_ones_ul; + stdc_count_ones_ull; + + stdc_has_single_bit_uc; + stdc_has_single_bit_us; + stdc_has_single_bit_ui; + stdc_has_single_bit_ul; + stdc_has_single_bit_ull; + + stdc_bit_width_uc; + stdc_bit_width_us; + stdc_bit_width_ui; + stdc_bit_width_ul; + stdc_bit_width_ull; + + stdc_bit_floor_uc; + stdc_bit_floor_us; + stdc_bit_floor_ui; + stdc_bit_floor_ul; + stdc_bit_floor_ull; + + stdc_bit_ceil_uc; + stdc_bit_ceil_us; + stdc_bit_ceil_ui; + stdc_bit_ceil_ul; + stdc_bit_ceil_ull; +}; diff --git a/lib/libc/stdbit/stdc_bit_ceil.c b/lib/libc/stdbit/stdc_bit_ceil.c new file mode 100644 index 000000000000..2dfd7bbcbea2 --- /dev/null +++ b/lib/libc/stdbit/stdc_bit_ceil.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <assert.h> +#include <limits.h> +#include <stdbit.h> + +/* Ensure we don't shift 1U out of range. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_bit_ceil_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned char +stdc_bit_ceil_uc(unsigned char x) +{ + if (x <= 1) + return (1); + + return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); +} + +/* Ensure we don't shift 1U out of range. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_bit_ceil_us needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned short +stdc_bit_ceil_us(unsigned short x) +{ + if (x <= 1) + return (1); + + return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); +} + +unsigned int +stdc_bit_ceil_ui(unsigned int x) +{ + if (x <= 1) + return (1); + + if (x > UINT_MAX/2 + 1) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); +} + +unsigned long +stdc_bit_ceil_ul(unsigned long x) +{ + if (x <= 1) + return (1); + + if (x > ULONG_MAX/2 + 1) + return (0); + + return (1UL << (ULONG_WIDTH - __builtin_clzl(x - 1))); +} + +unsigned long long +stdc_bit_ceil_ull(unsigned long long x) +{ + if (x <= 1) + return (1); + + if (x > ULLONG_MAX/2 + 1) + return (0); + + return (1ULL << (ULLONG_WIDTH - __builtin_clzll(x - 1))); +} diff --git a/lib/libc/stdbit/stdc_bit_floor.c b/lib/libc/stdbit/stdc_bit_floor.c new file mode 100644 index 000000000000..0a491d6ec7b3 --- /dev/null +++ b/lib/libc/stdbit/stdc_bit_floor.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <limits.h> +#include <stdbit.h> + +unsigned char +stdc_bit_floor_uc(unsigned char x) +{ + if (x == 0) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x) - 1)); +} + +unsigned short +stdc_bit_floor_us(unsigned short x) +{ + if (x == 0) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x) - 1)); +} + +unsigned int +stdc_bit_floor_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (1U << (UINT_WIDTH - __builtin_clz(x) - 1)); +} + +unsigned long +stdc_bit_floor_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (1UL << (ULONG_WIDTH - __builtin_clzl(x) - 1)); +} + +unsigned long long +stdc_bit_floor_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (1ULL << (ULLONG_WIDTH - __builtin_clzll(x) - 1)); +} diff --git a/lib/libc/stdbit/stdc_bit_width.c b/lib/libc/stdbit/stdc_bit_width.c new file mode 100644 index 000000000000..e248fae48e9f --- /dev/null +++ b/lib/libc/stdbit/stdc_bit_width.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <limits.h> +#include <stdbit.h> + +unsigned int +stdc_bit_width_uc(unsigned char x) +{ + if (x == 0) + return (0); + + return (UINT_WIDTH - __builtin_clz(x)); +} + +unsigned int +stdc_bit_width_us(unsigned short x) +{ + if (x == 0) + return (0); + + return (UINT_WIDTH - __builtin_clz(x)); +} + +unsigned int +stdc_bit_width_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (UINT_WIDTH - __builtin_clz(x)); +} + +unsigned int +stdc_bit_width_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (ULONG_WIDTH - __builtin_clzl(x)); +} + +unsigned int +stdc_bit_width_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (ULLONG_WIDTH - __builtin_clzll(x)); +} diff --git a/lib/libc/stdbit/stdc_count_ones.c b/lib/libc/stdbit/stdc_count_ones.c new file mode 100644 index 000000000000..c5198dca84df --- /dev/null +++ b/lib/libc/stdbit/stdc_count_ones.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <limits.h> +#include <stdbit.h> + +unsigned int +stdc_count_ones_uc(unsigned char x) +{ + return (__builtin_popcount(x)); +} + +unsigned int +stdc_count_ones_us(unsigned short x) +{ + return (__builtin_popcount(x)); +} + +unsigned int +stdc_count_ones_ui(unsigned int x) +{ + return (__builtin_popcount(x)); +} + +unsigned int +stdc_count_ones_ul(unsigned long x) +{ + return (__builtin_popcountl(x)); +} + +unsigned int +stdc_count_ones_ull(unsigned long long x) +{ + return (__builtin_popcountll(x)); +} diff --git a/lib/libc/stdbit/stdc_count_zeros.c b/lib/libc/stdbit/stdc_count_zeros.c new file mode 100644 index 000000000000..35db965afcb5 --- /dev/null +++ b/lib/libc/stdbit/stdc_count_zeros.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <limits.h> +#include <stdbit.h> + +unsigned int +stdc_count_zeros_uc(unsigned char x) +{ + return (__builtin_popcount(x ^ UCHAR_MAX)); +} + +unsigned int +stdc_count_zeros_us(unsigned short x) +{ + return (__builtin_popcount(x ^ USHRT_MAX)); +} + +unsigned int +stdc_count_zeros_ui(unsigned int x) +{ + return (__builtin_popcount(~x)); +} + +unsigned int +stdc_count_zeros_ul(unsigned long x) +{ + return (__builtin_popcountl(~x)); +} + +unsigned int +stdc_count_zeros_ull(unsigned long long x) +{ + return (__builtin_popcountll(~x)); +} diff --git a/lib/libc/stdbit/stdc_first_leading_one.c b/lib/libc/stdbit/stdc_first_leading_one.c new file mode 100644 index 000000000000..de436856569f --- /dev/null +++ b/lib/libc/stdbit/stdc_first_leading_one.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <limits.h> +#include <stdbit.h> + +unsigned int +stdc_first_leading_one_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + if (x == 0) + return (0); + + return (__builtin_clz(x << offset) + 1); +} + +unsigned int +stdc_first_leading_one_us(unsigned short x) +{ + const int offset = UINT_WIDTH - USHRT_WIDTH; + + if (x == 0) + return (0); + + return (__builtin_clz(x << offset) + 1); +} + +unsigned int +stdc_first_leading_one_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (__builtin_clz(x) + 1); +} + +unsigned int +stdc_first_leading_one_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (__builtin_clzl(x) + 1); +} + +unsigned int +stdc_first_leading_one_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (__builtin_clzll(x) + 1); +} diff --git a/lib/libc/stdbit/stdc_first_leading_zero.c b/lib/libc/stdbit/stdc_first_leading_zero.c new file mode 100644 index 000000000000..e6609b51b648 --- /dev/null +++ b/lib/libc/stdbit/stdc_first_leading_zero.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <limits.h> +#include <stdbit.h> + +unsigned int +stdc_first_leading_zero_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + if (x == UCHAR_MAX) + return (0); + + return (__builtin_clz(~(unsigned int)x << offset) + 1); +} + +unsigned int +stdc_first_leading_zero_us(unsigned short x) +{ + const int offset = UINT_WIDTH - USHRT_WIDTH; + + if (x == USHRT_MAX) + return (0); + + return (__builtin_clz(~(unsigned int)x << offset) + 1); +} + +unsigned int +stdc_first_leading_zero_ui(unsigned int x) +{ + if (x == ~0U) + return (0); + + return (__builtin_clz(~x) + 1); +} + +unsigned int +stdc_first_leading_zero_ul(unsigned long x) +{ + if (x == ~0UL) + return (0); + + return (__builtin_clzl(~x) + 1); +} + +unsigned int +stdc_first_leading_zero_ull(unsigned long long x) +{ + if (x == ~0ULL) + return (0); + + return (__builtin_clzll(~x) + 1); +} diff --git a/lib/libc/stdbit/stdc_first_trailing_one.c b/lib/libc/stdbit/stdc_first_trailing_one.c new file mode 100644 index 000000000000..22972758d25d --- /dev/null +++ b/lib/libc/stdbit/stdc_first_trailing_one.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <stdbit.h> + +unsigned int +stdc_first_trailing_one_uc(unsigned char x) +{ + if (x == 0) + return (0); + + return (__builtin_ctz(x) + 1); +} + +unsigned int +stdc_first_trailing_one_us(unsigned short x) +{ + if (x == 0) + return (0); + + return (__builtin_ctz(x) + 1); +} + +unsigned int +stdc_first_trailing_one_ui(unsigned int x) +{ + if (x == 0) + return (0); + + return (__builtin_ctz(x) + 1); +} + +unsigned int +stdc_first_trailing_one_ul(unsigned long x) +{ + if (x == 0) + return (0); + + return (__builtin_ctzl(x) + 1); +} + +unsigned int +stdc_first_trailing_one_ull(unsigned long long x) +{ + if (x == 0) + return (0); + + return (__builtin_ctzll(x) + 1); +} diff --git a/lib/libc/stdbit/stdc_first_trailing_zero.c b/lib/libc/stdbit/stdc_first_trailing_zero.c new file mode 100644 index 000000000000..27395c6977c3 --- /dev/null +++ b/lib/libc/stdbit/stdc_first_trailing_zero.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <limits.h> +#include <stdbit.h> + +unsigned int +stdc_first_trailing_zero_uc(unsigned char x) +{ + if (x == UCHAR_MAX) + return (0); + + return (__builtin_ctz(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_us(unsigned short x) +{ + if (x == USHRT_MAX) + return (0); + + return (__builtin_ctz(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_ui(unsigned int x) +{ + if (x == ~0U) + return (0); + + return (__builtin_ctz(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_ul(unsigned long x) +{ + if (x == ~0UL) + return (0); + + return (__builtin_ctzl(~x) + 1); +} + +unsigned int +stdc_first_trailing_zero_ull(unsigned long long x) +{ + if (x == ~0ULL) + return (0); + + return (__builtin_ctzll(~x) + 1); +} diff --git a/lib/libc/stdbit/stdc_has_single_bit.c b/lib/libc/stdbit/stdc_has_single_bit.c new file mode 100644 index 000000000000..e5f676265551 --- /dev/null +++ b/lib/libc/stdbit/stdc_has_single_bit.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <stdbit.h> +#include <stdbool.h> + +bool +stdc_has_single_bit_uc(unsigned char x) +{ + return (x != 0 && (x & x - 1) == 0); +} + +bool +stdc_has_single_bit_us(unsigned short x) +{ + return (x != 0 && (x & x - 1) == 0); +} + +bool +stdc_has_single_bit_ui(unsigned int x) +{ + return (x != 0 && (x & x - 1) == 0); +} + +bool +stdc_has_single_bit_ul(unsigned long x) +{ + return (x != 0 && (x & x - 1) == 0); +} + +bool +stdc_has_single_bit_ull(unsigned long long x) +{ + return (x != 0 && (x & x - 1) == 0); +} diff --git a/lib/libc/stdbit/stdc_leading_ones.c b/lib/libc/stdbit/stdc_leading_ones.c new file mode 100644 index 000000000000..79d3ec7f2065 --- /dev/null +++ b/lib/libc/stdbit/stdc_leading_ones.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <assert.h> +#include <limits.h> +#include <stdbit.h> + +/* Avoid triggering undefined behavior if x == 0. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_leading_ones_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_leading_ones_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + return (__builtin_clz(~(x << offset))); +} + +/* Avoid triggering undefined behavior if x == 0. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_leading_ones_us needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_leading_ones_us(unsigned short x) +{ + const int offset = UINT_WIDTH - USHRT_WIDTH; + + return (__builtin_clz(~(x << offset))); +} + +unsigned int +stdc_leading_ones_ui(unsigned int x) +{ + if (x == ~0U) + return (UINT_WIDTH); + + return (__builtin_clz(~x)); +} + +unsigned int +stdc_leading_ones_ul(unsigned long x) +{ + if (x == ~0UL) + return (ULONG_WIDTH); + + return (__builtin_clzl(~x)); +} + +unsigned int +stdc_leading_ones_ull(unsigned long long x) +{ + if (x == ~0ULL) + return (ULLONG_WIDTH); + + return (__builtin_clzll(~x)); +} diff --git a/lib/libc/stdbit/stdc_leading_zeros.c b/lib/libc/stdbit/stdc_leading_zeros.c new file mode 100644 index 000000000000..2fdf64ec93d4 --- /dev/null +++ b/lib/libc/stdbit/stdc_leading_zeros.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Robert Clausecker <[email protected]> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <assert.h> +#include <limits.h> +#include <stdbit.h> + +/* Offset must be greater than zero. */ +static_assert(UCHAR_WIDTH < UINT_WIDTH, + "stdc_leading_zeros_uc needs UCHAR_WIDTH < UINT_WIDTH"); + +unsigned int +stdc_leading_zeros_uc(unsigned char x) +{ + const int offset = UINT_WIDTH - UCHAR_WIDTH; + + return (__builtin_clz((x << offset) + (1U << (offset - 1)))); +} + +/* Offset must be greater than zero. */ +static_assert(USHRT_WIDTH < UINT_WIDTH, + "stdc_leading_zeros_us needs USHRT_WIDTH < UINT_WIDTH"); + +unsigned int *** 157 LINES SKIPPED ***
