]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
RISC-V: implement private GCC library
authorHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Mon, 1 Dec 2025 17:49:03 +0000 (18:49 +0100)
committerLeo Yu-Chi Liang <ycliang@andestech.com>
Mon, 8 Dec 2025 04:10:55 +0000 (12:10 +0800)
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@canonical.com>
arch/Kconfig
arch/riscv/lib/Makefile
arch/riscv/lib/clz.c [new file with mode: 0644]
arch/riscv/lib/ctz.c [new file with mode: 0644]
lib/Kconfig

index 3133f892f945e465ec649b2ec680ba6461371176..4af0da2485fbbee8b6b6a4e9debb33ae34c93b6f 100644 (file)
@@ -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
index f1f50918effb45f8281d0d1b315523e42919f706..a527b3e9ae3703a75a02111bea908f67c3ad1ba1 100644 (file)
@@ -6,6 +6,8 @@
 # Copyright (C) 2017 Andes Technology Corporation
 # Rick Chen, Andes Technology Corporation <rick@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 (file)
index 0000000..7b173d3
--- /dev/null
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * libgcc replacement - count leading bits
+ *
+ * Copyright 2025, Heinrich Schuchardt <heinrich.schuchardt@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 (file)
index 0000000..6c875e3
--- /dev/null
@@ -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
+}
index fdfe0bd504248e27e5df373de6c228cfa36e3a6c..fe0b878a206b7d600440f1e2fca644b599b22f94 100644 (file)
@@ -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.