Skip to content

Commit 9fa7998

Browse files
committed
[libc] Support for riscv32
This change adds basic support for baremetal riscv32 configuration. Differential Revision: https://reviews.llvm.org/D152563
1 parent 61e9198 commit 9fa7998

File tree

5 files changed

+316
-0
lines changed

5 files changed

+316
-0
lines changed

libc/cmake/modules/LLVMLibCArchitectures.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ function(get_arch_and_system_from_triple triple arch_var sys_var)
5555
set(target_arch "x86_64")
5656
elseif(target_arch MATCHES "^(powerpc|ppc)")
5757
set(target_arch "power")
58+
elseif(target_arch MATCHES "^riscv32")
59+
set(target_arch "riscv32")
5860
elseif(target_arch MATCHES "^riscv64")
5961
set(target_arch "riscv64")
6062
else()
@@ -148,6 +150,8 @@ elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "aarch64")
148150
set(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 TRUE)
149151
elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64")
150152
set(LIBC_TARGET_ARCHITECTURE_IS_X86 TRUE)
153+
elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv32")
154+
set(LIBC_TARGET_ARCHITECTURE_IS_RISCV32 TRUE)
151155
elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv64")
152156
set(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 TRUE)
153157
else()
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
set(TARGET_LIBC_ENTRYPOINTS
2+
# ctype.h entrypoints
3+
libc.src.ctype.isalnum
4+
libc.src.ctype.isalpha
5+
libc.src.ctype.isascii
6+
libc.src.ctype.isblank
7+
libc.src.ctype.iscntrl
8+
libc.src.ctype.isdigit
9+
libc.src.ctype.isgraph
10+
libc.src.ctype.islower
11+
libc.src.ctype.isprint
12+
libc.src.ctype.ispunct
13+
libc.src.ctype.isspace
14+
libc.src.ctype.isupper
15+
libc.src.ctype.isxdigit
16+
libc.src.ctype.toascii
17+
libc.src.ctype.tolower
18+
libc.src.ctype.toupper
19+
20+
# errno.h entrypoints
21+
libc.src.errno.errno
22+
23+
# string.h entrypoints
24+
libc.src.string.bcmp
25+
libc.src.string.bcopy
26+
libc.src.string.bzero
27+
libc.src.string.memccpy
28+
libc.src.string.memchr
29+
libc.src.string.memcmp
30+
libc.src.string.memcpy
31+
libc.src.string.memmem
32+
libc.src.string.memmove
33+
libc.src.string.mempcpy
34+
libc.src.string.memrchr
35+
libc.src.string.memset
36+
libc.src.string.stpcpy
37+
libc.src.string.stpncpy
38+
libc.src.string.strcasecmp
39+
libc.src.string.strcasestr
40+
libc.src.string.strcat
41+
libc.src.string.strchr
42+
libc.src.string.strchrnul
43+
libc.src.string.strcmp
44+
libc.src.string.strcpy
45+
libc.src.string.strcspn
46+
libc.src.string.strlcat
47+
libc.src.string.strlcpy
48+
libc.src.string.strlen
49+
libc.src.string.strncasecmp
50+
libc.src.string.strncat
51+
libc.src.string.strncmp
52+
libc.src.string.strncpy
53+
libc.src.string.strnlen
54+
libc.src.string.strpbrk
55+
libc.src.string.strrchr
56+
libc.src.string.strspn
57+
libc.src.string.strstr
58+
libc.src.string.strtok
59+
libc.src.string.strtok_r
60+
61+
# inttypes.h entrypoints
62+
libc.src.inttypes.imaxabs
63+
libc.src.inttypes.imaxdiv
64+
libc.src.inttypes.strtoimax
65+
libc.src.inttypes.strtoumax
66+
67+
# stdlib.h entrypoints
68+
libc.src.stdlib.abs
69+
libc.src.stdlib.atoi
70+
libc.src.stdlib.atol
71+
libc.src.stdlib.atoll
72+
libc.src.stdlib.bsearch
73+
libc.src.stdlib.div
74+
libc.src.stdlib.labs
75+
libc.src.stdlib.ldiv
76+
libc.src.stdlib.llabs
77+
libc.src.stdlib.lldiv
78+
libc.src.stdlib.qsort
79+
libc.src.stdlib.strtol
80+
libc.src.stdlib.strtoll
81+
libc.src.stdlib.strtoul
82+
libc.src.stdlib.strtoull
83+
)
84+
85+
set(TARGET_LIBM_ENTRYPOINTS
86+
# fenv.h entrypoints
87+
libc.src.fenv.feclearexcept
88+
libc.src.fenv.fedisableexcept
89+
libc.src.fenv.feenableexcept
90+
libc.src.fenv.fegetenv
91+
libc.src.fenv.fegetexcept
92+
libc.src.fenv.fegetexceptflag
93+
libc.src.fenv.fegetround
94+
libc.src.fenv.feholdexcept
95+
libc.src.fenv.fesetenv
96+
libc.src.fenv.fesetexceptflag
97+
libc.src.fenv.fesetround
98+
libc.src.fenv.feraiseexcept
99+
libc.src.fenv.fetestexcept
100+
libc.src.fenv.feupdateenv
101+
102+
# math.h entrypoints
103+
libc.src.math.fabs
104+
libc.src.math.fabsf
105+
libc.src.math.fabsl
106+
libc.src.math.fdim
107+
libc.src.math.fdimf
108+
libc.src.math.fdiml
109+
libc.src.math.fmax
110+
libc.src.math.fmaxf
111+
libc.src.math.fmaxl
112+
libc.src.math.fmin
113+
libc.src.math.fminf
114+
libc.src.math.fminl
115+
)
116+
117+
set(TARGET_LLVMLIBC_ENTRYPOINTS
118+
${TARGET_LIBC_ENTRYPOINTS}
119+
${TARGET_LIBM_ENTRYPOINTS}
120+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(TARGET_PUBLIC_HEADERS
2+
libc.include.ctype
3+
libc.include.fenv
4+
libc.include.errno
5+
libc.include.inttypes
6+
libc.include.math
7+
libc.include.stdlib
8+
libc.include.string
9+
libc.include.strings
10+
)

libc/src/__support/FPUtil/FEnvImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "x86_64/FEnvImpl.h"
3131
#elif defined(LIBC_TARGET_ARCH_IS_ARM)
3232
#include "arm/FEnvImpl.h"
33+
#elif defined(LIBC_TARGET_ARCH_IS_RISCV32)
34+
#include "riscv32/FEnvImpl.h"
3335
#elif defined(LIBC_TARGET_ARCH_IS_RISCV64)
3436
#include "riscv64/FEnvImpl.h"
3537
#else
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
//===-- riscv32 floating point env manipulation functions -------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_RISCV32_FENVIMPL_H
10+
#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_RISCV32_FENVIMPL_H
11+
12+
#include "src/__support/FPUtil/FPBits.h"
13+
#include "src/__support/macros/attributes.h" // For LIBC_INLINE_ASM
14+
#include "src/__support/macros/config.h" // For LIBC_INLINE
15+
16+
#include <fenv.h>
17+
#include <stdint.h>
18+
19+
namespace __llvm_libc {
20+
namespace fputil {
21+
22+
struct FEnv {
23+
// We will ignore RMM and DYN rounding modes.
24+
static constexpr uint32_t TONEAREST = 0x0;
25+
static constexpr uint32_t TOWARDZERO = 0x1;
26+
static constexpr uint32_t DOWNWARD = 0x2;
27+
static constexpr uint32_t UPWARD = 0x3;
28+
29+
// These are the bit locations of the corresponding exceptions in fcsr.
30+
static constexpr uint32_t INEXACT = 0x1;
31+
static constexpr uint32_t UNDERFLOW = 0x2;
32+
static constexpr uint32_t OVERFLOW = 0x4;
33+
static constexpr uint32_t DIVBYZERO = 0x8;
34+
static constexpr uint32_t INVALID = 0x10;
35+
36+
LIBC_INLINE static uint32_t get_frm() {
37+
unsigned int rm;
38+
LIBC_INLINE_ASM("frrm %0\n\t" : "=r"(rm));
39+
return rm;
40+
}
41+
42+
LIBC_INLINE static void set_frm(uint32_t rm) {
43+
LIBC_INLINE_ASM("fsrm %0, %0\n\t" : "+r"(rm));
44+
}
45+
46+
LIBC_INLINE static uint32_t get_fflags() {
47+
unsigned int flags;
48+
LIBC_INLINE_ASM("frflags %0\n\t" : "=r"(flags));
49+
return flags;
50+
}
51+
52+
LIBC_INLINE static void set_fflags(uint32_t flags) {
53+
LIBC_INLINE_ASM("fsflags %0, %0\n\t" : "+r"(flags));
54+
}
55+
56+
LIBC_INLINE static uint32_t get_fcsr() {
57+
unsigned int fcsr;
58+
LIBC_INLINE_ASM("frcsr %0\n\t" : "=r"(fcsr));
59+
return fcsr;
60+
}
61+
62+
LIBC_INLINE static void set_fcsr(uint32_t fcsr) {
63+
LIBC_INLINE_ASM("fscsr %0, %0\n\t" : "+r"(fcsr));
64+
}
65+
66+
LIBC_INLINE static int exception_bits_to_macro(uint32_t status) {
67+
return (status & INVALID ? FE_INVALID : 0) |
68+
(status & DIVBYZERO ? FE_DIVBYZERO : 0) |
69+
(status & OVERFLOW ? FE_OVERFLOW : 0) |
70+
(status & UNDERFLOW ? FE_UNDERFLOW : 0) |
71+
(status & INEXACT ? FE_INEXACT : 0);
72+
}
73+
74+
LIBC_INLINE static uint32_t exception_macro_to_bits(int except) {
75+
return (except & FE_INVALID ? INVALID : 0) |
76+
(except & FE_DIVBYZERO ? DIVBYZERO : 0) |
77+
(except & FE_OVERFLOW ? OVERFLOW : 0) |
78+
(except & FE_UNDERFLOW ? UNDERFLOW : 0) |
79+
(except & FE_INEXACT ? INEXACT : 0);
80+
}
81+
};
82+
83+
// Since RISCV does not have exception enable bits, we will just return
84+
// the failure indicator.
85+
LIBC_INLINE int enable_except(int) { return -1; }
86+
87+
// Always succeed.
88+
LIBC_INLINE int disable_except(int) { return 0; }
89+
90+
// Always return "no exceptions enabled".
91+
LIBC_INLINE int get_except() { return 0; }
92+
93+
LIBC_INLINE int clear_except(int excepts) {
94+
uint32_t flags = FEnv::get_fflags();
95+
uint32_t to_clear = FEnv::exception_macro_to_bits(excepts);
96+
flags &= ~to_clear;
97+
FEnv::set_fflags(flags);
98+
return 0;
99+
}
100+
101+
LIBC_INLINE int test_except(int excepts) {
102+
uint32_t to_test = FEnv::exception_macro_to_bits(excepts);
103+
uint32_t flags = FEnv::get_fflags();
104+
return FEnv::exception_bits_to_macro(flags & to_test);
105+
}
106+
107+
LIBC_INLINE int set_except(int excepts) {
108+
uint32_t flags = FEnv::get_fflags();
109+
FEnv::set_fflags(flags | FEnv::exception_macro_to_bits(excepts));
110+
return 0;
111+
}
112+
113+
LIBC_INLINE int raise_except(int excepts) {
114+
// Since there are no traps, we just set the exception flags.
115+
uint32_t flags = FEnv::get_fflags();
116+
FEnv::set_fflags(flags | FEnv::exception_macro_to_bits(excepts));
117+
return 0;
118+
}
119+
120+
LIBC_INLINE int get_round() {
121+
uint32_t rm = FEnv::get_frm();
122+
switch (rm) {
123+
case FEnv::TONEAREST:
124+
return FE_TONEAREST;
125+
case FEnv::DOWNWARD:
126+
return FE_DOWNWARD;
127+
case FEnv::UPWARD:
128+
return FE_UPWARD;
129+
case FEnv::TOWARDZERO:
130+
return FE_TOWARDZERO;
131+
default:
132+
return -1; // Error value.
133+
}
134+
return 0;
135+
}
136+
137+
LIBC_INLINE int set_round(int mode) {
138+
uint32_t rm;
139+
switch (mode) {
140+
case FE_TONEAREST:
141+
rm = FEnv::TONEAREST;
142+
break;
143+
case FE_DOWNWARD:
144+
rm = FEnv::DOWNWARD;
145+
break;
146+
case FE_UPWARD:
147+
rm = FEnv::UPWARD;
148+
break;
149+
case FE_TOWARDZERO:
150+
rm = FEnv::TOWARDZERO;
151+
break;
152+
default:
153+
return -1; // To indicate failure
154+
}
155+
FEnv::set_frm(rm);
156+
return 0;
157+
}
158+
159+
LIBC_INLINE int get_env(fenv_t *envp) {
160+
uint32_t *state = reinterpret_cast<uint32_t *>(envp);
161+
*state = FEnv::get_fcsr();
162+
return 0;
163+
}
164+
165+
LIBC_INLINE int set_env(const fenv_t *envp) {
166+
if (envp == FE_DFL_ENV) {
167+
FEnv::set_frm(FEnv::TONEAREST);
168+
FEnv::set_fflags(0);
169+
return 0;
170+
}
171+
uint32_t status = *reinterpret_cast<const uint32_t *>(envp);
172+
// We have to do the masking to preserve the reserved bits.
173+
FEnv::set_fcsr((status & 0xFF) | (FEnv::get_fcsr() & 0xFFFFFF00));
174+
return 0;
175+
}
176+
177+
} // namespace fputil
178+
} // namespace __llvm_libc
179+
180+
#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_RISCV32_FENVIMPL_H

0 commit comments

Comments
 (0)