diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-12-14 23:50:32 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-12-14 23:50:32 +0000 |
commit | a5d076476a358e91356d2fc7e2dcc2ae72928a02 (patch) | |
tree | 48f8b21fc99c0eb2a16f18ae4328e1d4ce7e9ada /sys/lib/libkern | |
parent | c2d69d98fced9161d5159b65c2b5b7d57e29e6f4 (diff) |
add __ctzdi2 to sparc64 kernel
If __builtin_ctzl() is used on sparc64, gcc 4.2 will emit a call to
__ctzdi2. For userland this is in libgcc or compiler-rt. In the kernel
we put these functions in libkern.
'looks good' deraadt@ miod@
Diffstat (limited to 'sys/lib/libkern')
-rw-r--r-- | sys/lib/libkern/ctzdi2.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/sys/lib/libkern/ctzdi2.c b/sys/lib/libkern/ctzdi2.c new file mode 100644 index 00000000000..495657b6011 --- /dev/null +++ b/sys/lib/libkern/ctzdi2.c @@ -0,0 +1,61 @@ +/* $OpenBSD: ctzdi2.c,v 1.1 2022/12/14 23:50:31 jsg Exp $ */ + +/* + * Public domain. + * Written by Dale Rahn. + */ + +#include <lib/libkern/libkern.h> + +/* + * ffsl -- vax ffs instruction with long arg + */ + +#ifdef __LP64__ +static int +ffsl(long mask) +{ + int bit; + unsigned long r = mask; + static const signed char t[16] = { + -60, 1, 2, 1, + 3, 1, 2, 1, + 4, 1, 2, 1, + 3, 1, 2, 1 + }; + + bit = 0; + if (!(r & 0xffffffff)) { + bit += 32; + r >>= 32; + } + if (!(r & 0xffff)) { + bit += 16; + r >>= 16; + } + if (!(r & 0xff)) { + bit += 8; + r >>= 8; + } + if (!(r & 0xf)) { + bit += 4; + r >>= 4; + } + + return (bit + t[ r & 0xf ]); +} +#else +static int +ffsl(long mask) +{ + return ffs(mask); +} +#endif + +int +__ctzdi2(long mask) +{ + if (mask == 0) + return 0; + return ffsl(mask) - 1; +} |