Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144591591
D53657.1775620491.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
D53657.1775620491.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: func ## _ui, \
+ unsigned long: func ## _ul, \
+ unsigned long long: func ## _ull)(x))
+
+__BEGIN_DECLS
+unsigned stdc_leading_zeros_uc(unsigned char) __pure2;
+unsigned stdc_leading_zeros_us(unsigned short) __pure2;
+unsigned stdc_leading_zeros_ui(unsigned) __pure2;
+unsigned stdc_leading_zeros_ul(unsigned long) __pure2;
+unsigned stdc_leading_zeros_ull(unsigned long long) __pure2;
+#define stdc_leading_zeros(x) __generic_bitfunc(stdc_leading_zeros, x)
+
+unsigned stdc_leading_ones_uc(unsigned char) __pure2;
+unsigned stdc_leading_ones_us(unsigned short) __pure2;
+unsigned stdc_leading_ones_ui(unsigned) __pure2;
+unsigned stdc_leading_ones_ul(unsigned long) __pure2;
+unsigned stdc_leading_ones_ull(unsigned long long) __pure2;
+#define stdc_leading_ones(x) __generic_bitfunc(stdc_leading_ones, x)
+
+unsigned stdc_trailing_zeros_uc(unsigned char) __pure2;
+unsigned stdc_trailing_zeros_us(unsigned short) __pure2;
+unsigned stdc_trailing_zeros_ui(unsigned) __pure2;
+unsigned stdc_trailing_zeros_ul(unsigned long) __pure2;
+unsigned stdc_trailing_zeros_ull(unsigned long long) __pure2;
+#define stdc_trailing_zeros(x) __generic_bitfunc(stdc_trailing_zeros, x)
+
+unsigned stdc_trailing_ones_uc(unsigned char) __pure2;
+unsigned stdc_trailing_ones_us(unsigned short) __pure2;
+unsigned stdc_trailing_ones_ui(unsigned) __pure2;
+unsigned stdc_trailing_ones_ul(unsigned long) __pure2;
+unsigned stdc_trailing_ones_ull(unsigned long long) __pure2;
+#define stdc_trailing_ones(x) __generic_bitfunc(stdc_trailing_ones, x)
+
+unsigned stdc_first_leading_zero_uc(unsigned char) __pure2;
+unsigned stdc_first_leading_zero_us(unsigned short) __pure2;
+unsigned stdc_first_leading_zero_ui(unsigned) __pure2;
+unsigned stdc_first_leading_zero_ul(unsigned long) __pure2;
+unsigned stdc_first_leading_zero_ull(unsigned long long) __pure2;
+#define stdc_first_leading_zero(x) __generic_bitfunc(stdc_first_leading_zero, x)
+
+unsigned stdc_first_leading_one_uc(unsigned char) __pure2;
+unsigned stdc_first_leading_one_us(unsigned short) __pure2;
+unsigned stdc_first_leading_one_ui(unsigned) __pure2;
+unsigned stdc_first_leading_one_ul(unsigned long) __pure2;
+unsigned stdc_first_leading_one_ull(unsigned long long) __pure2;
+#define stdc_first_leading_one(x) __generic_bitfunc(stdc_first_leading_one, x)
+
+unsigned stdc_first_trailing_zero_uc(unsigned char) __pure2;
+unsigned stdc_first_trailing_zero_us(unsigned short) __pure2;
+unsigned stdc_first_trailing_zero_ui(unsigned) __pure2;
+unsigned stdc_first_trailing_zero_ul(unsigned long) __pure2;
+unsigned stdc_first_trailing_zero_ull(unsigned long long) __pure2;
+#define stdc_first_trailing_zero(x) __generic_bitfunc(stdc_first_trailing_zero, x)
+
+unsigned stdc_first_trailing_one_uc(unsigned char) __pure2;
+unsigned stdc_first_trailing_one_us(unsigned short) __pure2;
+unsigned stdc_first_trailing_one_ui(unsigned) __pure2;
+unsigned stdc_first_trailing_one_ul(unsigned long) __pure2;
+unsigned stdc_first_trailing_one_ull(unsigned long long) __pure2;
+#define stdc_first_trailing_one(x) __generic_bitfunc(stdc_first_trailing_one, x)
+
+unsigned stdc_count_zeros_uc(unsigned char) __pure2;
+unsigned stdc_count_zeros_us(unsigned short) __pure2;
+unsigned stdc_count_zeros_ui(unsigned) __pure2;
+unsigned stdc_count_zeros_ul(unsigned long) __pure2;
+unsigned stdc_count_zeros_ull(unsigned long long) __pure2;
+#define stdc_count_zeros(x) __generic_bitfunc(stdc_count_zeros, x)
+
+unsigned stdc_count_ones_uc(unsigned char) __pure2;
+unsigned stdc_count_ones_us(unsigned short) __pure2;
+unsigned stdc_count_ones_ui(unsigned) __pure2;
+unsigned stdc_count_ones_ul(unsigned long) __pure2;
+unsigned 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) __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 stdc_bit_width_uc(unsigned char) __pure2;
+unsigned stdc_bit_width_us(unsigned short) __pure2;
+unsigned stdc_bit_width_ui(unsigned) __pure2;
+unsigned stdc_bit_width_ul(unsigned long) __pure2;
+unsigned 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) __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 stdc_bit_ceil_ui(unsigned) __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_leading_zeros.c \
+ stdc_leading_ones.c \
+ stdc_trailing_zeros.c \
+ stdc_trailing_ones.c \
+ stdc_first_leading_zero.c \
+ stdc_first_leading_one.c \
+ stdc_first_trailing_zero.c \
+ stdc_first_trailing_one.c \
+ stdc_count_zeros.c \
+ stdc_count_ones.c \
+ stdc_has_single_bit.c \
+ stdc_bit_width.c \
+ stdc_bit_floor.c \
+ stdc_bit_ceil.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,69 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbit.h>
+
+static_assert(sizeof(unsigned char) < sizeof(unsigned),
+ "stdc_bit_ceil_uc needs sizeof(unsigned char) < sizeof(unsigned)");
+
+unsigned char
+stdc_bit_ceil_uc(unsigned char x)
+{
+ if (x <= 1)
+ return (1);
+
+ return (1U << (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x - 1)));
+}
+
+static_assert(sizeof(unsigned short) < sizeof(unsigned),
+ "stdc_bit_ceil_us needs sizeof(unsigned short) < sizeof(unsigned)");
+
+unsigned short
+stdc_bit_ceil_us(unsigned short x)
+{
+ if (x <= 1)
+ return (1);
+
+ return (1U << (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x - 1)));
+}
+
+unsigned
+stdc_bit_ceil_ui(unsigned x)
+{
+ if (x <= 1)
+ return (1);
+
+ if (x > UINT_MAX/2 + 1)
+ return (0);
+
+ return (1U << (CHAR_BIT * sizeof(unsigned) - __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 << (CHAR_BIT * sizeof(unsigned long) - __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 << (CHAR_BIT * sizeof(unsigned long long) - __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 << (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x) - 1));
+}
+
+unsigned short
+stdc_bit_floor_us(unsigned short x)
+{
+ if (x == 0)
+ return (0);
+
+ return (1U << (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x) - 1));
+}
+
+unsigned
+stdc_bit_floor_ui(unsigned x)
+{
+ if (x == 0)
+ return (0);
+
+ return (1U << (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x) - 1));
+}
+
+unsigned long
+stdc_bit_floor_ul(unsigned long x)
+{
+ if (x == 0)
+ return (0);
+
+ return (1UL << (CHAR_BIT * sizeof(unsigned long) - __builtin_clzl(x) - 1));
+}
+
+unsigned long long
+stdc_bit_floor_ull(unsigned long long x)
+{
+ if (x == 0)
+ return (0);
+
+ return (1ULL << (CHAR_BIT * sizeof(unsigned long long) - __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
+stdc_bit_width_uc(unsigned char x)
+{
+ if (x == 0)
+ return 0;
+
+ return (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x));
+}
+
+unsigned
+stdc_bit_width_us(unsigned short x)
+{
+ if (x == 0)
+ return 0;
+
+ return (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x));
+}
+
+unsigned
+stdc_bit_width_ui(unsigned x)
+{
+ if (x == 0)
+ return 0;
+
+ return (CHAR_BIT * sizeof(unsigned) - __builtin_clz(x));
+}
+
+unsigned
+stdc_bit_width_ul(unsigned long x)
+{
+ if (x == 0)
+ return 0;
+
+ return (CHAR_BIT * sizeof(unsigned long) - __builtin_clzl(x));
+}
+
+unsigned
+stdc_bit_width_ull(unsigned long long x)
+{
+ if (x == 0)
+ return 0;
+
+ return (CHAR_BIT * sizeof(unsigned long long) - __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
+stdc_count_ones_uc(unsigned char x)
+{
+ return (__builtin_popcount(x));
+}
+
+unsigned
+stdc_count_ones_us(unsigned short x)
+{
+ return (__builtin_popcount(x));
+}
+
+unsigned
+stdc_count_ones_ui(unsigned x)
+{
+ return (__builtin_popcount(x));
+}
+
+unsigned
+stdc_count_ones_ul(unsigned long x)
+{
+ return (__builtin_popcountl(x));
+}
+
+unsigned
+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
+stdc_count_zeros_uc(unsigned char x)
+{
+ return (__builtin_popcount(x ^ UCHAR_MAX));
+}
+
+unsigned
+stdc_count_zeros_us(unsigned short x)
+{
+ return (__builtin_popcount(x ^ USHRT_MAX));
+}
+
+unsigned
+stdc_count_zeros_ui(unsigned x)
+{
+ return (__builtin_popcount(~x));
+}
+
+unsigned
+stdc_count_zeros_ul(unsigned long x)
+{
+ return (__builtin_popcountl(~x));
+}
+
+unsigned
+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
+stdc_first_leading_one_uc(unsigned char x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ if (x == 0)
+ return (0);
+
+ return (__builtin_clz(x << offset) + 1);
+}
+
+unsigned
+stdc_first_leading_one_us(unsigned short x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ if (x == 0)
+ return (0);
+
+ return (__builtin_clz(x << offset) + 1);
+}
+
+unsigned
+stdc_first_leading_one_ui(unsigned x)
+{
+ if (x == 0)
+ return (0);
+
+ return (__builtin_clz(x) + 1);
+}
+
+unsigned
+stdc_first_leading_one_ul(unsigned long x)
+{
+ if (x == 0)
+ return (0);
+
+ return (__builtin_clzl(x) + 1);
+}
+
+unsigned
+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
+stdc_first_leading_zero_uc(unsigned char x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ if (x == UCHAR_MAX)
+ return (0);
+
+ return (__builtin_clz(~(unsigned)x << offset) + 1);
+}
+
+unsigned
+stdc_first_leading_zero_us(unsigned short x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ if (x == USHRT_MAX)
+ return (0);
+
+ return (__builtin_clz(~(unsigned)x << offset) + 1);
+}
+
+unsigned
+stdc_first_leading_zero_ui(unsigned x)
+{
+ if (x == ~0U)
+ return (0);
+
+ return (__builtin_clz(~x) + 1);
+}
+
+unsigned
+stdc_first_leading_zero_ul(unsigned long x)
+{
+ if (x == ~0UL)
+ return (0);
+
+ return (__builtin_clzl(~x) + 1);
+}
+
+unsigned
+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
+stdc_first_trailing_one_uc(unsigned char x)
+{
+ if (x == 0)
+ return (0);
+
+ return (__builtin_ctz(x) + 1);
+}
+
+unsigned
+stdc_first_trailing_one_us(unsigned short x)
+{
+ if (x == 0)
+ return (0);
+
+ return (__builtin_ctz(x) + 1);
+}
+
+unsigned
+stdc_first_trailing_one_ui(unsigned x)
+{
+ if (x == 0)
+ return (0);
+
+ return (__builtin_ctz(x) + 1);
+}
+
+unsigned
+stdc_first_trailing_one_ul(unsigned long x)
+{
+ if (x == 0)
+ return (0);
+
+ return (__builtin_ctzl(x) + 1);
+}
+
+unsigned
+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
+stdc_first_trailing_zero_uc(unsigned char x)
+{
+ if (x == UCHAR_MAX)
+ return (0);
+
+ return (__builtin_ctz(~x) + 1);
+}
+
+unsigned
+stdc_first_trailing_zero_us(unsigned short x)
+{
+ if (x == USHRT_MAX)
+ return (0);
+
+ return (__builtin_ctz(~x) + 1);
+}
+
+unsigned
+stdc_first_trailing_zero_ui(unsigned x)
+{
+ if (x == ~0U)
+ return (0);
+
+ return (__builtin_ctz(~x) + 1);
+}
+
+unsigned
+stdc_first_trailing_zero_ul(unsigned long x)
+{
+ if (x == ~0UL)
+ return (0);
+
+ return (__builtin_ctzl(~x) + 1);
+}
+
+unsigned
+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 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,58 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbit.h>
+
+static_assert(sizeof(unsigned char) < sizeof(unsigned),
+ "stdc_leading_ones_uc needs sizeof(unsigned char) < sizeof(unsigned)");
+
+unsigned
+stdc_leading_ones_uc(unsigned char x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ return (__builtin_clz(~(x << offset)));
+}
+
+static_assert(sizeof(unsigned short) < sizeof(unsigned),
+ "stdc_leading_ones_us needs sizeof(unsigned short) < sizeof(unsigned)");
+
+unsigned
+stdc_leading_ones_us(unsigned short x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ return (__builtin_clz(~(x << offset)));
+}
+
+unsigned
+stdc_leading_ones_ui(unsigned x)
+{
+ if (x == ~0U)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_clz(~x));
+}
+
+unsigned
+stdc_leading_ones_ul(unsigned long x)
+{
+ if (x == ~0UL)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_clzl(~x));
+}
+
+unsigned
+stdc_leading_ones_ull(unsigned long long x)
+{
+ if (x == ~0ULL)
+ return (sizeof(x) * CHAR_BIT);
+
+ 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,58 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbit.h>
+
+static_assert(sizeof(unsigned char) < sizeof(unsigned),
+ "stdc_leading_zeros_uc needs sizeof(unsigned char) < sizeof(unsigned)");
+
+unsigned
+stdc_leading_zeros_uc(unsigned char x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ return (__builtin_clz((x << offset) + (1 << (offset - 1))));
+}
+
+static_assert(sizeof(unsigned short) < sizeof(unsigned),
+ "stdc_leading_zeros_us needs sizeof(unsigned short) < sizeof(unsigned)");
+
+unsigned
+stdc_leading_zeros_us(unsigned short x)
+{
+ const int offset = CHAR_BIT * (sizeof(unsigned) - sizeof(x));
+
+ return (__builtin_clz((x << offset) + (1 << (offset - 1))));
+}
+
+unsigned
+stdc_leading_zeros_ui(unsigned x)
+{
+ if (x == 0)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_clz(x));
+}
+
+unsigned
+stdc_leading_zeros_ul(unsigned long x)
+{
+ if (x == 0)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_clzl(x));
+}
+
+unsigned
+stdc_leading_zeros_ull(unsigned long long x)
+{
+ if (x == 0)
+ return (sizeof(x) * CHAR_BIT);
+
+ 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,54 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbit.h>
+
+static_assert(sizeof(unsigned char) < sizeof(unsigned),
+ "stdc_trailing_ones_uc needs sizeof(unsigned char) < sizeof(unsigned)");
+
+unsigned
+stdc_trailing_ones_uc(unsigned char x)
+{
+ return (__builtin_ctz(~x));
+}
+
+static_assert(sizeof(unsigned short) < sizeof(unsigned),
+ "stdc_trailing_ones_us needs sizeof(unsigned short) < sizeof(unsigned)");
+
+unsigned
+stdc_trailing_ones_us(unsigned short x)
+{
+ return (__builtin_ctz(~x));
+}
+
+unsigned
+stdc_trailing_ones_ui(unsigned x)
+{
+ if (x == ~0U)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_ctz(~x));
+}
+
+unsigned
+stdc_trailing_ones_ul(unsigned long x)
+{
+ if (x == ~0UL)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_ctzl(~x));
+}
+
+unsigned
+stdc_trailing_ones_ull(unsigned long long x)
+{
+ if (x == ~0ULL)
+ return (sizeof(x) * CHAR_BIT);
+
+ 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,54 @@
+/*
+ * Copyright (c) 2025 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbit.h>
+
+static_assert(sizeof(unsigned char) < sizeof(unsigned),
+ "stdc_trailing_zeros_uc needs sizeof(unsigned char) < sizeof(unsigned)");
+
+unsigned
+stdc_trailing_zeros_uc(unsigned char x)
+{
+ return (__builtin_ctz(x + UCHAR_MAX + 1));
+}
+
+static_assert(sizeof(unsigned short) < sizeof(unsigned),
+ "stdc_trailing_zeros_us needs sizeof(unsigned short) < sizeof(unsigned)");
+
+unsigned
+stdc_trailing_zeros_us(unsigned short x)
+{
+ return (__builtin_ctz(x + USHRT_MAX + 1));
+}
+
+unsigned
+stdc_trailing_zeros_ui(unsigned x)
+{
+ if (x == 0)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_ctz(x));
+}
+
+unsigned
+stdc_trailing_zeros_ul(unsigned long x)
+{
+ if (x == 0)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_ctzl(x));
+}
+
+unsigned
+stdc_trailing_zeros_ull(unsigned long long x)
+{
+ if (x == 0)
+ return (sizeof(x) * CHAR_BIT);
+
+ return (__builtin_ctzll(x));
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 8, 3:54 AM (4 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28297610
Default Alt Text
D53657.1775620491.diff (24 KB)
Attached To
Mode
D53657: libc: implement C23 <stdbit.h> functions
Attached
Detach File
Event Timeline
Log In to Comment