RISC-V glibc Port v1

365 views
Skip to first unread message

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:05 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
We'd like to submit for inclusion in glibc a port for the RISC-V architecture.
While it is doubtlessly not complete, we think it is far enough along to start
the upstreaming process. Our binutils and GCC ports have been accepted and
released. Our Linux port was submitted a few weeks ago and is in the review
process, while it's not upstream yet the process seems to be going pretty well
and I anticipate RISC-V support will be merged by the 4.14 release.

This port targets Version 2.2 of the RISC-V User ISA, and supports both the
RV32I and RV64I base ISAs as well as the M, A, F, D, and C extensions as well
as our Linux port which is based on the 1.10 supervisor specification. The
RISC-V community and the 60-some member companies of the RISC-V Foundation are
quite eager to have a single, standard glibc port. We thank you in advance for
your help in this process and for your feedback on the software contribution
itself.

These patches build on top of master from sourceware's git repo from last
night, a65ea28d18 ("Make copy of <bits/std_abs.h> from GCC 7 [BZ #21573]"). We
have a handful of distributions chomping at the bit to begin porting to RISC-V
and we've asked them to hold off on this process until our glibc port is
upstream and released, as that's when our ABI will officially be stable. As
such we're really hoping we can get this port in for the next release, which to
the best of my understanding will be 2.26 and should be relased in early
August. Sorry if this is a bit late in the release process, but I'm hoping
it's still managable as our port doesn't touch any existing code outside of
config.h.in.

The one problem I know of in this port is that we want to put the atomic
compare and exchange system call in the VDSO so it can be implemented more
efficiently on kernels that support the A extension. This is currently a work
in progress, but I wanted to try and submit these patches as soon as possible.
I'll include this change as part of the v2 patch set I assume I'll be
submitting.

Darius, Andrew and I will volunteer to maintain this port if it's OK with
everyone. We have our FSF copyright assignment forms filled out via our
employers (SiFive for Andrew and I, BlueSpec for Darius).

We'd like to thank the various members of the RISC-V software community who
have helped us with the port.

I've attempted to split up the patches into small enough chunks that they would
get through the mailing list, but I haveted tested anything except the full
patch set (and I don't expect that to work at all). In case anything gets
lost, our port can be found on Git Hub

https://github.com/riscv/riscv-glibc/tree/riscv-for-submission-v1

[PATCH 01/12] RISC-V: Build Infastructure
[PATCH 02/12] RISC-V: ABI Implementation
[PATCH 03/12] RISC-V: Startup and Dynamic Loading Code
[PATCH 04/12] RISC-V: Thread-Local Storage Support
[PATCH 05/12] RISC-V: Generic <string.h> Routines
[PATCH 06/12] RISC-V: Generic <math.h> and soft-fp Routines
[PATCH 07/12] RISC-V: RV32F Support
[PATCH 08/12] RISC-V: RV32D, RV64F, and RV64D Support
[PATCH 09/12] RISC-V: Atomic and Locking Routines
[PATCH 10/12] RISC-V: Linux Syscall Interface
[PATCH 11/12] RISC-V: Linux ABI
[PATCH 12/12] RISC-V: Linux Startup and Dynamic Loading Code

Thanks!

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:07 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch lays out the top-level orginazition of the RISC-V port. It
contains all the Implies files as well as various other fragments of
build infastructure for the RISC-V port. This contains the only change
to a shared file: config.h.in.

RISC-V is a family of base ISAs with optional extensions. The base ISAs
are RV32I and RV64I, which are 32-bit and 64-bit integer-only ISAs.
Support for these live in sysdeps/riscv/rv{32,64}. In addition to these
ISAs, our glibc port supports most of the currently-defined extensions:
the A extension for atomics, the M extension for multiplication, the C
extension for compressed instructions, and the F/D extensions for
single/double precision IEEE floating-point. Most of these extensions
are handled by GCC, but glibc defines various floating-point wrappers
(in sysdeps/riscv/rv{32,64}/rv{f,d}) and emulation routines (in
sysdeps/riscv/soft-fp).

We support running glibc-based programs on Linux, the suppor for which
lives in sysdeps/unix/sysv/linux/riscv.
---
config.h.in | 5 ++
sysdeps/riscv/Implies | 6 ++
sysdeps/riscv/Makefile | 45 +++++++++++++++
sysdeps/riscv/Versions | 5 ++
sysdeps/riscv/configure | 86 ++++++++++++++++++++++++++++
sysdeps/riscv/configure.in | 4 ++
sysdeps/riscv/nptl/Makefile | 25 ++++++++
sysdeps/riscv/preconfigure | 50 ++++++++++++++++
sysdeps/riscv/rv32/Implies-after | 1 +
sysdeps/riscv/rv32/rvd/Implies | 2 +
sysdeps/riscv/rv32/rvf/Implies | 1 +
sysdeps/riscv/rv64/Implies-after | 1 +
sysdeps/riscv/rv64/rvd/Implies | 2 +
sysdeps/riscv/rv64/rvf/Implies | 1 +
sysdeps/riscv/soft-fp/Makefile | 3 +
sysdeps/unix/sysv/linux/riscv/Implies | 1 +
sysdeps/unix/sysv/linux/riscv/Makefile | 26 +++++++++
sysdeps/unix/sysv/linux/riscv/configure | 7 +++
sysdeps/unix/sysv/linux/riscv/configure.in | 8 +++
sysdeps/unix/sysv/linux/riscv/rv32/Implies | 3 +
sysdeps/unix/sysv/linux/riscv/rv64/Implies | 3 +
sysdeps/unix/sysv/linux/riscv/rv64/Makefile | 9 +++
sysdeps/unix/sysv/linux/riscv/shlib-versions | 17 ++++++
23 files changed, 311 insertions(+)
create mode 100644 sysdeps/riscv/Implies
create mode 100644 sysdeps/riscv/Makefile
create mode 100644 sysdeps/riscv/Versions
create mode 100644 sysdeps/riscv/configure
create mode 100644 sysdeps/riscv/configure.in
create mode 100644 sysdeps/riscv/nptl/Makefile
create mode 100644 sysdeps/riscv/preconfigure
create mode 100644 sysdeps/riscv/rv32/Implies-after
create mode 100644 sysdeps/riscv/rv32/rvd/Implies
create mode 100644 sysdeps/riscv/rv32/rvf/Implies
create mode 100644 sysdeps/riscv/rv64/Implies-after
create mode 100644 sysdeps/riscv/rv64/rvd/Implies
create mode 100644 sysdeps/riscv/rv64/rvf/Implies
create mode 100644 sysdeps/riscv/soft-fp/Makefile
create mode 100644 sysdeps/unix/sysv/linux/riscv/Implies
create mode 100644 sysdeps/unix/sysv/linux/riscv/Makefile
create mode 100644 sysdeps/unix/sysv/linux/riscv/configure
create mode 100644 sysdeps/unix/sysv/linux/riscv/configure.in
create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/Implies
create mode 100644 sysdeps/unix/sysv/linux/riscv/rv64/Implies
create mode 100644 sysdeps/unix/sysv/linux/riscv/rv64/Makefile
create mode 100644 sysdeps/unix/sysv/linux/riscv/shlib-versions

diff --git a/config.h.in b/config.h.in
index 22418576a0..f870267870 100644
--- a/config.h.in
+++ b/config.h.in
@@ -99,6 +99,11 @@
/* AArch64 big endian ABI */
#undef HAVE_AARCH64_BE

+/* RISC-V integer ABI for ld.so. */
+#undef RISCV_ABI_XLEN
+
+/* RISC-V floating-point ABI for ld.so. */
+#undef RISCV_ABI_FLEN

/* Defined to some form of __attribute__ ((...)) if the compiler supports
a different, more efficient calling convention. */
diff --git a/sysdeps/riscv/Implies b/sysdeps/riscv/Implies
new file mode 100644
index 0000000000..15b9e02448
--- /dev/null
+++ b/sysdeps/riscv/Implies
@@ -0,0 +1,6 @@
+init_array
+
+ieee754/ldbl-128
+ieee754/dbl-64
+ieee754/flt-32
+riscv/soft-fp
diff --git a/sysdeps/riscv/Makefile b/sysdeps/riscv/Makefile
new file mode 100644
index 0000000000..5a699a2e64
--- /dev/null
+++ b/sysdeps/riscv/Makefile
@@ -0,0 +1,45 @@
+ifneq ($(all-rtld-routines),)
+CFLAGS-rtld.c += -mno-plt
+CFLAGS-dl-load.c += -mno-plt
+CFLAGS-dl-cache.c += -mno-plt
+CFLAGS-dl-lookup.c += -mno-plt
+CFLAGS-dl-object.c += -mno-plt
+CFLAGS-dl-reloc.c += -mno-plt
+CFLAGS-dl-deps.c += -mno-plt
+CFLAGS-dl-runtime.c += -mno-plt
+CFLAGS-dl-error.c += -mno-plt
+CFLAGS-dl-init.c += -mno-plt
+CFLAGS-dl-fini.c += -mno-plt
+CFLAGS-dl-debug.c += -mno-plt
+CFLAGS-dl-misc.c += -mno-plt
+CFLAGS-dl-version.c += -mno-plt
+CFLAGS-dl-profile.c += -mno-plt
+CFLAGS-dl-conflict.c += -mno-plt
+CFLAGS-dl-tls.c += -mno-plt
+CFLAGS-dl-origin.c += -mno-plt
+CFLAGS-dl-scope.c += -mno-plt
+CFLAGS-dl-execstack.c += -mno-plt
+CFLAGS-dl-caller.c += -mno-plt
+CFLAGS-dl-open.c += -mno-plt
+CFLAGS-dl-close.c += -mno-plt
+CFLAGS-dl-sysdep.c += -mno-plt
+CFLAGS-dl-environ.c += -mno-plt
+CFLAGS-dl-minimal.c += -mno-plt
+CFLAGS-dl-static.c += -mno-plt
+CFLAGS-dl-brk.c += -mno-plt
+CFLAGS-dl-sbrk.c += -mno-plt
+CFLAGS-dl-getcwd.c += -mno-plt
+CFLAGS-dl-openat64.c += -mno-plt
+CFLAGS-dl-opendir.c += -mno-plt
+CFLAGS-dl-fxstatat64.c += -mno-plt
+endif
+
+CFLAGS-closedir.c += -mno-plt
+CFLAGS-exit.c += -mno-plt
+CFLAGS-cxa_atexit.c += -mno-plt
+
+ifeq ($(subdir),misc)
+sysdep_headers += sys/asm.h
+endif
+
+ASFLAGS-.os += $(pic-ccflag)
diff --git a/sysdeps/riscv/Versions b/sysdeps/riscv/Versions
new file mode 100644
index 0000000000..5a0c2d23f8
--- /dev/null
+++ b/sysdeps/riscv/Versions
@@ -0,0 +1,5 @@
+libc {
+ GLIBC_2.14 {
+ __memcpy_g;
+ }
+}
diff --git a/sysdeps/riscv/configure b/sysdeps/riscv/configure
new file mode 100644
index 0000000000..9f790ec527
--- /dev/null
+++ b/sysdeps/riscv/configure
@@ -0,0 +1,86 @@
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/riscv/elf.
+
+$as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h
diff --git a/sysdeps/riscv/configure.in b/sysdeps/riscv/configure.in
new file mode 100644
index 0000000000..34f62d4b4b
--- /dev/null
+++ b/sysdeps/riscv/configure.in
@@ -0,0 +1,4 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/riscv/elf.
+
+AC_DEFINE(PI_STATIC_AND_HIDDEN)
diff --git a/sysdeps/riscv/nptl/Makefile b/sysdeps/riscv/nptl/Makefile
new file mode 100644
index 0000000000..d0c59a5091
--- /dev/null
+++ b/sysdeps/riscv/nptl/Makefile
@@ -0,0 +1,25 @@
+# Copyright (C) 2005 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA.
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
+
+ifeq ($(subdir),nptl)
+libpthread-sysdep_routines += nptl-sysdep
+endif
diff --git a/sysdeps/riscv/preconfigure b/sysdeps/riscv/preconfigure
new file mode 100644
index 0000000000..43e2a4fac0
--- /dev/null
+++ b/sysdeps/riscv/preconfigure
@@ -0,0 +1,50 @@
+xlen=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __riscv_xlen \(.*\)/\1/p'`
+flen=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __riscv_flen \(.*\)/\1/p'`
+float_abi=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __riscv_float_abi_\([^ ]*\) .*/\1/p'`
+
+case "$xlen" in
+32 | 64)
+ ;;
+*)
+ echo "Unable to determine XLEN" >&2
+ exit 1
+ ;;
+esac
+
+case "$flen" in
+64)
+ float_machine=rvd
+ ;;
+32)
+ float_machine=rvf
+ ;;
+"")
+ float_machine=
+ ;;
+*)
+ echo "Unable to determine FLEN" >&2
+ exit 1
+ ;;
+esac
+
+case "$float_abi" in
+soft)
+ abi_flen=0
+ ;;
+single)
+ abi_flen=32
+ ;;
+double)
+ abi_flen=64
+ ;;
+*)
+ echo "Unable to determine floating-point ABI" >&2
+ exit 1
+ ;;
+esac
+
+base_machine=riscv
+machine=riscv/rv$xlen/$float_machine
+
+$as_echo "#define RISCV_ABI_XLEN $xlen" >>confdefs.h
+$as_echo "#define RISCV_ABI_FLEN $abi_flen" >>confdefs.h
diff --git a/sysdeps/riscv/rv32/Implies-after b/sysdeps/riscv/rv32/Implies-after
new file mode 100644
index 0000000000..39a34c5f57
--- /dev/null
+++ b/sysdeps/riscv/rv32/Implies-after
@@ -0,0 +1 @@
+wordsize-32
diff --git a/sysdeps/riscv/rv32/rvd/Implies b/sysdeps/riscv/rv32/rvd/Implies
new file mode 100644
index 0000000000..9438838e98
--- /dev/null
+++ b/sysdeps/riscv/rv32/rvd/Implies
@@ -0,0 +1,2 @@
+riscv/rvd
+riscv/rvf
diff --git a/sysdeps/riscv/rv32/rvf/Implies b/sysdeps/riscv/rv32/rvf/Implies
new file mode 100644
index 0000000000..66c401443b
--- /dev/null
+++ b/sysdeps/riscv/rv32/rvf/Implies
@@ -0,0 +1 @@
+riscv/rvf
diff --git a/sysdeps/riscv/rv64/Implies-after b/sysdeps/riscv/rv64/Implies-after
new file mode 100644
index 0000000000..a8cae95f9d
--- /dev/null
+++ b/sysdeps/riscv/rv64/Implies-after
@@ -0,0 +1 @@
+wordsize-64
diff --git a/sysdeps/riscv/rv64/rvd/Implies b/sysdeps/riscv/rv64/rvd/Implies
new file mode 100644
index 0000000000..9438838e98
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/Implies
@@ -0,0 +1,2 @@
+riscv/rvd
+riscv/rvf
diff --git a/sysdeps/riscv/rv64/rvf/Implies b/sysdeps/riscv/rv64/rvf/Implies
new file mode 100644
index 0000000000..66c401443b
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvf/Implies
@@ -0,0 +1 @@
+riscv/rvf
diff --git a/sysdeps/riscv/soft-fp/Makefile b/sysdeps/riscv/soft-fp/Makefile
new file mode 100644
index 0000000000..ada13e8b70
--- /dev/null
+++ b/sysdeps/riscv/soft-fp/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),math)
+CPPFLAGS += -I../soft-fp
+endif
diff --git a/sysdeps/unix/sysv/linux/riscv/Implies b/sysdeps/unix/sysv/linux/riscv/Implies
new file mode 100644
index 0000000000..6faec70115
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/Implies
@@ -0,0 +1 @@
+riscv/nptl
diff --git a/sysdeps/unix/sysv/linux/riscv/Makefile b/sysdeps/unix/sysv/linux/riscv/Makefile
new file mode 100644
index 0000000000..a71840f70c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/Makefile
@@ -0,0 +1,26 @@
+ifeq ($(subdir),elf)
+ifeq ($(build-shared),yes)
+# This is needed for DSO loading from static binaries.
+sysdep-dl-routines += dl-static
+sysdep_routines += dl-static
+sysdep-rtld-routines += dl-static
+endif
+endif
+
+ifeq ($(subdir),stdlib)
+gen-as-const-headers += ucontext_i.sym
+endif
+
+ifeq ($(subdir),crypt)
+libcrypt-sysdep_routines += sysdep
+endif
+
+ifeq ($(subdir),nss)
+libnss_db-sysdep_routines += sysdep
+libnss_db-shared-only-routines += sysdep
+endif
+
+ifeq ($(subdir),rt)
+librt-sysdep_routines += sysdep
+librt-shared-only-routines += sysdep
+endif
diff --git a/sysdeps/unix/sysv/linux/riscv/configure b/sysdeps/unix/sysv/linux/riscv/configure
new file mode 100644
index 0000000000..2bb3062cc3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/configure
@@ -0,0 +1,7 @@
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/unix/sysv/linux/riscv.
+
+if test -z "$arch_minimum_kernel"; then
+ arch_minimum_kernel=3.0.0
+ libc_cv_gcc_unwind_find_fde=no
+fi
diff --git a/sysdeps/unix/sysv/linux/riscv/configure.in b/sysdeps/unix/sysv/linux/riscv/configure.in
new file mode 100644
index 0000000000..5b48e1aed6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/configure.in
@@ -0,0 +1,8 @@
+sinclude(./aclocal.m4)dnl Autoconf lossage
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/unix/sysv/linux/riscv.
+
+if test -z "$arch_minimum_kernel"; then
+ arch_minimum_kernel=3.0.0
+ libc_cv_gcc_unwind_find_fde=no
+fi
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/Implies b/sysdeps/unix/sysv/linux/riscv/rv32/Implies
new file mode 100644
index 0000000000..8b7deb33cd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/Implies
@@ -0,0 +1,3 @@
+unix/sysv/linux/riscv
+unix/sysv/linux/generic/wordsize-32
+unix/sysv/linux/generic
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/Implies b/sysdeps/unix/sysv/linux/riscv/rv64/Implies
new file mode 100644
index 0000000000..f042343bf7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/Implies
@@ -0,0 +1,3 @@
+unix/sysv/linux/riscv
+unix/sysv/linux/generic
+unix/sysv/linux/wordsize-64
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/Makefile b/sysdeps/unix/sysv/linux/riscv/rv64/Makefile
new file mode 100644
index 0000000000..0a37c5b9b4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/Makefile
@@ -0,0 +1,9 @@
+ifeq ($(subdir),socket)
+CFLAGS-recv.c += -fexceptions
+CFLAGS-send.c += -fexceptions
+endif
+
+ifeq ($(subdir),nptl)
+CFLAGS-recv.c += -fexceptions
+CFLAGS-send.c += -fexceptions
+endif
diff --git a/sysdeps/unix/sysv/linux/riscv/shlib-versions b/sysdeps/unix/sysv/linux/riscv/shlib-versions
new file mode 100644
index 0000000000..66214b953e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/shlib-versions
@@ -0,0 +1,17 @@
+DEFAULT GLIBC_2.25
+
+%if RISCV_ABI_XLEN == 64 && RISCV_ABI_FLEN == 64
+ld=ld-linux-riscv64-lp64d.so.1
+%elif RISCV_ABI_XLEN == 64 && RISCV_ABI_FLEN == 32
+ld=ld-linux-riscv64-lp64f.so.1
+%elif RISCV_ABI_XLEN == 64 && RISCV_ABI_FLEN == 0
+ld=ld-linux-riscv64-lp64.so.1
+%elif RISCV_ABI_XLEN == 32 && RISCV_ABI_FLEN == 64
+ld=ld-linux-riscv32-ilp32d.so.1
+%elif RISCV_ABI_XLEN == 32 && RISCV_ABI_FLEN == 32
+ld=ld-linux-riscv32-ilp32f.so.1
+%elif RISCV_ABI_XLEN == 32 && RISCV_ABI_FLEN == 0
+ld=ld-linux-riscv32-ilp32.so.1
+%else
+%error cannot determine ABI
+%endif
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:08 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch contains code that needs to directly know about the RISC-V
ABI, which is specified in a work-in-progress psABI document:

https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md

This is meant to contain all the RISC-V code that needs to explicitly
name registers or manage in-memory structure layout. This does not
contain any of the Linux-specific code.
---
sysdeps/riscv/__longjmp.S | 58 +++++++++++++++++
sysdeps/riscv/bits/endian.h | 5 ++
sysdeps/riscv/bits/setjmp.h | 38 +++++++++++
sysdeps/riscv/bits/wordsize.h | 31 +++++++++
sysdeps/riscv/bsd-_setjmp.c | 1 +
sysdeps/riscv/bsd-setjmp.c | 1 +
sysdeps/riscv/dl-trampoline.S | 44 +++++++++++++
sysdeps/riscv/gccframe.h | 22 +++++++
sysdeps/riscv/jmpbuf-unwind.h | 46 +++++++++++++
sysdeps/riscv/machine-gmon.h | 34 ++++++++++
sysdeps/riscv/memusage.h | 21 ++++++
sysdeps/riscv/nptl/sysdep-cancel.h | 129 +++++++++++++++++++++++++++++++++++++
sysdeps/riscv/setjmp.S | 75 +++++++++++++++++++++
sysdeps/riscv/sys/asm.h | 79 +++++++++++++++++++++++
14 files changed, 584 insertions(+)
create mode 100644 sysdeps/riscv/__longjmp.S
create mode 100644 sysdeps/riscv/bits/endian.h
create mode 100644 sysdeps/riscv/bits/setjmp.h
create mode 100644 sysdeps/riscv/bits/wordsize.h
create mode 100644 sysdeps/riscv/bsd-_setjmp.c
create mode 100644 sysdeps/riscv/bsd-setjmp.c
create mode 100644 sysdeps/riscv/dl-trampoline.S
create mode 100644 sysdeps/riscv/gccframe.h
create mode 100644 sysdeps/riscv/jmpbuf-unwind.h
create mode 100644 sysdeps/riscv/machine-gmon.h
create mode 100644 sysdeps/riscv/memusage.h
create mode 100644 sysdeps/riscv/nptl/sysdep-cancel.h
create mode 100644 sysdeps/riscv/setjmp.S
create mode 100644 sysdeps/riscv/sys/asm.h

diff --git a/sysdeps/riscv/__longjmp.S b/sysdeps/riscv/__longjmp.S
new file mode 100644
index 0000000000..06382660a8
--- /dev/null
+++ b/sysdeps/riscv/__longjmp.S
@@ -0,0 +1,58 @@
+/* Copyright (C) 1996, 1997, 2000, 2002-2004, 2017
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+ENTRY (__longjmp)
+ REG_L ra, 0*SZREG(a0)
+ REG_L s0, 1*SZREG(a0)
+ REG_L s1, 2*SZREG(a0)
+ REG_L s2, 3*SZREG(a0)
+ REG_L s3, 4*SZREG(a0)
+ REG_L s4, 5*SZREG(a0)
+ REG_L s5, 6*SZREG(a0)
+ REG_L s6, 7*SZREG(a0)
+ REG_L s7, 8*SZREG(a0)
+ REG_L s8, 9*SZREG(a0)
+ REG_L s9, 10*SZREG(a0)
+ REG_L s10,11*SZREG(a0)
+ REG_L s11,12*SZREG(a0)
+ REG_L sp, 13*SZREG(a0)
+
+#ifndef __riscv_float_abi_soft
+ FREG_L fs0, 14*SZREG+ 0*SZFREG(a0)
+ FREG_L fs1, 14*SZREG+ 1*SZFREG(a0)
+ FREG_L fs2, 14*SZREG+ 2*SZFREG(a0)
+ FREG_L fs3, 14*SZREG+ 3*SZFREG(a0)
+ FREG_L fs4, 14*SZREG+ 4*SZFREG(a0)
+ FREG_L fs5, 14*SZREG+ 5*SZFREG(a0)
+ FREG_L fs6, 14*SZREG+ 6*SZFREG(a0)
+ FREG_L fs7, 14*SZREG+ 7*SZFREG(a0)
+ FREG_L fs8, 14*SZREG+ 8*SZFREG(a0)
+ FREG_L fs9, 14*SZREG+ 9*SZFREG(a0)
+ FREG_L fs10,14*SZREG+10*SZFREG(a0)
+ FREG_L fs11,14*SZREG+11*SZFREG(a0)
+#endif
+
+ seqz a0, a1
+ add a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1
+ ret
+
+END(__longjmp)
diff --git a/sysdeps/riscv/bits/endian.h b/sysdeps/riscv/bits/endian.h
new file mode 100644
index 0000000000..4aaf559d4f
--- /dev/null
+++ b/sysdeps/riscv/bits/endian.h
@@ -0,0 +1,5 @@
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/sysdeps/riscv/bits/setjmp.h b/sysdeps/riscv/bits/setjmp.h
new file mode 100644
index 0000000000..749269bd90
--- /dev/null
+++ b/sysdeps/riscv/bits/setjmp.h
@@ -0,0 +1,38 @@
+/* Define the machine-dependent type `jmp_buf'. RISC-V version.
+ Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _RISCV_BITS_SETJMP_H
+#define _RISCV_BITS_SETJMP_H
+
+typedef struct __jmp_buf_internal_tag
+ {
+ /* Program counter. */
+ long __pc;
+ /* Callee-saved registers. */
+ long __regs[12];
+ /* Stack pointer. */
+ long __sp;
+
+ /* Callee-saved floating point registers.
+ Note that there are an even number of preceding words in this struct,
+ so no padding will be inserted before __fpregs, even for RV32. */
+ double __fpregs[12];
+ } __jmp_buf[1];
+
+#endif /* _RISCV_BITS_SETJMP_H */
diff --git a/sysdeps/riscv/bits/wordsize.h b/sysdeps/riscv/bits/wordsize.h
new file mode 100644
index 0000000000..7cc222d337
--- /dev/null
+++ b/sysdeps/riscv/bits/wordsize.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2002, 2003, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#if __riscv_xlen == (__SIZEOF_POINTER__ * 8)
+# define __WORDSIZE __riscv_xlen
+#else
+# error unsupported ABI
+#endif
+
+#if __riscv_xlen == 64
+# define __WORDSIZE_TIME64_COMPAT32 1
+#else
+# define __WORDSIZE_TIME64_COMPAT32 0
+# define __WORDSIZE32_SIZE_ULONG 0
+# define __WORDSIZE32_PTRDIFF_LONG 0
+#endif
diff --git a/sysdeps/riscv/bsd-_setjmp.c b/sysdeps/riscv/bsd-_setjmp.c
new file mode 100644
index 0000000000..0d413101ce
--- /dev/null
+++ b/sysdeps/riscv/bsd-_setjmp.c
@@ -0,0 +1 @@
+/* _setjmp is implemented in setjmp.S */
diff --git a/sysdeps/riscv/bsd-setjmp.c b/sysdeps/riscv/bsd-setjmp.c
new file mode 100644
index 0000000000..ee7c5e3437
--- /dev/null
+++ b/sysdeps/riscv/bsd-setjmp.c
@@ -0,0 +1 @@
+/* setjmp is implemented in setjmp.S */
diff --git a/sysdeps/riscv/dl-trampoline.S b/sysdeps/riscv/dl-trampoline.S
new file mode 100644
index 0000000000..3d4dd9fc8c
--- /dev/null
+++ b/sysdeps/riscv/dl-trampoline.S
@@ -0,0 +1,44 @@
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* Assembler veneer called from the PLT header code for lazy loading.
+ The PLT header passes its own args in t0-t2. */
+
+#define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
+
+ENTRY(_dl_runtime_resolve)
+ # Save arguments to stack.
+ addi sp, sp, -FRAME_SIZE
+ REG_S ra, 9*SZREG(sp)
+ REG_S a0, 1*SZREG(sp)
+ REG_S a1, 2*SZREG(sp)
+ REG_S a2, 3*SZREG(sp)
+ REG_S a3, 4*SZREG(sp)
+ REG_S a4, 5*SZREG(sp)
+ REG_S a5, 6*SZREG(sp)
+ REG_S a6, 7*SZREG(sp)
+ REG_S a7, 8*SZREG(sp)
+
+ # Update .got.plt and obtain runtime address of callee.
+ slli a1, t1, 1
+ mv a0, t0 # link map
+ add a1, a1, t1 # reloc offset (== thrice the .got.plt offset)
+ la a2, _dl_fixup
+ jalr a2
+ mv t1, a0
+
+ # Restore arguments from stack.
+ REG_L ra, 9*SZREG(sp)
+ REG_L a0, 1*SZREG(sp)
+ REG_L a1, 2*SZREG(sp)
+ REG_L a2, 3*SZREG(sp)
+ REG_L a3, 4*SZREG(sp)
+ REG_L a4, 5*SZREG(sp)
+ REG_L a5, 6*SZREG(sp)
+ REG_L a6, 7*SZREG(sp)
+ REG_L a7, 8*SZREG(sp)
+ addi sp, sp, FRAME_SIZE
+
+ # Invoke the callee.
+ jr t1
+END(_dl_runtime_resolve)
diff --git a/sysdeps/riscv/gccframe.h b/sysdeps/riscv/gccframe.h
new file mode 100644
index 0000000000..664c2c85f1
--- /dev/null
+++ b/sysdeps/riscv/gccframe.h
@@ -0,0 +1,22 @@
+/* Definition of object in frame unwind info. RISC-V version.
+ Copyright (C) 2001, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define FIRST_PSEUDO_REGISTER 66
+
+#include <sysdeps/generic/gccframe.h>
diff --git a/sysdeps/riscv/jmpbuf-unwind.h b/sysdeps/riscv/jmpbuf-unwind.h
new file mode 100644
index 0000000000..daf7898cb7
--- /dev/null
+++ b/sysdeps/riscv/jmpbuf-unwind.h
@@ -0,0 +1,46 @@
+/* Copyright (C) 2003, 2005, 2006, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <setjmp.h>
+#include <stdint.h>
+#include <unwind.h>
+#include <sysdep.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+ ((void *) (address) < (void *) demangle ((jmpbuf)[0].__sp))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf regs)
+{
+ uintptr_t sp = regs[0].__sp;
+#ifdef PTR_DEMANGLE
+ PTR_DEMANGLE (sp);
+#endif
+ return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+/* We use the normal longjmp for unwinding. */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/sysdeps/riscv/machine-gmon.h b/sysdeps/riscv/machine-gmon.h
new file mode 100644
index 0000000000..2ec7a34d9b
--- /dev/null
+++ b/sysdeps/riscv/machine-gmon.h
@@ -0,0 +1,34 @@
+/* RISC-V definitions for profiling support.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Accept 'frompc' address as argument from the function that calls
+ _mcount for profiling. Use __builtin_return_address (0)
+ for the 'selfpc' address. */
+
+#include <sysdep.h>
+
+static void mcount_internal (u_long frompc, u_long selfpc);
+
+#define _MCOUNT_DECL(frompc, selfpc) \
+static inline void mcount_internal (u_long frompc, u_long selfpc)
+
+#define MCOUNT \
+void _mcount (void *frompc) \
+{ \
+ mcount_internal ((u_long) frompc, (u_long) RETURN_ADDRESS (0)); \
+}
diff --git a/sysdeps/riscv/memusage.h b/sysdeps/riscv/memusage.h
new file mode 100644
index 0000000000..606a9e5336
--- /dev/null
+++ b/sysdeps/riscv/memusage.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 2000, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define GETSP() ({ register uintptr_t stack_ptr asm ("sp"); stack_ptr; })
+
+#include <sysdeps/generic/memusage.h>
diff --git a/sysdeps/riscv/nptl/sysdep-cancel.h b/sysdeps/riscv/nptl/sysdep-cancel.h
new file mode 100644
index 0000000000..dfa09aa9ac
--- /dev/null
+++ b/sysdeps/riscv/nptl/sysdep-cancel.h
@@ -0,0 +1,129 @@
+/* Copyright (C) 2003-2006, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#include <sysdeps/generic/sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <nptl/pthreadP.h>
+#endif
+#include <sys/asm.h>
+
+/* Gas will put the initial save of $gp into the CIE, because it appears to
+ happen before any instructions. So we use cfi_same_value instead of
+ cfi_restore. */
+
+#if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .align 2; \
+ L(pseudo_start): \
+ 99: j __syscall_error; \
+ ENTRY (name) \
+ SINGLE_THREAD_P(t0); \
+ bnez t0, L(pseudo_cancel); \
+ .type __##syscall_name##_nocancel, @function; \
+ .globl __##syscall_name##_nocancel; \
+ __##syscall_name##_nocancel: \
+ li a7, SYS_ify(syscall_name); \
+ scall; \
+ bltz a0, 99b; \
+ ret; \
+ .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
+ L(pseudo_cancel): \
+ addi sp, sp, -STKSPACE; \
+ REG_S ra, STKOFF_RA(sp); \
+ cfi_rel_offset (ra, STKOFF_RA); \
+ PUSHARGS_##args; /* save syscall args */ \
+ CENABLE; \
+ REG_S a0, STKOFF_SVMSK(sp); /* save mask */ \
+ POPARGS_##args; /* restore syscall args */ \
+ li a7, SYS_ify (syscall_name); \
+ scall; \
+ REG_S a0, STKOFF_A0(sp); /* save syscall result */ \
+ REG_L a0, STKOFF_SVMSK(sp); /* pass mask as arg1 */ \
+ CDISABLE; \
+ REG_L ra, STKOFF_RA(sp); /* restore return address */ \
+ REG_L a0, STKOFF_A0(sp); /* restore syscall result */ \
+ addi sp, sp, STKSPACE; \
+ bltz a0, 99b; \
+ L(pseudo_end):
+
+
+# define PUSHARGS_0 /* nothing to do */
+# define PUSHARGS_1 PUSHARGS_0 REG_S a0, STKOFF_A0(sp); cfi_rel_offset (a0, STKOFF_A0);
+# define PUSHARGS_2 PUSHARGS_1 REG_S a1, STKOFF_A1(sp); cfi_rel_offset (a1, STKOFF_A1);
+# define PUSHARGS_3 PUSHARGS_2 REG_S a2, STKOFF_A2(sp); cfi_rel_offset (a2, STKOFF_A2);
+# define PUSHARGS_4 PUSHARGS_3 REG_S a3, STKOFF_A3(sp); cfi_rel_offset (a3, STKOFF_A3);
+# define PUSHARGS_5 PUSHARGS_4 REG_S a4, STKOFF_A4(sp); cfi_rel_offset (a4, STKOFF_A4);
+# define PUSHARGS_6 PUSHARGS_5 REG_S a5, STKOFF_A5(sp); cfi_rel_offset (a5, STKOFF_A5);
+
+# define POPARGS_0 /* nothing to do */
+# define POPARGS_1 POPARGS_0 REG_L a0, STKOFF_A0(sp);
+# define POPARGS_2 POPARGS_1 REG_L a1, STKOFF_A1(sp);
+# define POPARGS_3 POPARGS_2 REG_L a2, STKOFF_A2(sp);
+# define POPARGS_4 POPARGS_3 REG_L a3, STKOFF_A3(sp);
+# define POPARGS_5 POPARGS_4 REG_L a4, STKOFF_A4(sp);
+# define POPARGS_6 POPARGS_5 REG_L a5, STKOFF_A5(sp);
+
+/* Avoid D$ misses by keeping less-used arguments further down stack. */
+# define STKOFF_A5 0
+# define STKOFF_A4 (STKOFF_A5 + SZREG)
+# define STKOFF_A3 (STKOFF_A4 + SZREG)
+# define STKOFF_A2 (STKOFF_A3 + SZREG)
+# define STKOFF_A1 (STKOFF_A2 + SZREG)
+# define STKOFF_A0 (STKOFF_A1 + SZREG)
+# define STKOFF_SVMSK (STKOFF_A0 + SZREG)
+# define STKOFF_RA (STKOFF_SVMSK + SZREG)
+# define STKSPACE (STKOFF_RA + SZREG)
+
+# if IS_IN (libpthread)
+# define CENABLE call __pthread_enable_asynccancel
+# define CDISABLE call __pthread_disable_asynccancel
+# elif IS_IN (librt)
+# define CENABLE call __librt_enable_asynccancel
+# define CDISABLE call __librt_disable_asynccancel
+# else
+# define CENABLE call __libc_enable_asynccancel
+# define CDISABLE call __libc_disable_asynccancel
+# endif
+
+# ifndef __ASSEMBLER__
+# define SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) \
+ == 0, 1)
+# else
+# include "tcb-offsets.h"
+# define SINGLE_THREAD_P(reg) \
+ lw reg, MULTIPLE_THREADS_OFFSET(tp)
+#endif
+
+#elif !defined __ASSEMBLER__
+
+# define SINGLE_THREAD_P 1
+# define NO_CANCELLATION 1
+
+#endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+#endif
diff --git a/sysdeps/riscv/setjmp.S b/sysdeps/riscv/setjmp.S
new file mode 100644
index 0000000000..d8f9dda5f1
--- /dev/null
+++ b/sysdeps/riscv/setjmp.S
@@ -0,0 +1,75 @@
+/* Copyright (C) 1996, 1997, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+ENTRY (_setjmp)
+ li a1, 0
+ j __sigsetjmp
+END (_setjmp)
+ENTRY (setjmp)
+ li a1, 1
+ /* Fallthrough */
+END (setjmp)
+ENTRY (__sigsetjmp)
+ REG_S ra, 0*SZREG(a0)
+ REG_S s0, 1*SZREG(a0)
+ REG_S s1, 2*SZREG(a0)
+ REG_S s2, 3*SZREG(a0)
+ REG_S s3, 4*SZREG(a0)
+ REG_S s4, 5*SZREG(a0)
+ REG_S s5, 6*SZREG(a0)
+ REG_S s6, 7*SZREG(a0)
+ REG_S s7, 8*SZREG(a0)
+ REG_S s8, 9*SZREG(a0)
+ REG_S s9, 10*SZREG(a0)
+ REG_S s10,11*SZREG(a0)
+ REG_S s11,12*SZREG(a0)
+ REG_S sp, 13*SZREG(a0)
+
+#ifndef __riscv_float_abi_soft
+ FREG_S fs0, 14*SZREG+ 0*SZFREG(a0)
+ FREG_S fs1, 14*SZREG+ 1*SZFREG(a0)
+ FREG_S fs2, 14*SZREG+ 2*SZFREG(a0)
+ FREG_S fs3, 14*SZREG+ 3*SZFREG(a0)
+ FREG_S fs4, 14*SZREG+ 4*SZFREG(a0)
+ FREG_S fs5, 14*SZREG+ 5*SZFREG(a0)
+ FREG_S fs6, 14*SZREG+ 6*SZFREG(a0)
+ FREG_S fs7, 14*SZREG+ 7*SZFREG(a0)
+ FREG_S fs8, 14*SZREG+ 8*SZFREG(a0)
+ FREG_S fs9, 14*SZREG+ 9*SZFREG(a0)
+ FREG_S fs10,14*SZREG+10*SZFREG(a0)
+ FREG_S fs11,14*SZREG+11*SZFREG(a0)
+#endif
+
+#if !IS_IN (libc) && IS_IN (rtld)
+ /* In ld.so we never save the signal mask. */
+ li a0, 0
+ ret
+#else
+ /* Make a tail call to __sigjmp_save; it takes the same args. */
+ j __sigjmp_save
+#endif
+
+
+END(__sigsetjmp)
+
+hidden_def (__sigsetjmp)
+weak_alias(_setjmp, __GI__setjmp)
diff --git a/sysdeps/riscv/sys/asm.h b/sysdeps/riscv/sys/asm.h
new file mode 100644
index 0000000000..bd31c72bd3
--- /dev/null
+++ b/sysdeps/riscv/sys/asm.h
@@ -0,0 +1,79 @@
+/* copyright (c) 1997, 1998, 2002, 2003-2005, 2017
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ralf Baechle <ra...@gnu.org>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _SYS_ASM_H
+#define _SYS_ASM_H
+
+/*
+ * Macros to handle different pointer/register sizes for 32/64-bit code
+ */
+#if __riscv_xlen == 64
+# define PTRLOG 3
+# define SZREG 8
+# define REG_S sd
+# define REG_L ld
+#elif __riscv_xlen == 32
+# define PTRLOG 2
+# define SZREG 4
+# define REG_S sw
+# define REG_L lw
+#else
+# error __riscv_xlen must equal 32 or 64
+#endif
+
+#ifndef __riscv_float_abi_soft
+/* For ABI uniformity, reserve 8 bytes for floats, even if double-precision
+ floating-point is not supported in hardware. */
+# define SZFREG 8
+# ifdef __riscv_float_abi_single
+# define FREG_L flw
+# define FREG_S fsw
+# elif defined(__riscv_float_abi_double)
+# define FREG_L fld
+# define FREG_S fsd
+# else
+# error unsupported FLEN
+# endif
+#endif
+
+/*
+ * LEAF - declare leaf routine
+ */
+#define LEAF(symbol) \
+ .globl symbol; \
+ .align 2; \
+ .type symbol,@function; \
+symbol: \
+ cfi_startproc;
+
+/*
+ * END - mark end of function
+ */
+#undef END
+#define END(function) \
+ cfi_endproc; \
+ .size function,.-function
+
+/*
+ * Stack alignment
+ */
+#define ALMASK ~15
+
+#endif /* sys/asm.h */
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:09 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch contains the various bits of support used by the C startup
code and the dynamic loader when running on a RISC-V system. This
contains the implementation of our PLT entries, various ld.so hooks, and
_start. This does not contain any Linux-specific code.
---
sysdeps/riscv/bits/link.h | 56 ++++++++
sysdeps/riscv/crti.S | 14 ++
sysdeps/riscv/dl-machine.h | 317 ++++++++++++++++++++++++++++++++++++++++++++
sysdeps/riscv/ldsodefs.h | 48 +++++++
sysdeps/riscv/linkmap.h | 4 +
sysdeps/riscv/sotruss-lib.c | 51 +++++++
sysdeps/riscv/start.S | 82 ++++++++++++
sysdeps/riscv/tst-audit.h | 26 ++++
8 files changed, 598 insertions(+)
create mode 100644 sysdeps/riscv/bits/link.h
create mode 100644 sysdeps/riscv/crti.S
create mode 100644 sysdeps/riscv/dl-machine.h
create mode 100644 sysdeps/riscv/ldsodefs.h
create mode 100644 sysdeps/riscv/linkmap.h
create mode 100644 sysdeps/riscv/sotruss-lib.c
create mode 100644 sysdeps/riscv/start.S
create mode 100644 sysdeps/riscv/tst-audit.h

