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 +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 + */ + +#include + +/** + * __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 + +/** + * __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 fdfe0bd5042..fe0b878a206 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.