[newlib-cygwin/main] Fix stdbit functions for 16-bit targets
Jeff Johnston
jjohnstn@sourceware.org
Tue Sep 15 16:10:51 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=00208dc31e790b8c130f32c4a0528c781fc07328
commit 00208dc31e790b8c130f32c4a0528c781fc07328
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Sep 15 11:56:04 2026 -0400
Fix stdbit functions for 16-bit targets
All the USHRT_WIDTH < UINT_WIDTH assertions fail for 16-bit int targets,
such as msp430-elf. Remove those static assertions and instead fix the
stdc_xxx_us functions to work correctly when USHRT_WIDTH == UINT_WIDTH.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
Diff:
---
newlib/libc/stdbit/stdc_bit_ceil.c | 7 ++++++-
newlib/libc/stdbit/stdc_leading_ones.c | 7 +++++++
newlib/libc/stdbit/stdc_leading_zeros.c | 7 +++++++
newlib/libc/stdbit/stdc_trailing_ones.c | 7 +++++++
newlib/libc/stdbit/stdc_trailing_zeros.c | 9 +++++++++
5 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/newlib/libc/stdbit/stdc_bit_ceil.c b/newlib/libc/stdbit/stdc_bit_ceil.c
index f25d184af..1108c2ba6 100644
--- a/newlib/libc/stdbit/stdc_bit_ceil.c
+++ b/newlib/libc/stdbit/stdc_bit_ceil.c
@@ -23,16 +23,21 @@ stdc_bit_ceil_uc(unsigned char x)
return (1U << (UINT_WIDTH - __builtin_clz(x - 1)));
}
+#ifndef __NEWLIB_H__
/* Ensure we don't shift 1U out of range. */
_Static_assert(USHRT_WIDTH < UINT_WIDTH,
"stdc_bit_ceil_us needs USHRT_WIDTH < UINT_WIDTH");
+#endif
unsigned short
stdc_bit_ceil_us(unsigned short x)
{
if (x <= 1)
return (1);
-
+#if defined(__NEWLIB_H__) && USHRT_WIDTH == UINT_WIDTH
+ if (x > USHRT_MAX/2 + 1)
+ return (0);
+#endif
return (1U << (UINT_WIDTH - __builtin_clz(x - 1)));
}
diff --git a/newlib/libc/stdbit/stdc_leading_ones.c b/newlib/libc/stdbit/stdc_leading_ones.c
index c7ab75b98..551794c20 100644
--- a/newlib/libc/stdbit/stdc_leading_ones.c
+++ b/newlib/libc/stdbit/stdc_leading_ones.c
@@ -22,13 +22,20 @@ stdc_leading_ones_uc(unsigned char x)
return (__builtin_clz(~(x << offset)));
}
+#ifndef __NEWLIB_H__
/* Avoid triggering undefined behavior if x == 0. */
_Static_assert(USHRT_WIDTH < UINT_WIDTH,
"stdc_leading_ones_us needs USHRT_WIDTH < UINT_WIDTH");
+#endif
unsigned int
stdc_leading_ones_us(unsigned short x)
{
+#if defined(__NEWLIB_H__) && USHRT_WIDTH == UINT_WIDTH
+ /* Avoid triggering undefined behavior if x == 0. */
+ if (x == ~0U)
+ return (USHRT_WIDTH);
+#endif
const int offset = UINT_WIDTH - USHRT_WIDTH;
return (__builtin_clz(~(x << offset)));
diff --git a/newlib/libc/stdbit/stdc_leading_zeros.c b/newlib/libc/stdbit/stdc_leading_zeros.c
index dba6a14e2..bd751a1cd 100644
--- a/newlib/libc/stdbit/stdc_leading_zeros.c
+++ b/newlib/libc/stdbit/stdc_leading_zeros.c
@@ -22,13 +22,20 @@ stdc_leading_zeros_uc(unsigned char x)
return (__builtin_clz((x << offset) + (1U << (offset - 1))));
}
+#ifndef __NEWLIB_H__
/* Offset must be greater than zero. */
_Static_assert(USHRT_WIDTH < UINT_WIDTH,
"stdc_leading_zeros_us needs USHRT_WIDTH < UINT_WIDTH");
+#endif
unsigned int
stdc_leading_zeros_us(unsigned short x)
{
+#if defined(__NEWLIB_H__) && USHRT_WIDTH == UINT_WIDTH
+ /* Offset must be greater than zero. */
+ if (x == 0)
+ return (USHRT_WIDTH);
+#endif
const int offset = UINT_WIDTH - USHRT_WIDTH;
return (__builtin_clz((x << offset) + (1U << (offset - 1))));
diff --git a/newlib/libc/stdbit/stdc_trailing_ones.c b/newlib/libc/stdbit/stdc_trailing_ones.c
index 0f7ccb553..8ee2a8989 100644
--- a/newlib/libc/stdbit/stdc_trailing_ones.c
+++ b/newlib/libc/stdbit/stdc_trailing_ones.c
@@ -20,13 +20,20 @@ stdc_trailing_ones_uc(unsigned char x)
return (__builtin_ctz(~x));
}
+#ifndef __NEWLIB_H__
/* Avoid triggering undefined behavior if x == ~0. */
_Static_assert(USHRT_WIDTH < UINT_WIDTH,
"stdc_trailing_ones_uc needs USHRT_WIDTH < UINT_WIDTH");
+#endif
unsigned int
stdc_trailing_ones_us(unsigned short x)
{
+#if defined(__NEWLIB_H__) && USHRT_WIDTH == UINT_WIDTH
+ /* Avoid triggering undefined behavior if x == ~0. */
+ if (x == ~0U)
+ return (USHRT_WIDTH);
+#endif
return (__builtin_ctz(~x));
}
diff --git a/newlib/libc/stdbit/stdc_trailing_zeros.c b/newlib/libc/stdbit/stdc_trailing_zeros.c
index 396333e17..0a9d823dd 100644
--- a/newlib/libc/stdbit/stdc_trailing_zeros.c
+++ b/newlib/libc/stdbit/stdc_trailing_zeros.c
@@ -20,14 +20,23 @@ stdc_trailing_zeros_uc(unsigned char x)
return (__builtin_ctz(x | 1U << UCHAR_WIDTH));
}
+#ifndef __NEWLIB_H__
/* Ensure we do not shift 1U out of range. */
_Static_assert(USHRT_WIDTH < UINT_WIDTH,
"stdc_trailing_zeros_uc needs USHRT_WIDTH < UINT_WIDTH");
+#endif
unsigned int
stdc_trailing_zeros_us(unsigned short x)
{
+#if defined(__NEWLIB_H__) && USHRT_WIDTH == UINT_WIDTH
+ /* Ensure we do not shift 1U out of range. */
+ if (x == 0U)
+ return (USHRT_WIDTH);
+ return (__builtin_ctz(x));
+#else
return (__builtin_ctz(x | 1U << USHRT_WIDTH));
+#endif
}
unsigned int
More information about the Newlib-cvs
mailing list