diff --git a/sysdeps/riscv/bits/link.h b/sysdeps/riscv/bits/link.h
new file mode 100644
index 0000000000..4e0cd96553
--- /dev/null
+++ b/sysdeps/riscv/bits/link.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2005, 2009, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+typedef struct La_riscv_regs
+{
+ unsigned long lr_reg[8]; /* a0 - a7 */
+ double lr_fpreg[8]; /* fa0 - fa7 */
+ unsigned long lr_ra;
+ unsigned long lr_sp;
+} La_riscv_regs;
+
+/* Return values for calls from PLT on RISC-V. */
+typedef struct La_riscv_retval
+{
+ unsigned long lrv_a0;
+ unsigned long lrv_a1;
+ double lrv_fa0;
+ double lrv_fa1;
+} La_riscv_retval;
+
+__BEGIN_DECLS
+
+extern ElfW(Addr) la_riscv_gnu_pltenter (ElfW(Sym) *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_riscv_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_riscv_gnu_pltexit (ElfW(Sym) *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_riscv_regs *__inregs,
+ La_riscv_retval *__outregs,
+ const char *__symname);
+
+__END_DECLS
diff --git a/sysdeps/riscv/crti.S b/sysdeps/riscv/crti.S
new file mode 100644
index 0000000000..a4332d2d64
--- /dev/null
+++ b/sysdeps/riscv/crti.S
@@ -0,0 +1,14 @@
+/* Facilitate pthread initialization using init_array. */
+
+#include <sys/asm.h>
+
+#ifdef PREINIT_FUNCTION
+
+#if PREINIT_FUNCTION_WEAK
+# error PREINIT_FUNCTION_WEAK is unsupported
+#endif
+
+ .section .init_array, "aw"
+ .dc.a PREINIT_FUNCTION
+
+#endif
diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
new file mode 100644
index 0000000000..b93f088765
--- /dev/null
+++ b/sysdeps/riscv/dl-machine.h
@@ -0,0 +1,317 @@
+/* Machine-dependent ELF dynamic relocation inline functions. RISC-V version.
+ Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+#ifndef dl_machine_h
+#define dl_machine_h
+
+#define ELF_MACHINE_NAME "RISC-V"
+#define EM_RISCV 243
+
+/* Relocs. */
+#define R_RISCV_NONE 0
+#define R_RISCV_32 1
+#define R_RISCV_64 2
+#define R_RISCV_RELATIVE 3
+#define R_RISCV_COPY 4
+#define R_RISCV_JUMP_SLOT 5
+#define R_RISCV_TLS_DTPMOD32 6
+#define R_RISCV_TLS_DTPMOD64 7
+#define R_RISCV_TLS_DTPREL32 8
+#define R_RISCV_TLS_DTPREL64 9
+#define R_RISCV_TLS_TPREL32 10
+#define R_RISCV_TLS_TPREL64 11
+
+#include <entry.h>
+
+#include <sys/asm.h>
+#include <dl-tls.h>
+
+#ifndef _RTLD_PROLOGUE
+# define _RTLD_PROLOGUE(entry) \
+ ".globl\t" __STRING(entry) "\n\t" \
+ ".type\t" __STRING(entry) ", @function\n" \
+ __STRING(entry) ":\n\t"
+#endif
+
+#ifndef _RTLD_EPILOGUE
+# define _RTLD_EPILOGUE(entry) \
+ ".size\t" __STRING(entry) ", . - " __STRING(entry) "\n\t"
+#endif
+
+#define ELF_MACHINE_JMP_SLOT R_RISCV_JUMP_SLOT
+
+#define elf_machine_type_class(type) \
+ ((ELF_RTYPE_CLASS_PLT * ((type) == ELF_MACHINE_JMP_SLOT \
+ || (__WORDSIZE == 32 && (type) == R_RISCV_TLS_DTPREL32) \
+ || (__WORDSIZE == 32 && (type) == R_RISCV_TLS_DTPMOD32) \
+ || (__WORDSIZE == 32 && (type) == R_RISCV_TLS_TPREL32) \
+ || (__WORDSIZE == 64 && (type) == R_RISCV_TLS_DTPREL64) \
+ || (__WORDSIZE == 64 && (type) == R_RISCV_TLS_DTPMOD64) \
+ || (__WORDSIZE == 64 && (type) == R_RISCV_TLS_TPREL64))) \
+ | (ELF_RTYPE_CLASS_COPY * ((type) == R_RISCV_COPY)))
+
+#define ELF_MACHINE_NO_REL 1
+#define ELF_MACHINE_NO_RELA 0
+
+/* Return nonzero iff ELF header is compatible with the running host. */
+static inline int __attribute_used__
+elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
+{
+ return ehdr->e_machine == EM_RISCV;
+}
+
+/* Return the link-time address of _DYNAMIC. */
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+ extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__((visibility("hidden")));
+ return _GLOBAL_OFFSET_TABLE_;
+}
+
+#define STRINGXP(X) __STRING(X)
+#define STRINGXV(X) STRINGV_(X)
+#define STRINGV_(...) # __VA_ARGS__
+
+/* Return the run-time load address of the shared object. */
+static inline ElfW(Addr)
+elf_machine_load_address (void)
+{
+ ElfW(Addr) load_addr;
+ asm ("lla %0, _DYNAMIC" : "=r"(load_addr));
+ return load_addr - elf_machine_dynamic ();
+}
+
+/* Initial entry point code for the dynamic linker.
+ The C function `_dl_start' is the real entry point;
+ its return value is the user program's entry point. */
+
+#define RTLD_START asm (\
+ ".text\n\
+ " _RTLD_PROLOGUE(ENTRY_POINT) "\
+ mv a0, sp\n\
+ jal _dl_start\n\
+ # Stash user entry point in s0.\n\
+ mv s0, a0\n\
+ # See if we were run as a command with the executable file\n\
+ # name as an extra leading argument.\n\
+ lw a0, _dl_skip_args\n\
+ # Load the original argument count.\n\
+ " STRINGXP(REG_L) " a1, 0(sp)\n\
+ # Subtract _dl_skip_args from it.\n\
+ sub a1, a1, a0\n\
+ # Adjust the stack pointer to skip _dl_skip_args words.\n\
+ sll a0, a0, " STRINGXP (PTRLOG) "\n\
+ add sp, sp, a0\n\
+ # Save back the modified argument count.\n\
+ " STRINGXP(REG_S) " a1, 0(sp)\n\
+ # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
+ " STRINGXP(REG_L) " a0, _rtld_local\n\
+ add a2, sp, " STRINGXP (SZREG) "\n\
+ sll a3, a1, " STRINGXP (PTRLOG) "\n\
+ add a3, a3, a2\n\
+ add a3, a3, " STRINGXP (SZREG) "\n\
+ # Call the function to run the initializers.\n\
+ jal _dl_init\n\
+ # Pass our finalizer function to _start.\n\
+ lla a0, _dl_fini\n\
+ # Jump to the user entry point.\n\
+ jr s0\n\
+ " _RTLD_EPILOGUE(ENTRY_POINT) "\
+ .previous" \
+);
+
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER riscv_gnu_pltenter
+#define ARCH_LA_PLTEXIT riscv_gnu_pltexit
+
+/* Bias .got.plt entry by the offset requested by the PLT header. */
+#define elf_machine_plt_value(map, reloc, value) (value)
+#define elf_machine_fixup_plt(map, t, reloc, reloc_addr, value) \
+ (*(ElfW(Addr) *)(reloc_addr) = (value))
+
+#endif /* !dl_machine_h */
+
+#ifdef RESOLVE_MAP
+
+/* Perform a relocation described by R_INFO at the location pointed to
+ by RELOC_ADDR. SYM is the relocation symbol specified by R_INFO and
+ MAP is the object containing the reloc. */
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
+ const ElfW(Sym) *sym, const struct r_found_version *version,
+ void *const reloc_addr, int skip_ifunc)
+{
+ ElfW(Addr) r_info = reloc->r_info;
+ const unsigned long int r_type = ELFW(R_TYPE) (r_info);
+ ElfW(Addr) *addr_field = (ElfW(Addr) *) reloc_addr;
+ const ElfW(Sym) *const __attribute__((unused)) refsym = sym;
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+ ElfW(Addr) value = 0;
+ if (sym_map != NULL)
+ value = sym_map->l_addr + sym->st_value + reloc->r_addend;
+
+ switch (r_type)
+ {
+#ifndef RTLD_BOOTSTRAP
+ case __WORDSIZE == 64 ? R_RISCV_TLS_DTPMOD64 : R_RISCV_TLS_DTPMOD32:
+ if (sym_map)
+ *addr_field = sym_map->l_tls_modid;
+ break;
+
+ case __WORDSIZE == 64 ? R_RISCV_TLS_DTPREL64 : R_RISCV_TLS_DTPREL32:
+ if (sym != NULL)
+ *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend;
+ break;
+
+ case __WORDSIZE == 64 ? R_RISCV_TLS_TPREL64 : R_RISCV_TLS_TPREL32:
+ if (sym != NULL)
+ {
+ CHECK_STATIC_TLS (map, sym_map);
+ *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend;
+ }
+ break;
+
+ case R_RISCV_COPY:
+ {
+ if (__builtin_expect (sym == NULL, 0))
+ /* This can happen in trace mode if an object could not be
+ found. */
+ break;
+
+ /* Handle TLS copy relocations. */
+ if (__glibc_unlikely (ELFW(ST_TYPE) (sym->st_info) == STT_TLS))
+ {
+ /* There's nothing to do if the symbol is in .tbss. */
+ if (__glibc_likely (sym->st_value >= sym_map->l_tls_initimage_size))
+ break;
+ value += (ElfW(Addr)) sym_map->l_tls_initimage - sym_map->l_addr;
+ }
+
+ size_t size = sym->st_size;
+ if (__builtin_expect (sym->st_size != refsym->st_size, 0))
+ {
+ const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+ if (sym->st_size > refsym->st_size)
+ size = refsym->st_size;
+ if (sym->st_size > refsym->st_size || GLRO(dl_verbose))
+ _dl_error_printf ("\
+ %s: Symbol `%s' has different size in shared object, consider re-linking\n",
+ rtld_progname ?: "<program name unknown>",
+ strtab + refsym->st_name);
+ }
+
+ memcpy (reloc_addr, (void *)value, size);
+ break;
+ }
+#endif
+
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+ case R_RISCV_RELATIVE:
+ {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+ /* This is defined in rtld.c, but nowhere in the static libc.a;
+ make the reference weak so static programs can still link.
+ This declaration cannot be done when compiling rtld.c
+ (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
+ common defn for _dl_rtld_map, which is incompatible with a
+ weak decl in the same file. */
+# ifndef SHARED
+ weak_extern (GL(dl_rtld_map));
+# endif
+ if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
+# endif
+ *addr_field = map->l_addr + reloc->r_addend;
+ break;
+ }
+#endif
+
+ case R_RISCV_JUMP_SLOT:
+ case __WORDSIZE == 64 ? R_RISCV_64 : R_RISCV_32:
+ *addr_field = value;
+ break;
+
+ case R_RISCV_NONE:
+ break;
+
+ default:
+ _dl_reloc_bad_type (map, r_type, 0);
+ break;
+ }
+}
+
+auto inline void
+__attribute__((always_inline))
+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+ void *const reloc_addr)
+{
+ *(ElfW(Addr) *)reloc_addr = l_addr + reloc->r_addend;
+}
+
+auto inline void
+__attribute__((always_inline))
+elf_machine_lazy_rel (struct link_map *map, ElfW(Addr) l_addr,
+ const ElfW(Rela) *reloc, int skip_ifunc)
+{
+ ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+ const unsigned int r_type = ELFW(R_TYPE) (reloc->r_info);
+
+ /* Check for unexpected PLT reloc type. */
+ if (__builtin_expect (r_type == R_RISCV_JUMP_SLOT, 1))
+ {
+ if (__builtin_expect (map->l_mach.plt, 0) == 0)
+ {
+ if (l_addr)
+ *reloc_addr += l_addr;
+ }
+ else
+ *reloc_addr = map->l_mach.plt;
+ }
+ else
+ _dl_reloc_bad_type (map, r_type, 1);
+}
+
+/* Set up the loaded object described by L so its stub function
+ will jump to the on-demand fixup code __dl_runtime_resolve. */
+
+auto inline int
+__attribute__((always_inline))
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+{
+#ifndef RTLD_BOOTSTRAP
+ /* If using PLTs, fill in the first two entries of .got.plt. */
+ if (l->l_info[DT_JMPREL])
+ {
+ extern void _dl_runtime_resolve (void) __attribute__((visibility("hidden")));
+ ElfW(Addr) *gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
+ /* If a library is prelinked but we have to relocate anyway,
+ we have to be able to undo the prelinking of .got.plt.
+ The prelinker saved the address of .plt for us here. */
+ if (gotplt[1])
+ l->l_mach.plt = gotplt[1] + l->l_addr;
+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve;
+ gotplt[1] = (ElfW(Addr)) l;
+ }
+#endif
+
+ return lazy;
+}
+
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/riscv/ldsodefs.h b/sysdeps/riscv/ldsodefs.h
new file mode 100644
index 0000000000..794871a4f6
--- /dev/null
+++ b/sysdeps/riscv/ldsodefs.h
@@ -0,0 +1,48 @@
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+ Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+#ifndef _RISCV_LDSODEFS_H
+#define _RISCV_LDSODEFS_H 1
+
+#include <elf.h>
+
+struct La_riscv_regs;
+struct La_riscv_retval;
+
+#define ARCH_PLTENTER_MEMBERS \
+ Elf64_Addr (*riscv_gnu_pltenter) (Elf64_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ const struct La_riscv_regs *, \
+ unsigned int *, const char *name, \
+ long int *framesizep);
+
+#define ARCH_PLTEXIT_MEMBERS \
+ unsigned int (*riscv_gnu_pltexit) (Elf64_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ const struct La_riscv_regs *, \
+ struct La_riscv_retval *, \
+ const char *);
+
+/* The RISC-V ABI specifies that the dynamic section has to be read-only. */
+
+#define DL_RO_DYN_SECTION 1
+
+#include_next <ldsodefs.h>
+
+#endif
diff --git a/sysdeps/riscv/linkmap.h b/sysdeps/riscv/linkmap.h
new file mode 100644
index 0000000000..a6df7821e6
--- /dev/null
+++ b/sysdeps/riscv/linkmap.h
@@ -0,0 +1,4 @@
+struct link_map_machine
+ {
+ ElfW(Addr) plt; /* Address of .plt */
+ };
diff --git a/sysdeps/riscv/sotruss-lib.c b/sysdeps/riscv/sotruss-lib.c
new file mode 100644
index 0000000000..ef57f6885a
--- /dev/null
+++ b/sysdeps/riscv/sotruss-lib.c
@@ -0,0 +1,51 @@
+/* Override generic sotruss-lib.c to define actual functions for RISC-V.
+ Copyright (C) 2012-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+#define HAVE_ARCH_PLTENTER
+#define HAVE_ARCH_PLTEXIT
+
+#include <elf/sotruss-lib.c>
+
+ElfW(Addr)
+la_riscv_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)),
+ unsigned int ndx __attribute__ ((unused)),
+ uintptr_t *refcook, uintptr_t *defcook,
+ La_riscv_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ print_enter (refcook, defcook, symname,
+ regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
+ *flags);
+
+ /* No need to copy anything, we will not need the parameters in any case. */
+ *framesizep = 0;
+
+ return sym->st_value;
+}
+
+unsigned int
+la_riscv_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook,
+ const struct La_riscv_regs *inregs,
+ struct La_riscv_retval *outregs,
+ const char *symname)
+{
+ print_exit (refcook, defcook, symname, outregs->lrv_a0);
+
+ return 0;
+}
diff --git a/sysdeps/riscv/start.S b/sysdeps/riscv/start.S
new file mode 100644
index 0000000000..dcb20e4500
--- /dev/null
+++ b/sysdeps/riscv/start.S
@@ -0,0 +1,82 @@
+/* Startup code compliant to the ELF RISC-V ABI.
+ Copyright (C) 1995, 1997, 2000-2004, 2017
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define __ASSEMBLY__ 1
+#include <entry.h>
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* The entry point's job is to call __libc_start_main. Per the ABI,
+ a0 contains the address of a function to be passed to atexit.
+ __libc_start_main wants this in a5. */
+
+ENTRY(ENTRY_POINT)
+ call .Lload_gp
+ mv a5, a0 /* rtld_fini */
+ lla a0, main
+ REG_L a1, 0(sp) /* argc */
+ addi a2, sp, SZREG /* argv */
+ andi sp, sp, ALMASK /* Align stack. */
+ lla a3, __libc_csu_init
+ lla a4, __libc_csu_fini
+ mv a6, sp /* stack_end */
+
+ tail __libc_start_main@plt
+END(ENTRY_POINT)
+
+/* Dynamic links need the global pointer to be initialized prior to calling
+ any shared library's initializers, so we use preinit_array to load it.
+ This doesn't cut it for static links, though, since the global pointer
+ needs to be initialized before calling __libc_start_main in that case.
+ So we redundantly initialize it at the beginning of _start. */
+
+.Lload_gp:
+.option push
+.option norelax
+ lla gp, __global_pointer$
+.option pop
+ ret
+
+ .section .preinit_array,"aw"
+ .dc.a .Lload_gp
+
+/* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .weak data_start
+ data_start = __data_start
diff --git a/sysdeps/riscv/tst-audit.h b/sysdeps/riscv/tst-audit.h
new file mode 100644
index 0000000000..44a4107460
--- /dev/null
+++ b/sysdeps/riscv/tst-audit.h
@@ -0,0 +1,26 @@
+/* Definitions for testing PLT entry/exit auditing. RISC-V version.
+
+ Copyright (C) 2005, 2017 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define pltenter la_riscv_gnu_pltenter
+#define pltexit la_riscv_gnu_pltexit
+#define La_regs La_riscv_regs
+#define La_retval La_riscv_retval
+#define int_retval lrv_a0
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:10 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch implements TLS support for RISC-V. We support all four
standard TLS addressing modes (LE, IE, LD, and GD) when running on
Linux via NPTL. There is a draft psABI document that defines our TLS
ABI here

https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#thread-local-storage
---
sysdeps/riscv/dl-tls.h | 49 ++++++++++++
sysdeps/riscv/libc-tls.c | 37 +++++++++
sysdeps/riscv/nptl/tcb-offsets.sym | 6 ++
sysdeps/riscv/nptl/tls.h | 149 +++++++++++++++++++++++++++++++++++++
sysdeps/riscv/stackinfo.h | 33 ++++++++
5 files changed, 274 insertions(+)
create mode 100644 sysdeps/riscv/dl-tls.h
create mode 100644 sysdeps/riscv/libc-tls.c
create mode 100644 sysdeps/riscv/nptl/tcb-offsets.sym
create mode 100644 sysdeps/riscv/nptl/tls.h
create mode 100644 sysdeps/riscv/stackinfo.h

diff --git a/sysdeps/riscv/dl-tls.h b/sysdeps/riscv/dl-tls.h
new file mode 100644
index 0000000000..24a502b10f
--- /dev/null
+++ b/sysdeps/riscv/dl-tls.h
@@ -0,0 +1,49 @@
+/* Thread-local storage handling in the ELF dynamic linker. RISC-V version.
+ Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+/* Type used for the representation of TLS information in the GOT. */
+typedef struct
+{
+ unsigned long int ti_module;
+ unsigned long int ti_offset;
+} tls_index;
+
+/* The thread pointer points to the first static TLS block. */
+#define TLS_TP_OFFSET 0
+
+/* Dynamic thread vector pointers point 0x800 past the start of each
+ TLS block. */
+#define TLS_DTV_OFFSET 0x800
+
+/* Compute the value for a GOTTPREL reloc. */
+#define TLS_TPREL_VALUE(sym_map, sym) \
+ ((sym_map)->l_tls_offset + (sym)->st_value - TLS_TP_OFFSET)
+
+/* Compute the value for a DTPREL reloc. */
+#define TLS_DTPREL_VALUE(sym) \
+ ((sym)->st_value - TLS_DTV_OFFSET)
+
+extern void *__tls_get_addr (tls_index *ti);
+
+# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET)
+# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET)
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff --git a/sysdeps/riscv/libc-tls.c b/sysdeps/riscv/libc-tls.c
new file mode 100644
index 0000000000..7b0479cca1
--- /dev/null
+++ b/sysdeps/riscv/libc-tls.c
@@ -0,0 +1,37 @@
+/* Thread-local storage handling in the ELF dynamic linker. RISC-V version.
+ Copyright (C) 2011-2016 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <csu/libc-tls.c>
+#include <dl-tls.h>
+
+#if USE_TLS
+
+/* On RISC-V, linker optimizations are not required, so __tls_get_addr
+ can be called even in statically linked binaries. In this case module
+ must be always 1 and PT_TLS segment exist in the binary, otherwise it
+ would not link. */
+
+void *
+__tls_get_addr (tls_index *ti)
+{
+ dtv_t *dtv = THREAD_DTV ();
+ return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET;
+}
+
+#endif
diff --git a/sysdeps/riscv/nptl/tcb-offsets.sym b/sysdeps/riscv/nptl/tcb-offsets.sym
new file mode 100644
index 0000000000..a989031aad
--- /dev/null
+++ b/sysdeps/riscv/nptl/tcb-offsets.sym
@@ -0,0 +1,6 @@
+#include <sysdep.h>
+#include <tls.h>
+
+#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
diff --git a/sysdeps/riscv/nptl/tls.h b/sysdeps/riscv/nptl/tls.h
new file mode 100644
index 0000000000..8090d2c8ba
--- /dev/null
+++ b/sysdeps/riscv/nptl/tls.h
@@ -0,0 +1,149 @@
+/* Definition for thread-local data handling. NPTL/RISC-V version.
+ Copyright (C) 2011-2014, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _RISCV_TLS_H
+#define _RISCV_TLS_H 1
+
+#include <dl-sysdep.h>
+
+/* Signal that TLS support is available. */
+#define USE_TLS 1
+
+#ifndef __ASSEMBLER__
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+# include <dl-dtv.h>
+
+register void* __thread_self asm("tp");
+# define READ_THREAD_POINTER() ({ __thread_self; })
+
+/* Get system call information. */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks. */
+# define TLS_DTV_AT_TP 1
+# define TLS_TCB_AT_TP 0
+
+/* Get the thread descriptor definition. */
+# include <nptl/descr.h>
+
+typedef struct
+{
+ dtv_t *dtv;
+ void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB. Because our TCB is before the thread
+ pointer, we don't need this. */
+# define TLS_INIT_TCB_SIZE 0
+
+/* Alignment requirements for the initial TCB. */
+# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
+
+/* This is the size of the TCB. Because our TCB is before the thread
+ pointer, we don't need this. */
+# define TLS_TCB_SIZE 0
+
+/* Alignment requirements for the TCB. */
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
+
+/* This is the size we need before TCB - actually, it includes the TCB. */
+# define TLS_PRE_TCB_SIZE \
+ (sizeof (struct pthread) \
+ + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+
+/* The thread pointer tp points to the end of the TCB.
+ The pthread_descr structure is immediately in front of the TCB. */
+# define TLS_TCB_OFFSET 0
+
+/* Install the dtv pointer. The pointer passed is to the element with
+ index -1 which contain the length. */
+# define INSTALL_DTV(tcbp, dtvp) \
+ (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread. */
+# define INSTALL_NEW_DTV(dtv) \
+ (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor. */
+# define GET_DTV(tcbp) \
+ (((tcbhead_t *) (tcbp))[-1].dtv)
+
+/* Code to initially initialize the thread pointer. */
+# define TLS_INIT_TP(tcbp) \
+ ({ __thread_self = (char*)tcbp + TLS_TCB_OFFSET; NULL; })
+
+/* Return the address of the dtv for the current thread. */
+# define THREAD_DTV() \
+ (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread. */
+# define THREAD_SELF \
+ ((struct pthread *) (READ_THREAD_POINTER () \
+ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+/* Value passed to 'clone' for initialization of the thread register. */
+# define TLS_DEFINE_INIT_TP(tp, pd) \
+ void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE
+
+/* Magic for libthread_db to know how to do THREAD_SELF. */
+# define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+
+/* Access to data in the thread descriptor is easy. */
+# define THREAD_GETMEM(descr, member) \
+ descr->member
+# define THREAD_GETMEM_NC(descr, member, idx) \
+ descr->member[idx]
+# define THREAD_SETMEM(descr, member, value) \
+ descr->member = (value)
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+ descr->member[idx] = (value)
+
+/* l_tls_offset == 0 is perfectly valid, so we have to use some different
+ value to mean unset l_tls_offset. */
+# define NO_TLS_OFFSET -1
+
+/* Get and set the global scope generation counter in struct pthread. */
+# define THREAD_GSCOPE_FLAG_UNUSED 0
+# define THREAD_GSCOPE_FLAG_USED 1
+# define THREAD_GSCOPE_FLAG_WAIT 2
+# define THREAD_GSCOPE_RESET_FLAG() \
+ do \
+ { int __res \
+ = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \
+ THREAD_GSCOPE_FLAG_UNUSED); \
+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
+ } \
+ while (0)
+# define THREAD_GSCOPE_SET_FLAG() \
+ do \
+ { \
+ THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
+ atomic_write_barrier (); \
+ } \
+ while (0)
+# define THREAD_GSCOPE_WAIT() \
+ GL(dl_wait_lookup_done) ()
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* tls.h */
diff --git a/sysdeps/riscv/stackinfo.h b/sysdeps/riscv/stackinfo.h
new file mode 100644
index 0000000000..047c74e938
--- /dev/null
+++ b/sysdeps/riscv/stackinfo.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This file contains a bit of information about the stack allocation
+ of the processor. */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H 1
+
+#include <elf.h>
+
+/* On RISC-V the stack grows down. */
+#define _STACK_GROWS_DOWN 1
+
+/* Default to a non-executable stack. */
+#define DEFAULT_STACK_PERMS (PF_R|PF_W)
+
+#endif /* stackinfo.h */
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:11 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch contains fast versions of the various routines from string.h
that have been implemented for RISC-V. Since RISC-V doesn't define any
specific performance characteristics they're not optimized for any
particular microarchitecture, but are designed to be generally good.
---
sysdeps/riscv/bits/string.h | 25 +++++++
sysdeps/riscv/memcpy.c | 74 +++++++++++++++++++++
sysdeps/riscv/memset.S | 107 +++++++++++++++++++++++++++++
sysdeps/riscv/strcmp.S | 159 ++++++++++++++++++++++++++++++++++++++++++++
sysdeps/riscv/strcpy.c | 54 +++++++++++++++
sysdeps/riscv/strlen.c | 39 +++++++++++
6 files changed, 458 insertions(+)
create mode 100644 sysdeps/riscv/bits/string.h
create mode 100644 sysdeps/riscv/memcpy.c
create mode 100644 sysdeps/riscv/memset.S
create mode 100644 sysdeps/riscv/strcmp.S
create mode 100644 sysdeps/riscv/strcpy.c
create mode 100644 sysdeps/riscv/strlen.c

diff --git a/sysdeps/riscv/bits/string.h b/sysdeps/riscv/bits/string.h
new file mode 100644
index 0000000000..8160b8cc77
--- /dev/null
+++ b/sysdeps/riscv/bits/string.h
@@ -0,0 +1,25 @@
+/* This file should provide inline versions of string functions.
+
+ Surround GCC-specific parts with #ifdef __GNUC__, and use `__extern_inline'.
+
+ This file should define __STRING_INLINES if functions are actually defined
+ as inlines. */
+
+#ifndef _BITS_STRING_H
+#define _BITS_STRING_H 1
+
+#define _STRING_INLINE_unaligned 0
+
+#if defined(__GNUC__) && !defined(__cplusplus)
+
+static __inline__ unsigned long __libc_detect_null(unsigned long w)
+{
+ unsigned long mask = 0x7f7f7f7f;
+ if (sizeof(long) == 8)
+ mask = ((mask << 16) << 16) | mask;
+ return ~(((w & mask) + mask) | w | mask);
+}
+
+#endif /* __GNUC__ && !__cplusplus */
+
+#endif /* bits/string.h */
diff --git a/sysdeps/riscv/memcpy.c b/sysdeps/riscv/memcpy.c
new file mode 100644
index 0000000000..f816a54b9b
--- /dev/null
+++ b/sysdeps/riscv/memcpy.c
@@ -0,0 +1,74 @@
+#include <string.h>
+#include <stdint.h>
+
+#define MEMCPY_LOOP_BODY(a, b, t) { \
+ t tt = *b; \
+ a++, b++; \
+ *(a - 1) = tt; \
+ }
+
+void *__memcpy(void *aa, const void *bb, size_t n)
+{
+ uintptr_t msk = sizeof(long) - 1;
+ char *a = (char *)aa, *end = a + n;
+ const char *b = (const char *)bb;
+ long *la, *lend;
+ const long *lb;
+ int same_alignment = ((uintptr_t)a & msk) == ((uintptr_t)b & msk);
+
+ /* Handle small cases, and those without mutual alignment. */
+ if (__glibc_unlikely(!same_alignment || n < sizeof(long)))
+ {
+small:
+ while (a < end)
+ MEMCPY_LOOP_BODY(a, b, char);
+ return aa;
+ }
+
+ /* Obtain alignment. */
+ if (__glibc_unlikely(((uintptr_t)a & msk) != 0))
+ while ((uintptr_t)a & msk)
+ MEMCPY_LOOP_BODY(a, b, char);
+
+ la = (long *)a;
+ lb = (const long *)b;
+ lend = (long *)((uintptr_t)end & ~msk);
+
+ /* Handle large, aligned cases. */
+ if (__glibc_unlikely(la < lend - 8))
+ while (la < lend - 8)
+ {
+ long b0 = *lb++;
+ long b1 = *lb++;
+ long b2 = *lb++;
+ long b3 = *lb++;
+ long b4 = *lb++;
+ long b5 = *lb++;
+ long b6 = *lb++;
+ long b7 = *lb++;
+ long b8 = *lb++;
+ *la++ = b0;
+ *la++ = b1;
+ *la++ = b2;
+ *la++ = b3;
+ *la++ = b4;
+ *la++ = b5;
+ *la++ = b6;
+ *la++ = b7;
+ *la++ = b8;
+ }
+
+ /* Handle aligned, small case. */
+ while (la < lend)
+ MEMCPY_LOOP_BODY(la, lb, long);
+
+ /* Handle misaligned remainder. */
+ a = (char *)la;
+ b = (const char *)lb;
+ if (__glibc_unlikely(a < end))
+ goto small;
+
+ return aa;
+}
+weak_alias (__memcpy, memcpy)
+libc_hidden_builtin_def (memcpy)
diff --git a/sysdeps/riscv/memset.S b/sysdeps/riscv/memset.S
new file mode 100644
index 0000000000..a85d72b4fc
--- /dev/null
+++ b/sysdeps/riscv/memset.S
@@ -0,0 +1,107 @@
+/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+ENTRY(memset)
+ li a6, 15
+ mv a4, a0
+ bleu a2, a6, .Ltiny
+ and a5, a4, 15
+ bnez a5, .Lmisaligned
+
+.Laligned:
+ bnez a1, .Lwordify
+
+.Lwordified:
+ and a3, a2, ~15
+ and a2, a2, 15
+ add a3, a3, a4
+
+#if __riscv_xlen == 64
+1:sd a1, 0(a4)
+ sd a1, 8(a4)
+#else
+1:sw a1, 0(a4)
+ sw a1, 4(a4)
+ sw a1, 8(a4)
+ sw a1, 12(a4)
+#endif
+ add a4, a4, 16
+ bltu a4, a3, 1b
+
+ bnez a2, .Ltiny
+ ret
+
+.Ltiny:
+ sub a3, a6, a2
+ sll a3, a3, 2
+1:auipc t0, %pcrel_hi(.Ltable)
+ add a3, a3, t0
+.option push
+.option norvc
+.Ltable_misaligned:
+ jr a3, %pcrel_lo(1b)
+.Ltable:
+ sb a1,14(a4)
+ sb a1,13(a4)
+ sb a1,12(a4)
+ sb a1,11(a4)
+ sb a1,10(a4)
+ sb a1, 9(a4)
+ sb a1, 8(a4)
+ sb a1, 7(a4)
+ sb a1, 6(a4)
+ sb a1, 5(a4)
+ sb a1, 4(a4)
+ sb a1, 3(a4)
+ sb a1, 2(a4)
+ sb a1, 1(a4)
+ sb a1, 0(a4)
+.option pop
+ ret
+
+.Lwordify:
+ and a1, a1, 0xFF
+ sll a3, a1, 8
+ or a1, a1, a3
+ sll a3, a1, 16
+ or a1, a1, a3
+#if __riscv_xlen == 64
+ sll a3, a1, 32
+ or a1, a1, a3
+#endif
+ j .Lwordified
+
+.Lmisaligned:
+ sll a3, a5, 2
+1:auipc t0, %pcrel_hi(.Ltable_misaligned)
+ add a3, a3, t0
+ mv t0, ra
+ jalr a3, %pcrel_lo(1b)
+ mv ra, t0
+
+ add a5, a5, -16
+ sub a4, a4, a5
+ add a2, a2, a5
+ bleu a2, a6, .Ltiny
+ j .Laligned
+END(memset)
+
+weak_alias(memset, __GI_memset)
diff --git a/sysdeps/riscv/strcmp.S b/sysdeps/riscv/strcmp.S
new file mode 100644
index 0000000000..8cd113e5d4
--- /dev/null
+++ b/sysdeps/riscv/strcmp.S
@@ -0,0 +1,159 @@
+/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+# error
+#endif
+
+ENTRY(strcmp)
+ or a4, a0, a1
+ li t2, -1
+ and a4, a4, SZREG-1
+ bnez a4, .Lmisaligned
+
+#if SZREG == 4
+ li t3, 0x7f7f7f7f
+#else
+ ld t3, mask
+#endif
+
+ .macro check_one_word i n
+ REG_L a2, \i*SZREG(a0)
+ REG_L a3, \i*SZREG(a1)
+
+ and t0, a2, t3
+ or t1, a2, t3
+ add t0, t0, t3
+ or t0, t0, t1
+
+ bne t0, t2, .Lnull\i
+ .if \i+1-\n
+ bne a2, a3, .Lmismatch
+ .else
+ add a0, a0, \n*SZREG
+ add a1, a1, \n*SZREG
+ beq a2, a3, .Lloop
+ # fall through to .Lmismatch
+ .endif
+ .endm
+
+ .macro foundnull i n
+ .ifne \i
+ .Lnull\i:
+ add a0, a0, \i*SZREG
+ add a1, a1, \i*SZREG
+ .ifeq \i-1
+ .Lnull0:
+ .endif
+ bne a2, a3, .Lmisaligned
+ li a0, 0
+ ret
+ .endif
+ .endm
+
+.Lloop:
+ # examine full words at a time, favoring strings of a couple dozen chars
+#if __riscv_xlen == 32
+ check_one_word 0 5
+ check_one_word 1 5
+ check_one_word 2 5
+ check_one_word 3 5
+ check_one_word 4 5
+#else
+ check_one_word 0 3
+ check_one_word 1 3
+ check_one_word 2 3
+#endif
+ # backwards branch to .Lloop contained above
+
+.Lmismatch:
+ # words don't match, but a2 has no null byte.
+#if __riscv_xlen == 64
+ sll a4, a2, 48
+ sll a5, a3, 48
+ bne a4, a5, .Lmismatch_upper
+ sll a4, a2, 32
+ sll a5, a3, 32
+ bne a4, a5, .Lmismatch_upper
+#endif
+ sll a4, a2, 16
+ sll a5, a3, 16
+ bne a4, a5, .Lmismatch_upper
+
+ srl a4, a2, 8*SZREG-16
+ srl a5, a3, 8*SZREG-16
+ sub a0, a4, a5
+ and a1, a0, 0xff
+ bnez a1, 1f
+ ret
+
+.Lmismatch_upper:
+ srl a4, a4, 8*SZREG-16
+ srl a5, a5, 8*SZREG-16
+ sub a0, a4, a5
+ and a1, a0, 0xff
+ bnez a1, 1f
+ ret
+
+1:and a4, a4, 0xff
+ and a5, a5, 0xff
+ sub a0, a4, a5
+ ret
+
+.Lmisaligned:
+ # misaligned
+ lbu a2, 0(a0)
+ lbu a3, 0(a1)
+ add a0, a0, 1
+ add a1, a1, 1
+ bne a2, a3, 1f
+ bnez a2, .Lmisaligned
+
+1:
+ sub a0, a2, a3
+ ret
+
+ # cases in which a null byte was detected
+#if __riscv_xlen == 32
+ foundnull 0 5
+ foundnull 1 5
+ foundnull 2 5
+ foundnull 3 5
+ foundnull 4 5
+#else
+ foundnull 0 3
+ foundnull 1 3
+ foundnull 2 3
+#endif
+
+END(strcmp)
+
+weak_alias(strcmp, __GI_strcmp)
+
+#if SZREG == 8
+#ifdef __PIC__
+.section .rodata.cst8,"aM",@progbits,8
+#else
+.section .srodata.cst8,"aM",@progbits,8
+#endif
+.align 3
+mask: .8byte 0x7f7f7f7f7f7f7f7f
+#endif
diff --git a/sysdeps/riscv/strcpy.c b/sysdeps/riscv/strcpy.c
new file mode 100644
index 0000000000..c01c506a55
--- /dev/null
+++ b/sysdeps/riscv/strcpy.c
@@ -0,0 +1,54 @@
+#include <string.h>
+#include <stdint.h>
+
+#undef strcpy
+
+char* strcpy(char* dst, const char* src)
+{
+ char* dst0 = dst;
+
+ int misaligned = ((uintptr_t)dst | (uintptr_t)src) & (sizeof(long)-1);
+ if (__builtin_expect(!misaligned, 1))
+ {
+ long* ldst = (long*)dst;
+ const long* lsrc = (const long*)src;
+
+ while (!__libc_detect_null(*lsrc))
+ *ldst++ = *lsrc++;
+
+ dst = (char*)ldst;
+ src = (const char*)lsrc;
+
+ char c0 = src[0];
+ char c1 = src[1];
+ char c2 = src[2];
+ if (!(*dst++ = c0)) return dst0;
+ if (!(*dst++ = c1)) return dst0;
+ char c3 = src[3];
+ if (!(*dst++ = c2)) return dst0;
+ if (sizeof(long) == 4) goto out;
+ char c4 = src[4];
+ if (!(*dst++ = c3)) return dst0;
+ char c5 = src[5];
+ if (!(*dst++ = c4)) return dst0;
+ char c6 = src[6];
+ if (!(*dst++ = c5)) return dst0;
+ if (!(*dst++ = c6)) return dst0;
+
+out:
+ *dst++ = 0;
+ return dst0;
+ }
+
+ char ch;
+ do
+ {
+ ch = *src;
+ src++;
+ dst++;
+ *(dst-1) = ch;
+ } while(ch);
+
+ return dst0;
+}
+libc_hidden_def(strcpy)
diff --git a/sysdeps/riscv/strlen.c b/sysdeps/riscv/strlen.c
new file mode 100644
index 0000000000..049e1ebd8f
--- /dev/null
+++ b/sysdeps/riscv/strlen.c
@@ -0,0 +1,39 @@
+#include <string.h>
+#include <stdint.h>
+
+#undef strlen
+
+size_t strlen(const char* str)
+{
+ const char* start = str;
+
+ if (__builtin_expect((uintptr_t)str & (sizeof(long)-1), 0)) do
+ {
+ char ch = *str;
+ str++;
+ if (!ch)
+ return str - start - 1;
+ } while ((uintptr_t)str & (sizeof(long)-1));
+
+ unsigned long* ls = (unsigned long*)str;
+ while (!__libc_detect_null(*ls++))
+ ;
+ asm volatile ("" : "+r"(ls)); /* prevent "optimization" */
+
+ str = (const char*)ls;
+ size_t ret = str - start, sl = sizeof(long);
+
+ char c0 = str[0-sl], c1 = str[1-sl], c2 = str[2-sl], c3 = str[3-sl];
+ if (c0 == 0) return ret + 0 - sl;
+ if (c1 == 0) return ret + 1 - sl;
+ if (c2 == 0) return ret + 2 - sl;
+ if (sl == 4 || c3 == 0) return ret + 3 - sl;
+
+ c0 = str[4-sl], c1 = str[5-sl], c2 = str[6-sl], c3 = str[7-sl];
+ if (c0 == 0) return ret + 4 - sl;
+ if (c1 == 0) return ret + 5 - sl;
+ if (c2 == 0) return ret + 6 - sl;
+
+ return ret + 7 - sl;
+}
+libc_hidden_def(strlen)
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:13 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch contains the miscellaneous math routines and headers we have
implemented for RISC-V. This includes things from <math.h> that aren't
completely ISA-generic, floating-point bit manipulation, and soft-fp
hooks.
---
sysdeps/riscv/bits/fenv.h | 65 ++++++++
sysdeps/riscv/bits/mathdef.h | 21 +++
sysdeps/riscv/bits/mathinline.h | 142 ++++++++++++++++
sysdeps/riscv/fpu_control.h | 77 +++++++++
sysdeps/riscv/ieee754.h | 325 ++++++++++++++++++++++++++++++++++++
sysdeps/riscv/soft-fp/e_sqrtl.c | 1 +
sysdeps/riscv/soft-fp/sfp-machine.h | 93 +++++++++++
7 files changed, 724 insertions(+)
create mode 100644 sysdeps/riscv/bits/fenv.h
create mode 100644 sysdeps/riscv/bits/mathdef.h
create mode 100644 sysdeps/riscv/bits/mathinline.h
create mode 100644 sysdeps/riscv/fpu_control.h
create mode 100644 sysdeps/riscv/ieee754.h
create mode 100644 sysdeps/riscv/soft-fp/e_sqrtl.c
create mode 100644 sysdeps/riscv/soft-fp/sfp-machine.h

diff --git a/sysdeps/riscv/bits/fenv.h b/sysdeps/riscv/bits/fenv.h
new file mode 100644
index 0000000000..a7a8c604ca
--- /dev/null
+++ b/sysdeps/riscv/bits/fenv.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 1998, 1999, 2000, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _FENV_H
+# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
+#endif
+
+enum
+ {
+ FE_INEXACT = 0x01,
+#define FE_INEXACT FE_INEXACT
+ FE_UNDERFLOW = 0x02,
+#define FE_UNDERFLOW FE_UNDERFLOW
+ FE_OVERFLOW = 0x04,
+#define FE_OVERFLOW FE_OVERFLOW
+ FE_DIVBYZERO = 0x08,
+#define FE_DIVBYZERO FE_DIVBYZERO
+ FE_INVALID = 0x10,
+#define FE_INVALID FE_INVALID
+ };
+
+#define FE_ALL_EXCEPT \
+ (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
+
+enum
+ {
+ FE_TONEAREST = 0x0,
+#define FE_TONEAREST FE_TONEAREST
+ FE_TOWARDZERO = 0x1,
+#define FE_TOWARDZERO FE_TOWARDZERO
+ FE_DOWNWARD = 0x2,
+#define FE_DOWNWARD FE_DOWNWARD
+ FE_UPWARD = 0x3
+#define FE_UPWARD FE_UPWARD
+ };
+
+
+typedef unsigned int fexcept_t;
+typedef unsigned int fenv_t;
+
+/* If the default argument is used we use this value. */
+#define FE_DFL_ENV ((__const fenv_t *) -1)
+
+#if __GLIBC_USE (IEC_60559_BFP_EXT)
+/* Type representing floating-point control modes. */
+typedef unsigned int femode_t;
+
+/* Default floating-point control modes. */
+# define FE_DFL_MODE ((const femode_t *) -1L)
+#endif
diff --git a/sysdeps/riscv/bits/mathdef.h b/sysdeps/riscv/bits/mathdef.h
new file mode 100644
index 0000000000..c0b9be2bd5
--- /dev/null
+++ b/sysdeps/riscv/bits/mathdef.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#if !defined _MATH_H && !defined _COMPLEX_H
+# error "Never use <bits/mathdef.h> directly; include <math.h> instead"
+#endif
diff --git a/sysdeps/riscv/bits/mathinline.h b/sysdeps/riscv/bits/mathinline.h
new file mode 100644
index 0000000000..9fd009e362
--- /dev/null
+++ b/sysdeps/riscv/bits/mathinline.h
@@ -0,0 +1,142 @@
+/* Copyright (C) 2011-2015, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Chris Metcalf <cmet...@tilera.com>, 2011.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MATH_H
+# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
+#endif
+
+#ifndef __extern_always_inline
+# define __MATH_INLINE __inline
+#else
+# define __MATH_INLINE __extern_always_inline
+#endif
+
+
+#if defined __USE_ISOC99 && defined __GNUC__
+
+/* Test for negative number. Used in the signbit() macro. */
+__MATH_INLINE int
+__NTH (__signbitf (float __x))
+{
+ return __builtin_signbitf (__x);
+}
+__MATH_INLINE int
+__NTH (__signbit (double __x))
+{
+ return __builtin_signbit (__x);
+}
+
+/* Leave it to the compiler to optimize these if __NO_MATH_ERRNO__. */
+# if defined __riscv_flen && !defined __NO_MATH_ERRNO__
+
+# if __riscv_xlen >= 64
+
+__MATH_INLINE long long int
+__NTH (llrintf (float __x))
+{
+ long long int __res;
+ __asm__ __volatile__ ("fcvt.l.s %0, %1" : "=r" (__res) : "f" (__x));
+ return __res;
+}
+
+__MATH_INLINE long long int
+__NTH (llroundf (float __x))
+{
+ long long int __res;
+ __asm__ __volatile__ ("fcvt.l.s %0, %1, rmm" : "=r" (__res) : "f" (__x));
+ return __res;
+}
+
+# endif /* __riscv_xlen >= 64 */
+
+__MATH_INLINE long int
+__NTH (lrintf (float __x))
+{
+#ifdef __LP64__
+ return (long int) llrintf (__x);
+#else
+ long int __res;
+ __asm__ __volatile__ ("fcvt.w.s %0, %1" : "=r" (__res) : "f" (__x));
+ return __res;
+#endif
+}
+
+__MATH_INLINE long int
+__NTH (lroundf (float __x))
+{
+#ifdef __LP64__
+ return (long int) llroundf (__x);
+#else
+ long int __res;
+ __asm__ __volatile__ ("fcvt.w.s %0, %1, rmm" : "=r" (__res) : "f" (__x));
+ return __res;
+#endif
+}
+
+# endif /* __riscv_flen && !__NO_MATH_ERRNO__ */
+
+/* Leave it to the compiler to optimize these if __NO_MATH_ERRNO__. */
+# if defined __riscv_flen && __riscv_flen >= 64 && !defined __NO_MATH_ERRNO__
+
+# if __riscv_xlen >= 64
+
+__MATH_INLINE long long int
+__NTH (llrint (double __x))
+{
+ long long int __res;
+ __asm__ __volatile__ ("fcvt.l.d %0, %1" : "=r" (__res) : "f" (__x));
+ return __res;
+}
+
+__MATH_INLINE long long int
+__NTH (llround (double __x))
+{
+ long long int __res;
+ __asm__ __volatile__ ("fcvt.l.d %0, %1, rmm" : "=r" (__res) : "f" (__x));
+ return __res;
+}
+
+# endif /* __riscv_xlen >= 64 */
+
+__MATH_INLINE long int
+__NTH (lrint (double __x))
+{
+#ifdef __LP64__
+ return (long int) llrint (__x);
+#else
+ long int __res;
+ __asm__ __volatile__ ("fcvt.w.d %0, %1" : "=r" (__res) : "f" (__x));
+ return __res;
+#endif
+}
+
+__MATH_INLINE long int
+__NTH (lround (double __x))
+{
+#ifdef __LP64__
+ return (long int) llround (__x);
+#else
+ long int __res;
+ __asm__ __volatile__ ("fcvt.w.d %0, %1, rmm" : "=r" (__res) : "f" (__x));
+ return __res;
+#endif
+}
+
+# endif /* __riscv_flen >= 64 && !__NO_MATH_ERRNO__ */
+
+#endif
diff --git a/sysdeps/riscv/fpu_control.h b/sysdeps/riscv/fpu_control.h
new file mode 100644
index 0000000000..ca0fa15a0c
--- /dev/null
+++ b/sysdeps/riscv/fpu_control.h
@@ -0,0 +1,77 @@
+/* FPU control word bits. RISC-V version.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2006, 2008, 2017
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Olaf Flebbe and Ralf Baechle.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _FPU_CONTROL_H
+#define _FPU_CONTROL_H
+
+#include <features.h>
+
+#ifndef __riscv_flen
+
+#define _FPU_RESERVED 0xffffffff
+#define _FPU_DEFAULT 0x00000000
+typedef unsigned int fpu_control_t;
+#define _FPU_GETCW(cw) (cw) = 0
+#define _FPU_SETCW(cw) do { } while (0)
+extern fpu_control_t __fpu_control;
+
+#else /* __riscv_flen */
+
+#define _FPU_RESERVED 0
+#define _FPU_DEFAULT 0
+#define _FPU_IEEE _FPU_DEFAULT
+
+/* Type of the control word. */
+typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
+
+/* Macros for accessing the hardware control word. */
+#define _FPU_GETCW(cw) __asm__ volatile ("frsr %0" : "=r" (cw))
+#define _FPU_SETCW(cw) __asm__ volatile ("fssr %z0" : : "rJ" (cw))
+
+/* Default control word set at startup. */
+extern fpu_control_t __fpu_control;
+
+#define _FCLASS(x) ({ int res; \
+ if (sizeof (x) * 8 > __riscv_flen) __builtin_trap (); \
+ if (sizeof (x) == 4) asm ("fclass.s %0, %1" : "=r" (res) : "f" (x)); \
+ else if (sizeof (x) == 8) asm ("fclass.d %0, %1" : "=r" (res) : "f" (x)); \
+ else __builtin_trap (); \
+ res; })
+
+#define _FCLASS_MINF (1<<0)
+#define _FCLASS_MNORM (1<<1)
+#define _FCLASS_MSUBNORM (1<<2)
+#define _FCLASS_MZERO (1<<3)
+#define _FCLASS_PZERO (1<<4)
+#define _FCLASS_PSUBNORM (1<<5)
+#define _FCLASS_PNORM (1<<6)
+#define _FCLASS_PINF (1<<7)
+#define _FCLASS_SNAN (1<<8)
+#define _FCLASS_QNAN (1<<9)
+#define _FCLASS_ZERO (_FCLASS_MZERO | _FCLASS_PZERO)
+#define _FCLASS_SUBNORM (_FCLASS_MSUBNORM | _FCLASS_PSUBNORM)
+#define _FCLASS_NORM (_FCLASS_MNORM | _FCLASS_PNORM)
+#define _FCLASS_INF (_FCLASS_MINF | _FCLASS_PINF)
+#define _FCLASS_NAN (_FCLASS_SNAN | _FCLASS_QNAN)
+
+#endif /* __riscv_flen */
+
+#endif /* fpu_control.h */
diff --git a/sysdeps/riscv/ieee754.h b/sysdeps/riscv/ieee754.h
new file mode 100644
index 0000000000..f515aa4b36
--- /dev/null
+++ b/sysdeps/riscv/ieee754.h
@@ -0,0 +1,325 @@
+/* Copyright (C) 1992, 1995, 1996, 1999, 2002, 2003, 2017
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _IEEE754_H
+
+#define _IEEE754_H 1
+#include <features.h>
+
+#include <endian.h>
+
+#include <float.h>
+
+__BEGIN_DECLS
+
+union ieee754_float
+ {
+ float f;
+
+ /* This is the IEEE 754 single-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int mantissa:23;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:23;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa:22;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:22;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee_nan;
+ };
+
+#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
+
+
+union ieee754_double
+ {
+ double d;
+
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:20;
+ unsigned int mantissa1:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:19;
+ unsigned int mantissa1:32;
+#else
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
+
+#if LDBL_MANT_DIG == 113
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 854 quad-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:16;
+ unsigned int mantissa1:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa3:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa3:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:16;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:15;
+ unsigned int mantissa1:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa3:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa3:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:15;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff /* Added to exponent. */
+
+#elif LDBL_MANT_DIG == 64
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:32;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee;
+
+ /* This is for NaNs in the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int one:1;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa0:30;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
+
+#elif LDBL_MANT_DIG == 53
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:20;
+ unsigned int mantissa1:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:19;
+ unsigned int mantissa1:32;
+#else
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent. */
+
+#endif /* LDBL_MANT_DIG == 53 */
+
+__END_DECLS
+
+#endif /* ieee754.h */
diff --git a/sysdeps/riscv/soft-fp/e_sqrtl.c b/sysdeps/riscv/soft-fp/e_sqrtl.c
new file mode 100644
index 0000000000..3241a877ac
--- /dev/null
+++ b/sysdeps/riscv/soft-fp/e_sqrtl.c
@@ -0,0 +1 @@
+#include "sysdeps/aarch64/soft-fp/e_sqrtl.c"
diff --git a/sysdeps/riscv/soft-fp/sfp-machine.h b/sysdeps/riscv/soft-fp/sfp-machine.h
new file mode 100644
index 0000000000..3068b5de78
--- /dev/null
+++ b/sysdeps/riscv/soft-fp/sfp-machine.h
@@ -0,0 +1,93 @@
+#include <fenv.h>
+#include <fpu_control.h>
+
+#if __riscv_xlen == 32
+
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S _FP_QNANBIT_S
+#define _FP_NANFRAC_D _FP_QNANBIT_D, 0
+#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0
+
+#else
+
+#define _FP_W_TYPE_SIZE 64
+#define _FP_W_TYPE unsigned long long
+#define _FP_WS_TYPE signed long long
+#define _FP_I_TYPE long long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S _FP_QNANBIT_S
+#define _FP_NANFRAC_D _FP_QNANBIT_D
+#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0
+
+#endif
+
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 0
+#define _FP_QNANNEGATEDP 0
+
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define _FP_DECL_EX int _frm __attribute__ ((unused));
+#define FP_ROUNDMODE _frm
+
+#define FP_RND_NEAREST FE_TONEAREST
+#define FP_RND_ZERO FE_TOWARDZERO
+#define FP_RND_PINF FE_UPWARD
+#define FP_RND_MINF FE_DOWNWARD
+
+#define FP_EX_INVALID FE_INVALID
+#define FP_EX_OVERFLOW FE_OVERFLOW
+#define FP_EX_UNDERFLOW FE_UNDERFLOW
+#define FP_EX_DIVZERO FE_DIVBYZERO
+#define FP_EX_INEXACT FE_INEXACT
+
+#define _FP_TININESS_AFTER_ROUNDING 1
+
+#ifdef __riscv_flen
+#define FP_INIT_ROUNDMODE \
+do { \
+ __asm__ volatile ("frrm %0" : "=r" (_frm)); \
+} while (0)
+
+#define FP_HANDLE_EXCEPTIONS \
+do { \
+ if (__builtin_expect (_fex, 0)) \
+ __asm__ volatile ("csrs fflags, %0" : : "rK" (_fex)); \
+} while (0)
+#else
+#define FP_INIT_ROUNDMODE _frm = FP_RND_NEAREST
+#endif
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:15 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This contains the base floating-point support for RISC-V, which is
defined by the F extension. The code in this patch sufficies to
implement RV32F systems only, additional routines are necessary to add
support for RV32D, RV64F, and RV64D. These additional routines have
been split out to avoid having too large of a patch.
---
sysdeps/riscv/rvf/e_sqrtf.c | 27 ++++++
sysdeps/riscv/rvf/fclrexcpt.c | 30 +++++++
sysdeps/riscv/rvf/fedisblxcpt.c | 29 ++++++
sysdeps/riscv/rvf/feenablxcpt.c | 29 ++++++
sysdeps/riscv/rvf/fegetenv.c | 34 +++++++
sysdeps/riscv/rvf/fegetexcept.c | 29 ++++++
sysdeps/riscv/rvf/fegetround.c | 31 +++++++
sysdeps/riscv/rvf/feholdexcpt.c | 32 +++++++
sysdeps/riscv/rvf/fesetenv.c | 32 +++++++
sysdeps/riscv/rvf/fesetround.c | 41 +++++++++
sysdeps/riscv/rvf/feupdateenv.c | 32 +++++++
sysdeps/riscv/rvf/fgetexcptflg.c | 32 +++++++
sysdeps/riscv/rvf/fraiseexcpt.c | 32 +++++++
sysdeps/riscv/rvf/fsetexcptflg.c | 32 +++++++
sysdeps/riscv/rvf/ftestexcept.c | 29 ++++++
sysdeps/riscv/rvf/get-rounding-mode.h | 34 +++++++
sysdeps/riscv/rvf/math_private.h | 161 ++++++++++++++++++++++++++++++++++
sysdeps/riscv/rvf/s_ceilf.c | 50 +++++++++++
sysdeps/riscv/rvf/s_copysignf.c | 27 ++++++
sysdeps/riscv/rvf/s_fabsf.c | 27 ++++++
sysdeps/riscv/rvf/s_finitef.c | 28 ++++++
sysdeps/riscv/rvf/s_floorf.c | 50 +++++++++++
sysdeps/riscv/rvf/s_fmaf.c | 29 ++++++
sysdeps/riscv/rvf/s_fmaxf.c | 27 ++++++
sysdeps/riscv/rvf/s_fminf.c | 27 ++++++
sysdeps/riscv/rvf/s_fpclassifyf.c | 36 ++++++++
sysdeps/riscv/rvf/s_isinff.c | 29 ++++++
sysdeps/riscv/rvf/s_isnanf.c | 28 ++++++
sysdeps/riscv/rvf/s_issignalingf.c | 27 ++++++
sysdeps/riscv/rvf/s_lrintf.c | 33 +++++++
sysdeps/riscv/rvf/s_lroundf.c | 33 +++++++
sysdeps/riscv/rvf/s_nearbyintf.c | 50 +++++++++++
sysdeps/riscv/rvf/s_rintf.c | 50 +++++++++++
sysdeps/riscv/rvf/s_roundf.c | 50 +++++++++++
sysdeps/riscv/rvf/s_truncf.c | 50 +++++++++++
35 files changed, 1317 insertions(+)
create mode 100644 sysdeps/riscv/rvf/e_sqrtf.c
create mode 100644 sysdeps/riscv/rvf/fclrexcpt.c
create mode 100644 sysdeps/riscv/rvf/fedisblxcpt.c
create mode 100644 sysdeps/riscv/rvf/feenablxcpt.c
create mode 100644 sysdeps/riscv/rvf/fegetenv.c
create mode 100644 sysdeps/riscv/rvf/fegetexcept.c
create mode 100644 sysdeps/riscv/rvf/fegetround.c
create mode 100644 sysdeps/riscv/rvf/feholdexcpt.c
create mode 100644 sysdeps/riscv/rvf/fesetenv.c
create mode 100644 sysdeps/riscv/rvf/fesetround.c
create mode 100644 sysdeps/riscv/rvf/feupdateenv.c
create mode 100644 sysdeps/riscv/rvf/fgetexcptflg.c
create mode 100644 sysdeps/riscv/rvf/fraiseexcpt.c
create mode 100644 sysdeps/riscv/rvf/fsetexcptflg.c
create mode 100644 sysdeps/riscv/rvf/ftestexcept.c
create mode 100644 sysdeps/riscv/rvf/get-rounding-mode.h
create mode 100644 sysdeps/riscv/rvf/math_private.h
create mode 100644 sysdeps/riscv/rvf/s_ceilf.c
create mode 100644 sysdeps/riscv/rvf/s_copysignf.c
create mode 100644 sysdeps/riscv/rvf/s_fabsf.c
create mode 100644 sysdeps/riscv/rvf/s_finitef.c
create mode 100644 sysdeps/riscv/rvf/s_floorf.c
create mode 100644 sysdeps/riscv/rvf/s_fmaf.c
create mode 100644 sysdeps/riscv/rvf/s_fmaxf.c
create mode 100644 sysdeps/riscv/rvf/s_fminf.c
create mode 100644 sysdeps/riscv/rvf/s_fpclassifyf.c
create mode 100644 sysdeps/riscv/rvf/s_isinff.c
create mode 100644 sysdeps/riscv/rvf/s_isnanf.c
create mode 100644 sysdeps/riscv/rvf/s_issignalingf.c
create mode 100644 sysdeps/riscv/rvf/s_lrintf.c
create mode 100644 sysdeps/riscv/rvf/s_lroundf.c
create mode 100644 sysdeps/riscv/rvf/s_nearbyintf.c
create mode 100644 sysdeps/riscv/rvf/s_rintf.c
create mode 100644 sysdeps/riscv/rvf/s_roundf.c
create mode 100644 sysdeps/riscv/rvf/s_truncf.c

diff --git a/sysdeps/riscv/rvf/e_sqrtf.c b/sysdeps/riscv/rvf/e_sqrtf.c
new file mode 100644
index 0000000000..ba1ad6db8b
--- /dev/null
+++ b/sysdeps/riscv/rvf/e_sqrtf.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+float
+__ieee754_sqrtf (float x)
+{
+ asm ("fsqrt.s %0, %1" : "=f" (x) : "f" (x));
+ return x;
+}
+strong_alias (__ieee754_sqrtf, __sqrtf_finite)
diff --git a/sysdeps/riscv/rvf/fclrexcpt.c b/sysdeps/riscv/rvf/fclrexcpt.c
new file mode 100644
index 0000000000..38411f6724
--- /dev/null
+++ b/sysdeps/riscv/rvf/fclrexcpt.c
@@ -0,0 +1,30 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1998-2000, 2002, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ asm volatile ("csrc fflags, %0" : : "r" (excepts));
+ return 0;
+}
+libm_hidden_def (feclearexcept)
diff --git a/sysdeps/riscv/rvf/fedisblxcpt.c b/sysdeps/riscv/rvf/fedisblxcpt.c
new file mode 100644
index 0000000000..89434de352
--- /dev/null
+++ b/sysdeps/riscv/rvf/fedisblxcpt.c
@@ -0,0 +1,29 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2000, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fedisableexcept (int excepts)
+{
+ /* FP exceptions never generate traps. */
+ return 0;
+}
diff --git a/sysdeps/riscv/rvf/feenablxcpt.c b/sysdeps/riscv/rvf/feenablxcpt.c
new file mode 100644
index 0000000000..e664a2fb3c
--- /dev/null
+++ b/sysdeps/riscv/rvf/feenablxcpt.c
@@ -0,0 +1,29 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2000, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+feenableexcept (int excepts)
+{
+ /* FP exceptions never generate traps. */
+ return -1;
+}
diff --git a/sysdeps/riscv/rvf/fegetenv.c b/sysdeps/riscv/rvf/fegetenv.c
new file mode 100644
index 0000000000..e8e95dee3c
--- /dev/null
+++ b/sysdeps/riscv/rvf/fegetenv.c
@@ -0,0 +1,34 @@
+/* Store current floating-point environment.
+ Copyright (C) 1998-2000, 2002, 2010, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__fegetenv (fenv_t *envp)
+{
+ _FPU_GETCW (*envp);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (__fegetenv)
+weak_alias (__fegetenv, fegetenv)
+libm_hidden_weak (fegetenv)
diff --git a/sysdeps/riscv/rvf/fegetexcept.c b/sysdeps/riscv/rvf/fegetexcept.c
new file mode 100644
index 0000000000..00dafd96fb
--- /dev/null
+++ b/sysdeps/riscv/rvf/fegetexcept.c
@@ -0,0 +1,29 @@
+/* Get enabled floating-point exceptions.
+ Copyright (C) 2000, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetexcept (void)
+{
+ /* FP exceptions never generate traps. */
+ return 0;
+}
diff --git a/sysdeps/riscv/rvf/fegetround.c b/sysdeps/riscv/rvf/fegetround.c
new file mode 100644
index 0000000000..171063c319
--- /dev/null
+++ b/sysdeps/riscv/rvf/fegetround.c
@@ -0,0 +1,31 @@
+/* Return current rounding direction.
+ Copyright (C) 1998, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@arthur.rhein-neckar.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <math_private.h>
+
+int
+__fegetround (void)
+{
+ return riscv_getround ();
+}
+libm_hidden_def (__fegetround)
+weak_alias (__fegetround, fegetround)
+libm_hidden_weak (fegetround)
diff --git a/sysdeps/riscv/rvf/feholdexcpt.c b/sysdeps/riscv/rvf/feholdexcpt.c
new file mode 100644
index 0000000000..710314e339
--- /dev/null
+++ b/sysdeps/riscv/rvf/feholdexcpt.c
@@ -0,0 +1,32 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 2000, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <math_private.h>
+
+int
+__feholdexcept (fenv_t *envp)
+{
+ libc_feholdexcept_riscv (envp);
+ return 0;
+}
+libm_hidden_def (__feholdexcept)
+weak_alias (__feholdexcept, feholdexcept)
+libm_hidden_weak (feholdexcept)
diff --git a/sysdeps/riscv/rvf/fesetenv.c b/sysdeps/riscv/rvf/fesetenv.c
new file mode 100644
index 0000000000..cadb0ee962
--- /dev/null
+++ b/sysdeps/riscv/rvf/fesetenv.c
@@ -0,0 +1,32 @@
+/* Install given floating-point environment.
+ Copyright (C) 1998-2000, 2002, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <math_private.h>
+
+int
+__fesetenv (const fenv_t *envp)
+{
+ libc_fesetenv_riscv (envp);
+ return 0;
+}
+libm_hidden_def (__fesetenv)
+weak_alias (__fesetenv, fesetenv)
+libm_hidden_weak (fesetenv)
diff --git a/sysdeps/riscv/rvf/fesetround.c b/sysdeps/riscv/rvf/fesetround.c
new file mode 100644
index 0000000000..938bf4a170
--- /dev/null
+++ b/sysdeps/riscv/rvf/fesetround.c
@@ -0,0 +1,41 @@
+/* Set current rounding direction.
+ Copyright (C) 1998, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@arthur.rhein-neckar.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <math_private.h>
+
+int
+__fesetround (int round)
+{
+ switch (round)
+ {
+ case FE_TONEAREST:
+ case FE_TOWARDZERO:
+ case FE_DOWNWARD:
+ case FE_UPWARD:
+ riscv_setround (round);
+ return 0;
+ default:
+ return round; /* a nonzero value */
+ }
+}
+libm_hidden_def (__fesetround)
+weak_alias (__fesetround, fesetround)
+libm_hidden_weak (fesetround)
diff --git a/sysdeps/riscv/rvf/feupdateenv.c b/sysdeps/riscv/rvf/feupdateenv.c
new file mode 100644
index 0000000000..9c7e091ed5
--- /dev/null
+++ b/sysdeps/riscv/rvf/feupdateenv.c
@@ -0,0 +1,32 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1998-2000, 2002, 2010, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <math_private.h>
+
+int
+__feupdateenv (const fenv_t *envp)
+{
+ libc_feupdateenv_riscv (envp);
+ return 0;
+}
+libm_hidden_def (__feupdateenv)
+weak_alias (__feupdateenv, feupdateenv)
+libm_hidden_weak (feupdateenv)
diff --git a/sysdeps/riscv/rvf/fgetexcptflg.c b/sysdeps/riscv/rvf/fgetexcptflg.c
new file mode 100644
index 0000000000..867f673cdb
--- /dev/null
+++ b/sysdeps/riscv/rvf/fgetexcptflg.c
@@ -0,0 +1,32 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1998-2000, 2002, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <math_private.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ /* Get the current exceptions. */
+ *flagp = riscv_getflags () & excepts;
+
+ /* Success. */
+ return 0;
+}
diff --git a/sysdeps/riscv/rvf/fraiseexcpt.c b/sysdeps/riscv/rvf/fraiseexcpt.c
new file mode 100644
index 0000000000..2796f37713
--- /dev/null
+++ b/sysdeps/riscv/rvf/fraiseexcpt.c
@@ -0,0 +1,32 @@
+/* Raise given exceptions.
+ Copyright (C) 2000, 2002, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__feraiseexcept (int excepts)
+{
+ asm volatile ("csrs fflags, %0" : : "r" (excepts));
+ return 0;
+}
+libm_hidden_def (__feraiseexcept)
+weak_alias (__feraiseexcept, feraiseexcept)
+libm_hidden_weak (feraiseexcept)
diff --git a/sysdeps/riscv/rvf/fsetexcptflg.c b/sysdeps/riscv/rvf/fsetexcptflg.c
new file mode 100644
index 0000000000..570421dafc
--- /dev/null
+++ b/sysdeps/riscv/rvf/fsetexcptflg.c
@@ -0,0 +1,32 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1998-2000, 2002, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Hartvig Ekner <hart...@mips.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fexcept_t flags = *flagp;
+ asm volatile ("csrc fflags, %0" : : "r" (excepts));
+ asm volatile ("csrs fflags, %0" : : "r" (flags & excepts));
+
+ return 0;
+}
diff --git a/sysdeps/riscv/rvf/ftestexcept.c b/sysdeps/riscv/rvf/ftestexcept.c
new file mode 100644
index 0000000000..b84a980f29
--- /dev/null
+++ b/sysdeps/riscv/rvf/ftestexcept.c
@@ -0,0 +1,29 @@
+/* Test exception in current environment.
+ Copyright (C) 1998, 2010, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@arthur.rhein-neckar.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv.h>
+#include <math_private.h>
+
+int
+fetestexcept (int excepts)
+{
+ return libc_fetestexcept_riscv (excepts);
+}
+libm_hidden_def (fetestexcept)
diff --git a/sysdeps/riscv/rvf/get-rounding-mode.h b/sysdeps/riscv/rvf/get-rounding-mode.h
new file mode 100644
index 0000000000..0f325607e3
--- /dev/null
+++ b/sysdeps/riscv/rvf/get-rounding-mode.h
@@ -0,0 +1,34 @@
+/* Determine floating-point rounding mode within libc. RISC-V version.
+
+ Copyright (C) 2015, 2017 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+#ifndef _RISCV_GET_ROUNDING_MODE_H
+#define _RISCV_GET_ROUNDING_MODE_H
+
+/* Return the floating-point rounding mode. */
+
+static inline int
+get_rounding_mode (void)
+{
+ int rm;
+ asm volatile ("frrm %0" : "=r" (rm));
+ return rm;
+}
+
+#endif /* get-rounding-mode.h */
diff --git a/sysdeps/riscv/rvf/math_private.h b/sysdeps/riscv/rvf/math_private.h
new file mode 100644
index 0000000000..6e4be81919
--- /dev/null
+++ b/sysdeps/riscv/rvf/math_private.h
@@ -0,0 +1,161 @@
+/* Private floating point rounding and exceptions handling. RISC-V version.
+ Copyright (C) 2014-2015, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+#ifndef RISCV_MATH_PRIVATE_H
+#define RISCV_MATH_PRIVATE_H 1
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include <get-rounding-mode.h>
+
+static __always_inline int
+riscv_getround (void)
+{
+ return get_rounding_mode ();
+}
+
+static __always_inline void
+riscv_setround (int rm)
+{
+ asm volatile ("fsrm %z0" : : "rJ" (rm));
+}
+
+static __always_inline int
+riscv_getflags (void)
+{
+ int flags;
+ asm volatile ("frflags %0" : "=r" (flags));
+ return flags;
+}
+
+static __always_inline void
+riscv_setflags (int flags)
+{
+ asm volatile ("fsflags %z0" : : "rJ" (flags));
+}
+
+static __always_inline void
+libc_feholdexcept_riscv (fenv_t *envp)
+{
+ asm volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT));
+}
+
+#define libc_feholdexcept libc_feholdexcept_riscv
+#define libc_feholdexceptf libc_feholdexcept_riscv
+#define libc_feholdexceptl libc_feholdexcept_riscv
+
+static __always_inline void
+libc_fesetround_riscv (int round)
+{
+ riscv_setround (round);
+}
+
+#define libc_fesetround libc_fesetround_riscv
+#define libc_fesetroundf libc_fesetround_riscv
+#define libc_fesetroundl libc_fesetround_riscv
+
+static __always_inline void
+libc_feholdexcept_setround_riscv (fenv_t *envp, int round)
+{
+ libc_fesetround_riscv (round);
+ libc_feholdexcept_riscv (envp);
+}
+
+#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv
+#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv
+#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv
+
+static __always_inline int
+libc_fetestexcept_riscv (int ex)
+{
+ return riscv_getflags () & ex;
+}
+
+#define libc_fetestexcept libc_fetestexcept_riscv
+#define libc_fetestexceptf libc_fetestexcept_riscv
+#define libc_fetestexceptl libc_fetestexcept_riscv
+
+static __always_inline void
+libc_fesetenv_riscv (const fenv_t *envp)
+{
+ long env = (long) envp - (long) FE_DFL_ENV;
+ if (env != 0)
+ env = *envp;
+
+ _FPU_SETCW (env);
+}
+
+#define libc_fesetenv libc_fesetenv_riscv
+#define libc_fesetenvf libc_fesetenv_riscv
+#define libc_fesetenvl libc_fesetenv_riscv
+#define libc_feresetround_noex libc_fesetenv_riscv
+#define libc_feresetround_noexf libc_fesetenv_riscv
+#define libc_feresetround_noexl libc_fesetenv_riscv
+
+static __always_inline int
+libc_feupdateenv_test_riscv (const fenv_t *envp, int ex)
+{
+ fenv_t env = *envp;
+ int flags = riscv_getflags ();
+ asm volatile ("csrw fcsr, %z0" : : "rJ" (env | flags));
+ return flags & ex;
+}
+
+#define libc_feupdateenv_test libc_feupdateenv_test_riscv
+#define libc_feupdateenv_testf libc_feupdateenv_test_riscv
+#define libc_feupdateenv_testl libc_feupdateenv_test_riscv
+
+static __always_inline void
+libc_feupdateenv_riscv (const fenv_t *envp)
+{
+ _FPU_SETCW (*envp | riscv_getflags ());
+}
+
+#define libc_feupdateenv libc_feupdateenv_riscv
+#define libc_feupdateenvf libc_feupdateenv_riscv
+#define libc_feupdateenvl libc_feupdateenv_riscv
+
+static __always_inline void
+libc_feholdsetround_riscv (fenv_t *envp, int round)
+{
+ /* Note this implementation makes an improperly-formatted fenv_t and
+ so should only be used in conjunction with libc_feresetround. */
+ int old_round;
+ asm volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round));
+ *envp = old_round;
+}
+
+#define libc_feholdsetround libc_feholdsetround_riscv
+#define libc_feholdsetroundf libc_feholdsetround_riscv
+#define libc_feholdsetroundl libc_feholdsetround_riscv
+
+static __always_inline void
+libc_feresetround_riscv (fenv_t *envp)
+{
+ /* Note this implementation takes an improperly-formatted fenv_t and
+ so should only be used in conjunction with libc_feholdsetround. */
+ riscv_setround (*envp);
+}
+
+#define libc_feresetround libc_feresetround_riscv
+#define libc_feresetroundf libc_feresetround_riscv
+#define libc_feresetroundl libc_feresetround_riscv
+
+#include_next <math_private.h>
+
+#endif
diff --git a/sysdeps/riscv/rvf/s_ceilf.c b/sysdeps/riscv/rvf/s_ceilf.c
new file mode 100644
index 0000000000..c168f5f93b
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_ceilf.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+float
+__ceilf (float x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnanf (x);
+ float mag = fabsf (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1 << __FLT_MANT_DIG__))
+ {
+ int i;
+ float new_x;
+
+ asm volatile ("fcvt.w.s %0, %1, rup" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.s.w %0, %1, rup" : "=f" (new_x) : "r" (i));
+
+ /* ceil(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysignf (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__ceilf, ceilf)
diff --git a/sysdeps/riscv/rvf/s_copysignf.c b/sysdeps/riscv/rvf/s_copysignf.c
new file mode 100644
index 0000000000..eda12d014a
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_copysignf.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+float
+__copysignf (float x, float y)
+{
+ asm ("fsgnj.s %0, %1, %2" : "=f" (x) : "f" (x), "f" (y));
+ return x;
+}
+weak_alias (__copysignf, copysignf)
diff --git a/sysdeps/riscv/rvf/s_fabsf.c b/sysdeps/riscv/rvf/s_fabsf.c
new file mode 100644
index 0000000000..c85961ed0f
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_fabsf.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+float
+__fabsf (float x)
+{
+ asm ("fabs.s %0, %1" : "=f" (x) : "f" (x));
+ return x;
+}
+weak_alias (__fabsf, fabsf)
diff --git a/sysdeps/riscv/rvf/s_finitef.c b/sysdeps/riscv/rvf/s_finitef.c
new file mode 100644
index 0000000000..83eaf26d21
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_finitef.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__finitef (float x)
+{
+ return _FCLASS (x) & ~(_FCLASS_INF | _FCLASS_NAN);
+}
+hidden_def (__finitef)
+weak_alias (__finitef, finitef)
diff --git a/sysdeps/riscv/rvf/s_floorf.c b/sysdeps/riscv/rvf/s_floorf.c
new file mode 100644
index 0000000000..e33c0a8aad
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_floorf.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+float
+__floorf (float x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnanf (x);
+ float mag = fabsf (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1 << __FLT_MANT_DIG__))
+ {
+ int i;
+ float new_x;
+
+ asm volatile ("fcvt.w.s %0, %1, rdn" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.s.w %0, %1, rdn" : "=f" (new_x) : "r" (i));
+
+ /* floor(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysignf (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__floorf, floorf)
diff --git a/sysdeps/riscv/rvf/s_fmaf.c b/sysdeps/riscv/rvf/s_fmaf.c
new file mode 100644
index 0000000000..487d67c2cc
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_fmaf.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <fenv.h>
+#include <ieee754.h>
+
+float
+__fmaf (float x, float y, float z)
+{
+ asm ("fmadd.s %0, %1, %2, %3" : "=f" (x) : "f" (x), "f" (y), "f" (z));
+ return x;
+}
+weak_alias (__fmaf, fmaf)
diff --git a/sysdeps/riscv/rvf/s_fmaxf.c b/sysdeps/riscv/rvf/s_fmaxf.c
new file mode 100644
index 0000000000..26b732e794
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_fmaxf.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+float
+__fmaxf (float x, float y)
+{
+ asm ("fmax.s %0, %1, %2" : "=f" (x) : "f" (x), "f" (y));
+ return x;
+}
+weak_alias (__fmaxf, fmaxf)
diff --git a/sysdeps/riscv/rvf/s_fminf.c b/sysdeps/riscv/rvf/s_fminf.c
new file mode 100644
index 0000000000..a0ae10a7d5
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_fminf.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+float
+__fminf (float x, float y)
+{
+ asm ("fmin.s %0, %1, %2" : "=f" (x) : "f" (x), "f" (y));
+ return x;
+}
+weak_alias (__fminf, fminf)
diff --git a/sysdeps/riscv/rvf/s_fpclassifyf.c b/sysdeps/riscv/rvf/s_fpclassifyf.c
new file mode 100644
index 0000000000..7df9d55ea1
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_fpclassifyf.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__fpclassifyf (float x)
+{
+ int cls = _FCLASS (x);
+ if (__builtin_expect (cls & _FCLASS_NORM, _FCLASS_NORM))
+ return FP_NORMAL;
+ if (__builtin_expect (cls & _FCLASS_ZERO, _FCLASS_ZERO))
+ return FP_ZERO;
+ if (__builtin_expect (cls & _FCLASS_SUBNORM, _FCLASS_SUBNORM))
+ return FP_SUBNORMAL;
+ if (__builtin_expect (cls & _FCLASS_INF, _FCLASS_INF))
+ return FP_INFINITE;
+ return FP_NAN;
+}
+libm_hidden_def (__fpclassifyf)
diff --git a/sysdeps/riscv/rvf/s_isinff.c b/sysdeps/riscv/rvf/s_isinff.c
new file mode 100644
index 0000000000..a34f5d769a
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_isinff.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__isinff (float x)
+{
+ int cls = _FCLASS (x);
+ return -((cls & _FCLASS_MINF) ? 1 : 0) | ((cls & _FCLASS_PINF) ? 1 : 0);
+}
+hidden_def (__isinff)
+weak_alias (__isinff, isinff)
diff --git a/sysdeps/riscv/rvf/s_isnanf.c b/sysdeps/riscv/rvf/s_isnanf.c
new file mode 100644
index 0000000000..a025cfd3b1
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_isnanf.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__isnanf (float x)
+{
+ return _FCLASS (x) & _FCLASS_NAN;
+}
+hidden_def (__isnanf)
+weak_alias (__isnanf, isnanf)
diff --git a/sysdeps/riscv/rvf/s_issignalingf.c b/sysdeps/riscv/rvf/s_issignalingf.c
new file mode 100644
index 0000000000..a73267cede
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_issignalingf.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__issignalingf (float x)
+{
+ return _FCLASS (x) & _FCLASS_SNAN;
+}
+libm_hidden_def (__issignalingf)
diff --git a/sysdeps/riscv/rvf/s_lrintf.c b/sysdeps/riscv/rvf/s_lrintf.c
new file mode 100644
index 0000000000..a2bf280094
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_lrintf.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __LP64__
+
+#include <math.h>
+
+long
+__lrintf (float x)
+{
+ long res;
+ asm ("fcvt.w.s %0, %1" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__lrintf, lrintf)
+
+#endif
diff --git a/sysdeps/riscv/rvf/s_lroundf.c b/sysdeps/riscv/rvf/s_lroundf.c
new file mode 100644
index 0000000000..3f01945ea0
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_lroundf.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __LP64__
+
+#include <math.h>
+
+long
+__lroundf (float x)
+{
+ long res;
+ asm ("fcvt.w.s %0, %1, rmm" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__lroundf, lroundf)
+
+#endif
diff --git a/sysdeps/riscv/rvf/s_nearbyintf.c b/sysdeps/riscv/rvf/s_nearbyintf.c
new file mode 100644
index 0000000000..e890d0ce8b
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_nearbyintf.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+float
+__nearbyintf (float x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnanf (x);
+ float mag = fabsf (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1 << __FLT_MANT_DIG__))
+ {
+ int i;
+ float new_x;
+
+ asm volatile ("fcvt.w.s %0, %1" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.s.w %0, %1" : "=f" (new_x) : "r" (i));
+
+ /* nearbyint(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysignf (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__nearbyintf, nearbyintf)
diff --git a/sysdeps/riscv/rvf/s_rintf.c b/sysdeps/riscv/rvf/s_rintf.c
new file mode 100644
index 0000000000..2150b7916b
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_rintf.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+float
+__rintf (float x)
+{
+ int nan;
+ float mag;
+
+ nan = isnanf (x);
+ mag = fabsf (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1 << __FLT_MANT_DIG__))
+ {
+ int i;
+ float new_x;
+
+ asm ("fcvt.w.s %0, %1" : "=r" (i) : "f" (x));
+ asm ("fcvt.s.w %0, %1" : "=f" (new_x) : "r" (i));
+
+ /* rint(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysignf (new_x, x);
+ }
+
+ return x;
+}
+
+weak_alias (__rintf, rintf)
diff --git a/sysdeps/riscv/rvf/s_roundf.c b/sysdeps/riscv/rvf/s_roundf.c
new file mode 100644
index 0000000000..b8ceb33298
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_roundf.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+float
+__roundf (float x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnanf (x);
+ float mag = fabsf (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1 << __FLT_MANT_DIG__))
+ {
+ int i;
+ float new_x;
+
+ asm volatile ("fcvt.w.s %0, %1, rmm" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.s.w %0, %1, rmm" : "=f" (new_x) : "r" (i));
+
+ /* round(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysignf (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__roundf, roundf)
diff --git a/sysdeps/riscv/rvf/s_truncf.c b/sysdeps/riscv/rvf/s_truncf.c
new file mode 100644
index 0000000000..55eb27c610
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_truncf.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+float
+__truncf (float x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnanf (x);
+ float mag = fabsf (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1 << __FLT_MANT_DIG__))
+ {
+ int i;
+ float new_x;
+
+ asm volatile ("fcvt.w.s %0, %1, rtz" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.s.w %0, %1, rtz" : "=f" (new_x) : "r" (i));
+
+ /* trunc(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysignf (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__truncf, truncf)
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:16 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch adds support for the various other hardware floating point
configurations that RISC-V supports. This is split from the RV32F patch
to avoid mailing list size restrictions.
---
sysdeps/riscv/rv64/rvd/s_ceil.c | 50 ++++++++++++++++++++++++++++++++++++
sysdeps/riscv/rv64/rvd/s_floor.c | 50 ++++++++++++++++++++++++++++++++++++
sysdeps/riscv/rv64/rvd/s_llrint.c | 31 ++++++++++++++++++++++
sysdeps/riscv/rv64/rvd/s_llround.c | 31 ++++++++++++++++++++++
sysdeps/riscv/rv64/rvd/s_nearbyint.c | 50 ++++++++++++++++++++++++++++++++++++
sysdeps/riscv/rv64/rvd/s_rint.c | 50 ++++++++++++++++++++++++++++++++++++
sysdeps/riscv/rv64/rvd/s_round.c | 50 ++++++++++++++++++++++++++++++++++++
sysdeps/riscv/rv64/rvd/s_trunc.c | 50 ++++++++++++++++++++++++++++++++++++
sysdeps/riscv/rv64/rvf/s_llrintf.c | 31 ++++++++++++++++++++++
sysdeps/riscv/rv64/rvf/s_llroundf.c | 31 ++++++++++++++++++++++
sysdeps/riscv/rvd/e_sqrt.c | 27 +++++++++++++++++++
sysdeps/riscv/rvd/s_copysign.c | 27 +++++++++++++++++++
sysdeps/riscv/rvd/s_fabs.c | 27 +++++++++++++++++++
sysdeps/riscv/rvd/s_finite.c | 28 ++++++++++++++++++++
sysdeps/riscv/rvd/s_fma.c | 29 +++++++++++++++++++++
sysdeps/riscv/rvd/s_fmax.c | 27 +++++++++++++++++++
sysdeps/riscv/rvd/s_fmin.c | 27 +++++++++++++++++++
sysdeps/riscv/rvd/s_fpclassify.c | 36 ++++++++++++++++++++++++++
sysdeps/riscv/rvd/s_isinf.c | 29 +++++++++++++++++++++
sysdeps/riscv/rvd/s_isnan.c | 28 ++++++++++++++++++++
sysdeps/riscv/rvd/s_issignaling.c | 27 +++++++++++++++++++
sysdeps/riscv/rvd/s_lrint.c | 33 ++++++++++++++++++++++++
sysdeps/riscv/rvd/s_lround.c | 33 ++++++++++++++++++++++++
23 files changed, 802 insertions(+)
create mode 100644 sysdeps/riscv/rv64/rvd/s_ceil.c
create mode 100644 sysdeps/riscv/rv64/rvd/s_floor.c
create mode 100644 sysdeps/riscv/rv64/rvd/s_llrint.c
create mode 100644 sysdeps/riscv/rv64/rvd/s_llround.c
create mode 100644 sysdeps/riscv/rv64/rvd/s_nearbyint.c
create mode 100644 sysdeps/riscv/rv64/rvd/s_rint.c
create mode 100644 sysdeps/riscv/rv64/rvd/s_round.c
create mode 100644 sysdeps/riscv/rv64/rvd/s_trunc.c
create mode 100644 sysdeps/riscv/rv64/rvf/s_llrintf.c
create mode 100644 sysdeps/riscv/rv64/rvf/s_llroundf.c
create mode 100644 sysdeps/riscv/rvd/e_sqrt.c
create mode 100644 sysdeps/riscv/rvd/s_copysign.c
create mode 100644 sysdeps/riscv/rvd/s_fabs.c
create mode 100644 sysdeps/riscv/rvd/s_finite.c
create mode 100644 sysdeps/riscv/rvd/s_fma.c
create mode 100644 sysdeps/riscv/rvd/s_fmax.c
create mode 100644 sysdeps/riscv/rvd/s_fmin.c
create mode 100644 sysdeps/riscv/rvd/s_fpclassify.c
create mode 100644 sysdeps/riscv/rvd/s_isinf.c
create mode 100644 sysdeps/riscv/rvd/s_isnan.c
create mode 100644 sysdeps/riscv/rvd/s_issignaling.c
create mode 100644 sysdeps/riscv/rvd/s_lrint.c
create mode 100644 sysdeps/riscv/rvd/s_lround.c

diff --git a/sysdeps/riscv/rv64/rvd/s_ceil.c b/sysdeps/riscv/rv64/rvd/s_ceil.c
new file mode 100644
index 0000000000..93d613cab1
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_ceil.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+double
+__ceil (double x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnan (x);
+ double mag = fabs (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1ULL << __DBL_MANT_DIG__))
+ {
+ long i;
+ double new_x;
+
+ asm volatile ("fcvt.l.d %0, %1, rup" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.d.l %0, %1, rup" : "=f" (new_x) : "r" (i));
+
+ /* ceil(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysign (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__ceil, ceil)
diff --git a/sysdeps/riscv/rv64/rvd/s_floor.c b/sysdeps/riscv/rv64/rvd/s_floor.c
new file mode 100644
index 0000000000..db4ad9b153
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_floor.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+double
+__floor (double x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnan (x);
+ double mag = fabs (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1ULL << __DBL_MANT_DIG__))
+ {
+ long i;
+ double new_x;
+
+ asm volatile ("fcvt.l.d %0, %1, rdn" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.d.l %0, %1, rdn" : "=f" (new_x) : "r" (i));
+
+ /* floor(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysign (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__floor, floor)
diff --git a/sysdeps/riscv/rv64/rvd/s_llrint.c b/sysdeps/riscv/rv64/rvd/s_llrint.c
new file mode 100644
index 0000000000..47a60b9f58
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_llrint.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+long long
+__llrint (double x)
+{
+ long long res;
+ asm ("fcvt.l.d %0, %1" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__llrint, llrint)
+#ifdef __LP64__
+strong_alias (__llrint, __lrint)
+weak_alias (__llrint, lrint)
+#endif
diff --git a/sysdeps/riscv/rv64/rvd/s_llround.c b/sysdeps/riscv/rv64/rvd/s_llround.c
new file mode 100644
index 0000000000..4563240509
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_llround.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+long long
+__llround (double x)
+{
+ long long res;
+ asm ("fcvt.l.d %0, %1, rmm" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__llround, llround)
+#ifdef __LP64__
+strong_alias (__llround, __lround)
+weak_alias (__llround, lround)
+#endif
diff --git a/sysdeps/riscv/rv64/rvd/s_nearbyint.c b/sysdeps/riscv/rv64/rvd/s_nearbyint.c
new file mode 100644
index 0000000000..ea1805d9a0
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_nearbyint.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+double
+__nearbyint (double x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnan (x);
+ double mag = fabs (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1ULL << __DBL_MANT_DIG__))
+ {
+ long i;
+ double new_x;
+
+ asm volatile ("fcvt.l.d %0, %1" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.d.l %0, %1" : "=f" (new_x) : "r" (i));
+
+ /* nearbyint(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysign (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__nearbyint, nearbyint)
diff --git a/sysdeps/riscv/rv64/rvd/s_rint.c b/sysdeps/riscv/rv64/rvd/s_rint.c
new file mode 100644
index 0000000000..08d218178a
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_rint.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+double
+__rint (double x)
+{
+ int nan;
+ double mag;
+
+ nan = isnan (x);
+ mag = fabs (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1ULL << __DBL_MANT_DIG__))
+ {
+ long i;
+ double new_x;
+
+ asm ("fcvt.l.d %0, %1" : "=r" (i) : "f" (x));
+ asm ("fcvt.d.l %0, %1" : "=f" (new_x) : "r" (i));
+
+ /* rint(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysign (new_x, x);
+ }
+
+ return x;
+}
+
+weak_alias (__rint, rint)
diff --git a/sysdeps/riscv/rv64/rvd/s_round.c b/sysdeps/riscv/rv64/rvd/s_round.c
new file mode 100644
index 0000000000..5cc3370ba4
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_round.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+double
+__round (double x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnan (x);
+ double mag = fabs (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1ULL << __DBL_MANT_DIG__))
+ {
+ long i;
+ double new_x;
+
+ asm volatile ("fcvt.l.d %0, %1, rmm" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.d.l %0, %1, rmm" : "=f" (new_x) : "r" (i));
+
+ /* round(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysign (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__round, round)
diff --git a/sysdeps/riscv/rv64/rvd/s_trunc.c b/sysdeps/riscv/rv64/rvd/s_trunc.c
new file mode 100644
index 0000000000..0b5482025e
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvd/s_trunc.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+double
+__trunc (double x)
+{
+ int flags = riscv_getflags ();
+ int nan = isnan (x);
+ double mag = fabs (x);
+
+ if (nan)
+ return x + x;
+
+ if (mag < (1ULL << __DBL_MANT_DIG__))
+ {
+ long i;
+ double new_x;
+
+ asm volatile ("fcvt.l.d %0, %1, rtz" : "=r" (i) : "f" (x));
+ asm volatile ("fcvt.d.l %0, %1, rtz" : "=f" (new_x) : "r" (i));
+
+ /* trunc(-0) == -0, and in general we'll always have the same
+ sign as our input. */
+ x = copysign (new_x, x);
+
+ riscv_setflags (flags);
+ }
+
+ return x;
+}
+
+weak_alias (__trunc, trunc)
diff --git a/sysdeps/riscv/rv64/rvf/s_llrintf.c b/sysdeps/riscv/rv64/rvf/s_llrintf.c
new file mode 100644
index 0000000000..5f2bed76af
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvf/s_llrintf.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+long long
+__llrintf (float x)
+{
+ long long res;
+ asm ("fcvt.l.s %0, %1" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__llrintf, llrintf)
+#ifdef __LP64__
+strong_alias (__llrintf, __lrintf)
+weak_alias (__llrintf, lrintf)
+#endif
diff --git a/sysdeps/riscv/rv64/rvf/s_llroundf.c b/sysdeps/riscv/rv64/rvf/s_llroundf.c
new file mode 100644
index 0000000000..9f992bfbaf
--- /dev/null
+++ b/sysdeps/riscv/rv64/rvf/s_llroundf.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+long long
+__llroundf (float x)
+{
+ long long res;
+ asm ("fcvt.l.s %0, %1, rmm" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__llroundf, llroundf)
+#ifdef __LP64__
+strong_alias (__llroundf, __lroundf)
+weak_alias (__llroundf, lroundf)
+#endif
diff --git a/sysdeps/riscv/rvd/e_sqrt.c b/sysdeps/riscv/rvd/e_sqrt.c
new file mode 100644
index 0000000000..3dc8a81721
--- /dev/null
+++ b/sysdeps/riscv/rvd/e_sqrt.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+double
+__ieee754_sqrt (double x)
+{
+ asm ("fsqrt.d %0, %1" : "=f" (x) : "f" (x));
+ return x;
+}
+strong_alias (__ieee754_sqrt, __sqrt_finite)
diff --git a/sysdeps/riscv/rvd/s_copysign.c b/sysdeps/riscv/rvd/s_copysign.c
new file mode 100644
index 0000000000..58b9babd64
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_copysign.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+double
+__copysign (double x, double y)
+{
+ asm ("fsgnj.d %0, %1, %2" : "=f" (x) : "f" (x), "f" (y));
+ return x;
+}
+weak_alias (__copysign, copysign)
diff --git a/sysdeps/riscv/rvd/s_fabs.c b/sysdeps/riscv/rvd/s_fabs.c
new file mode 100644
index 0000000000..9c762307ad
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_fabs.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+double
+__fabs (double x)
+{
+ asm ("fabs.d %0, %1" : "=f" (x) : "f" (x));
+ return x;
+}
+weak_alias (__fabs, fabs)
diff --git a/sysdeps/riscv/rvd/s_finite.c b/sysdeps/riscv/rvd/s_finite.c
new file mode 100644
index 0000000000..95e51dddf3
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_finite.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__finite (double x)
+{
+ return _FCLASS (x) & ~(_FCLASS_INF | _FCLASS_NAN);
+}
+hidden_def (__finite)
+weak_alias (__finite, finite)
diff --git a/sysdeps/riscv/rvd/s_fma.c b/sysdeps/riscv/rvd/s_fma.c
new file mode 100644
index 0000000000..f1f4adf28b
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_fma.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <fenv.h>
+#include <ieee754.h>
+
+double
+__fma (double x, double y, double z)
+{
+ asm ("fmadd.d %0, %1, %2, %3" : "=f" (x) : "f" (x), "f" (y), "f" (z));
+ return x;
+}
+weak_alias (__fma, fma)
diff --git a/sysdeps/riscv/rvd/s_fmax.c b/sysdeps/riscv/rvd/s_fmax.c
new file mode 100644
index 0000000000..c0c6b8ea2b
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_fmax.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+double
+__fmax (double x, double y)
+{
+ asm ("fmax.d %0, %1, %2" : "=f" (x) : "f" (x), "f" (y));
+ return x;
+}
+weak_alias (__fmax, fmax)
diff --git a/sysdeps/riscv/rvd/s_fmin.c b/sysdeps/riscv/rvd/s_fmin.c
new file mode 100644
index 0000000000..b71c076a60
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_fmin.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+double
+__fmin (double x, double y)
+{
+ asm ("fmin.d %0, %1, %2" : "=f" (x) : "f" (x), "f" (y));
+ return x;
+}
+weak_alias (__fmin, fmin)
diff --git a/sysdeps/riscv/rvd/s_fpclassify.c b/sysdeps/riscv/rvd/s_fpclassify.c
new file mode 100644
index 0000000000..b02a7be8cf
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_fpclassify.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__fpclassify (double x)
+{
+ int cls = _FCLASS (x);
+ if (__builtin_expect (cls & _FCLASS_NORM, _FCLASS_NORM))
+ return FP_NORMAL;
+ if (__builtin_expect (cls & _FCLASS_ZERO, _FCLASS_ZERO))
+ return FP_ZERO;
+ if (__builtin_expect (cls & _FCLASS_SUBNORM, _FCLASS_SUBNORM))
+ return FP_SUBNORMAL;
+ if (__builtin_expect (cls & _FCLASS_INF, _FCLASS_INF))
+ return FP_INFINITE;
+ return FP_NAN;
+}
+libm_hidden_def (__fpclassify)
diff --git a/sysdeps/riscv/rvd/s_isinf.c b/sysdeps/riscv/rvd/s_isinf.c
new file mode 100644
index 0000000000..bc2382e5b7
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_isinf.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__isinf (double x)
+{
+ int cls = _FCLASS (x);
+ return -((cls & _FCLASS_MINF) ? 1 : 0) | ((cls & _FCLASS_PINF) ? 1 : 0);
+}
+hidden_def (__isinf)
+weak_alias (__isinf, isinf)
diff --git a/sysdeps/riscv/rvd/s_isnan.c b/sysdeps/riscv/rvd/s_isnan.c
new file mode 100644
index 0000000000..b7567336f6
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_isnan.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__isnan (double x)
+{
+ return _FCLASS (x) & _FCLASS_NAN;
+}
+hidden_def (__isnan)
+weak_alias (__isnan, isnan)
diff --git a/sysdeps/riscv/rvd/s_issignaling.c b/sysdeps/riscv/rvd/s_issignaling.c
new file mode 100644
index 0000000000..8853b00bae
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_issignaling.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__issignaling (double x)
+{
+ return _FCLASS (x) & _FCLASS_SNAN;
+}
+libm_hidden_def (__issignaling)
diff --git a/sysdeps/riscv/rvd/s_lrint.c b/sysdeps/riscv/rvd/s_lrint.c
new file mode 100644
index 0000000000..90b4be0184
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_lrint.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __LP64__
+
+#include <math.h>
+
+long
+__lrint (double x)
+{
+ long res;
+ asm ("fcvt.w.d %0, %1" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__lrint, lrint)
+
+#endif
diff --git a/sysdeps/riscv/rvd/s_lround.c b/sysdeps/riscv/rvd/s_lround.c
new file mode 100644
index 0000000000..617fc3dcb7
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_lround.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __LP64__
+
+#include <math.h>
+
+long
+__lround (double x)
+{
+ long res;
+ asm ("fcvt.w.d %0, %1, rmm" : "=r" (res) : "f" (x));
+ return res;
+}
+
+weak_alias (__lround, lround)
+
+#endif
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:16 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This patch implements various atomic and locking routines on RISC-V,
either via the A extension (when present) or via a Linux system call
that does a compare-and-exchange. This contains both the library
routines and the syscall wrapper.
---
sysdeps/riscv/atomic-machine.h | 132 +++++++++++++++++++++++++
sysdeps/riscv/nptl/bits/pthreadtypes-arch.h | 98 ++++++++++++++++++
sysdeps/riscv/nptl/bits/semaphore.h | 33 +++++++
sysdeps/riscv/nptl/libc-lowlevellock.c | 8 ++
sysdeps/riscv/nptl/pthread_spin_lock.c | 43 ++++++++
sysdeps/riscv/nptl/pthread_spin_trylock.c | 43 ++++++++
sysdeps/unix/sysv/linux/riscv/atomic-machine.h | 53 ++++++++++
7 files changed, 410 insertions(+)
create mode 100644 sysdeps/riscv/atomic-machine.h
create mode 100644 sysdeps/riscv/nptl/bits/pthreadtypes-arch.h
create mode 100644 sysdeps/riscv/nptl/bits/semaphore.h
create mode 100644 sysdeps/riscv/nptl/libc-lowlevellock.c
create mode 100644 sysdeps/riscv/nptl/pthread_spin_lock.c
create mode 100644 sysdeps/riscv/nptl/pthread_spin_trylock.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/atomic-machine.h

diff --git a/sysdeps/riscv/atomic-machine.h b/sysdeps/riscv/atomic-machine.h
new file mode 100644
index 0000000000..c88dc1ce33
--- /dev/null
+++ b/sysdeps/riscv/atomic-machine.h
@@ -0,0 +1,132 @@
+/* Low-level functions for atomic operations. RISC-V version.
+ Copyright (C) 2011-2016 Free Software Foundation, Inc.
+
+ Contributed by Andrew Waterman (and...@sifive.com).
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _RISCV_BITS_ATOMIC_H
+#define _RISCV_BITS_ATOMIC_H 1
+
+#include <inttypes.h>
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+#define atomic_full_barrier() __sync_synchronize()
+
+#ifdef __riscv_atomic
+
+#define __HAVE_64B_ATOMICS (__riscv_xlen >= 64)
+#define USE_ATOMIC_COMPILER_BUILTINS 1
+
+/* MIPS uses swap on machines that have it, and uses CAS on machines that
+ * don't. This, we use amoswap when the A extension is enabled, and fall back
+ * to the atomic system call when the A extension is disabled. */
+#ifdef __riscv_atomic
+# define ATOMIC_EXCHANGE_USES_CAS 0
+#else
+# define ATOMIC_EXCHANGE_USES_CAS 1
+#endif
+
+#define asm_amo(which, ordering, mem, value) ({ \
+ typeof(*mem) __tmp; \
+ if (sizeof(__tmp) == 4) \
+ asm volatile (which ".w" ordering "\t%0, %z2, %1" \
+ : "=r"(__tmp), "+A"(*(mem)) \
+ : "rJ"(value)); \
+ else if (sizeof(__tmp) == 8) \
+ asm volatile (which ".d" ordering "\t%0, %z2, %1" \
+ : "=r"(__tmp), "+A"(*(mem)) \
+ : "rJ"(value)); \
+ else \
+ abort(); \
+ __tmp; })
+
+/* Atomic compare and exchange. */
+
+#define atomic_cas(ordering, mem, newval, oldval) ({ \
+ typeof(*mem) __tmp; \
+ int __tmp2; \
+ if (sizeof(__tmp) == 4) \
+ asm volatile ("1: lr.w" ordering "\t%0, %2\n" \
+ "bne\t%0, %z4, 1f\n" \
+ "sc.w" ordering "\t%1, %z3, %2\n" \
+ "bnez\t%1, 1b\n" \
+ "1:" \
+ : "=&r"(__tmp), "=&r"(__tmp2), "+A"(*(mem)) \
+ : "rJ"(newval), "rJ"(oldval)); \
+ else if (sizeof(__tmp) == 8) \
+ asm volatile ("1: lr.d" ordering "\t%0, %2\n" \
+ "bne\t%0, %z4, 1f\n" \
+ "sc.d" ordering "\t%1, %z3, %2\n" \
+ "bnez\t%1, 1b\n" \
+ "1:" \
+ : "=&r"(__tmp), "=&r"(__tmp2), "+A"(*(mem)) \
+ : "rJ"(newval), "rJ"(oldval)); \
+ else \
+ abort(); \
+ __tmp; })
+
+#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
+ atomic_cas(".aq", mem, newval, oldval)
+
+#define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
+ atomic_cas(".rl", mem, newval, oldval)
+
+/* Atomic exchange (without compare). */
+
+#define atomic_exchange_acq(mem, value) asm_amo("amoswap", ".aq", mem, value)
+#define atomic_exchange_rel(mem, value) asm_amo("amoswap", ".rl", mem, value)
+
+
+/* Atomically add value and return the previous (unincremented) value. */
+
+#define atomic_exchange_and_add(mem, value) asm_amo("amoadd", "", mem, value)
+
+#define atomic_max(mem, value) asm_amo("amomaxu", "", mem, value)
+#define atomic_min(mem, value) asm_amo("amominu", "", mem, value)
+
+#define atomic_bit_test_set(mem, bit) \
+ ({ typeof(*mem) __mask = (typeof(*mem))1 << (bit); \
+ asm_amo("amoor", "", mem, __mask) & __mask; })
+
+#define catomic_exchange_and_add(mem, value) \
+ atomic_exchange_and_add(mem, value)
+#define catomic_max(mem, value) atomic_max(mem, value)
+
+#else /* __riscv_atomic */
+
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
+#endif /* !__riscv_atomic */
+
+#endif /* bits/atomic.h */
diff --git a/sysdeps/riscv/nptl/bits/pthreadtypes-arch.h b/sysdeps/riscv/nptl/bits/pthreadtypes-arch.h
new file mode 100644
index 0000000000..4473b0891a
--- /dev/null
+++ b/sysdeps/riscv/nptl/bits/pthreadtypes-arch.h
@@ -0,0 +1,98 @@
+/* Machine-specific pthread type layouts. RISC-V version.
+ Copyright (C) 2011-2014, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _BITS_PTHREADTYPES_ARCH_H
+#define _BITS_PTHREADTYPES_ARCH_H 1
+
+#include <endian.h>
+
+#if __riscv_xlen == 64
+# define __SIZEOF_PTHREAD_ATTR_T 56
+# define __SIZEOF_PTHREAD_MUTEX_T 40
+# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+# define __SIZEOF_PTHREAD_COND_T 48
+# define __SIZEOF_PTHREAD_CONDATTR_T 4
+# define __SIZEOF_PTHREAD_RWLOCK_T 56
+# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+# define __SIZEOF_PTHREAD_BARRIER_T 32
+# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+#else
+# define __SIZEOF_PTHREAD_ATTR_T 36
+# define __SIZEOF_PTHREAD_MUTEX_T 24
+# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+# define __SIZEOF_PTHREAD_COND_T 48
+# define __SIZEOF_PTHREAD_CONDATTR_T 4
+# define __SIZEOF_PTHREAD_RWLOCK_T 32
+# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+# define __SIZEOF_PTHREAD_BARRIER_T 20
+# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+#endif
+
+#define __PTHREAD_COMPAT_PADDING_MID
+#define __PTHREAD_COMPAT_PADDING_END
+#define __PTHREAD_MUTEX_LOCK_ELISION 0
+
+#define __LOCK_ALIGNMENT
+#define __ONCE_ALIGNMENT
+
+struct __pthread_rwlock_arch_t
+{
+# if __riscv_xlen == 64
+ unsigned int __readers;
+ unsigned int __writers;
+ unsigned int __wrphase_futex;
+ unsigned int __writers_futex;
+ int __cur_writer;
+ int __shared;
+ int __pad3;
+ int __pad4;
+ unsigned long int __pad1;
+ unsigned long int __pad2;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned int __flags;
+# else
+ unsigned int __readers;
+ unsigned int __writers;
+ unsigned int __wrphase_futex;
+ unsigned int __writers_futex;
+ int __cur_writer;
+ int __pad3;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char __pad1;
+ unsigned char __pad2;
+ unsigned char __shared;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned char __flags;
+#else
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned char __flags;
+ unsigned char __shared;
+ unsigned char __pad1;
+ unsigned char __pad2;
+#endif
+ int __writer;
+# endif
+};
+
+#define __PTHREAD_RWLOCK_ELISION_EXTRA 0
+
+#endif /* bits/pthreadtypes.h */
diff --git a/sysdeps/riscv/nptl/bits/semaphore.h b/sysdeps/riscv/nptl/bits/semaphore.h
new file mode 100644
index 0000000000..003c9c2bcc
--- /dev/null
+++ b/sysdeps/riscv/nptl/bits/semaphore.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2002, 2005, 2007, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+#define __SIZEOF_SEM_T (4 * __SIZEOF_POINTER__)
+
+/* Value returned if `sem_open' failed. */
+#define SEM_FAILED ((sem_t *) 0)
+
+
+typedef union
+{
+ char __size[__SIZEOF_SEM_T];
+ long int __align;
+} sem_t;
diff --git a/sysdeps/riscv/nptl/libc-lowlevellock.c b/sysdeps/riscv/nptl/libc-lowlevellock.c
new file mode 100644
index 0000000000..0ecd41e630
--- /dev/null
+++ b/sysdeps/riscv/nptl/libc-lowlevellock.c
@@ -0,0 +1,8 @@
+/* This kludge works around a libpthread static linking problem:
+ https://sourceware.org/bugzilla/show_bug.cgi?id=15648 */
+
+#ifndef SHARED
+# define __lll_lock_wait_private weak_function __lll_lock_wait_private
+#endif
+
+#include <lowlevellock.c>
diff --git a/sysdeps/riscv/nptl/pthread_spin_lock.c b/sysdeps/riscv/nptl/pthread_spin_lock.c
new file mode 100644
index 0000000000..dd5ffae97f
--- /dev/null
+++ b/sysdeps/riscv/nptl/pthread_spin_lock.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifdef __riscv_atomic
+
+#include <errno.h>
+
+int pthread_spin_lock(pthread_spinlock_t* lock)
+{
+ int tmp1, tmp2;
+
+ asm volatile ("\n\
+ 1:lw %0, 0(%2)\n\
+ li %1, %3\n\
+ bnez %0, 1b\n\
+ amoswap.w.aq %0, %1, 0(%2)\n\
+ bnez %0, 1b"
+ : "=&r"(tmp1), "=&r"(tmp2) : "r"(lock), "i"(EBUSY)
+ );
+
+ return tmp1;
+}
+
+#else /* __riscv_atomic */
+
+#include <sysdeps/../nptl/pthread_spin_lock.c>
+
+#endif /* !__riscv_atomic */
diff --git a/sysdeps/riscv/nptl/pthread_spin_trylock.c b/sysdeps/riscv/nptl/pthread_spin_trylock.c
new file mode 100644
index 0000000000..9bd5d80fd6
--- /dev/null
+++ b/sysdeps/riscv/nptl/pthread_spin_trylock.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifdef __riscv_atomic
+
+#include <errno.h>
+
+int pthread_spin_trylock(pthread_spinlock_t* lock)
+{
+ int tmp1, tmp2;
+
+ asm volatile ("\n\
+ lw %0, 0(%2)\n\
+ li %1, %3\n\
+ bnez %0, 1f\n\
+ amoswap.w.aq %0, %1, 0(%2)\n\
+ 1:"
+ : "=&r"(tmp1), "=&r"(tmp2) : "r"(lock), "i"(EBUSY)
+ );
+
+ return tmp1;
+}
+
+#else /* __riscv_atomic */
+
+#include <sysdeps/../nptl/pthread_spin_trylock.c>
+
+#endif /* !__riscv_atomic */
diff --git a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
new file mode 100644
index 0000000000..5ce6f8da40
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
@@ -0,0 +1,53 @@
+/* Low-level functions for atomic operations. RISC-V version.
+ Copyright (C) 2014-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINUX_RISCV_BITS_ATOMIC_H
+#define _LINUX_RISCV_BITS_ATOMIC_H 1
+
+#include_next <atomic-machine.h>
+
+#ifndef __riscv_atomic
+
+#include <sys/syscall.h>
+#include <sysdep.h>
+
+#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
+ (abort (), (__typeof (*mem)) 0)
+
+#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
+ (abort (), (__typeof (*mem)) 0)
+
+/* The only basic operation needed is compare and exchange. */
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ (__typeof (*mem)) INTERNAL_SYSCALL (sysriscv, __err, 4, \
+ RISCV_ATOMIC_CMPXCHG, mem, oldval, newval); \
+ })
+
+#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ (__typeof (*mem)) INTERNAL_SYSCALL (sysriscv, __err, 4, \
+ RISCV_ATOMIC_CMPXCHG64, mem, oldval, newval); \
+ })
+
+#endif /* __riscv_atomic */
+
+#endif /* bits/atomic.h */
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:17 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
Contains the Linux system call interface, as well as the definitions of
a handful of system calls.
---
sysdeps/riscv/nptl/nptl-sysdep.S | 2 +
sysdeps/unix/sysv/linux/riscv/arch-fork.h | 1 +
sysdeps/unix/sysv/linux/riscv/clone.S | 86 ++++++++
sysdeps/unix/sysv/linux/riscv/getmsg.c | 1 +
sysdeps/unix/sysv/linux/riscv/kernel-features.h | 22 ++
sysdeps/unix/sysv/linux/riscv/profil-counter.h | 2 +
sysdeps/unix/sysv/linux/riscv/pt-vfork.S | 0
sysdeps/unix/sysv/linux/riscv/putmsg.c | 1 +
sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c | 1 +
sysdeps/unix/sysv/linux/riscv/rv32/readahead.c | 1 +
sysdeps/unix/sysv/linux/riscv/syscall.c | 38 ++++
sysdeps/unix/sysv/linux/riscv/sysdep.S | 51 +++++
sysdeps/unix/sysv/linux/riscv/sysdep.h | 262 ++++++++++++++++++++++++
sysdeps/unix/sysv/linux/riscv/vfork.S | 44 ++++
14 files changed, 512 insertions(+)
create mode 100644 sysdeps/riscv/nptl/nptl-sysdep.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/arch-fork.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/clone.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/getmsg.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/kernel-features.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/profil-counter.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/pt-vfork.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/putmsg.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/syscall.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/vfork.S

