[PATCH 1/2] RISC-V: implement private GCC library

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Mon Dec 1 18:47:04 CET 2025


From: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>

The following functions are provided:

Count leading zero bits

* int __clzsi2 (unsigned int a)
* int __clzdi2 (unsigned long a)
* int __clzti2 (unsigned long long a)

Count trailing zero bits

* int __ctzsi2 (unsigned int a)
* int __ctzdi2 (unsigned long a)
* int __ctzti2 (unsigned long long a)

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
Signed-off-by: Heinrich Schuchardt <zfsdt at canonical.com>
---
 arch/Kconfig            |   1 +
 arch/riscv/lib/Makefile |   2 +
 arch/riscv/lib/clz.c    | 105 ++++++++++++++++++++++++++++++++++++++++
 arch/riscv/lib/ctz.c    |  95 ++++++++++++++++++++++++++++++++++++
 lib/Kconfig             |   2 +-
 5 files changed, 204 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/lib/clz.c
 create mode 100644 arch/riscv/lib/ctz.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 3133f892f94..4af0da2485f 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -159,6 +159,7 @@ config PPC
 config RISCV
 	bool "RISC-V architecture"
 	select CREATE_ARCH_SYMLINK
+	select HAVE_PRIVATE_LIBGCC if 64BIT
 	select HAVE_SETJMP
 	select HAVE_INITJMP
 	select SUPPORT_ACPI
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index f1f50918eff..a527b3e9ae3 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -6,6 +6,8 @@
 # Copyright (C) 2017 Andes Technology Corporation
 # Rick Chen, Andes Technology Corporation <rick at andestech.com>
 
+lib-$(CONFIG_USE_PRIVATE_LIBGCC) += clz.o ctz.o
+
 obj-$(CONFIG_$(PHASE_)LIB_BOOTM) += bootm.o
 obj-$(CONFIG_$(PHASE_)LIB_BOOTI) += image.o
 obj-$(CONFIG_CMD_GO) += boot.o
diff --git a/arch/riscv/lib/clz.c b/arch/riscv/lib/clz.c
new file mode 100644
index 00000000000..7b173d3c858
--- /dev/null
+++ b/arch/riscv/lib/clz.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * libgcc replacement - count leading bits
+ *
+ * Copyright 2025, Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
+ */
+
+#include <linux/types.h>
+
+/**
+ * __clzti2() - count number of leading zero bits
+ *
+ * @x:		number to check
+ * Return:	number of leading zero bits
+ */
+int __clzti2(long long x)
+{
+	int ret = 64;
+
+	if (!x)
+		return 64;
+
+	if (x & 0xFFFFFFFF00000000LL) {
+		ret -= 32;
+		x >>= 32;
+	}
+	if (x & 0xFFFF0000LL) {
+		ret -= 16;
+		x >>= 16;
+	}
+	if (x & 0xFF00LL) {
+		ret -= 8;
+		x >>= 8;
+	}
+	if (x & 0xF0LL) {
+		ret -= 4;
+		x >>= 4;
+	}
+	if (x & 0xCLL) {
+		ret -= 2;
+		x >>= 2;
+	}
+	if (x & 0x2LL) {
+		ret -= 1;
+		x >>= 1;
+	}
+	if (x)
+		ret -= 1;
+
+	return ret;
+}
+
+/**
+ * __clzsi2() - count number of leading zero bits
+ *
+ * @x:		number to check
+ * Return:	number of leading zero bits
+ */
+int __clzsi2(int x)
+{
+	int ret = 32;
+
+	if (!x)
+		return 32;
+
+	if (x & 0xFFFF0000) {
+		ret -= 16;
+		x >>= 16;
+	}
+	if (x & 0xFF00) {
+		ret -= 8;
+		x >>= 8;
+	}
+	if (x & 0xF0) {
+		ret -= 4;
+		x >>= 4;
+	}
+	if (x & 0xC) {
+		ret -= 2;
+		x >>= 2;
+	}
+	if (x & 0x2) {
+		ret -= 1;
+		x >>= 1;
+	}
+	if (x)
+		ret -= 1;
+
+	return ret;
+}
+
+/**
+ * __clzdi2() - count number of leading zero bits
+ *
+ * @x:		number to check
+ * Return:	number of leading zero bits
+ */
+int __clzdi2(long x)
+{
+#if BITS_PER_LONG == 64
+	return __clzti2(x);
+#else
+	return __clzsi2(x);
+#endif
+}
diff --git a/arch/riscv/lib/ctz.c b/arch/riscv/lib/ctz.c
new file mode 100644
index 00000000000..6c875e39f0e
--- /dev/null
+++ b/arch/riscv/lib/ctz.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * libgcc replacement - count trailing bits
+ */
+
+#include <linux/types.h>
+
+/**
+ * __ctzti2() - count number of trailing zero bits
+ *
+ * @x:		number to check
+ * Return:	number of trailing zero bits
+ */
+int __ctzti2(long long x)
+{
+	int ret = 0;
+
+	if (!x)
+		return 64;
+
+	if (!(x & 0xFFFFFFFFLL)) {
+		ret += 32;
+		x >>= 32;
+	}
+	if (!(x & 0xFFFFLL)) {
+		ret += 16;
+		x >>= 16;
+	}
+	if (!(x & 0xFFLL)) {
+		ret += 8;
+		x >>= 8;
+	}
+	if (!(x & 0xFLL)) {
+		ret += 4;
+		x >>= 4;
+	}
+	if (!(x & 0x3LL)) {
+		ret += 2;
+		x >>= 2;
+	}
+	if (!(x & 0x1ll))
+		ret += 1;
+
+	return ret;
+}
+
+/**
+ * __ctzsi2() - count number of trailing zero bits
+ *
+ * @x:		number to check
+ * Return:	number of trailing zero bits
+ */
+int __ctzsi2(int x)
+{
+	int ret = 0;
+
+	if (!x)
+		return 32;
+
+	if (!(x & 0xFFFF)) {
+		ret += 16;
+		x >>= 16;
+	}
+	if (!(x & 0xFF)) {
+		ret += 8;
+		x >>= 8;
+	}
+	if (!(x & 0xF)) {
+		ret += 4;
+		x >>= 4;
+	}
+	if (!(x & 0x3)) {
+		ret += 2;
+		x >>= 2;
+	}
+	if (!(x & 0x1))
+		ret += 1;
+
+	return ret;
+}
+
+/**
+ * __ctzdi2() - count number of trailing zero bits
+ *
+ * @x:		number to check
+ * Return:	number of trailing zero bits
+ */
+int __ctzdi2(long x)
+{
+#if BITS_PER_LONG == 64
+	return __ctzti2(x);
+#else
+	return __ctzsi2(x);
+#endif
+}
diff --git a/lib/Kconfig b/lib/Kconfig
index f5c1731f456..7b390608b33 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -212,7 +212,7 @@ config IMAGE_SPARSE_FILLBUF_SIZE
 config USE_PRIVATE_LIBGCC
 	bool "Use private libgcc"
 	depends on HAVE_PRIVATE_LIBGCC
-	default y if HAVE_PRIVATE_LIBGCC && ((ARM && !ARM64) || MIPS)
+	default y if HAVE_PRIVATE_LIBGCC && ((ARM && !ARM64) || MIPS || RISCV)
 	help
 	  This option allows you to use the built-in libgcc implementation
 	  of U-Boot instead of the one provided by the compiler.
-- 
2.51.0



More information about the U-Boot mailing list