Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147743729
D53657.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D53657.diff
View Options
diff --git a/include/Makefile b/include/Makefile
--- a/include/Makefile
+++ b/include/Makefile
@@ -29,8 +29,8 @@
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
--- /dev/null
+++ b/include/stdbit.h
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -118,6 +118,7 @@
.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
--- /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
--- /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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_bit_ceil.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_bit_floor.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_bit_width.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_count_ones.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_count_zeros.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_first_leading_one.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_first_leading_zero.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_first_trailing_one.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_first_trailing_zero.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_has_single_bit.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_leading_ones.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
--- /dev/null
+++ b/lib/libc/stdbit/stdc_leading_zeros.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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
+stdc_leading_zeros_us(unsigned short x)
+{
+ const int offset = UINT_WIDTH - USHRT_WIDTH;
+
+ return (__builtin_clz((x << offset) + (1U << (offset - 1))));
+}
+
+unsigned int
+stdc_leading_zeros_ui(unsigned int x)
+{
+ if (x == 0)
+ return (UINT_WIDTH);
+
+ return (__builtin_clz(x));
+}
+
+unsigned int
+stdc_leading_zeros_ul(unsigned long x)
+{
+ if (x == 0)
+ return (ULONG_WIDTH);
+
+ return (__builtin_clzl(x));
+}
+
+unsigned int
+stdc_leading_zeros_ull(unsigned long long x)
+{
+ if (x == 0)
+ return (ULLONG_WIDTH);
+
+ return (__builtin_clzll(x));
+}
diff --git a/lib/libc/stdbit/stdc_trailing_ones.c b/lib/libc/stdbit/stdc_trailing_ones.c
new file mode 100644
--- /dev/null
+++ b/lib/libc/stdbit/stdc_trailing_ones.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * 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_trailing_ones_uc needs UCHAR_WIDTH < UINT_WIDTH");
+
+unsigned int
+stdc_trailing_ones_uc(unsigned char x)
+{
+ return (__builtin_ctz(~x));
+}
+
+/* Avoid triggering undefined behavior if x == ~0. */
+static_assert(USHRT_WIDTH < UINT_WIDTH,
+ "stdc_trailing_ones_uc needs USHRT_WIDTH < UINT_WIDTH");
+
+unsigned int
+stdc_trailing_ones_us(unsigned short x)
+{
+ return (__builtin_ctz(~x));
+}
+
+unsigned int
+stdc_trailing_ones_ui(unsigned int x)
+{
+ if (x == ~0U)
+ return (UINT_WIDTH);
+
+ return (__builtin_ctz(~x));
+}
+
+unsigned int
+stdc_trailing_ones_ul(unsigned long x)
+{
+ if (x == ~0UL)
+ return (ULONG_WIDTH);
+
+ return (__builtin_ctzl(~x));
+}
+
+unsigned int
+stdc_trailing_ones_ull(unsigned long long x)
+{
+ if (x == ~0ULL)
+ return (ULLONG_WIDTH);
+
+ return (__builtin_ctzll(~x));
+}
diff --git a/lib/libc/stdbit/stdc_trailing_zeros.c b/lib/libc/stdbit/stdc_trailing_zeros.c
new file mode 100644
--- /dev/null
+++ b/lib/libc/stdbit/stdc_trailing_zeros.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbit.h>
+
+/* Ensure we do not shift 1U out of range. */
+static_assert(UCHAR_WIDTH < UINT_WIDTH,
+ "stdc_trailing_zeros_uc needs UCHAR_WIDTH < UINT_WIDTH");
+
+unsigned int
+stdc_trailing_zeros_uc(unsigned char x)
+{
+ return (__builtin_ctz(x | 1U << UCHAR_WIDTH));
+}
+
+/* Ensure we do not shift 1U out of range. */
+static_assert(USHRT_WIDTH < UINT_WIDTH,
+ "stdc_trailing_zeros_uc needs USHRT_WIDTH < UINT_WIDTH");
+
+unsigned int
+stdc_trailing_zeros_us(unsigned short x)
+{
+ return (__builtin_ctz(x | 1U << USHRT_WIDTH));
+}
+
+unsigned int
+stdc_trailing_zeros_ui(unsigned int x)
+{
+ if (x == 0U)
+ return (UINT_WIDTH);
+
+ return (__builtin_ctz(x));
+}
+
+unsigned int
+stdc_trailing_zeros_ul(unsigned long x)
+{
+ if (x == 0UL)
+ return (ULONG_WIDTH);
+
+ return (__builtin_ctzl(x));
+}
+
+unsigned int
+stdc_trailing_zeros_ull(unsigned long long x)
+{
+ if (x == 0ULL)
+ return (ULLONG_WIDTH);
+
+ return (__builtin_ctzll(x));
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 14, 8:37 AM (40 m, 16 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29661930
Default Alt Text
D53657.diff (25 KB)
Attached To
Mode
D53657: libc: implement C23 <stdbit.h> functions
Attached
Detach File
Event Timeline
Log In to Comment