diff --git a/sysdeps/riscv/nptl/nptl-sysdep.S b/sysdeps/riscv/nptl/nptl-sysdep.S
new file mode 100644
index 0000000000..3f5c2a364a
--- /dev/null
+++ b/sysdeps/riscv/nptl/nptl-sysdep.S
@@ -0,0 +1,2 @@
+/* Pull in __syscall_error. */
+#include <sysdep.S>
diff --git a/sysdeps/unix/sysv/linux/riscv/arch-fork.h b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
new file mode 100644
index 0000000000..5f945378ee
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/arch-fork.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S
new file mode 100644
index 0000000000..716ab877f5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/clone.S
@@ -0,0 +1,86 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ralf Baechle <ra...@linux-mips.org>, 1996.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* clone() is even more special than fork() as it mucks with stacks
+ and invokes a function in the right context after its all over. */
+
+#include <sys/asm.h>
+#include <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+#include <tls.h>
+#include "tcb-offsets.h"
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ void *parent_tidptr, void *tls, void *child_tidptr) */
+
+ .text
+LEAF(__clone)
+
+ /* Sanity check arguments. */
+ beqz a0,L(invalid) /* No NULL function pointers. */
+ beqz a1,L(invalid) /* No NULL stack pointers. */
+
+ addi a1,a1,-16 /* Reserve argument save space. */
+ REG_S a0,0(a1) /* Save function pointer. */
+ REG_S a3,SZREG(a1) /* Save argument pointer. */
+
+ /* The syscall expects the args to be in different slots. */
+ mv a0,a2
+ mv a2,a4
+ mv a3,a5
+ mv a4,a6
+
+ /* Do the system call */
+ li a7,__NR_clone
+ scall
+
+ bltz a0,L(error)
+ beqz a0,L(thread_start)
+
+ /* Successful return from the parent */
+ ret
+
+L(invalid):
+ li a0, -EINVAL
+ /* Something bad happened -- no child created */
+L(error):
+ j __syscall_error
+ END(__clone)
+
+/* Load up the arguments to the function. Put this block of code in
+ its own function so that we can terminate the stack trace with our
+ debug info. */
+
+ENTRY(__thread_start)
+L(thread_start):
+ /* Restore the arg for user's function. */
+ REG_L a1,0(sp) /* Function pointer. */
+ REG_L a0,SZREG(sp) /* Argument pointer. */
+
+ /* Call the user's function. */
+ jalr a1
+
+ /* Call _exit with the function's return value. */
+ j _exit
+
+ END(__thread_start)
+
+libc_hidden_def(__clone)
+weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/riscv/getmsg.c b/sysdeps/unix/sysv/linux/riscv/getmsg.c
new file mode 100644
index 0000000000..3a1fa08525
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/getmsg.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/getmsg.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/kernel-features.h b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
new file mode 100644
index 0000000000..2db504b53b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
@@ -0,0 +1,22 @@
+/* Copyright (C) 2014, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define __ASSUME_ACCEPT4_SYSCALL 1
+#define __ASSUME_RECVMMSG_SYSCALL 1
+#define __ASSUME_SENDMMSG_SYSCALL 1
+
+#include_next <kernel-features.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/profil-counter.h b/sysdeps/unix/sysv/linux/riscv/profil-counter.h
new file mode 100644
index 0000000000..8a6a0bcf3d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/profil-counter.h
@@ -0,0 +1,2 @@
+/* We can use the ix86 version. */
+#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/sysdeps/unix/sysv/linux/riscv/putmsg.c b/sysdeps/unix/sysv/linux/riscv/putmsg.c
new file mode 100644
index 0000000000..ebc1680ca7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/putmsg.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/putmsg.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c b/sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
new file mode 100644
index 0000000000..a88f5a784a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/lockf64.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
new file mode 100644
index 0000000000..80170c3e8a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/arm/readahead.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/syscall.c b/sysdeps/unix/sysv/linux/riscv/syscall.c
new file mode 100644
index 0000000000..f37a8b58aa
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/syscall.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2001-2003, 2005, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+long
+syscall (long syscall_number, long arg1, long arg2, long arg3, long arg4,
+ long arg5, long arg6, long arg7)
+{
+ long ret;
+ INTERNAL_SYSCALL_DECL (err);
+
+ ret = INTERNAL_SYSCALL_NCS (syscall_number, err, 7, arg1, arg2, arg3, arg4,
+ arg5, arg6, arg7);
+
+ if (INTERNAL_SYSCALL_ERROR_P (ret, err))
+ {
+ extern long __syscall_error (long neg_errno);
+ return __syscall_error (ret);
+ }
+
+ return ret;
+}
diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.S b/sysdeps/unix/sysv/linux/riscv/sysdep.S
new file mode 100644
index 0000000000..a32ac69088
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.S
@@ -0,0 +1,51 @@
+/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Andrew Waterman (and...@sifive.com).
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+#if IS_IN (libc)
+# define errno __libc_errno
+#endif
+
+ENTRY (__syscall_error)
+ mv t0, ra
+ /* Fall through to __syscall_set_errno. */
+END (__syscall_error)
+
+/* Non-standard calling convention: argument in a0, return address in t0,
+ and clobber only t1. */
+ENTRY (__syscall_set_errno)
+ /* We got here because a0 < 0, but only codes in the range [-4095, -1]
+ represent errors. Otherwise, just return the result normally. */
+ li t1, -4096
+ bleu a0, t1, 1f
+ neg a0, a0
+#if RTLD_PRIVATE_ERRNO
+ sw a0, rtld_errno, t1
+#elif defined(__PIC__)
+ la.tls.ie t1, errno
+ add t1, t1, tp
+ sw a0, 0(t1)
+#else
+ lui t1, %tprel_hi(errno)
+ add t1, t1, tp, %tprel_add(errno)
+ sw a0, %tprel_lo(errno)(t1)
+#endif
+ li a0, -1
+1: jr t0
+END (__syscall_set_errno)
diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h
new file mode 100644
index 0000000000..eddb0a586e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h
@@ -0,0 +1,262 @@
+/* Copyright (C) 2011-2014, 2017
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LINUX_RISCV_SYSDEP_H
+#define _LINUX_RISCV_SYSDEP_H 1
+
+#include <sysdeps/unix/sysv/linux/generic/sysdep.h>
+#include <tls.h>
+
+#ifdef __ASSEMBLER__
+
+#include <sys/asm.h>
+
+#define ENTRY(name) LEAF(name)
+
+#undef PSEUDO_END
+#define PSEUDO_END(sym) END(sym)
+
+#define PSEUDO_NOERRNO(name, syscall_name, args) \
+ .align 2; \
+ ENTRY(name) \
+ li a7, SYS_ify(syscall_name); \
+ scall
+
+#define ret_NOERRNO ret
+
+#define PSEUDO_ERRVAL(name, syscall_name, args) \
+ PSEUDO_NOERRNO(name, syscall_name, args)
+
+#define ret_ERRVAL ret
+
+#define L(label) .L ## label
+
+#define PSEUDO(name, syscall_name, args) \
+ .align 2; \
+ 99: j __syscall_error; \
+ ENTRY(name) \
+ li a7, SYS_ify(syscall_name); \
+ scall; \
+ bltz a0, 99b; \
+L(syse1):
+
+#endif /* __ASSEMBLER__ */
+
+#include <sysdeps/unix/sysdep.h>
+
+#undef SYS_ify
+#define SYS_ify(syscall_name) __NR_##syscall_name
+
+#ifndef __ASSEMBLER__
+
+/* Define a macro which expands into the inline wrapper code for a system
+ call. */
+#undef INLINE_SYSCALL
+#define INLINE_SYSCALL(name, nr, args...) \
+ ({ INTERNAL_SYSCALL_DECL(err); \
+ long result = INTERNAL_SYSCALL (name, err, nr, args); \
+ register long __a0 asm ("a0") = result; \
+ if (__a0 < 0) \
+ __asm__ volatile ("call t0, __syscall_set_errno" \
+ : "+r" (__a0) : : "t0", "t1", "t2"); \
+ __a0; })
+
+/* Set error number and return -1. Return the internal function,
+ __syscall_error, which sets errno from the negative error number
+ and returns -1. */
+#undef INLINE_SYSCALL_ERROR_RETURN_VALUE
+#define INLINE_SYSCALL_ERROR_RETURN_VALUE(resultvar) \
+ ({ extern int __syscall_error (long neg_errno); \
+ __syscall_error (-(resultvar)); })
+
+#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
+#define INTERNAL_SYSCALL_ERROR_P(val, err) ((unsigned long) (val) > -4096UL)
+
+#define INTERNAL_SYSCALL_ERRNO(val, err) (-val)
+
+#define INTERNAL_SYSCALL(name, err, nr, args...) \
+ internal_syscall##nr (SYS_ify (name), err, args)
+
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+ internal_syscall##nr (number, err, args)
+
+#define internal_syscall0(number, err, dummy...) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0"); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "=r" (__a0) \
+ : "r" (__a7) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define internal_syscall1(number, err, arg0) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0") = (long) (arg0); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define internal_syscall2(number, err, arg0, arg1) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0") = (long) (arg0); \
+ register long __a1 asm("a1") = (long) (arg1); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7), "r"(__a1) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define internal_syscall3(number, err, arg0, arg1, arg2) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0") = (long) (arg0); \
+ register long __a1 asm("a1") = (long) (arg1); \
+ register long __a2 asm("a2") = (long) (arg2); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7), "r"(__a1), "r"(__a2) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define internal_syscall4(number, err, arg0, arg1, arg2, arg3) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0") = (long) (arg0); \
+ register long __a1 asm("a1") = (long) (arg1); \
+ register long __a2 asm("a2") = (long) (arg2); \
+ register long __a3 asm("a3") = (long) (arg3); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0") = (long) (arg0); \
+ register long __a1 asm("a1") = (long) (arg1); \
+ register long __a2 asm("a2") = (long) (arg2); \
+ register long __a3 asm("a3") = (long) (arg3); \
+ register long __a4 asm("a4") = (long) (arg4); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0") = (long) (arg0); \
+ register long __a1 asm("a1") = (long) (arg1); \
+ register long __a2 asm("a2") = (long) (arg2); \
+ register long __a3 asm("a3") = (long) (arg3); \
+ register long __a4 asm("a4") = (long) (arg4); \
+ register long __a5 asm("a5") = (long) (arg5); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4), "r"(__a5) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \
+({ \
+ long _sys_result; \
+ \
+ { \
+ register long __a7 asm("a7") = number; \
+ register long __a0 asm("a0") = (long) (arg0); \
+ register long __a1 asm("a1") = (long) (arg1); \
+ register long __a2 asm("a2") = (long) (arg2); \
+ register long __a3 asm("a3") = (long) (arg3); \
+ register long __a4 asm("a4") = (long) (arg4); \
+ register long __a5 asm("a5") = (long) (arg5); \
+ register long __a6 asm("a6") = (long) (arg6); \
+ __asm__ volatile ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4), "r"(__a5), "r"(__a6) \
+ : __SYSCALL_CLOBBERS); \
+ _sys_result = __a0; \
+ } \
+ _sys_result; \
+})
+
+#define __SYSCALL_CLOBBERS "memory"
+#endif /* ! __ASSEMBLER__ */
+
+/* Pointer mangling is not supported. */
+#define PTR_MANGLE(var) (void) (var)
+#define PTR_DEMANGLE(var) (void) (var)
+
+#endif /* linux/mips/sysdep.h */
diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S
new file mode 100644
index 0000000000..ff7176a40f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/vfork.S
@@ -0,0 +1,44 @@
+/* Copyright (C) 2005, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* vfork() is just a special case of clone(). */
+
+#include <sys/asm.h>
+#include <sysdep.h>
+#define __ASSEMBLY__
+#include <linux/sched.h>
+#include <asm/signal.h>
+
+ .text
+LEAF(__libc_vfork)
+
+ li a0, (CLONE_VFORK | CLONE_VM | SIGCHLD)
+ mv a1, sp
+
+ li a7, __NR_clone
+ scall
+
+ bltz a0, 1f
+ ret
+
+1: j __syscall_error
+END(__libc_vfork)
+
+weak_alias (__libc_vfork, vfork)
+strong_alias (__libc_vfork, __vfork)
+libc_hidden_def (__vfork)
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:19 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
This contains the Linux-specific code for loading programs on RISC-V.
---
sysdeps/unix/sysv/linux/riscv/dl-static.c | 85 +++++++++++++++++++++++++++++++
sysdeps/unix/sysv/linux/riscv/ldconfig.h | 37 ++++++++++++++
sysdeps/unix/sysv/linux/riscv/ldsodefs.h | 34 +++++++++++++
3 files changed, 156 insertions(+)
create mode 100644 sysdeps/unix/sysv/linux/riscv/dl-static.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/ldconfig.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/ldsodefs.h

