RISC-V: implement private GCC library

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>
This commit is contained in:
Heinrich Schuchardt 2025-12-01 18:49:03 +01:00 committed by Leo Yu-Chi Liang
parent 7a12507e35
commit dd0ad45920
5 changed files with 204 additions and 1 deletions

View 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

View 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

105
arch/riscv/lib/clz.c Normal file
View File

@ -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
}

95
arch/riscv/lib/ctz.c Normal file
View File

@ -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
}

View 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.