[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