diff --git a/sysdeps/unix/sysv/linux/riscv/dl-static.c b/sysdeps/unix/sysv/linux/riscv/dl-static.c
new file mode 100644
index 0000000000..2a6b849c61
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/dl-static.c
@@ -0,0 +1,85 @@
+/* Variable initialization. RISC-V version
+ Copyright (C) 2001-2003, 2005, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ldsodefs.h>
+
+#ifdef SHARED
+
+void
+_dl_var_init (void *array[])
+{
+ /* It has to match "variables" below. */
+ enum
+ {
+ DL_PAGESIZE = 0
+ };
+
+ GLRO(dl_pagesize) = *((size_t *) array[DL_PAGESIZE]);
+}
+
+#else
+
+static void *variables[] =
+{
+ &GLRO(dl_pagesize)
+};
+
+static void
+_dl_unprotect_relro (struct link_map *l)
+{
+ ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
+ & ~(GLRO(dl_pagesize) - 1));
+ ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
+ & ~(GLRO(dl_pagesize) - 1));
+
+ if (start != end)
+ __mprotect ((void *) start, end - start, PROT_READ | PROT_WRITE);
+}
+
+void
+_dl_static_init (struct link_map *l)
+{
+ struct link_map *rtld_map = l;
+ struct r_scope_elem **scope;
+ const ElfW(Sym) *ref = NULL;
+ lookup_t loadbase;
+ void (*f) (void *[]);
+ size_t i;
+
+ loadbase = _dl_lookup_symbol_x ("_dl_var_init", l, &ref, l->l_local_scope,
+ NULL, 0, 1, NULL);
+
+ for (scope = l->l_local_scope; *scope != NULL; scope++)
+ for (i = 0; i < (*scope)->r_nlist; i++)
+ if ((*scope)->r_list[i] == loadbase)
+ {
+ rtld_map = (*scope)->r_list[i];
+ break;
+ }
+
+ if (ref != NULL)
+ {
+ f = (void (*) (void *[])) DL_SYMBOL_ADDRESS (loadbase, ref);
+ _dl_unprotect_relro (rtld_map);
+ f (variables);
+ _dl_protect_relro (rtld_map);
+ }
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/riscv/ldconfig.h b/sysdeps/unix/sysv/linux/riscv/ldconfig.h
new file mode 100644
index 0000000000..4a5d2fbb1c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/ldconfig.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2001, 2002, 2003, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdeps/generic/ldconfig.h>
+
+#define LD_SO_PREFIX "/lib/ld-linux-"
+#define LD_SO_SUFFIX ".so.1"
+
+#if __riscv_xlen == 64
+# define LD_SO_ABI "riscv64-lp64"
+#else
+# define LD_SO_ABI "riscv32-ilp32"
+#endif
+
+#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+ { LD_SO_PREFIX LD_SO_ABI "d" LD_SO_SUFFIX, FLAG_ELF_LIBC6 }, \
+ { LD_SO_PREFIX LD_SO_ABI "f" LD_SO_SUFFIX, FLAG_ELF_LIBC6 }, \
+ { LD_SO_PREFIX LD_SO_ABI LD_SO_SUFFIX, FLAG_ELF_LIBC6 },
+
+#define SYSDEP_KNOWN_LIBRARY_NAMES \
+ { "libc.so.6", FLAG_ELF_LIBC6 }, \
+ { "libm.so.6", FLAG_ELF_LIBC6 },
diff --git a/sysdeps/unix/sysv/linux/riscv/ldsodefs.h b/sysdeps/unix/sysv/linux/riscv/ldsodefs.h
new file mode 100644
index 0000000000..3959603975
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/ldsodefs.h
@@ -0,0 +1,34 @@
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+ RISC-V
+ Copyright (C) 2001, 2003, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LDSODEFS_H
+
+/* Get the real definitions. */
+#include_next <ldsodefs.h>
+
+/* Now define our stuff. */
+
+/* We need special support to initialize DSO loaded for statically linked
+ binaries. */
+extern void _dl_static_init (struct link_map *map);
+#undef DL_STATIC_INIT
+#define DL_STATIC_INIT(map) _dl_static_init (map)
+
+#endif /* ldsodefs.h */
--
2.13.0

Palmer Dabbelt

unread,
Jun 14, 2017, 2:33:19 PM6/14/17
to libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Palmer Dabbelt
Linux-specific code that is required for maintaining ABI compatibility.
This doesn't contain the actual system call interface, that is split out
in order to avoid having a patch that's too big.
---
sysdeps/riscv/nptl/pthreaddef.h | 32 ++++++
sysdeps/riscv/rv32/divdi3.c | 1 +
sysdeps/riscv/rv32/symbol-hacks.h | 1 +
sysdeps/unix/sysv/linux/riscv/____longjmp_chk.S | 2 +
sysdeps/unix/sysv/linux/riscv/bits/mman.h | 38 +++++++
sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h | 33 ++++++
sysdeps/unix/sysv/linux/riscv/getcontext.S | 82 +++++++++++++++
sysdeps/unix/sysv/linux/riscv/makecontext.c | 72 +++++++++++++
sysdeps/unix/sysv/linux/riscv/register-dump.h | 65 ++++++++++++
sysdeps/unix/sysv/linux/riscv/setcontext.S | 126 +++++++++++++++++++++++
sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h | 29 ++++++
sysdeps/unix/sysv/linux/riscv/swapcontext.S | 130 ++++++++++++++++++++++++
sysdeps/unix/sysv/linux/riscv/sys/procfs.h | 113 ++++++++++++++++++++
sysdeps/unix/sysv/linux/riscv/sys/ucontext.h | 67 ++++++++++++
sysdeps/unix/sysv/linux/riscv/sys/user.h | 2 +
sysdeps/unix/sysv/linux/riscv/ucontext_i.sym | 33 ++++++
16 files changed, 826 insertions(+)
create mode 100644 sysdeps/riscv/nptl/pthreaddef.h
create mode 100644 sysdeps/riscv/rv32/divdi3.c
create mode 100644 sysdeps/riscv/rv32/symbol-hacks.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/____longjmp_chk.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/bits/mman.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/getcontext.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/makecontext.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/register-dump.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/setcontext.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/swapcontext.S
create mode 100644 sysdeps/unix/sysv/linux/riscv/sys/procfs.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/sys/ucontext.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/sys/user.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/ucontext_i.sym

diff --git a/sysdeps/riscv/nptl/pthreaddef.h b/sysdeps/riscv/nptl/pthreaddef.h
new file mode 100644
index 0000000000..6df6bd4122
--- /dev/null
+++ b/sysdeps/riscv/nptl/pthreaddef.h
@@ -0,0 +1,32 @@
+/* Copyright (C) 2011-2014, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Default stack size. */
+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning. */
+#define STACK_ALIGN 16
+
+/* Minimal stack size after allocating thread descriptor and guard size. */
+#define MINIMAL_REST_STACK 2048
+
+/* Alignment requirement for TCB. */
+#define TCB_ALIGNMENT 16
+
+/* Location of current stack frame. */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/riscv/rv32/divdi3.c b/sysdeps/riscv/rv32/divdi3.c
new file mode 100644
index 0000000000..52f3a0396c
--- /dev/null
+++ b/sysdeps/riscv/rv32/divdi3.c
@@ -0,0 +1 @@
+/* libgcc.a provides optimized versions of these routines. */
diff --git a/sysdeps/riscv/rv32/symbol-hacks.h b/sysdeps/riscv/rv32/symbol-hacks.h
new file mode 100644
index 0000000000..22aad04437
--- /dev/null
+++ b/sysdeps/riscv/rv32/symbol-hacks.h
@@ -0,0 +1 @@
+#include <sysdeps/generic/symbol-hacks.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/____longjmp_chk.S b/sysdeps/unix/sysv/linux/riscv/____longjmp_chk.S
new file mode 100644
index 0000000000..e903c7e0df
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/____longjmp_chk.S
@@ -0,0 +1,2 @@
+#define __longjmp ____longjmp_chk
+#include <__longjmp.S>
diff --git a/sysdeps/unix/sysv/linux/riscv/bits/mman.h b/sysdeps/unix/sysv/linux/riscv/bits/mman.h
new file mode 100644
index 0000000000..4a85eee71e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/bits/mman.h
@@ -0,0 +1,38 @@
+/* Definitions for POSIX memory map interface. Linux/RISC-V version.
+ Copyright (C) 1997, 2000, 2003, 2004, 2005, 2006, 2009, 2011, 2017
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _SYS_MMAN_H
+# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
+#endif
+
+#ifdef __USE_MISC
+# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */
+# define MAP_DENYWRITE 0x00800 /* ETXTBSY */
+# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */
+# define MAP_LOCKED 0x02000 /* Lock the mapping. */
+# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */
+# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */
+# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */
+# define MAP_STACK 0x20000 /* Allocation is for a stack. */
+# define MAP_HUGETLB 0x40000 /* Create huge page mapping. */
+#endif
+
+/* Include generic Linux declarations. */
+#include <bits/mman-linux.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h b/sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h
new file mode 100644
index 0000000000..4ebf5afa2a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 1996, 1997, 1998, 2003, 2004, 2006, 2017 Free Software
+ Foundation, Inc. This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _BITS_SIGCONTEXT_H
+#define _BITS_SIGCONTEXT_H 1
+
+#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
+# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead."
+#endif
+
+struct sigcontext {
+ /* gregs[0] holds the program counter. */
+ unsigned long gregs[32];
+ unsigned long long fpregs[32];
+ unsigned int fsr;
+};
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/riscv/getcontext.S b/sysdeps/unix/sysv/linux/riscv/getcontext.S
new file mode 100644
index 0000000000..b2ff959950
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/getcontext.S
@@ -0,0 +1,82 @@
+/* Save current context.
+ Copyright (C) 2009, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Maciej W. Rozycki <ma...@codesourcery.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+#include "ucontext_i.h"
+
+/* int getcontext (ucontext_t *ucp) */
+
+ .text
+LEAF (__getcontext)
+ REG_S ra, MCONTEXT_PC(a0)
+ REG_S ra, ( 1 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S sp, ( 2 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s0, ( 8 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s1, ( 9 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S x0, (10 * SZREG + MCONTEXT_GREGS)(a0) /* return 0 */
+ REG_S s2, (18 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s3, (19 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s4, (20 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s5, (21 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s6, (22 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s7, (23 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s8, (24 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s9, (25 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s10,(26 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s11,(27 * SZREG + MCONTEXT_GREGS)(a0)
+
+#ifndef __riscv_float_abi_soft
+ frsr a1
+
+ FREG_S fs0, ( 8 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs1, ( 9 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs2, (18 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs3, (19 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs4, (20 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs5, (21 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs6, (22 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs7, (23 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs8, (24 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs9, (25 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs10,(26 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs11,(27 * SZFREG + MCONTEXT_FPREGS)(a0)
+
+ sw a1, MCONTEXT_FSR(a0)
+#endif /* __riscv_float_abi_soft */
+
+/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+ li a3, _NSIG8
+ add a2, a0, UCONTEXT_SIGMASK
+ mv a1, zero
+ li a0, SIG_BLOCK
+
+ li a7, SYS_ify (rt_sigprocmask)
+ scall
+ bltz a0, 99f
+
+ ret
+
+99: j __syscall_error
+
+PSEUDO_END (__getcontext)
+
+weak_alias (__getcontext, getcontext)
diff --git a/sysdeps/unix/sysv/linux/riscv/makecontext.c b/sysdeps/unix/sysv/linux/riscv/makecontext.c
new file mode 100644
index 0000000000..0b53023166
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/makecontext.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2001-2003, 2005, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+
+#include <sysdep.h>
+#include <sys/asm.h>
+#include <sys/ucontext.h>
+#include <stdarg.h>
+#include <assert.h>
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc,
+ long a0, long a1, long a2, long a3, long a4, ...)
+{
+ extern void __start_context (void) attribute_hidden;
+ long i, sp;
+
+ _Static_assert (REG_NARGS == 8, "__makecontext assumes 8 argument registers");
+
+ /* Set up the stack. */
+ sp = ((long)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) & ALMASK;
+
+ /* Set up the register context.
+ ra = s0 = 0, terminating the stack for backtracing purposes.
+ s1 = the function we must call.
+ s2 = the subsequent context to run. */
+ ucp->uc_mcontext.gregs[REG_RA] = 0;
+ ucp->uc_mcontext.gregs[REG_S0 + 0] = 0;
+ ucp->uc_mcontext.gregs[REG_S0 + 1] = (long)func;
+ ucp->uc_mcontext.gregs[REG_S0 + 2] = (long)ucp->uc_link;
+ ucp->uc_mcontext.gregs[REG_SP] = sp;
+ ucp->uc_mcontext.gregs[REG_PC] = (long)&__start_context;
+
+ /* Put args in a0-a7, then put any remaining args on the stack. */
+ ucp->uc_mcontext.gregs[REG_A0 + 0] = a0;
+ ucp->uc_mcontext.gregs[REG_A0 + 1] = a1;
+ ucp->uc_mcontext.gregs[REG_A0 + 2] = a2;
+ ucp->uc_mcontext.gregs[REG_A0 + 3] = a3;
+ ucp->uc_mcontext.gregs[REG_A0 + 4] = a4;
+
+ if (__builtin_expect (argc > 5, 0))
+ {
+ va_list vl;
+ va_start (vl, a4);
+
+ long reg_args = argc < REG_NARGS ? argc : REG_NARGS;
+ sp = (sp - (argc - reg_args) * sizeof (long)) & ALMASK;
+ for (i = 5; i < reg_args; i++)
+ ucp->uc_mcontext.gregs[REG_A0 + i] = va_arg (vl, long);
+ for (i = 0; i < argc - reg_args; i++)
+ ((long*)sp)[i] = va_arg (vl, long);
+
+ va_end (vl);
+ }
+}
+
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/unix/sysv/linux/riscv/register-dump.h b/sysdeps/unix/sysv/linux/riscv/register-dump.h
new file mode 100644
index 0000000000..7ce4edfc9e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/register-dump.h
@@ -0,0 +1,65 @@
+/* Dump registers.
+ Copyright (C) 2000, 2001, 2002, 2006, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <unistd.h>
+#include <string.h>
+#include <_itoa.h>
+
+static void
+hexvalue (unsigned long int value, char *buf, size_t len)
+{
+ char *cp = _itoa_word (value, buf + len, 16, 0);
+ while (cp > buf)
+ *--cp = '0';
+}
+
+#define REGDUMP_NREGS 32
+#define REGDUMP_PER_LINE (80 / (__WORDSIZE/4 + 4))
+
+static void
+register_dump (int fd, struct ucontext *ctx)
+{
+ int i;
+ char regvalue[__WORDSIZE/4 + 1];
+ char str[82 * ((REGDUMP_NREGS + REGDUMP_PER_LINE - 1) / REGDUMP_PER_LINE)];
+
+ static const char names[REGDUMP_NREGS][4] = {
+ "pc", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
+ "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
+ "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "sA", "sB", "t3", "t4", "t5", "t6"
+ };
+
+ str[0] = 0;
+ for (i = 0; i < REGDUMP_NREGS; i++)
+ {
+ strcat (str, names[i]);
+ strcat (str, " ");
+ hexvalue (ctx->uc_mcontext.gregs[i], regvalue, __WORDSIZE/4);
+ strcat (str, regvalue);
+
+ if ((i + 1) % REGDUMP_PER_LINE == 0)
+ strcat (str, "\n");
+ }
+
+ write (fd, str, strlen (str));
+}
+
+#define REGISTER_DUMP register_dump (fd, ctx)
diff --git a/sysdeps/unix/sysv/linux/riscv/setcontext.S b/sysdeps/unix/sysv/linux/riscv/setcontext.S
new file mode 100644
index 0000000000..2cfaae5e4b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/setcontext.S
@@ -0,0 +1,126 @@
+/* Set current context.
+ Copyright (C) 2009, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Maciej W. Rozycki <ma...@codesourcery.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+#include "ucontext_i.h"
+
+#define RESTORE_FP_REG(name, num, base) \
+ FREG_L name, ((num) * SZFREG + MCONTEXT_FPREGS)(base)
+
+#define RESTORE_FP_REG_CFI(name, num, base) \
+ RESTORE_FP_REG (name, num, base); \
+ cfi_offset (name, (num) * SZREG + MCONTEXT_GREGS)
+
+#define RESTORE_INT_REG(name, num, base) \
+ REG_L name, ((num) * SZREG + MCONTEXT_GREGS)(base)
+
+#define RESTORE_INT_REG_CFI(name, num, base) \
+ RESTORE_INT_REG (name, num, base); \
+ cfi_offset (name, (num) * SZREG + MCONTEXT_GREGS)
+
+/* int setcontext (const ucontext_t *ucp) */
+
+ .text
+LEAF (__setcontext)
+
+ mv t0, a0 /* t0 <- ucp */
+
+/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
+ li a3, _NSIG8
+ mv a2, zero
+ add a1, a0, UCONTEXT_SIGMASK
+ li a0, SIG_SETMASK
+
+ li a7, SYS_ify (rt_sigprocmask)
+ scall
+
+ bltz a0, 99f
+
+ cfi_def_cfa (t0, 0)
+
+#ifndef __riscv_float_abi_soft
+ lw t1, MCONTEXT_FSR(t0)
+
+ RESTORE_FP_REG_CFI (fs0, 8, t0)
+ RESTORE_FP_REG_CFI (fs1, 9, t0)
+ RESTORE_FP_REG_CFI (fs2, 18, t0)
+ RESTORE_FP_REG_CFI (fs3, 19, t0)
+ RESTORE_FP_REG_CFI (fs4, 20, t0)
+ RESTORE_FP_REG_CFI (fs5, 21, t0)
+ RESTORE_FP_REG_CFI (fs6, 22, t0)
+ RESTORE_FP_REG_CFI (fs7, 23, t0)
+ RESTORE_FP_REG_CFI (fs8, 24, t0)
+ RESTORE_FP_REG_CFI (fs9, 25, t0)
+ RESTORE_FP_REG_CFI (fs10, 26, t0)
+ RESTORE_FP_REG_CFI (fs11, 27, t0)
+
+ fssr t1
+#endif /* __riscv_float_abi_soft */
+
+ /* Note the contents of argument registers will be random
+ unless makecontext() has been called. */
+ REG_L t1, MCONTEXT_PC(t0)
+ RESTORE_INT_REG_CFI (ra, 1, t0)
+ RESTORE_INT_REG (sp, 2, t0)
+ RESTORE_INT_REG_CFI (s0, 8, t0)
+ RESTORE_INT_REG_CFI (s1, 9, t0)
+ RESTORE_INT_REG (a0, 10, t0)
+ RESTORE_INT_REG (a1, 11, t0)
+ RESTORE_INT_REG (a2, 12, t0)
+ RESTORE_INT_REG (a3, 13, t0)
+ RESTORE_INT_REG (a4, 14, t0)
+ RESTORE_INT_REG (a5, 15, t0)
+ RESTORE_INT_REG (a6, 16, t0)
+ RESTORE_INT_REG (a7, 17, t0)
+ RESTORE_INT_REG_CFI (s2, 18, t0)
+ RESTORE_INT_REG_CFI (s3, 19, t0)
+ RESTORE_INT_REG_CFI (s4, 20, t0)
+ RESTORE_INT_REG_CFI (s5, 21, t0)
+ RESTORE_INT_REG_CFI (s6, 22, t0)
+ RESTORE_INT_REG_CFI (s7, 23, t0)
+ RESTORE_INT_REG_CFI (s8, 24, t0)
+ RESTORE_INT_REG_CFI (s9, 25, t0)
+ RESTORE_INT_REG_CFI (s10, 26, t0)
+ RESTORE_INT_REG_CFI (s11, 27, t0)
+
+ jr t1
+
+99: j __syscall_error
+
+PSEUDO_END (__setcontext)
+weak_alias (__setcontext, setcontext)
+
+LEAF (__start_context)
+
+ /* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */
+ cfi_register (ra, s0)
+
+ /* Call the function passed to makecontext. */
+ jalr s1
+
+ /* Invoke subsequent context if present, else exit(0). */
+ mv a0, s2
+ beqz s2, 1f
+ jal __setcontext
+1: j exit
+
+PSEUDO_END (__start_context)
diff --git a/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h b/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h
new file mode 100644
index 0000000000..ae4069b293
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 2000, 2001, 2003, 2004, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <a...@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sys/ucontext.h>
+
+#define SIGCONTEXT siginfo_t *_si, struct ucontext *
+#define SIGCONTEXT_EXTRA_ARGS _si,
+#define GET_PC(ctx) ((void *) ctx->uc_mcontext.gregs[REG_PC])
+#define GET_FRAME(ctx) ((void *) ctx->uc_mcontext.gregs[REG_S0])
+#define GET_STACK(ctx) ((void *) ctx->uc_mcontext.gregs[REG_SP])
+
+#define CALL_SIGHANDLER(handler, signo, ctx) \
+ (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
diff --git a/sysdeps/unix/sysv/linux/riscv/swapcontext.S b/sysdeps/unix/sysv/linux/riscv/swapcontext.S
new file mode 100644
index 0000000000..5b2508c25b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/swapcontext.S
@@ -0,0 +1,130 @@
+/* Save and set current context.
+ Copyright (C) 2009, 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Maciej W. Rozycki <ma...@codesourcery.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+#include "ucontext_i.h"
+
+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
+
+LEAF (__swapcontext)
+ mv t0, a1 /* t0 <- ucp */
+
+ REG_S ra, MCONTEXT_PC(a0)
+ REG_S ra, ( 1 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S sp, ( 2 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s0, ( 8 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s1, ( 9 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S x0, (10 * SZREG + MCONTEXT_GREGS)(a0) /* return 0 */
+ REG_S s2, (18 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s3, (19 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s4, (20 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s5, (21 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s6, (22 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s7, (23 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s8, (24 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s9, (25 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s10,(26 * SZREG + MCONTEXT_GREGS)(a0)
+ REG_S s11,(27 * SZREG + MCONTEXT_GREGS)(a0)
+
+#ifndef __riscv_float_abi_soft
+ frsr a1
+
+ FREG_S fs0, ( 8 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs1, ( 9 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs2, (18 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs3, (19 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs4, (20 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs5, (21 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs6, (22 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs7, (23 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs8, (24 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs9, (25 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs10,(26 * SZFREG + MCONTEXT_FPREGS)(a0)
+ FREG_S fs11,(27 * SZFREG + MCONTEXT_FPREGS)(a0)
+
+ sw a1, MCONTEXT_FSR(a0)
+#endif /* __riscv_float_abi_soft */
+
+/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
+ li a3, _NSIG8
+ mv a2, zero
+ add a1, a0, UCONTEXT_SIGMASK
+ li a0, SIG_SETMASK
+
+ li a7, SYS_ify (rt_sigprocmask)
+ scall
+
+ bltz a0, 99f
+
+#ifndef __riscv_float_abi_soft
+ lw t1, MCONTEXT_FSR(t0)
+
+ FREG_L fs0, ( 8 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs1, ( 9 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs2, (18 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs3, (19 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs4, (20 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs5, (21 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs6, (22 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs7, (23 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs8, (24 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs9, (25 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs10,(26 * SZFREG + MCONTEXT_FPREGS)(t0)
+ FREG_L fs11,(27 * SZFREG + MCONTEXT_FPREGS)(t0)
+
+ fssr t1
+#endif /* __riscv_float_abi_soft */
+
+ /* Note the contents of argument registers will be random
+ unless makecontext() has been called. */
+ REG_L t1, MCONTEXT_PC(t0)
+ REG_L ra, ( 1 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L sp, ( 2 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s0, ( 8 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s1, ( 9 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a0, (10 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a1, (11 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a2, (12 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a3, (13 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a4, (14 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a5, (15 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a6, (16 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L a7, (17 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s2, (18 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s3, (19 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s4, (20 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s5, (21 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s6, (22 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s7, (23 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s8, (24 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s9, (25 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s10,(26 * SZREG + MCONTEXT_GREGS)(t0)
+ REG_L s11,(27 * SZREG + MCONTEXT_GREGS)(t0)
+
+ jr t1
+
+
+99: j __syscall_error
+
+PSEUDO_END (__swapcontext)
+
+weak_alias (__swapcontext, swapcontext)
diff --git a/sysdeps/unix/sysv/linux/riscv/sys/procfs.h b/sysdeps/unix/sysv/linux/riscv/sys/procfs.h
new file mode 100644
index 0000000000..3ba1f07d7e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sys/procfs.h
@@ -0,0 +1,113 @@
+/* Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2017
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _SYS_PROCFS_H
+#define _SYS_PROCFS_H 1
+
+/* This is somehow modelled after the file of the same name on SysVr4
+ systems. It provides a definition of the core file format for ELF
+ used on Linux. */
+
+#include <features.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/ucontext.h>
+
+/* ELF register definitions */
+#define ELF_NGREG NGREG
+#define ELF_NFPREG NFPREG
+
+typedef greg_t elf_greg_t;
+typedef gregset_t elf_gregset_t;
+typedef fpreg_t elf_fpreg_t;
+typedef fpregset_t elf_fpregset_t;
+
+__BEGIN_DECLS
+
+struct elf_siginfo
+ {
+ int si_signo; /* Signal number. */
+ int si_code; /* Extra code. */
+ int si_errno; /* Errno. */
+ };
+
+
+/* Definitions to generate Intel SVR4-like core files. These mostly
+ have the same names as the SVR4 types with "elf_" tacked on the
+ front to prevent clashes with linux definitions, and the typedef
+ forms have been avoided. This is mostly like the SVR4 structure,
+ but more Linuxy, with things that Linux does not support and which
+ gdb doesn't really use excluded. Fields present but not used are
+ marked with "XXX". */
+struct elf_prstatus
+ {
+ struct elf_siginfo pr_info; /* Info associated with signal. */
+ short int pr_cursig; /* Current signal. */
+ unsigned long int pr_sigpend; /* Set of pending signals. */
+ unsigned long int pr_sighold; /* Set of held signals. */
+ __pid_t pr_pid;
+ __pid_t pr_ppid;
+ __pid_t pr_pgrp;
+ __pid_t pr_sid;
+ struct timeval pr_utime; /* User time. */
+ struct timeval pr_stime; /* System time. */
+ struct timeval pr_cutime; /* Cumulative user time. */
+ struct timeval pr_cstime; /* Cumulative system time. */
+ elf_gregset_t pr_reg; /* GP registers. */
+ int pr_fpvalid; /* True if math copro being used. */
+ };
+
+
+#define ELF_PRARGSZ (80) /* Number of chars for args */
+
+struct elf_prpsinfo
+ {
+ char pr_state; /* Numeric process state. */
+ char pr_sname; /* Char for pr_state. */
+ char pr_zomb; /* Zombie. */
+ char pr_nice; /* Nice val. */
+ unsigned long int pr_flag; /* Flags. */
+ long pr_uid;
+ long pr_gid;
+ int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* Filename of executable. */
+ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
+ };
+
+
+/* Addresses. */
+typedef void *psaddr_t;
+
+/* Register sets. Linux has different names. */
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+
+/* We don't have any differences between processes and threads,
+ therefore habe only ine PID type. */
+typedef __pid_t lwpid_t;
+
+
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+
+__END_DECLS
+
+#endif /* sys/procfs.h */
diff --git a/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h b/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h
new file mode 100644
index 0000000000..d9cce75449
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 1997, 1998, 2000, 2003, 2004, 2006, 2009, 2017 Free Software
+ Foundation, Inc. This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Don't rely on this, the interface is currently messed up and may need to
+ be broken to be fixed. */
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H 1
+
+#include <features.h>
+#include <signal.h>
+
+/* We need the signal context definitions even if they are not used
+ included in <signal.h>. */
+#include <bits/sigcontext.h>
+
+/* Type for general register. Even in o32 we assume 64-bit registers,
+ like the kernel. */
+__extension__ typedef unsigned long long int greg_t;
+typedef double fpreg_t;
+
+/* Number of general registers. */
+#define NGREG 32
+#define NFPREG 32
+
+#define REG_PC 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_TP 4
+#define REG_S0 8
+#define REG_A0 10
+#define REG_NARGS 8
+
+/* Container for all general registers. */
+typedef greg_t gregset_t[NGREG];
+
+/* Container for all FPU registers. */
+typedef fpreg_t fpregset_t[NFPREG];
+
+/* Context to describe whole processor state. */
+typedef struct sigcontext mcontext_t;
+
+/* Userlevel context. */
+typedef struct ucontext
+ {
+ unsigned long int uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ __sigset_t uc_sigmask;
+ } ucontext_t;
+
+#endif /* sys/ucontext.h */
diff --git a/sysdeps/unix/sysv/linux/riscv/sys/user.h b/sysdeps/unix/sysv/linux/riscv/sys/user.h
new file mode 100644
index 0000000000..faf307936b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sys/user.h
@@ -0,0 +1,2 @@
+/* x86 puts "struct user_regs_struct" in here, this is just a shim. */
+#include <asm/ptrace.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/ucontext_i.sym b/sysdeps/unix/sysv/linux/riscv/ucontext_i.sym
new file mode 100644
index 0000000000..67f50d4a5b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/ucontext_i.sym
@@ -0,0 +1,33 @@
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+-- Constants used by the rt_sigprocmask call.
+
+SIG_BLOCK
+SIG_SETMASK
+
+_NSIG8 (_NSIG / 8)
+
+-- Offsets of the fields in the ucontext_t structure.
+#define ucontext(member) offsetof (ucontext_t, member)
+#define stack(member) ucontext (uc_stack.member)
+#define mcontext(member) ucontext (uc_mcontext.member)
+
+UCONTEXT_FLAGS ucontext (uc_flags)
+UCONTEXT_LINK ucontext (uc_link)
+UCONTEXT_STACK ucontext (uc_stack)
+UCONTEXT_MCONTEXT ucontext (uc_mcontext)
+UCONTEXT_SIGMASK ucontext (uc_sigmask)
+
+STACK_SP stack (ss_sp)
+STACK_SIZE stack (ss_size)
+STACK_FLAGS stack (ss_flags)
+
+MCONTEXT_GREGS mcontext (gregs)
+MCONTEXT_FPREGS mcontext (fpregs)
+MCONTEXT_PC mcontext (gregs)
+MCONTEXT_FSR mcontext (fsr)
+
+UCONTEXT_SIZE sizeof (ucontext_t)
--
2.13.0

Florian Weimer

unread,
Jun 14, 2017, 3:56:48 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Palmer Dabbelt <pal...@dabbelt.com> writes:

> +++ b/sysdeps/riscv/nptl/tls.h
> @@ -0,0 +1,149 @@

> +/* Signal that TLS support is available. */
> +#define USE_TLS 1

USE_TLS has been eliminated in 2006, and I don't think there aren't any
traces left in current master.

Florian

Florian Weimer

unread,
Jun 14, 2017, 4:02:44 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Palmer Dabbelt <pal...@dabbelt.com> writes:

> This port targets Version 2.2 of the RISC-V User ISA, and supports
> both the RV32I and RV64I base ISAs as well as the M, A, F, D, and C
> extensions as well as our Linux port which is based on the 1.10
> supervisor specification.

I would recommend to delay the addition of the 32-bit port, so that you
can start with a 64-bit time_t.

Florian

Joseph Myers

unread,
Jun 14, 2017, 4:14:33 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
General observations, to be addressed globally for the patch series:

* All new files should have a descriptive comment on their first line,
before the copyright notice.

* All copyright notices should use a single range of years, <year>-2017,
assuming the first year is no earlier than 1990.

* No "Contributed by" notices in any new files.

* All license notices should have a URL, not an old FSF postal address.

* Please include changes to build-many-glibcs.py to make it build glibc
for all the supported ABI variants (I think from this patch series there
are six different mutually incompatible ABI variants supported?). Make
sure that, if you use your patched Linux kernel sources, all six variants,
as built with build-many-glibcs.py, both build cleanly and produce clean
results for the compilation parts of the glibc testsuite, with both GCC 7
and current GCC trunk. (For variations that are instruction set variants
rather than ABI variants, it's at your discretion whether it's useful to
build glibc for such variants as well; that depends on whether doing so
covers significant extra code in glibc that would not otherwise be built.)

* Also include details of the full testsuite results, including execution
tests (which build-many-glibcs.py can't run), for all ABI variants again,
in the next submission of the port.

--
Joseph S. Myers
jos...@codesourcery.com

Palmer Dabbelt

unread,
Jun 14, 2017, 4:15:26 PM6/14/17
to fwe...@redhat.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Our port has been around for a while, but I don't think it's been around since
2006 so I'm not sure where that came from. The only other reference was in
sysdeps/riscv/libc-tls.c, which I've made unconditional.

https://github.com/riscv/riscv-glibc/commit/4482ec3dbdfb802250b5c221781166fcf8d8f9c2

I'll submit it as part of a v2 patch set.

Palmer Dabbelt

unread,
Jun 14, 2017, 4:15:27 PM6/14/17
to fwe...@redhat.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Do you have an idea of when there will be a 64-bit time_t clean release? I'd
be OK holding off on the 32-bit port for a bit, as we don't expect RV32I-based
Linux-compatible systems to be popular.

One sticking point is that the RV32I and RV64I base ISAs are very similar, and
as such share a lot of code. I'd prefer to avoid removing the rv32 code just
to add it back in later, as that will be a big headache.

Would it be sufficient to just disallow RV32I in our preconfigure with a patch
like this, and then turn RV32I back on when we can support a 64-bit time_t
clean ABI?

diff --git a/sysdeps/riscv/preconfigure b/sysdeps/riscv/preconfigure
index 43e2a4fac0..a15e563a31 100644
--- a/sysdeps/riscv/preconfigure
+++ b/sysdeps/riscv/preconfigure
@@ -3,7 +3,11 @@ flen=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __riscv_fl
float_abi=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __riscv_float_abi_\([^ ]*\) .*/\1/p'`

case "$xlen" in
-32 | 64)
+32)
+ echo "rv32i is not supported, we're waiting for a 64-bit time_t clean ABI" >&2
+ exit 1
+ ;;
+64)
;;
*)

Joseph Myers

unread,
Jun 14, 2017, 4:29:29 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> diff --git a/sysdeps/riscv/Implies b/sysdeps/riscv/Implies
> new file mode 100644
> index 0000000000..15b9e02448
> --- /dev/null
> +++ b/sysdeps/riscv/Implies
> @@ -0,0 +1,6 @@
> +init_array
> +
> +ieee754/ldbl-128
> +ieee754/dbl-64
> +ieee754/flt-32
> +riscv/soft-fp

You should never need to have <arch>/Implies referencing <arch>/<subdir>;
in such a case, remove the unnecessary soft-fp directory level and put
sfp-machine.h directly in <arch>. See
<https://sourceware.org/ml/libc-alpha/2014-10/msg00369.html>.
I think this at least needs some explanatory comment. It feels very
fragile to require lots of architecture-independent files to be built with
an architecture-specific option - it's the sort of thing where people
making architecture-independent changes could easily break the build
accidentally without realising that their change requires the option to be
added for a new file. So if you can find a way to avoid needing such an
architecture-specific list of files, that would be a good idea.

> diff --git a/sysdeps/riscv/Versions b/sysdeps/riscv/Versions
> new file mode 100644
> index 0000000000..5a0c2d23f8
> --- /dev/null
> +++ b/sysdeps/riscv/Versions
> @@ -0,0 +1,5 @@
> +libc {
> + GLIBC_2.14 {
> + __memcpy_g;
> + }
> +}

No, the minimum version should be 2.26, and you shouldn't need any such
special string variants (given that we've killed bits/string2.h, are about
to kill bits/string.h, and such exports as there are from old string
function inlines are or should soon be compat symbols).

> diff --git a/sysdeps/riscv/configure b/sysdeps/riscv/configure
> new file mode 100644
> index 0000000000..9f790ec527
> --- /dev/null
> +++ b/sysdeps/riscv/configure
> @@ -0,0 +1,86 @@
> +
> +# as_fn_set_status STATUS
> +# -----------------------
> +# Set $? to STATUS, without forking.
> +as_fn_set_status ()
> +{
> + return $1
> +} # as_fn_set_status

Please make sure this file is regenerated. Any sysdeps configure script
generated with current aclocal.m4 should not contain such functions,
assuming the GLIBC_PROVIDES in aclocal.m4 is correct.

> diff --git a/sysdeps/riscv/configure.in b/sysdeps/riscv/configure.in
> new file mode 100644
> index 0000000000..34f62d4b4b
> --- /dev/null
> +++ b/sysdeps/riscv/configure.in

We use configure.ac naming now, not configure.in.

Since you have multiple ABI variants, you should be setting default-abi
here via LIBC_CONFIG_VAR. Then sysdeps/unix/sysv/linux/riscv/Makefile
should set abi-variants and appropriate options for each ABI variant (see
other such Makefiles for examples) - this is used in building
bits/syscall.h.

> diff --git a/sysdeps/unix/sysv/linux/riscv/configure.in b/sysdeps/unix/sysv/linux/riscv/configure.in
> new file mode 100644
> index 0000000000..5b48e1aed6
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/configure.in
> @@ -0,0 +1,8 @@
> +sinclude(./aclocal.m4)dnl Autoconf lossage
> +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
> +# Local configure fragment for sysdeps/unix/sysv/linux/riscv.
> +
> +if test -z "$arch_minimum_kernel"; then
> + arch_minimum_kernel=3.0.0
> + libc_cv_gcc_unwind_find_fde=no
> +fi

Should use .ac naming. No need for the 'if test -z
"$arch_minimum_kernel"; then'. No need to set
libc_cv_gcc_unwind_find_fde=no. Should set arch_minimum_kernel=10.0.0
until the kernel port is actually in Linus's tree (of course you then need
to change that locally for testing purposes).

> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/Makefile b/sysdeps/unix/sysv/linux/riscv/rv64/Makefile
> new file mode 100644
> index 0000000000..0a37c5b9b4
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/Makefile
> @@ -0,0 +1,9 @@
> +ifeq ($(subdir),socket)
> +CFLAGS-recv.c += -fexceptions
> +CFLAGS-send.c += -fexceptions
> +endif
> +
> +ifeq ($(subdir),nptl)
> +CFLAGS-recv.c += -fexceptions
> +CFLAGS-send.c += -fexceptions
> +endif

In the nptl directory this is the default and should not be needed.

> diff --git a/sysdeps/unix/sysv/linux/riscv/shlib-versions b/sysdeps/unix/sysv/linux/riscv/shlib-versions
> new file mode 100644
> index 0000000000..66214b953e
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/shlib-versions
> @@ -0,0 +1,17 @@
> +DEFAULT GLIBC_2.25

Should be GLIBC_2.26.

Joseph Myers

unread,
Jun 14, 2017, 4:33:14 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> diff --git a/sysdeps/riscv/dl-trampoline.S b/sysdeps/riscv/dl-trampoline.S
> new file mode 100644
> index 0000000000..3d4dd9fc8c
> --- /dev/null
> +++ b/sysdeps/riscv/dl-trampoline.S
> @@ -0,0 +1,44 @@

Missing copyright / license notices, on a file big enough to need them.

> diff --git a/sysdeps/riscv/sys/asm.h b/sysdeps/riscv/sys/asm.h
> new file mode 100644
> index 0000000000..bd31c72bd3
> --- /dev/null
> +++ b/sysdeps/riscv/sys/asm.h
> @@ -0,0 +1,79 @@
> +/* copyright (c) 1997, 1998, 2002, 2003-2005, 2017

Uppercase Copyright (C), everywhere (not checked if this issue appears
elsewhere).

Palmer Dabbelt

unread,
Jun 14, 2017, 4:33:52 PM6/14/17
to jos...@codesourcery.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017 13:14:22 PDT (-0700), jos...@codesourcery.com wrote:
> General observations, to be addressed globally for the patch series:
>
> * All new files should have a descriptive comment on their first line,
> before the copyright notice.
>
> * All copyright notices should use a single range of years, <year>-2017,
> assuming the first year is no earlier than 1990.
>
> * No "Contributed by" notices in any new files.
>
> * All license notices should have a URL, not an old FSF postal address.

OK, I'll change those for the v2.

> * Please include changes to build-many-glibcs.py to make it build glibc
> for all the supported ABI variants (I think from this patch series there
> are six different mutually incompatible ABI variants supported?). Make
> sure that, if you use your patched Linux kernel sources, all six variants,
> as built with build-many-glibcs.py, both build cleanly and produce clean
> results for the compilation parts of the glibc testsuite, with both GCC 7
> and current GCC trunk. (For variations that are instruction set variants
> rather than ABI variants, it's at your discretion whether it's useful to
> build glibc for such variants as well; that depends on whether doing so
> covers significant extra code in glibc that would not otherwise be built.)

RISC-V is a modular ISA, and as such there are many ISA variants. The actual
number is the Cartesian product of:

* RV32I, RV64I: base ISA, which defines the length of GP registers (which we
call XLEN).
* M or no-M: multiply support or not.
* A or no-A: atomic instruction support or not.
* none, F, or D: the floating-point format supported, either none, single or
double.
* C or no-C: compressed instructions support or not.

In addition to the ISA variants, we support soft, single-hard, and double-hard
float ABIs on any ISA that includes the required floating-point registers.

In order to avoid building this huge number of ISA variants we only actively
support and test the following configurations

march=rv32imac/mabi=ilp32
march=rv32imafdc/mabi=ilp32d
march=rv64imac/mabi=lp64
march=rv64imafdc/mabi=lp64d

for glibc. I'll add those to the build script, and verify they build with the
relevant GCC versions.

> * Also include details of the full testsuite results, including execution
> tests (which build-many-glibcs.py can't run), for all ABI variants again,
> in the next submission of the port.

We've just been running the GCC test suite. I'll take a shot at running the
glibc test suite as well.

Thanks!

Florian Weimer

unread,
Jun 14, 2017, 4:35:53 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad, Arnd Bergmann
On 06/14/2017 10:15 PM, Palmer Dabbelt wrote:
> Do you have an idea of when there will be a 64-bit time_t clean release? I'd
> be OK holding off on the 32-bit port for a bit, as we don't expect RV32I-based
> Linux-compatible systems to be popular.

Sorry, no idea. I'm Cc:ing Arnd, who believe worked on the kernel side
of things.

> One sticking point is that the RV32I and RV64I base ISAs are very similar, and
> as such share a lot of code. I'd prefer to avoid removing the rv32 code just
> to add it back in later, as that will be a big headache.
>
> Would it be sufficient to just disallow RV32I in our preconfigure with a patch
> like this, and then turn RV32I back on when we can support a 64-bit time_t
> clean ABI?

I think that would be acceptable. aarch64 is basically in the same boat
today (but they want to use a 32-bit time_t for their ILP32 port).

Thanks,
Florian

Florian Weimer

unread,
Jun 14, 2017, 4:39:54 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Palmer Dabbelt <pal...@dabbelt.com> writes:

> Linux-specific code that is required for maintaining ABI compatibility.
> This doesn't contain the actual system call interface, that is split out
> in order to avoid having a patch that's too big.

You likely need to override bits/sigstack.h in one of these patches
because the generic MINSIGSTKSZ and SIGSTKSZ values are likely too
small, especially if you want to add more or broader vector registers in
the future.

PTHREAD_STACK_MIN might warrant adjustment, too.

Florian

Joseph Myers

unread,
Jun 14, 2017, 5:00:03 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> diff --git a/sysdeps/riscv/bits/fenv.h b/sysdeps/riscv/bits/fenv.h

> +enum
> + {
> + FE_INEXACT = 0x01,
> +#define FE_INEXACT FE_INEXACT
> + FE_UNDERFLOW = 0x02,
> +#define FE_UNDERFLOW FE_UNDERFLOW
> + FE_OVERFLOW = 0x04,
> +#define FE_OVERFLOW FE_OVERFLOW
> + FE_DIVBYZERO = 0x08,
> +#define FE_DIVBYZERO FE_DIVBYZERO
> + FE_INVALID = 0x10,
> +#define FE_INVALID FE_INVALID
> + };

This clearly hasn't passed the glibc testsuite. See how other bits/fenv.h
headers now define macros to make them usable in #if (which the conform/
tests test for).

> diff --git a/sysdeps/riscv/bits/mathdef.h b/sysdeps/riscv/bits/mathdef.h

You shouldn't need this file any more.

> diff --git a/sysdeps/riscv/bits/mathinline.h b/sysdeps/riscv/bits/mathinline.h

> +/* Test for negative number. Used in the signbit() macro. */
> +__MATH_INLINE int
> +__NTH (__signbitf (float __x))
> +{
> + return __builtin_signbitf (__x);
> +}
> +__MATH_INLINE int
> +__NTH (__signbit (double __x))
> +{
> + return __builtin_signbit (__x);
> +}

Is this really of any use now, given that signbit uses __builtin_signbit
directly and that the signbit macro, rather than __signbit etc. functions,
is used for internal calls within glibc?

> +/* Leave it to the compiler to optimize these if __NO_MATH_ERRNO__. */
> +# if defined __riscv_flen && !defined __NO_MATH_ERRNO__
> +
> +# if __riscv_xlen >= 64
> +
> +__MATH_INLINE long long int
> +__NTH (llrintf (float __x))
> +{
> + long long int __res;
> + __asm__ __volatile__ ("fcvt.l.s %0, %1" : "=r" (__res) : "f" (__x));
> + return __res;

This all looks rather like making inline functions replicate the bugs of
out-of-line functions (bug 6797, 6798), i.e. a bad idea.

> diff --git a/sysdeps/riscv/ieee754.h b/sysdeps/riscv/ieee754.h

My reading of the ABI is that long double is 128-bit unconditionally for
RISC-V. Thus, you shouldn't need this header; the default
sysdeps/ieee754/ldbl-128/ieee754.h should suffice.

To pass the math/ tests for soft-float, I'd expect you to need to have
s_fma.c and s_fmaf.c that include the soft-fp versions, as on various
other architectures. (You also need a libm-test-ulps file or files, which
appear to be missing from this patch series, to reflect the actual ulps
seen on RISC-V.)

Joseph Myers

unread,
Jun 14, 2017, 5:02:02 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Also, the patch series is missing the *.abilist ABI test baselines. And
the c++-types.data ABI baseline.

Joseph Myers

unread,
Jun 14, 2017, 5:02:30 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h

> +#define EM_RISCV 243
> +
> +/* Relocs. */
> +#define R_RISCV_NONE 0
> +#define R_RISCV_32 1
> +#define R_RISCV_64 2
> +#define R_RISCV_RELATIVE 3
> +#define R_RISCV_COPY 4
> +#define R_RISCV_JUMP_SLOT 5
> +#define R_RISCV_TLS_DTPMOD32 6
> +#define R_RISCV_TLS_DTPMOD64 7
> +#define R_RISCV_TLS_DTPREL32 8
> +#define R_RISCV_TLS_DTPREL64 9
> +#define R_RISCV_TLS_TPREL32 10
> +#define R_RISCV_TLS_TPREL64 11

EM_* and relocation values go in elf/elf.h, not dl-machine.h. EM_RISCV is
already there.

Joseph Myers

unread,
Jun 14, 2017, 5:02:38 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> sysdeps/riscv/bits/string.h | 25 +++++++

bits/string.h is about to go away, you might wish to work relative to
Zack's patch <https://sourceware.org/ml/libc-alpha/2017-06/msg00497.html>
(or indeed help review it).

> diff --git a/sysdeps/riscv/bits/string.h b/sysdeps/riscv/bits/string.h
> new file mode 100644
> index 0000000000..8160b8cc77
> --- /dev/null
> +++ b/sysdeps/riscv/bits/string.h
> @@ -0,0 +1,25 @@
> +/* This file should provide inline versions of string functions.
> +
> + Surround GCC-specific parts with #ifdef __GNUC__, and use `__extern_inline'.
> +
> + This file should define __STRING_INLINES if functions are actually defined
> + as inlines. */
> +
> +#ifndef _BITS_STRING_H
> +#define _BITS_STRING_H 1
> +
> +#define _STRING_INLINE_unaligned 0
> +
> +#if defined(__GNUC__) && !defined(__cplusplus)
> +
> +static __inline__ unsigned long __libc_detect_null(unsigned long w)

That obviously should not go in a public header (and isn't namespace-clean
anyway).

> diff --git a/sysdeps/riscv/memcpy.c b/sysdeps/riscv/memcpy.c
> new file mode 100644
> index 0000000000..f816a54b9b
> --- /dev/null
> +++ b/sysdeps/riscv/memcpy.c
> @@ -0,0 +1,74 @@

Should have copyright and license notice.

> diff --git a/sysdeps/riscv/strcpy.c b/sysdeps/riscv/strcpy.c
> new file mode 100644
> index 0000000000..c01c506a55
> --- /dev/null
> +++ b/sysdeps/riscv/strcpy.c
> @@ -0,0 +1,54 @@

Likewise. Is there an actual advantage over the generic version based on
memcpy and strlen?

> diff --git a/sysdeps/riscv/strlen.c b/sysdeps/riscv/strlen.c
> new file mode 100644
> index 0000000000..049e1ebd8f
> --- /dev/null
> +++ b/sysdeps/riscv/strlen.c
> @@ -0,0 +1,39 @@

Likewise. This looks like fairly generic C. Would RTH's generic string
function improvements
<https://sourceware.org/ml/libc-alpha/2016-12/msg00830.html> be helpful to
RISC-V? If so, helping to review them might save you from maintaining
some architecture-specific variants in future.

Joseph Myers

unread,
Jun 14, 2017, 5:02:48 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> RISC-V is a modular ISA, and as such there are many ISA variants. The actual
> number is the Cartesian product of:
>
> * RV32I, RV64I: base ISA, which defines the length of GP registers (which we
> call XLEN).
> * M or no-M: multiply support or not.
> * A or no-A: atomic instruction support or not.
> * none, F, or D: the floating-point format supported, either none, single or
> double.
> * C or no-C: compressed instructions support or not.
>
> In addition to the ISA variants, we support soft, single-hard, and double-hard
> float ABIs on any ISA that includes the required floating-point registers.
>
> In order to avoid building this huge number of ISA variants we only actively
> support and test the following configurations
>
> march=rv32imac/mabi=ilp32
> march=rv32imafdc/mabi=ilp32d
> march=rv64imac/mabi=lp64
> march=rv64imafdc/mabi=lp64d
>
> for glibc. I'll add those to the build script, and verify they build with the
> relevant GCC versions.

Well, you are defining dynamic linker names explicitly for RISCV_ABI_FLEN
== 32, which I assume is the single-hard ABI variants (six dynamic linker
names). I think such a variant should either have an error at configure
time, or be included in the variants built with build-many-glibcs.py,
rather than having a dynamic linker name defined but not actually being
built. Of course it may not be tested very actively, but that's true of
many variants.

Once the port is in, all the dynamic linker names should be listed at
<https://sourceware.org/glibc/wiki/ABIList>.

> > * Also include details of the full testsuite results, including execution
> > tests (which build-many-glibcs.py can't run), for all ABI variants again,
> > in the next submission of the port.
>
> We've just been running the GCC test suite. I'll take a shot at running the
> glibc test suite as well.

Note that there is an expectation that each release cycle, the
architecture maintainer should, during the one-month release freeze, run
the full testsuite for that architecture and report on the results on the
per-release wiki page (e.g.
<https://sourceware.org/glibc/wiki/Release/2.25>. Preferably, failures
seen should be cleaned up as well rather than just reported on but not
fixed.

We don't require ports to have buildslaves for the buildbot
<https://sourceware.org/glibc/wiki/Buildbot>, but if you can contribute
such buildslaves to test the main variants you care about, and then
monitor the results for them so that regressions are discovered quickly,
that's helpful.

Arnd Bergmann

unread,
Jun 14, 2017, 5:13:46 PM6/14/17
to Florian Weimer, Palmer Dabbelt, GNU C Library, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, Jun 14, 2017 at 10:35 PM, Florian Weimer <fwe...@redhat.com> wrote:
> On 06/14/2017 10:15 PM, Palmer Dabbelt wrote:
>> Do you have an idea of when there will be a 64-bit time_t clean release? I'd
>> be OK holding off on the 32-bit port for a bit, as we don't expect RV32I-based
>> Linux-compatible systems to be popular.
>
> Sorry, no idea. I'm Cc:ing Arnd, who believe worked on the kernel side
> of things.

Progress has been slow for a while, but there are still a number of interested
parties, so it is continuing. I don't think it's important to wait
here, as 64-bit
time_t will be available for all architectures in glibc once the kernel support
is done, the question is more about rebuilding all 32-bit binaries in a distro
after the change.

Arnd

Joseph Myers

unread,
Jun 14, 2017, 5:14:12 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> diff --git a/sysdeps/riscv/rvf/fedisblxcpt.c b/sysdeps/riscv/rvf/fedisblxcpt.c
> new file mode 100644
> index 0000000000..89434de352
> --- /dev/null
> +++ b/sysdeps/riscv/rvf/fedisblxcpt.c
> @@ -0,0 +1,29 @@

You could just use the generic math/ version here.

> diff --git a/sysdeps/riscv/rvf/feenablxcpt.c b/sysdeps/riscv/rvf/feenablxcpt.c
> new file mode 100644
> index 0000000000..e664a2fb3c
> --- /dev/null
> +++ b/sysdeps/riscv/rvf/feenablxcpt.c
> @@ -0,0 +1,29 @@

Likewise, but if you don't, at least follow its error handling rules.

> diff --git a/sysdeps/riscv/rvf/fegetexcept.c b/sysdeps/riscv/rvf/fegetexcept.c
> new file mode 100644
> index 0000000000..00dafd96fb
> --- /dev/null
> +++ b/sysdeps/riscv/rvf/fegetexcept.c

Likewise.

You seem to be missing implementations of the fesetexcept, fegetmode and
fesetmode functions, new in 2.25 and generally needing
architecture-specific implementations. (Whereas the generic
fetestexceptflag is fine for most architectures.)

> diff --git a/sysdeps/riscv/rvf/s_ceilf.c b/sysdeps/riscv/rvf/s_ceilf.c
> new file mode 100644
> index 0000000000..c168f5f93b
> --- /dev/null
> +++ b/sysdeps/riscv/rvf/s_ceilf.c

Remark: I think you could implement roundevenf for RISC-V in a similar way
to the other round-to-integer functions, if that's beneficial.

> diff --git a/sysdeps/riscv/rvf/s_fabsf.c b/sysdeps/riscv/rvf/s_fabsf.c

If the generic sysdeps/ieee754/flt-32/s_fabsf.c, using __builtin_fabsf,
doesn't generate the same code, that's a problem with your GCC port and
should be addressed there rather than adding s_fabsf.c for this port.

Joseph Myers

unread,
Jun 14, 2017, 5:16:29 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Same comments apply as for the float patch, regarding not needing a
special fabs implementation, and the possibility of using hardware
rounding instructions to implement roundeven similar to the other
round-to-integer functions.

Joseph Myers

unread,
Jun 14, 2017, 5:20:49 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

These are all the default now; you shouldn't need this header.

> diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
> new file mode 100644
> index 0000000000..80170c3e8a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
> @@ -0,0 +1 @@
> +#include <sysdeps/unix/sysv/linux/arm/readahead.c>

Is it really a good idea for your kernel port to replicate the ARM
peculiarity regarding the arguments to this syscall?

Joseph Myers

unread,
Jun 14, 2017, 5:23:20 PM6/14/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017, Palmer Dabbelt wrote:

> diff --git a/sysdeps/riscv/rv32/divdi3.c b/sysdeps/riscv/rv32/divdi3.c
> new file mode 100644
> index 0000000000..52f3a0396c
> --- /dev/null
> +++ b/sysdeps/riscv/rv32/divdi3.c
> @@ -0,0 +1 @@
> +/* libgcc.a provides optimized versions of these routines. */

divdi3.c is now only used if an architecture explicitly requests it. You
shouldn't need this file.

> diff --git a/sysdeps/riscv/rv32/symbol-hacks.h b/sysdeps/riscv/rv32/symbol-hacks.h
> new file mode 100644
> index 0000000000..22aad04437
> --- /dev/null
> +++ b/sysdeps/riscv/rv32/symbol-hacks.h
> @@ -0,0 +1 @@
> +#include <sysdeps/generic/symbol-hacks.h>

Likewise, you shouldn't need this file either.

> diff --git a/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h b/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h

> +/* Number of general registers. */
> +#define NGREG 32
> +#define NFPREG 32
> +
> +#define REG_PC 0
> +#define REG_RA 1
> +#define REG_SP 2
> +#define REG_TP 4
> +#define REG_S0 8
> +#define REG_A0 10
> +#define REG_NARGS 8
> +
> +/* Container for all general registers. */
> +typedef greg_t gregset_t[NGREG];
> +
> +/* Container for all FPU registers. */
> +typedef fpreg_t fpregset_t[NFPREG];

See my recent cleanups, and make sure your sys/ucontext.h is
namespace-clean in all the ways in which I've cleaned up other
sys/ucontext.h files so far.

Joseph Myers

unread,
Jun 14, 2017, 5:25:36 PM6/14/17
to Palmer Dabbelt, fwe...@redhat.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Note that if you do include the 32-bit port, you may want a
bits/environments.h header, as for other architectures with both 32-bit
and 64-bit ABIs.

Palmer Dabbelt

unread,
Jun 14, 2017, 5:55:38 PM6/14/17
to Arnd Bergmann, fwe...@redhat.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
OK, then I vote we don't wait for RV32 support. While I don't think there's
going to be a flood of RV32 Linux-compatible hardware it'd be easier to port
userspace to both RV32 and RV64 at the same time, rather than doing it twice.

Does that sound OK?

Palmer Dabbelt

unread,
Jun 14, 2017, 7:44:03 PM6/14/17
to jos...@codesourcery.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
OK, that makes sense.

>> > * Also include details of the full testsuite results, including execution
>> > tests (which build-many-glibcs.py can't run), for all ABI variants again,
>> > in the next submission of the port.
>>
>> We've just been running the GCC test suite. I'll take a shot at running the
>> glibc test suite as well.
>
> Note that there is an expectation that each release cycle, the
> architecture maintainer should, during the one-month release freeze, run
> the full testsuite for that architecture and report on the results on the
> per-release wiki page (e.g.
> <https://sourceware.org/glibc/wiki/Release/2.25>. Preferably, failures
> seen should be cleaned up as well rather than just reported on but not
> fixed.

Ya, I love having tests -- the only reason I didn't run glibc tests is because
I didn't know about them. We've got some regression scripts for the
'riscv-gnu-toolchain' repository (a super-repository containing tagged commits
of binutils, gcc, and glibc as well as some build scripts) that I run, I'll get
the tests to run and then add them to that list.

> We don't require ports to have buildslaves for the buildbot
> <https://sourceware.org/glibc/wiki/Buildbot>, but if you can contribute
> such buildslaves to test the main variants you care about, and then
> monitor the results for them so that regressions are discovered quickly,
> that's helpful.

OK, I'll look into that. We've yet to provide any public infrastructure, but
running the tests manually on everyone's commits is becoming enough of a pain
that it might be worth it.

Joseph Myers

unread,
Jun 16, 2017, 7:18:52 AM6/16/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
Also missing from the patch series: a NEWS entry for the addition of the
port, and an addition of it to the list of supported configurations in
README.

Palmer Dabbelt

unread,
Jun 19, 2017, 7:34:08 PM6/19/17
to jos...@codesourcery.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017 13:29:17 PDT (-0700), jos...@codesourcery.com wrote:
> On Wed, 14 Jun 2017, Palmer Dabbelt wrote:
>
>> diff --git a/sysdeps/riscv/Implies b/sysdeps/riscv/Implies
>> new file mode 100644
>> index 0000000000..15b9e02448
>> --- /dev/null
>> +++ b/sysdeps/riscv/Implies
>> @@ -0,0 +1,6 @@
>> +init_array
>> +
>> +ieee754/ldbl-128
>> +ieee754/dbl-64
>> +ieee754/flt-32
>> +riscv/soft-fp
>
> You should never need to have <arch>/Implies referencing <arch>/<subdir>;
> in such a case, remove the unnecessary soft-fp directory level and put
> sfp-machine.h directly in <arch>. See
> <https://sourceware.org/ml/libc-alpha/2014-10/msg00369.html>.

Makes sense, I've moved everything from the subdirectory up a level

https://github.com/riscv/riscv-glibc/commit/7d9fb3b962e2749b54ddd906b4df91ad854ca45e
Andrew and I don't actually remember what that was for, we're hoping it's just
cruft leftover from working around a bug in binutils. He's going to take a
look at it.

>> diff --git a/sysdeps/riscv/Versions b/sysdeps/riscv/Versions
>> new file mode 100644
>> index 0000000000..5a0c2d23f8
>> --- /dev/null
>> +++ b/sysdeps/riscv/Versions
>> @@ -0,0 +1,5 @@
>> +libc {
>> + GLIBC_2.14 {
>> + __memcpy_g;
>> + }
>> +}
>
> No, the minimum version should be 2.26, and you shouldn't need any such
> special string variants (given that we've killed bits/string2.h, are about
> to kill bits/string.h, and such exports as there are from old string
> function inlines are or should soon be compat symbols).

OK, makes sense.

https://github.com/riscv/riscv-glibc/commit/bbab2031f32970763a0327925fabde969fcd9a77

>> diff --git a/sysdeps/riscv/configure b/sysdeps/riscv/configure
>> new file mode 100644
>> index 0000000000..9f790ec527
>> --- /dev/null
>> +++ b/sysdeps/riscv/configure
>> @@ -0,0 +1,86 @@
>> +
>> +# as_fn_set_status STATUS
>> +# -----------------------
>> +# Set $? to STATUS, without forking.
>> +as_fn_set_status ()
>> +{
>> + return $1
>> +} # as_fn_set_status
>
> Please make sure this file is regenerated. Any sysdeps configure script
> generated with current aclocal.m4 should not contain such functions,
> assuming the GLIBC_PROVIDES in aclocal.m4 is correct.

I think we missed the -I when regenerating this, it's been fixed

https://github.com/riscv/riscv-glibc/commit/bcb054441d6fe79c231a8420c67da907fa1ce10f

>> diff --git a/sysdeps/riscv/configure.in b/sysdeps/riscv/configure.in
>> new file mode 100644
>> index 0000000000..34f62d4b4b
>> --- /dev/null
>> +++ b/sysdeps/riscv/configure.in
>
> We use configure.ac naming now, not configure.in.

OK, fixed

https://github.com/riscv/riscv-glibc/commit/357e0312945c6746e52e5c58ade3182f29b4eaaf
https://github.com/riscv/riscv-glibc/commit/8b1b9a4f2f1db655b0d107d72b01e60210dd6329

> Since you have multiple ABI variants, you should be setting default-abi
> here via LIBC_CONFIG_VAR. Then sysdeps/unix/sysv/linux/riscv/Makefile
> should set abi-variants and appropriate options for each ABI variant (see
> other such Makefiles for examples) - this is used in building
> bits/syscall.h.

OK, that makes sense. I've patterned this after aarch64 and smoke tested it.

https://github.com/riscv/riscv-glibc/commit/e3944da6dfd861f4e40bb34c107d479568ba523d

>> diff --git a/sysdeps/unix/sysv/linux/riscv/configure.in b/sysdeps/unix/sysv/linux/riscv/configure.in
>> new file mode 100644
>> index 0000000000..5b48e1aed6
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/riscv/configure.in
>> @@ -0,0 +1,8 @@
>> +sinclude(./aclocal.m4)dnl Autoconf lossage
>> +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
>> +# Local configure fragment for sysdeps/unix/sysv/linux/riscv.
>> +
>> +if test -z "$arch_minimum_kernel"; then
>> + arch_minimum_kernel=3.0.0
>> + libc_cv_gcc_unwind_find_fde=no
>> +fi
>
> Should use .ac naming. No need for the 'if test -z
> "$arch_minimum_kernel"; then'. No need to set
> libc_cv_gcc_unwind_find_fde=no. Should set arch_minimum_kernel=10.0.0
> until the kernel port is actually in Linus's tree (of course you then need
> to change that locally for testing purposes).

OK, makes sense

https://github.com/riscv/riscv-glibc/commit/f70efbda1a01c87fb4e6e0d57138a49aa0100e88

>> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/Makefile b/sysdeps/unix/sysv/linux/riscv/rv64/Makefile
>> new file mode 100644
>> index 0000000000..0a37c5b9b4
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/Makefile
>> @@ -0,0 +1,9 @@
>> +ifeq ($(subdir),socket)
>> +CFLAGS-recv.c += -fexceptions
>> +CFLAGS-send.c += -fexceptions
>> +endif
>> +
>> +ifeq ($(subdir),nptl)
>> +CFLAGS-recv.c += -fexceptions
>> +CFLAGS-send.c += -fexceptions
>> +endif
>
> In the nptl directory this is the default and should not be needed.

https://github.com/riscv/riscv-glibc/commit/142092fc6b6a738e067e4ce22cf420aa502b06af

>> diff --git a/sysdeps/unix/sysv/linux/riscv/shlib-versions b/sysdeps/unix/sysv/linux/riscv/shlib-versions
>> new file mode 100644
>> index 0000000000..66214b953e
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/riscv/shlib-versions
>> @@ -0,0 +1,17 @@
>> +DEFAULT GLIBC_2.25
>
> Should be GLIBC_2.26.

https://github.com/riscv/riscv-glibc/commit/d94d34ef8c20b4c7554bbe25e758642492ee1c85

Palmer Dabbelt

unread,
Jun 19, 2017, 8:57:24 PM6/19/17
to jos...@codesourcery.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017 13:33:04 PDT (-0700), jos...@codesourcery.com wrote:
> On Wed, 14 Jun 2017, Palmer Dabbelt wrote:
>
>> diff --git a/sysdeps/riscv/dl-trampoline.S b/sysdeps/riscv/dl-trampoline.S
>> new file mode 100644
>> index 0000000000..3d4dd9fc8c
>> --- /dev/null
>> +++ b/sysdeps/riscv/dl-trampoline.S
>> @@ -0,0 +1,44 @@
>
> Missing copyright / license notices, on a file big enough to need them.

OK, we'll go through every file and fix it for the v2.

>
>> diff --git a/sysdeps/riscv/sys/asm.h b/sysdeps/riscv/sys/asm.h
>> new file mode 100644
>> index 0000000000..bd31c72bd3
>> --- /dev/null
>> +++ b/sysdeps/riscv/sys/asm.h
>> @@ -0,0 +1,79 @@
>> +/* copyright (c) 1997, 1998, 2002, 2003-2005, 2017
>
> Uppercase Copyright (C), everywhere (not checked if this issue appears
> elsewhere).

It looks like that was the only one. I've fixed it.

https://github.com/riscv/riscv-glibc/commit/3b6018974663e367a56b744be8c4ac86632cde61

Joseph Myers

unread,
Jun 20, 2017, 7:53:26 AM6/20/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Mon, 19 Jun 2017, Palmer Dabbelt wrote:

> >> diff --git a/sysdeps/riscv/Versions b/sysdeps/riscv/Versions
> >> new file mode 100644
> >> index 0000000000..5a0c2d23f8
> >> --- /dev/null
> >> +++ b/sysdeps/riscv/Versions
> >> @@ -0,0 +1,5 @@
> >> +libc {
> >> + GLIBC_2.14 {
> >> + __memcpy_g;
> >> + }
> >> +}
> >
> > No, the minimum version should be 2.26, and you shouldn't need any such
> > special string variants (given that we've killed bits/string2.h, are about
> > to kill bits/string.h, and such exports as there are from old string
> > function inlines are or should soon be compat symbols).
>
> OK, makes sense.
>
> https://github.com/riscv/riscv-glibc/commit/bbab2031f32970763a0327925fabde969fcd9a77

I'd expect this file to go away completely, instead of listing an empty
GLIBC_2.26 version.

> I think we missed the -I when regenerating this, it's been fixed
>
> https://github.com/riscv/riscv-glibc/commit/bcb054441d6fe79c231a8420c67da907fa1ce10f

It looks like your regeneration adds a blank line at the end of configure.
Files ending with blank lines (or whitespace at end of lines, or spaces
before tabs) can't be pushed to the glibc repository; you'll need a
comment at the end of configure.ac (as in some other versions) to avoid
such a blank line at the end of configure.

Torvald Riegel

unread,
Jun 20, 2017, 10:20:55 AM6/20/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 2017-06-14 at 11:30 -0700, Palmer Dabbelt wrote:
> This patch implements various atomic and locking routines on RISC-V,
> either via the A extension (when present) or via a Linux system call
> that does a compare-and-exchange. This contains both the library
> routines and the syscall wrapper.

In the overview email you seemed to say that you only support the HW
variants that have atomics. If that's so, why don't you just check that
this is the case and produce a compile-time error if it isn't?

> diff --git a/sysdeps/riscv/atomic-machine.h b/sysdeps/riscv/atomic-machine.h
> new file mode 100644
> index 0000000000..c88dc1ce33
> --- /dev/null
> +++ b/sysdeps/riscv/atomic-machine.h
> @@ -0,0 +1,132 @@
> +/* Low-level functions for atomic operations. RISC-V version.
> + Copyright (C) 2011-2016 Free Software Foundation, Inc.
> +
> + Contributed by Andrew Waterman (and...@sifive.com).
> +
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, write to the Free
> + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> + 02111-1307 USA. */
> +
> +#ifndef _RISCV_BITS_ATOMIC_H
> +#define _RISCV_BITS_ATOMIC_H 1
> +
> +#include <inttypes.h>
> +
> +typedef int32_t atomic32_t;
> +typedef uint32_t uatomic32_t;
> +typedef int_fast32_t atomic_fast32_t;
> +typedef uint_fast32_t uatomic_fast32_t;
> +
> +typedef int64_t atomic64_t;
> +typedef uint64_t uatomic64_t;
> +typedef int_fast64_t atomic_fast64_t;
> +typedef uint_fast64_t uatomic_fast64_t;

I believe the *fast* types aren't used anymore (yes we should clean that
up).

> +typedef intptr_t atomicptr_t;
> +typedef uintptr_t uatomicptr_t;
> +typedef intmax_t atomic_max_t;
> +typedef uintmax_t uatomic_max_t;
> +
> +#define atomic_full_barrier() __sync_synchronize()
> +
> +#ifdef __riscv_atomic
> +
> +#define __HAVE_64B_ATOMICS (__riscv_xlen >= 64)
> +#define USE_ATOMIC_COMPILER_BUILTINS 1

If the built-ins do what you want them to do, I suggest that you
implement the old-style glibc atomics using the compiler built-ins (see
aarch64 for example).

> +/* MIPS uses swap on machines that have it, and uses CAS on machines that

Refer to something else than MIPS I'd suggest, or clarify the link.

> + * don't. This, we use amoswap when the A extension is enabled, and fall back
> + * to the atomic system call when the A extension is disabled. */

That's not what the code does.

> +#ifdef __riscv_atomic

You are already in a__riscv_atomic #ifdef (see above).

If you assume that your HW is of the variant with atomics, then you
don't need to fall back to the kernel helper, or do you?

> +# define ATOMIC_EXCHANGE_USES_CAS 0
> +#else
> +# define ATOMIC_EXCHANGE_USES_CAS 1

The code for the old-style atomics doesn't seem to define an exchange;
do the compiler builtins have one?

> +#endif
> +
> +#define asm_amo(which, ordering, mem, value) ({ \
> + typeof(*mem) __tmp; \
> + if (sizeof(__tmp) == 4) \
> + asm volatile (which ".w" ordering "\t%0, %z2, %1" \
> + : "=r"(__tmp), "+A"(*(mem)) \
> + : "rJ"(value)); \
> + else if (sizeof(__tmp) == 8) \
> + asm volatile (which ".d" ordering "\t%0, %z2, %1" \
> + : "=r"(__tmp), "+A"(*(mem)) \
> + : "rJ"(value)); \
> + else \
> + abort(); \
> + __tmp; })
> +
> +/* Atomic compare and exchange. */
> +
> +#define atomic_cas(ordering, mem, newval, oldval) ({ \
> + typeof(*mem) __tmp; \
> + int __tmp2; \
> + if (sizeof(__tmp) == 4) \
> + asm volatile ("1: lr.w" ordering "\t%0, %2\n" \
> + "bne\t%0, %z4, 1f\n" \
> + "sc.w" ordering "\t%1, %z3, %2\n" \
> + "bnez\t%1, 1b\n" \
> + "1:" \
> + : "=&r"(__tmp), "=&r"(__tmp2), "+A"(*(mem)) \
> + : "rJ"(newval), "rJ"(oldval)); \
> + else if (sizeof(__tmp) == 8) \
> + asm volatile ("1: lr.d" ordering "\t%0, %2\n" \
> + "bne\t%0, %z4, 1f\n" \
> + "sc.d" ordering "\t%1, %z3, %2\n" \
> + "bnez\t%1, 1b\n" \
> + "1:" \
> + : "=&r"(__tmp), "=&r"(__tmp2), "+A"(*(mem)) \
> + : "rJ"(newval), "rJ"(oldval)); \
> + else \
> + abort(); \
> + __tmp; })
> +
> +#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
> + atomic_cas(".aq", mem, newval, oldval)
> +
> +#define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
> + atomic_cas(".rl", mem, newval, oldval)
> +
> +/* Atomic exchange (without compare). */
> +
> +#define atomic_exchange_acq(mem, value) asm_amo("amoswap", ".aq", mem, value)
> +#define atomic_exchange_rel(mem, value) asm_amo("amoswap", ".rl", mem, value)
> +
> +
> +/* Atomically add value and return the previous (unincremented) value. */
> +
> +#define atomic_exchange_and_add(mem, value) asm_amo("amoadd", "", mem, value)

The semantics of these old-style atomics aren't really well defined in
glibc (but we're moving to C11-like atomics anyway). The default is for
atomic_exchange_and_add to be the same as atomic_exchange_and_add_acq,
see for example include/atomic.h:

#ifndef atomic_exchange_and_add_acq
# ifdef atomic_exchange_and_add
# define atomic_exchange_and_add_acq(mem, value) \
atomic_exchange_and_add (mem, value)

I suggest you keep it that way, instead of making them have relaxed MO.

This will go away once we've completed the transition to C11 atomics.

> +
> +#define atomic_max(mem, value) asm_amo("amomaxu", "", mem, value)
> +#define atomic_min(mem, value) asm_amo("amominu", "", mem, value)
> +
> +#define atomic_bit_test_set(mem, bit) \
> + ({ typeof(*mem) __mask = (typeof(*mem))1 << (bit); \
> + asm_amo("amoor", "", mem, __mask) & __mask; })

Likewise.

> +#define catomic_exchange_and_add(mem, value) \
> + atomic_exchange_and_add(mem, value)
> +#define catomic_max(mem, value) atomic_max(mem, value)
> +
> +#else /* __riscv_atomic */
> +
> +#define __HAVE_64B_ATOMICS 0
> +#define USE_ATOMIC_COMPILER_BUILTINS 0

You need to provide at least a CAS to make this work. Having this file
be included from the linux-specific variant is confusing, I think. Do
you really need to support glibc not running on a Linux kernel?
Otherwise, perhaps just use the linux-specific atomic-machine.h?

> +
> +#endif /* !__riscv_atomic */
> +
> +#endif /* bits/atomic.h */
> diff --git a/sysdeps/riscv/nptl/bits/pthreadtypes-arch.h b/sysdeps/riscv/nptl/bits/pthreadtypes-arch.h
> new file mode 100644
> index 0000000000..4473b0891a
> --- /dev/null
> +++ b/sysdeps/riscv/nptl/bits/pthreadtypes-arch.h
> @@ -0,0 +1,98 @@
> +/* Machine-specific pthread type layouts. RISC-V version.
> + Copyright (C) 2011-2014, 2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, write to the Free
> + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> + 02111-1307 USA. */
> +
> +#ifndef _BITS_PTHREADTYPES_ARCH_H
> +#define _BITS_PTHREADTYPES_ARCH_H 1
> +
> +#include <endian.h>
> +
> +#if __riscv_xlen == 64
> +# define __SIZEOF_PTHREAD_ATTR_T 56
> +# define __SIZEOF_PTHREAD_MUTEX_T 40
> +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
> +# define __SIZEOF_PTHREAD_COND_T 48
> +# define __SIZEOF_PTHREAD_CONDATTR_T 4
> +# define __SIZEOF_PTHREAD_RWLOCK_T 56
> +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
> +# define __SIZEOF_PTHREAD_BARRIER_T 32
> +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
> +#else
> +# define __SIZEOF_PTHREAD_ATTR_T 36
> +# define __SIZEOF_PTHREAD_MUTEX_T 24
> +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
> +# define __SIZEOF_PTHREAD_COND_T 48
> +# define __SIZEOF_PTHREAD_CONDATTR_T 4
> +# define __SIZEOF_PTHREAD_RWLOCK_T 32
> +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
> +# define __SIZEOF_PTHREAD_BARRIER_T 20
> +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
> +#endif
> +
> +#define __PTHREAD_COMPAT_PADDING_MID
> +#define __PTHREAD_COMPAT_PADDING_END
> +#define __PTHREAD_MUTEX_LOCK_ELISION 0
> +
> +#define __LOCK_ALIGNMENT
> +#define __ONCE_ALIGNMENT
> +
> +struct __pthread_rwlock_arch_t
> +{
> +# if __riscv_xlen == 64
> + unsigned int __readers;
> + unsigned int __writers;
> + unsigned int __wrphase_futex;
> + unsigned int __writers_futex;
> + int __cur_writer;
> + int __shared;
> + int __pad3;
> + int __pad4;
> + unsigned long int __pad1;
> + unsigned long int __pad2;
> + /* FLAGS must stay at this position in the structure to maintain
> + binary compatibility. */

That's not the case, I assume, given that your port is new?

> + unsigned int __flags;
> +# else
> + unsigned int __readers;
> + unsigned int __writers;
> + unsigned int __wrphase_futex;
> + unsigned int __writers_futex;
> + int __cur_writer;
> + int __pad3;
> +#if __BYTE_ORDER == __BIG_ENDIAN
> + unsigned char __pad1;
> + unsigned char __pad2;
> + unsigned char __shared;
> + /* FLAGS must stay at this position in the structure to maintain
> + binary compatibility. */
> + unsigned char __flags;
> +#else
> + /* FLAGS must stay at this position in the structure to maintain
> + binary compatibility. */
> + unsigned char __flags;
> + unsigned char __shared;
> + unsigned char __pad1;
> + unsigned char __pad2;
> +#endif
> + int __writer;
> +# endif
> +};
> +
> +#define __PTHREAD_RWLOCK_ELISION_EXTRA 0
> +
> +#endif /* bits/pthreadtypes.h */

> diff --git a/sysdeps/riscv/nptl/pthread_spin_lock.c b/sysdeps/riscv/nptl/pthread_spin_lock.c
> new file mode 100644
> index 0000000000..dd5ffae97f
> --- /dev/null
> +++ b/sysdeps/riscv/nptl/pthread_spin_lock.c
> @@ -0,0 +1,43 @@
> +/* Copyright (C) 2005 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, write to the Free
> + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> + 02111-1307 USA. */
> +
> +#ifdef __riscv_atomic
> +
> +#include <errno.h>
> +
> +int pthread_spin_lock(pthread_spinlock_t* lock)
> +{
> + int tmp1, tmp2;
> +
> + asm volatile ("\n\
> + 1:lw %0, 0(%2)\n\
> + li %1, %3\n\
> + bnez %0, 1b\n\
> + amoswap.w.aq %0, %1, 0(%2)\n\
> + bnez %0, 1b"
> + : "=&r"(tmp1), "=&r"(tmp2) : "r"(lock), "i"(EBUSY)
> + );

Why do you need a custom spinlock? Why is the generic version not good
enough for you?
We try to have as little custom synchronization code as possible.

> + return tmp1;
> +}
> +
> +#else /* __riscv_atomic */
> +
> +#include <sysdeps/../nptl/pthread_spin_lock.c>
> +
> +#endif /* !__riscv_atomic */
> diff --git a/sysdeps/riscv/nptl/pthread_spin_trylock.c b/sysdeps/riscv/nptl/pthread_spin_trylock.c
> new file mode 100644
> index 0000000000..9bd5d80fd6
> --- /dev/null
> +++ b/sysdeps/riscv/nptl/pthread_spin_trylock.c
> @@ -0,0 +1,43 @@
> +/* Copyright (C) 2005 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, write to the Free
> + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> + 02111-1307 USA. */
> +
> +#ifdef __riscv_atomic
> +
> +#include <errno.h>
> +
> +int pthread_spin_trylock(pthread_spinlock_t* lock)
> +{
> + int tmp1, tmp2;
> +
> + asm volatile ("\n\
> + lw %0, 0(%2)\n\
> + li %1, %3\n\
> + bnez %0, 1f\n\
> + amoswap.w.aq %0, %1, 0(%2)\n\
> + 1:"
> + : "=&r"(tmp1), "=&r"(tmp2) : "r"(lock), "i"(EBUSY)
> + );

Likewise.

> +
> + return tmp1;
> +}
> +
> +#else /* __riscv_atomic */
> +
> +#include <sysdeps/../nptl/pthread_spin_trylock.c>
> +
> +#endif /* !__riscv_atomic */
> diff --git a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> new file mode 100644
> index 0000000000..5ce6f8da40
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> @@ -0,0 +1,53 @@
> +/* Low-level functions for atomic operations. RISC-V version.
> + Copyright (C) 2014-2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, write to the Free
> + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> + 02111-1307 USA. */
> +
> +#ifndef _LINUX_RISCV_BITS_ATOMIC_H
> +#define _LINUX_RISCV_BITS_ATOMIC_H 1
> +
> +#include_next <atomic-machine.h>

See above.

> +
> +#ifndef __riscv_atomic
> +
> +#include <sys/syscall.h>
> +#include <sysdep.h>
> +
> +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
> + (abort (), (__typeof (*mem)) 0)
> +
> +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
> + (abort (), (__typeof (*mem)) 0)
> +
> +/* The only basic operation needed is compare and exchange. */
> +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
> + ({ \
> + INTERNAL_SYSCALL_DECL (__err); \
> + (__typeof (*mem)) INTERNAL_SYSCALL (sysriscv, __err, 4, \
> + RISCV_ATOMIC_CMPXCHG, mem, oldval, newval); \
> + })
> +
> +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
> + ({ \
> + INTERNAL_SYSCALL_DECL (__err); \
> + (__typeof (*mem)) INTERNAL_SYSCALL (sysriscv, __err, 4, \
> + RISCV_ATOMIC_CMPXCHG64, mem, oldval, newval); \
> + })
> +

You should add a comment explaining what your syscall does exactly, in
particular why you don't need to use it for atomic stores.

Palmer Dabbelt

unread,
Jun 20, 2017, 5:14:57 PM6/20/17
to jos...@codesourcery.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Wed, 14 Jun 2017 13:59:48 PDT (-0700), jos...@codesourcery.com wrote:
> On Wed, 14 Jun 2017, Palmer Dabbelt wrote:
>
>> diff --git a/sysdeps/riscv/bits/fenv.h b/sysdeps/riscv/bits/fenv.h
>
>> +enum
>> + {
>> + FE_INEXACT = 0x01,
>> +#define FE_INEXACT FE_INEXACT
>> + FE_UNDERFLOW = 0x02,
>> +#define FE_UNDERFLOW FE_UNDERFLOW
>> + FE_OVERFLOW = 0x04,
>> +#define FE_OVERFLOW FE_OVERFLOW
>> + FE_DIVBYZERO = 0x08,
>> +#define FE_DIVBYZERO FE_DIVBYZERO
>> + FE_INVALID = 0x10,
>> +#define FE_INVALID FE_INVALID
>> + };
>
> This clearly hasn't passed the glibc testsuite. See how other bits/fenv.h
> headers now define macros to make them usable in #if (which the conform/
> tests test for).

Yep -- I went ahead and fixed this failure while cleaning up the test suite..
Thanks for the heads up!
Thanks for the feedback. Andrew went through and fixed a bunch of these up.
I'm triaging the test suite to see where we stand, and I'll make sure we
generate the ULPs files. I believe we need three (soft, single, and double).

Palmer Dabbelt

unread,
Jun 20, 2017, 5:14:58 PM6/20/17
to jos...@codesourcery.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
OK, we'll move these as part of the v2 patch set.

Thanks!

Joseph Myers

unread,
Jun 20, 2017, 5:21:36 PM6/20/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On Tue, 20 Jun 2017, Palmer Dabbelt wrote:

> Thanks for the feedback. Andrew went through and fixed a bunch of these up.
> I'm triaging the test suite to see where we stand, and I'll make sure we
> generate the ULPs files. I believe we need three (soft, single, and double).

Whatever libm-test-ulps files you have, you should have corresponding
libm-test-ulps-name files with the short description that goes in the
table of ulps in the manual.

Palmer Dabbelt

unread,
Jun 20, 2017, 5:22:41 PM6/20/17
to jos...@codesourcery.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
I saw those too -- thanks for checking, though, as I didn't know about the
manual part.

Palmer Dabbelt

unread,
Jun 20, 2017, 5:29:47 PM6/20/17
to fwe...@redhat.com, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
We're going to pick the most common values, which I believe are

MINSIGSTKSZ = 4KiB (alpha, powerpc, sparc, with aarch64 setting 5KiB)
SIGSTKSZ = 16KiB (aarch64, alpha, powerpc, sparc)
PTHERAD_STACK_MIN = 128KiB (aarch64, mips, ppc, tile)

We're writing a vector extension, but it'll configurable vector sizes so
reserving the worst case space now will be pretty big. Andrew and I think the
best thing to do here is similar to what aarch64 is doing with their SVE stuff
and have a system call to determine the minimum signal stack size dynamically
instead of reserving the space statically.

Does that seem reasonable?

Florian Weimer

unread,
Jun 21, 2017, 4:56:16 AM6/21/17
to Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org, Darius Rad
On 06/20/2017 11:29 PM, Palmer Dabbelt wrote:
> On Wed, 14 Jun 2017 13:39:50 PDT (-0700), fwe...@redhat.com wrote:
>> Palmer Dabbelt <pal...@dabbelt.com> writes:
>>
>>> Linux-specific code that is required for maintaining ABI compatibility.
>>> This doesn't contain the actual system call interface, that is split out
>>> in order to avoid having a patch that's too big.
>>
>> You likely need to override bits/sigstack.h in one of these patches
>> because the generic MINSIGSTKSZ and SIGSTKSZ values are likely too
>> small, especially if you want to add more or broader vector registers in
>> the future.
>>
>> PTHREAD_STACK_MIN might warrant adjustment, too.
>
> We're going to pick the most common values, which I believe are
>
> MINSIGSTKSZ = 4KiB (alpha, powerpc, sparc, with aarch64 setting 5KiB)

You need to check what your architecture actually needs: the amount of
data pushed by the kernel, and it's also good to take into account the
save area used by the dynamic linker trampoline. Then maybe add a
couple of kilobytes so that there is room for some actually work
performed by the application signal handler.

Thanks,
Florian

Darius Rad

unread,
Jun 22, 2017, 7:42:08 PM6/22/17
to Torvald Riegel, Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org
On 06/20/2017 10:20 AM, Torvald Riegel wrote:
> On Wed, 2017-06-14 at 11:30 -0700, Palmer Dabbelt wrote:
>> This patch implements various atomic and locking routines on RISC-V,
>> either via the A extension (when present) or via a Linux system call
>> that does a compare-and-exchange. This contains both the library
>> routines and the syscall wrapper.
>
> In the overview email you seemed to say that you only support the HW
> variants that have atomics. If that's so, why don't you just check that
> this is the case and produce a compile-time error if it isn't?
>

We do support variants without atomic instructions, although that is not
the highest priority now. The current implementation uses a Linux
syscall to emulate atomic operations (like Xtensa, ColdFire).
Ultimately, we plan to replace this with an operation in the VDSO (like
ARM) to improve performance.
Indeed, you are correct. The helper is not necessary if hardware
supports atomics.

>> +# define ATOMIC_EXCHANGE_USES_CAS 0
>> +#else
>> +# define ATOMIC_EXCHANGE_USES_CAS 1
>
> The code for the old-style atomics doesn't seem to define an exchange;
> do the compiler builtins have one?
>

Is that not atomic_exchange_acq and atomic_exchange_rel, or do I
misunderstand you?
I'm not aware of a need to support glibc on anything but Linux, but I
don't think we want to preclude it unnecessarily, either. Though we can
use a Linux-specific file until there is a need otherwise.
Correct, that should not be necessary.
The generic spinlock should be fine.
Understood about explaining the syscall.

Regarding atomic stores, this comment in
sysdeps/generic/atomic-machine.h suggests they are not necessary: "The
only basic operation needed is compare and exchange."

Separately, RISC-V guarantees naturally aligned stores are atomic in all
cases (even without atomic instructions), although that may not be
sufficient here.

Torvald Riegel

unread,
Jun 23, 2017, 5:41:34 AM6/23/17
to Darius Rad, Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org
On Thu, 2017-06-22 at 19:42 -0400, Darius Rad wrote:
> On 06/20/2017 10:20 AM, Torvald Riegel wrote:
> > On Wed, 2017-06-14 at 11:30 -0700, Palmer Dabbelt wrote:
> >> This patch implements various atomic and locking routines on RISC-V,
> >> either via the A extension (when present) or via a Linux system call
> >> that does a compare-and-exchange. This contains both the library
> >> routines and the syscall wrapper.
> >
> > In the overview email you seemed to say that you only support the HW
> > variants that have atomics. If that's so, why don't you just check that
> > this is the case and produce a compile-time error if it isn't?
> >
>
> We do support variants without atomic instructions, although that is not
> the highest priority now. The current implementation uses a Linux
> syscall to emulate atomic operations (like Xtensa, ColdFire).
> Ultimately, we plan to replace this with an operation in the VDSO (like
> ARM) to improve performance.

Thanks for providing some background. However, elsewhere in the thread
for the whole patch set, you seemed to say that you'll only officially
support target configurations that do have atomics (IIRC, that was a
discussion with Joseph about the target triples). These officially
supported ones are the configurations we'll test with
build-many-glibcs.py. I think that it would be better to only have code
in master that will be compiled by some build through
build-many-glibcs.py (ie, that there's no dead code from that build
coverage perspective).

Does this clarify my question / concern?

> >> +# define ATOMIC_EXCHANGE_USES_CAS 0
> >> +#else
> >> +# define ATOMIC_EXCHANGE_USES_CAS 1
> >
> > The code for the old-style atomics doesn't seem to define an exchange;
> > do the compiler builtins have one?
> >
>
> Is that not atomic_exchange_acq and atomic_exchange_rel, or do I
> misunderstand you?

You're right, you do make amoswap available. The compiler builtins
should use it to.

> > You need to provide at least a CAS to make this work. Having this file
> > be included from the linux-specific variant is confusing, I think. Do
> > you really need to support glibc not running on a Linux kernel?
> > Otherwise, perhaps just use the linux-specific atomic-machine.h?
> >
>
> I'm not aware of a need to support glibc on anything but Linux, but I
> don't think we want to preclude it unnecessarily, either. Though we can
> use a Linux-specific file until there is a need otherwise.

The latter sounds better. But if it turns out that you officially
support only target configurations with native atomics, then I'd suggest
to just include that, and then you won't need the syscall fallback.
That is true under the assumption that the CAS really is atomic wrt to
atomic stores and loads (maybe we should clarify that...). If the
syscall cannot be interrupted by stores, then you're good (eg, because
there's just a single HW thread and your syscall cannot be interrupted,
or because you stop all other threads in the syscall).

Joseph Myers

unread,
Jun 23, 2017, 7:52:28 AM6/23/17
to Torvald Riegel, Darius Rad, Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org
On Fri, 23 Jun 2017, Torvald Riegel wrote:

> Thanks for providing some background. However, elsewhere in the thread
> for the whole patch set, you seemed to say that you'll only officially
> support target configurations that do have atomics (IIRC, that was a
> discussion with Joseph about the target triples). These officially
> supported ones are the configurations we'll test with
> build-many-glibcs.py. I think that it would be better to only have code
> in master that will be compiled by some build through
> build-many-glibcs.py (ie, that there's no dead code from that build
> coverage perspective).

I'm pretty sure lots of existing glibc architectures have code that's not
covered by build-many-glibcs.py at present, even if there are
configurations that could be added (e.g. building for another CPU variant)
that would cover building that code. That doesn't mean it's a good thing
- more configurations to cover such code would be a good idea - but the
present minimum for build-many-glibcs.py coverage is that at least each
different ABI supported by glibcs is covered.

Darius Rad

unread,
Jun 23, 2017, 10:59:36 AM6/23/17
to Torvald Riegel, Palmer Dabbelt, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org
Yes, thank you. We'll ensure that build-many-glibcs.py is consistent
with the features in the patch.

>>>> +# define ATOMIC_EXCHANGE_USES_CAS 0
>>>> +#else
>>>> +# define ATOMIC_EXCHANGE_USES_CAS 1
>>>
>>> The code for the old-style atomics doesn't seem to define an exchange;
>>> do the compiler builtins have one?
>>>
>>
>> Is that not atomic_exchange_acq and atomic_exchange_rel, or do I
>> misunderstand you?
>
> You're right, you do make amoswap available. The compiler builtins
> should use it to.
>
>>> You need to provide at least a CAS to make this work. Having this file
>>> be included from the linux-specific variant is confusing, I think. Do
>>> you really need to support glibc not running on a Linux kernel?
>>> Otherwise, perhaps just use the linux-specific atomic-machine.h?
>>>
>>
>> I'm not aware of a need to support glibc on anything but Linux, but I
>> don't think we want to preclude it unnecessarily, either. Though we can
>> use a Linux-specific file until there is a need otherwise.
>
> The latter sounds better. But if it turns out that you officially
> support only target configurations with native atomics, then I'd suggest
> to just include that, and then you won't need the syscall fallback.
>

Understood. We'll use a single file, and locate it in the Linux area
only if the atomic syscall is used.
Good to know. We should be safe because the CAS syscall is atomic with
respect to loads and stores, due to the first reason you suggest (single
processor, uninterruptable).

Palmer Dabbelt

unread,
Jun 23, 2017, 1:04:53 PM6/23/17
to tri...@redhat.com, Darius Rad, libc-...@sourceware.org, Andrew Waterman, pat...@groups.riscv.org
Sorry, I guess I was a bit confused when answering the original question: we
only expect users to build standard Linux systems with the following
configurations

* -march=rv32imac -mabi=ilp32
* -march=rv32imafdc -mabi=ilp32d
* -march=rv64imac -mabi=lp64
* -march=rv64imafdc -mabi=lp64d

but we want to support the full RISC-V ISA, as we've gotten all the other
targets working and want to ensure they don't break. Thus we'll add many
configurations to build-many-glibcs.py, including at least

* -march=rv32i -mabi=ilp32
* -march=rv32imafdc -mabi=ilp32
* -march=rv32imafdc -mabi=ilp32f
* -march=rv64i -mabi=lp64
* -march=rv64imafdc -mabi=lp64
* -march=rv64imafdc -mabi=lp64f

which should serve to test all the code: the rv{32,64}i targets test just the
base ISA (which will trigger the atomic and soft-float code), and the
floating-point ISA with soft-float ABI tests that difference.
There's two cases this syscall is used:

* The kernel is built without A support. The kernel requires A support in
order to enable SMP, so this means it's a uniprocessor system. In that case
we just call preempt_{disable,enable} to get the atomicity, which isn't a
big deal because we know we're on a uniprocessor.

* The kernel is built with A support, but userspace is built without A
support. In this case we might be on an SMP system, but can just perform
the atomic operation in the kernel directly.
Reply all
Reply to author
Forward
0 new messages