[libc-commits] [libc] 9fa7998 - [libc] Support for riscv32
Petr Hosek via libc-commits
libc-commits at lists.llvm.org
Wed Jun 21 00:11:56 PDT 2023
Author: Petr Hosek
Date: 2023-06-21T07:11:22Z
New Revision: 9fa7998555e8c0f18bd9bf052adfa2395f54407e
URL: https://github.com/llvm/llvm-project/commit/9fa7998555e8c0f18bd9bf052adfa2395f54407e
DIFF: https://github.com/llvm/llvm-project/commit/9fa7998555e8c0f18bd9bf052adfa2395f54407e.diff
LOG: [libc] Support for riscv32
This change adds basic support for baremetal riscv32 configuration.
Differential Revision: https://reviews.llvm.org/D152563
Added:
libc/config/baremetal/riscv32/entrypoints.txt
libc/config/baremetal/riscv32/headers.txt
libc/src/__support/FPUtil/riscv32/FEnvImpl.h
Modified:
libc/cmake/modules/LLVMLibCArchitectures.cmake
libc/src/__support/FPUtil/FEnvImpl.h
Removed:
################################################################################
diff --git a/libc/cmake/modules/LLVMLibCArchitectures.cmake b/libc/cmake/modules/LLVMLibCArchitectures.cmake
index f3852e1b9e056..1e53e1a2b60bf 100644
--- a/libc/cmake/modules/LLVMLibCArchitectures.cmake
+++ b/libc/cmake/modules/LLVMLibCArchitectures.cmake
@@ -55,6 +55,8 @@ function(get_arch_and_system_from_triple triple arch_var sys_var)
set(target_arch "x86_64")
elseif(target_arch MATCHES "^(powerpc|ppc)")
set(target_arch "power")
+ elseif(target_arch MATCHES "^riscv32")
+ set(target_arch "riscv32")
elseif(target_arch MATCHES "^riscv64")
set(target_arch "riscv64")
else()
@@ -148,6 +150,8 @@ elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "aarch64")
set(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 TRUE)
elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64")
set(LIBC_TARGET_ARCHITECTURE_IS_X86 TRUE)
+elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv32")
+ set(LIBC_TARGET_ARCHITECTURE_IS_RISCV32 TRUE)
elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv64")
set(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 TRUE)
else()
diff --git a/libc/config/baremetal/riscv32/entrypoints.txt b/libc/config/baremetal/riscv32/entrypoints.txt
new file mode 100644
index 0000000000000..37651aaef1b08
--- /dev/null
+++ b/libc/config/baremetal/riscv32/entrypoints.txt
@@ -0,0 +1,120 @@
+set(TARGET_LIBC_ENTRYPOINTS
+ # ctype.h entrypoints
+ libc.src.ctype.isalnum
+ libc.src.ctype.isalpha
+ libc.src.ctype.isascii
+ libc.src.ctype.isblank
+ libc.src.ctype.iscntrl
+ libc.src.ctype.isdigit
+ libc.src.ctype.isgraph
+ libc.src.ctype.islower
+ libc.src.ctype.isprint
+ libc.src.ctype.ispunct
+ libc.src.ctype.isspace
+ libc.src.ctype.isupper
+ libc.src.ctype.isxdigit
+ libc.src.ctype.toascii
+ libc.src.ctype.tolower
+ libc.src.ctype.toupper
+
+ # errno.h entrypoints
+ libc.src.errno.errno
+
+ # string.h entrypoints
+ libc.src.string.bcmp
+ libc.src.string.bcopy
+ libc.src.string.bzero
+ libc.src.string.memccpy
+ libc.src.string.memchr
+ libc.src.string.memcmp
+ libc.src.string.memcpy
+ libc.src.string.memmem
+ libc.src.string.memmove
+ libc.src.string.mempcpy
+ libc.src.string.memrchr
+ libc.src.string.memset
+ libc.src.string.stpcpy
+ libc.src.string.stpncpy
+ libc.src.string.strcasecmp
+ libc.src.string.strcasestr
+ libc.src.string.strcat
+ libc.src.string.strchr
+ libc.src.string.strchrnul
+ libc.src.string.strcmp
+ libc.src.string.strcpy
+ libc.src.string.strcspn
+ libc.src.string.strlcat
+ libc.src.string.strlcpy
+ libc.src.string.strlen
+ libc.src.string.strncasecmp
+ libc.src.string.strncat
+ libc.src.string.strncmp
+ libc.src.string.strncpy
+ libc.src.string.strnlen
+ libc.src.string.strpbrk
+ libc.src.string.strrchr
+ libc.src.string.strspn
+ libc.src.string.strstr
+ libc.src.string.strtok
+ libc.src.string.strtok_r
+
+ # inttypes.h entrypoints
+ libc.src.inttypes.imaxabs
+ libc.src.inttypes.imaxdiv
+ libc.src.inttypes.strtoimax
+ libc.src.inttypes.strtoumax
+
+ # stdlib.h entrypoints
+ libc.src.stdlib.abs
+ libc.src.stdlib.atoi
+ libc.src.stdlib.atol
+ libc.src.stdlib.atoll
+ libc.src.stdlib.bsearch
+ libc.src.stdlib.div
+ libc.src.stdlib.labs
+ libc.src.stdlib.ldiv
+ libc.src.stdlib.llabs
+ libc.src.stdlib.lldiv
+ libc.src.stdlib.qsort
+ libc.src.stdlib.strtol
+ libc.src.stdlib.strtoll
+ libc.src.stdlib.strtoul
+ libc.src.stdlib.strtoull
+)
+
+set(TARGET_LIBM_ENTRYPOINTS
+ # fenv.h entrypoints
+ libc.src.fenv.feclearexcept
+ libc.src.fenv.fedisableexcept
+ libc.src.fenv.feenableexcept
+ libc.src.fenv.fegetenv
+ libc.src.fenv.fegetexcept
+ libc.src.fenv.fegetexceptflag
+ libc.src.fenv.fegetround
+ libc.src.fenv.feholdexcept
+ libc.src.fenv.fesetenv
+ libc.src.fenv.fesetexceptflag
+ libc.src.fenv.fesetround
+ libc.src.fenv.feraiseexcept
+ libc.src.fenv.fetestexcept
+ libc.src.fenv.feupdateenv
+
+ # math.h entrypoints
+ libc.src.math.fabs
+ libc.src.math.fabsf
+ libc.src.math.fabsl
+ libc.src.math.fdim
+ libc.src.math.fdimf
+ libc.src.math.fdiml
+ libc.src.math.fmax
+ libc.src.math.fmaxf
+ libc.src.math.fmaxl
+ libc.src.math.fmin
+ libc.src.math.fminf
+ libc.src.math.fminl
+)
+
+set(TARGET_LLVMLIBC_ENTRYPOINTS
+ ${TARGET_LIBC_ENTRYPOINTS}
+ ${TARGET_LIBM_ENTRYPOINTS}
+)
diff --git a/libc/config/baremetal/riscv32/headers.txt b/libc/config/baremetal/riscv32/headers.txt
new file mode 100644
index 0000000000000..fe7c88e922e07
--- /dev/null
+++ b/libc/config/baremetal/riscv32/headers.txt
@@ -0,0 +1,10 @@
+set(TARGET_PUBLIC_HEADERS
+ libc.include.ctype
+ libc.include.fenv
+ libc.include.errno
+ libc.include.inttypes
+ libc.include.math
+ libc.include.stdlib
+ libc.include.string
+ libc.include.strings
+)
diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h
index 2556f432b02cc..f525004c294c3 100644
--- a/libc/src/__support/FPUtil/FEnvImpl.h
+++ b/libc/src/__support/FPUtil/FEnvImpl.h
@@ -30,6 +30,8 @@
#include "x86_64/FEnvImpl.h"
#elif defined(LIBC_TARGET_ARCH_IS_ARM)
#include "arm/FEnvImpl.h"
+#elif defined(LIBC_TARGET_ARCH_IS_RISCV32)
+#include "riscv32/FEnvImpl.h"
#elif defined(LIBC_TARGET_ARCH_IS_RISCV64)
#include "riscv64/FEnvImpl.h"
#else
diff --git a/libc/src/__support/FPUtil/riscv32/FEnvImpl.h b/libc/src/__support/FPUtil/riscv32/FEnvImpl.h
new file mode 100644
index 0000000000000..bb2ffac72af16
--- /dev/null
+++ b/libc/src/__support/FPUtil/riscv32/FEnvImpl.h
@@ -0,0 +1,180 @@
+//===-- riscv32 floating point env manipulation functions -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_RISCV32_FENVIMPL_H
+#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_RISCV32_FENVIMPL_H
+
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/attributes.h" // For LIBC_INLINE_ASM
+#include "src/__support/macros/config.h" // For LIBC_INLINE
+
+#include <fenv.h>
+#include <stdint.h>
+
+namespace __llvm_libc {
+namespace fputil {
+
+struct FEnv {
+ // We will ignore RMM and DYN rounding modes.
+ static constexpr uint32_t TONEAREST = 0x0;
+ static constexpr uint32_t TOWARDZERO = 0x1;
+ static constexpr uint32_t DOWNWARD = 0x2;
+ static constexpr uint32_t UPWARD = 0x3;
+
+ // These are the bit locations of the corresponding exceptions in fcsr.
+ static constexpr uint32_t INEXACT = 0x1;
+ static constexpr uint32_t UNDERFLOW = 0x2;
+ static constexpr uint32_t OVERFLOW = 0x4;
+ static constexpr uint32_t DIVBYZERO = 0x8;
+ static constexpr uint32_t INVALID = 0x10;
+
+ LIBC_INLINE static uint32_t get_frm() {
+ unsigned int rm;
+ LIBC_INLINE_ASM("frrm %0\n\t" : "=r"(rm));
+ return rm;
+ }
+
+ LIBC_INLINE static void set_frm(uint32_t rm) {
+ LIBC_INLINE_ASM("fsrm %0, %0\n\t" : "+r"(rm));
+ }
+
+ LIBC_INLINE static uint32_t get_fflags() {
+ unsigned int flags;
+ LIBC_INLINE_ASM("frflags %0\n\t" : "=r"(flags));
+ return flags;
+ }
+
+ LIBC_INLINE static void set_fflags(uint32_t flags) {
+ LIBC_INLINE_ASM("fsflags %0, %0\n\t" : "+r"(flags));
+ }
+
+ LIBC_INLINE static uint32_t get_fcsr() {
+ unsigned int fcsr;
+ LIBC_INLINE_ASM("frcsr %0\n\t" : "=r"(fcsr));
+ return fcsr;
+ }
+
+ LIBC_INLINE static void set_fcsr(uint32_t fcsr) {
+ LIBC_INLINE_ASM("fscsr %0, %0\n\t" : "+r"(fcsr));
+ }
+
+ LIBC_INLINE static int exception_bits_to_macro(uint32_t status) {
+ return (status & INVALID ? FE_INVALID : 0) |
+ (status & DIVBYZERO ? FE_DIVBYZERO : 0) |
+ (status & OVERFLOW ? FE_OVERFLOW : 0) |
+ (status & UNDERFLOW ? FE_UNDERFLOW : 0) |
+ (status & INEXACT ? FE_INEXACT : 0);
+ }
+
+ LIBC_INLINE static uint32_t exception_macro_to_bits(int except) {
+ return (except & FE_INVALID ? INVALID : 0) |
+ (except & FE_DIVBYZERO ? DIVBYZERO : 0) |
+ (except & FE_OVERFLOW ? OVERFLOW : 0) |
+ (except & FE_UNDERFLOW ? UNDERFLOW : 0) |
+ (except & FE_INEXACT ? INEXACT : 0);
+ }
+};
+
+// Since RISCV does not have exception enable bits, we will just return
+// the failure indicator.
+LIBC_INLINE int enable_except(int) { return -1; }
+
+// Always succeed.
+LIBC_INLINE int disable_except(int) { return 0; }
+
+// Always return "no exceptions enabled".
+LIBC_INLINE int get_except() { return 0; }
+
+LIBC_INLINE int clear_except(int excepts) {
+ uint32_t flags = FEnv::get_fflags();
+ uint32_t to_clear = FEnv::exception_macro_to_bits(excepts);
+ flags &= ~to_clear;
+ FEnv::set_fflags(flags);
+ return 0;
+}
+
+LIBC_INLINE int test_except(int excepts) {
+ uint32_t to_test = FEnv::exception_macro_to_bits(excepts);
+ uint32_t flags = FEnv::get_fflags();
+ return FEnv::exception_bits_to_macro(flags & to_test);
+}
+
+LIBC_INLINE int set_except(int excepts) {
+ uint32_t flags = FEnv::get_fflags();
+ FEnv::set_fflags(flags | FEnv::exception_macro_to_bits(excepts));
+ return 0;
+}
+
+LIBC_INLINE int raise_except(int excepts) {
+ // Since there are no traps, we just set the exception flags.
+ uint32_t flags = FEnv::get_fflags();
+ FEnv::set_fflags(flags | FEnv::exception_macro_to_bits(excepts));
+ return 0;
+}
+
+LIBC_INLINE int get_round() {
+ uint32_t rm = FEnv::get_frm();
+ switch (rm) {
+ case FEnv::TONEAREST:
+ return FE_TONEAREST;
+ case FEnv::DOWNWARD:
+ return FE_DOWNWARD;
+ case FEnv::UPWARD:
+ return FE_UPWARD;
+ case FEnv::TOWARDZERO:
+ return FE_TOWARDZERO;
+ default:
+ return -1; // Error value.
+ }
+ return 0;
+}
+
+LIBC_INLINE int set_round(int mode) {
+ uint32_t rm;
+ switch (mode) {
+ case FE_TONEAREST:
+ rm = FEnv::TONEAREST;
+ break;
+ case FE_DOWNWARD:
+ rm = FEnv::DOWNWARD;
+ break;
+ case FE_UPWARD:
+ rm = FEnv::UPWARD;
+ break;
+ case FE_TOWARDZERO:
+ rm = FEnv::TOWARDZERO;
+ break;
+ default:
+ return -1; // To indicate failure
+ }
+ FEnv::set_frm(rm);
+ return 0;
+}
+
+LIBC_INLINE int get_env(fenv_t *envp) {
+ uint32_t *state = reinterpret_cast<uint32_t *>(envp);
+ *state = FEnv::get_fcsr();
+ return 0;
+}
+
+LIBC_INLINE int set_env(const fenv_t *envp) {
+ if (envp == FE_DFL_ENV) {
+ FEnv::set_frm(FEnv::TONEAREST);
+ FEnv::set_fflags(0);
+ return 0;
+ }
+ uint32_t status = *reinterpret_cast<const uint32_t *>(envp);
+ // We have to do the masking to preserve the reserved bits.
+ FEnv::set_fcsr((status & 0xFF) | (FEnv::get_fcsr() & 0xFFFFFF00));
+ return 0;
+}
+
+} // namespace fputil
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_RISCV32_FENVIMPL_H
More information about the libc-commits
mailing list