[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