Merge "arm64: simplify the fenv implementation a bit."
diff --git a/libc/Android.bp b/libc/Android.bp
index 890df95..de564a7 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -197,6 +197,9 @@
arm64: {
srcs: ["arch-arm64/bionic/__set_tls.c"],
},
+ riscv64: {
+ srcs: ["arch-riscv64/bionic/__set_tls.c"],
+ },
x86: {
srcs: [
"arch-x86/bionic/__libc_init_sysinfo.cpp",
@@ -661,6 +664,17 @@
"upstream-openbsd/lib/libc/string/strncmp.c",
],
},
+ riscv64: {
+ srcs: [
+ "arch-riscv64/string/memset_chk.c",
+ "upstream-freebsd/lib/libc/string/memcmp.c",
+ "upstream-freebsd/lib/libc/string/memcpy.c",
+ "upstream-freebsd/lib/libc/string/memmove.c",
+ "upstream-freebsd/lib/libc/string/memset.c",
+ "upstream-openbsd/lib/libc/string/strcmp.c",
+ "upstream-openbsd/lib/libc/string/strlen.c",
+ ],
+ },
x86: {
exclude_srcs: [
"upstream-openbsd/lib/libc/string/memchr.c",
@@ -906,6 +920,16 @@
],
},
+ riscv64: {
+ srcs: [
+ "arch-riscv64/bionic/__bionic_clone.S",
+ "arch-riscv64/bionic/_exit_with_stack_teardown.S",
+ "arch-riscv64/bionic/setjmp.S",
+ "arch-riscv64/bionic/syscall.S",
+ "arch-riscv64/bionic/vfork.S",
+ ],
+ },
+
x86: {
srcs: [
"arch-x86/generic/string/memcmp.S",
@@ -1736,6 +1760,15 @@
keep_symbols: true,
},
},
+ riscv64: {
+ version_script: ":libc.riscv64.map",
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
+ },
x86: {
// TODO: This is to work around b/24465209. Remove after root cause is fixed.
pack_relocations: false,
@@ -1811,6 +1844,14 @@
}
genrule {
+ name: "libc.riscv64.map",
+ out: ["libc.riscv64.map"],
+ srcs: ["libc.map.txt"],
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) riscv64 $(in) $(out)",
+}
+
+genrule {
name: "libc.x86.map",
out: ["libc.x86.map"],
srcs: ["libc.map.txt"],
@@ -2009,6 +2050,9 @@
arm64: {
version_script: ":libstdc++.arm64.map",
},
+ riscv64: {
+ version_script: ":libstdc++.riscv64.map",
+ },
x86: {
pack_relocations: false,
ldflags: ["-Wl,--hash-style=both"],
@@ -2037,6 +2081,14 @@
}
genrule {
+ name: "libstdc++.riscv64.map",
+ out: ["libstdc++.riscv64.map"],
+ srcs: ["libstdc++.map.txt"],
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) riscv64 $(in) $(out)",
+}
+
+genrule {
name: "libstdc++.x86.map",
out: ["libstdc++.x86.map"],
srcs: ["libstdc++.map.txt"],
diff --git a/libc/NOTICE b/libc/NOTICE
index 2edb78f..51f43f1 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -2052,6 +2052,38 @@
Copyright (c) 1990, 1993
The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Mike Hibler and Chris Torek.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1990, 1993
+ The Regents of the University of California. All rights reserved.
(c) UNIX System Laboratories, Inc.
All or some portions of this file are derived from material licensed
to the University of California by American Telephone and Telegraph
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index 9878e8d..9eb82d8 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -29,10 +29,7 @@
#include <platform/bionic/tls_defines.h>
#include <private/bionic_asm.h>
#include <asm/signal.h>
-
-// Must match the defines in linux/sched.h
-#define CLONE_VM 0x00000100
-#define CLONE_VFORK 0x00004000
+#include <linux/sched.h>
ENTRY(vfork)
__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(vfork)
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index 9b8ad4e..b87db64 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -56,6 +56,8 @@
__asm__(PRE
"xorl %ebp,%ebp; movl %esp,%eax; andl $~0xf,%esp; subl $12,%esp; pushl %eax;"
"call _start_main" POST);
+#elif defined(__riscv)
+__asm__(PRE "li fp,0; li ra,0; mv a0,sp; tail _start_main" POST);
#elif defined(__x86_64__)
__asm__(PRE "xorl %ebp, %ebp; movq %rsp,%rdi; andq $~0xf,%rsp; callq _start_main" POST);
#else
diff --git a/libc/arch-riscv64/bionic/__bionic_clone.S b/libc/arch-riscv64/bionic/__bionic_clone.S
new file mode 100644
index 0000000..d535095
--- /dev/null
+++ b/libc/arch-riscv64/bionic/__bionic_clone.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
+
+ENTRY_PRIVATE(__bionic_clone)
+ # Push 'fn' and 'arg' onto the child stack.
+ addi a1, a1, -16
+ sd a5, 0(a1)
+ sd a6, 8(a1)
+
+ # Make the system call.
+ li a7, __NR_clone
+ ecall
+
+ # Are we the child?
+ beqz a0, .L_bc_child
+
+ # Did the clone(2) fail?
+ bltz a0, .L_bc_failure
+ # Nope, we're the parent, and our work here is done.
+ ret
+
+.L_bc_failure:
+ # Set errno if something went wrong.
+ neg a0, a0
+ j __set_errno_internal
+
+.L_bc_child:
+ # We're in the child now. Set the end of the frame record chain.
+ li fp, 0
+ # Setting ra to 0 will make the unwinder stop at __start_thread.
+ li ra, 0
+ # Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
+ ld a0, 0(sp)
+ ld a1, 8(sp)
+ addi sp, sp, 16
+ j __start_thread
+END(__bionic_clone)
diff --git a/libc/arch-riscv64/bionic/__set_tls.c b/libc/arch-riscv64/bionic/__set_tls.c
new file mode 100644
index 0000000..57383ab
--- /dev/null
+++ b/libc/arch-riscv64/bionic/__set_tls.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__LIBC_HIDDEN__ void __set_tls(void* tls) {
+ asm("mv tp, %0" : : "r"(tls));
+}
diff --git a/libc/arch-riscv64/bionic/_exit_with_stack_teardown.S b/libc/arch-riscv64/bionic/_exit_with_stack_teardown.S
new file mode 100644
index 0000000..f7bf58b
--- /dev/null
+++ b/libc/arch-riscv64/bionic/_exit_with_stack_teardown.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+// void _exit_with_stack_teardown(void* stackBase, size_t stackSize)
+ENTRY_PRIVATE(_exit_with_stack_teardown)
+ li a7, __NR_munmap
+ ecall
+ // If munmap failed, we ignore the failure and exit anyway.
+
+ li a0, 0
+ li a7, __NR_exit
+ ecall
+ // The exit syscall does not return.
+END(_exit_with_stack_teardown)
diff --git a/libc/arch-riscv64/bionic/setjmp.S b/libc/arch-riscv64/bionic/setjmp.S
new file mode 100644
index 0000000..812cfd1
--- /dev/null
+++ b/libc/arch-riscv64/bionic/setjmp.S
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+#include <private/bionic_constants.h>
+
+// The internal structure of a jmp_buf is totally private.
+// Current layout (changes from release to release):
+//
+// word name description
+// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
+// 1 sigmask 64-bit signal mask
+// 2 ra
+// 3 s0
+// ......
+// 14 s11
+// 15 sp
+// 16 fs0
+// ......
+// 27 fs11
+// 28 checksum
+// _JBLEN: defined in bionic/libc/include/setjmp.h
+
+#define _JB_SIGFLAG 0
+#define _JB_SIGMASK 1 * 8
+#define _JB_RA 2 * 8
+#define _JB_S0 3 * 8
+#define _JB_S1 4 * 8
+#define _JB_S2 5 * 8
+#define _JB_S3 6 * 8
+#define _JB_S4 7 * 8
+#define _JB_S5 8 * 8
+#define _JB_S6 9 * 8
+#define _JB_S7 10 * 8
+#define _JB_S8 11 * 8
+#define _JB_S9 12 * 8
+#define _JB_S10 13 * 8
+#define _JB_S11 14 * 8
+#define _JB_SP 15 * 8
+#define _JB_FS0 16 * 8
+#define _JB_FS1 17 * 8
+#define _JB_FS2 18 * 8
+#define _JB_FS3 19 * 8
+#define _JB_FS4 20 * 8
+#define _JB_FS5 21 * 8
+#define _JB_FS6 22 * 8
+#define _JB_FS7 23 * 8
+#define _JB_FS8 24 * 8
+#define _JB_FS9 25 * 8
+#define _JB_FS10 26 * 8
+#define _JB_FS11 27 * 8
+#define _JB_CHECKSUM 28 * 8
+
+.macro m_mangle_registers reg, sp_reg
+ xor s0, s0, \reg
+ xor s1, s1, \reg
+ xor s2, s2, \reg
+ xor s3, s3, \reg
+ xor s4, s4, \reg
+ xor s5, s5, \reg
+ xor s6, s6, \reg
+ xor s7, s7, \reg
+ xor s8, s8, \reg
+ xor s9, s9, \reg
+ xor s10, s10, \reg
+ xor s11, s11, \reg
+ xor \sp_reg, \sp_reg, \reg
+.endm
+
+.macro m_calculate_checksum dst, src, scratch
+ li \dst, 0
+ .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27
+ ld \scratch, (\i * 8)(\src)
+ xor \dst, \dst, \scratch
+ .endr
+.endm
+
+.macro m_unmangle_registers reg, sp_reg
+ m_mangle_registers \reg, sp_reg=\sp_reg
+.endm
+
+ENTRY(setjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
+ li a1, 1
+ tail PIC_PLT(sigsetjmp)
+END(setjmp)
+
+ENTRY(_setjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
+ li a1, 0
+ tail PIC_PLT(sigsetjmp)
+END(_setjmp)
+
+// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
+ENTRY(sigsetjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
+ addi sp, sp, -24
+ sd a0, 0(sp)
+ sd a1, 8(sp)
+ sd ra, 16(sp)
+
+ // Get the cookie and store it along with the signal flag.
+ mv a0, a1
+ call PIC_PLT(__bionic_setjmp_cookie_get)
+ mv a1, a0
+ ld a0, 0(sp)
+ sd a1, _JB_SIGFLAG(a0)
+
+ // Do we need to save the signal mask?
+ andi a1, a1, 1
+ beqz a1, 1f
+
+ // Save current signal mask.
+ // The 'how'/a0 argument is ignored if set is NULL.
+ li a1, 0 // NULL
+ addi a2, a0, _JB_SIGMASK // old_mask.
+ call PIC_PLT(sigprocmask)
+
+ ld a1, 8(sp)
+
+1:
+ // Restore original a0/a1/ra.
+ ld a0, 0(sp)
+ ld a1, 8(sp)
+ ld ra, 16(sp)
+ addi sp, sp, 24
+
+ // Mask off the signal flag bit.
+ andi a1, a1, -2
+
+ // Save core registers.
+ mv a2, sp
+ m_mangle_registers a1, sp_reg=a2
+ sd ra, _JB_RA(a0)
+ sd s0, _JB_S0(a0)
+ sd s1, _JB_S1(a0)
+ sd s2, _JB_S2(a0)
+ sd s3, _JB_S3(a0)
+ sd s4, _JB_S4(a0)
+ sd s5, _JB_S5(a0)
+ sd s6, _JB_S6(a0)
+ sd s7, _JB_S7(a0)
+ sd s8, _JB_S8(a0)
+ sd s9, _JB_S9(a0)
+ sd s10, _JB_S10(a0)
+ sd s11, _JB_S11(a0)
+ sd sp, _JB_SP(a0)
+ m_unmangle_registers a1, sp_reg=a2
+
+ // Save floating point registers.
+ fsd fs0, _JB_FS0(a0)
+ fsd fs1, _JB_FS1(a0)
+ fsd fs2, _JB_FS2(a0)
+ fsd fs3, _JB_FS3(a0)
+ fsd fs4, _JB_FS4(a0)
+ fsd fs5, _JB_FS5(a0)
+ fsd fs6, _JB_FS6(a0)
+ fsd fs7, _JB_FS7(a0)
+ fsd fs8, _JB_FS8(a0)
+ fsd fs9, _JB_FS9(a0)
+ fsd fs10, _JB_FS10(a0)
+ fsd fs11, _JB_FS11(a0)
+
+ // Calculate the checksum and save it.
+ m_calculate_checksum t0, a0, t1
+ sd t0, _JB_CHECKSUM(a0)
+
+ li a0, 0
+ ret
+END(sigsetjmp)
+
+// void siglongjmp(sigjmp_buf env, int value);
+ENTRY(siglongjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
+ // Check the checksum before doing anything.
+ m_calculate_checksum t0, a0, t1
+ ld t1, _JB_CHECKSUM(a0)
+ bne t0, t1, 3f
+
+ // Do we need to restore the signal mask?
+ ld a2, _JB_SIGFLAG(a0)
+ andi a3, a2, 1
+ beqz a3, 1f
+
+ addi sp, sp, -16
+ sd a0, 0(sp)
+ sd ra, 8(sp)
+
+ // Restore the signal mask.
+ mv t0, a1 // Save 'value'.
+
+ mv a2, a0
+ li a0, 2 // SIG_SETMASK
+ addi a1, a2, _JB_SIGMASK // new_mask
+ li a2, 0 // NULL
+ call PIC_PLT(sigprocmask)
+ mv a1, t0 // Restore 'value'.
+
+ // Restore original a0 and ra.
+ ld a0, 0(sp)
+ ld ra, 8(sp)
+ addi sp, sp, 16
+
+ ld a2, _JB_SIGFLAG(a0)
+1:
+ // Restore core registers.
+ andi a2, a2, -2
+ ld ra, _JB_RA(a0)
+ ld s0, _JB_S0(a0)
+ ld s1, _JB_S1(a0)
+ ld s2, _JB_S2(a0)
+ ld s3, _JB_S3(a0)
+ ld s4, _JB_S4(a0)
+ ld s5, _JB_S5(a0)
+ ld s6, _JB_S6(a0)
+ ld s7, _JB_S7(a0)
+ ld s8, _JB_S8(a0)
+ ld s9, _JB_S9(a0)
+ ld s10, _JB_S10(a0)
+ ld s11, _JB_S11(a0)
+ ld a3, _JB_SP(a0)
+ m_unmangle_registers a2, sp_reg=a3
+ mv sp, a3
+
+ addi sp, sp, -24
+ sd ra, 0(sp)
+ sd a0, 8(sp)
+ sd a1, 16(sp)
+ ld a0, _JB_SIGFLAG(a0)
+ call PIC_PLT(__bionic_setjmp_cookie_check)
+ ld ra, 0(sp)
+ ld a0, 8(sp)
+ ld a1, 16(sp)
+ addi sp, sp, 24
+
+ // Restore floating point registers.
+ fld fs0, _JB_FS0(a0)
+ fld fs1, _JB_FS1(a0)
+ fld fs2, _JB_FS2(a0)
+ fld fs3, _JB_FS3(a0)
+ fld fs4, _JB_FS4(a0)
+ fld fs5, _JB_FS5(a0)
+ fld fs6, _JB_FS6(a0)
+ fld fs7, _JB_FS7(a0)
+ fld fs8, _JB_FS8(a0)
+ fld fs9, _JB_FS9(a0)
+ fld fs10, _JB_FS10(a0)
+ fld fs11, _JB_FS11(a0)
+
+ // Set return value.
+ beqz a1, 2f
+ li a0, 1
+2:
+ mv a0, a1
+ ret
+
+3:
+ call PIC_PLT(__bionic_setjmp_checksum_mismatch)
+END(siglongjmp)
+
+ALIAS_SYMBOL(longjmp, siglongjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
+ALIAS_SYMBOL(_longjmp, siglongjmp)
+__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)
diff --git a/libc/arch-riscv64/bionic/syscall.S b/libc/arch-riscv64/bionic/syscall.S
new file mode 100644
index 0000000..7b9d3ca
--- /dev/null
+++ b/libc/arch-riscv64/bionic/syscall.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+ENTRY(syscall)
+ // Move the syscall number up.
+ mv a7, a0
+
+ // Shuffle the arguments down.
+ mv a0, a1
+ mv a1, a2
+ mv a2, a3
+ mv a3, a4
+ mv a4, a5
+ mv a5, a6
+
+ ecall
+
+ // Did it fail?
+ li a7, -MAX_ERRNO
+ bgtu a0, a7, 1f
+
+ ret
+1:
+ neg a0, a0
+ j __set_errno_internal
+END(syscall)
diff --git a/libc/arch-riscv64/bionic/vfork.S b/libc/arch-riscv64/bionic/vfork.S
new file mode 100644
index 0000000..0eff9e9
--- /dev/null
+++ b/libc/arch-riscv64/bionic/vfork.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <platform/bionic/tls_defines.h>
+#include <private/bionic_asm.h>
+#include <asm/signal.h>
+#include <linux/sched.h>
+
+ENTRY(vfork)
+ // t0 = __get_tls()[TLS_SLOT_THREAD_ID]
+ mv t0, tp
+ ld t0, TLS_SLOT_THREAD_ID * 8(t0)
+
+ // Set cached_pid_ to 0, vforked_ to 1, and stash the previous value.
+ li t1, 0x80000000
+ lw t2, 20(t0)
+ sw t1, 20(t0)
+
+ li a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
+ li a1, 0 //uses a duplicate of the parent's stack
+ li a2, 0
+ li a3, 0
+ li a4, 0
+
+ li a7, __NR_clone
+ ecall
+
+ // if (rc == 0) we're the child, and finished...
+ beqz a0, .L_success
+
+ // else if (rc != 0): reset cached_pid_ and vforked_...
+ sw t2, 20(t0)
+ // ...and work out whether we succeeded or failed.
+ bltz a0, .L_failure
+.L_success:
+ ret
+
+.L_failure:
+ neg a0, a0
+ j __set_errno_internal
+END(vfork)
diff --git a/libc/arch-riscv64/string/memset_chk.c b/libc/arch-riscv64/string/memset_chk.c
new file mode 100644
index 0000000..bdd15a5
--- /dev/null
+++ b/libc/arch-riscv64/string/memset_chk.c
@@ -0,0 +1,9 @@
+#include <stdint.h>
+
+extern void* memset(void*, int, size_t);
+extern void* __memset_chk_fail(void*, int, size_t, size_t);
+
+void* __memset_chk(void* dst, int c, size_t n, size_t dst_len) {
+ if (dst_len < n) __memset_chk_fail(dst, c, n, dst_len);
+ return memset(dst, c, n);
+}
diff --git a/libc/include/setjmp.h b/libc/include/setjmp.h
index c2a9544..a3de9c7 100644
--- a/libc/include/setjmp.h
+++ b/libc/include/setjmp.h
@@ -52,6 +52,8 @@
#define _JBLEN 64
#elif defined(__i386__)
#define _JBLEN 10
+#elif defined(__riscv)
+#define _JBLEN 29
#elif defined(__x86_64__)
#define _JBLEN 11
#endif
diff --git a/libc/upstream-freebsd/lib/libc/string/bcopy.c b/libc/upstream-freebsd/lib/libc/string/bcopy.c
new file mode 100644
index 0000000..84715d0
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/bcopy.c
@@ -0,0 +1,137 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+typedef intptr_t word; /* "word" used for optimal copy speed */
+
+#define wsize sizeof(word)
+#define wmask (wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+#if defined(MEMCOPY) || defined(MEMMOVE)
+#include <string.h>
+
+void *
+#ifdef MEMCOPY
+memcpy
+#else
+memmove
+#endif
+(void *dst0, const void *src0, size_t length)
+#else
+#include <strings.h>
+
+void
+bcopy(const void *src0, void *dst0, size_t length)
+#endif
+{
+ char *dst = dst0;
+ const char *src = src0;
+ size_t t;
+
+ if (length == 0 || dst == src) /* nothing to do */
+ goto done;
+
+ /*
+ * Macros: loop-t-times; and loop-t-times, t>0
+ */
+#define TLOOP(s) if (t) TLOOP1(s)
+#define TLOOP1(s) do { s; } while (--t)
+
+ if ((unsigned long)dst < (unsigned long)src) {
+ /*
+ * Copy forward.
+ */
+ t = (uintptr_t)src; /* only need low bits */
+ if ((t | (uintptr_t)dst) & wmask) {
+ /*
+ * Try to align operands. This cannot be done
+ * unless the low bits match.
+ */
+ if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
+ t = length;
+ else
+ t = wsize - (t & wmask);
+ length -= t;
+ TLOOP1(*dst++ = *src++);
+ }
+ /*
+ * Copy whole words, then mop up any trailing bytes.
+ */
+ t = length / wsize;
+ TLOOP(*(word *)(void *)dst = *(const word *)(const void *)src;
+ src += wsize; dst += wsize);
+ t = length & wmask;
+ TLOOP(*dst++ = *src++);
+ } else {
+ /*
+ * Copy backwards. Otherwise essentially the same.
+ * Alignment works as before, except that it takes
+ * (t&wmask) bytes to align, not wsize-(t&wmask).
+ */
+ src += length;
+ dst += length;
+ t = (uintptr_t)src;
+ if ((t | (uintptr_t)dst) & wmask) {
+ if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
+ t = length;
+ else
+ t &= wmask;
+ length -= t;
+ TLOOP1(*--dst = *--src);
+ }
+ t = length / wsize;
+ TLOOP(src -= wsize; dst -= wsize;
+ *(word *)(void *)dst = *(const word *)(const void *)src);
+ t = length & wmask;
+ TLOOP(*--dst = *--src);
+ }
+done:
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ return (dst0);
+#else
+ return;
+#endif
+}
diff --git a/libc/upstream-freebsd/lib/libc/string/memcmp.c b/libc/upstream-freebsd/lib/libc/string/memcmp.c
new file mode 100644
index 0000000..c8d5d92
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memcmp.c
@@ -0,0 +1,58 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memcmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Compare memory regions.
+ */
+int
+memcmp(const void *s1, const void *s2, size_t n)
+{
+ if (n != 0) {
+ const unsigned char *p1 = s1, *p2 = s2;
+
+ do {
+ if (*p1++ != *p2++)
+ return (*--p1 - *--p2);
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/libc/upstream-freebsd/lib/libc/string/memcpy.c b/libc/upstream-freebsd/lib/libc/string/memcpy.c
new file mode 100644
index 0000000..ed03856
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memcpy.c
@@ -0,0 +1,5 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMCOPY
+#include "bcopy.c"
diff --git a/libc/upstream-freebsd/lib/libc/string/memmove.c b/libc/upstream-freebsd/lib/libc/string/memmove.c
new file mode 100644
index 0000000..05cf75a
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memmove.c
@@ -0,0 +1,5 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMMOVE
+#include "bcopy.c"
diff --git a/libc/upstream-freebsd/lib/libc/string/memset.c b/libc/upstream-freebsd/lib/libc/string/memset.c
new file mode 100644
index 0000000..e2d4027
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/string/memset.c
@@ -0,0 +1,133 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Hibler and Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memset.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <limits.h>
+
+#define wsize sizeof(u_long)
+#define wmask (wsize - 1)
+
+#ifdef BZERO
+#include <strings.h>
+
+#define RETURN return
+#define VAL 0
+#define WIDEVAL 0
+
+void
+bzero(void *dst0, size_t length)
+#else
+#include <string.h>
+
+#define RETURN return (dst0)
+#define VAL c0
+#define WIDEVAL c
+
+void *
+memset(void *dst0, int c0, size_t length)
+#endif
+{
+ size_t t;
+#ifndef BZERO
+ u_long c;
+#endif
+ u_char *dst;
+
+ dst = dst0;
+ /*
+ * If not enough words, just fill bytes. A length >= 2 words
+ * guarantees that at least one of them is `complete' after
+ * any necessary alignment. For instance:
+ *
+ * |-----------|-----------|-----------|
+ * |00|01|02|03|04|05|06|07|08|09|0A|00|
+ * ^---------------------^
+ * dst dst+length-1
+ *
+ * but we use a minimum of 3 here since the overhead of the code
+ * to do word writes is substantial.
+ *
+ * TODO: This threshold might not be sensible for 64-bit u_long.
+ * We should benchmark and revisit this decision.
+ */
+ if (length < 3 * wsize) {
+ while (length != 0) {
+ *dst++ = VAL;
+ --length;
+ }
+ RETURN;
+ }
+
+#ifndef BZERO
+ if ((c = (u_char)c0) != 0) { /* Fill the word. */
+ c = (c << 8) | c; /* u_long is 16 bits. */
+#if ULONG_MAX > 0xffff
+ c = (c << 16) | c; /* u_long is 32 bits. */
+#endif
+#if ULONG_MAX > 0xffffffff
+ c = (c << 32) | c; /* u_long is 64 bits. */
+#endif
+ }
+#endif
+ /* Align destination by filling in bytes. */
+ if ((t = (long)dst & wmask) != 0) {
+ t = wsize - t;
+ length -= t;
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ }
+
+ /* Fill words. Length was >= 2*words so we know t >= 1 here. */
+ t = length / wsize;
+ do {
+ *(u_long *)(void *)dst = WIDEVAL;
+ dst += wsize;
+ } while (--t != 0);
+
+ /* Mop up trailing bytes, if any. */
+ t = length & wmask;
+ if (t != 0)
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ RETURN;
+}
diff --git a/libm/Android.bp b/libm/Android.bp
index 641956c..effd7e9 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -344,6 +344,13 @@
version_script: ":libm.arm64.map",
},
+ riscv64: {
+ srcs: [
+ "riscv64/fenv.c",
+ ],
+ version_script: ":libm.riscv64.map",
+ },
+
x86: {
srcs: [
"i387/fenv.c",
@@ -573,6 +580,14 @@
}
genrule {
+ name: "libm.riscv64.map",
+ out: ["libm.riscv64.map"],
+ srcs: ["libm.map.txt"],
+ tools: ["generate-version-script"],
+ cmd: "$(location generate-version-script) riscv64 $(in) $(out)",
+}
+
+genrule {
name: "libm.x86.map",
out: ["libm.x86.map"],
srcs: ["libm.map.txt"],
diff --git a/libm/NOTICE b/libm/NOTICE
index 64d253a..bce49ad 100644
--- a/libm/NOTICE
+++ b/libm/NOTICE
@@ -309,6 +309,34 @@
-------------------------------------------------------------------
+Copyright (C) 2022 The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
Copyright (c) 1985, 1993
The Regents of the University of California. All rights reserved.
diff --git a/libm/riscv64/fenv.c b/libm/riscv64/fenv.c
new file mode 100644
index 0000000..f16e5a9
--- /dev/null
+++ b/libm/riscv64/fenv.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <fenv.h>
+#include <stdint.h>
+
+const fenv_t __fe_dfl_env = 0;
+
+int fegetenv(fenv_t* envp) {
+ __asm__ __volatile__("frcsr %0" : "=r"(*envp));
+ return 0;
+}
+
+int fesetenv(const fenv_t* envp) {
+ fenv_t env;
+ fegetenv(&env);
+ if (*envp != env) {
+ __asm__ __volatile__("fscsr %z0" : : "r"(*envp));
+ }
+ return 0;
+}
+
+int feclearexcept(int excepts) {
+ __asm__ __volatile__("csrc fflags, %0" : : "r"(excepts & FE_ALL_EXCEPT));
+ return 0;
+}
+
+int fegetexceptflag(fexcept_t* flagp, int excepts) {
+ *flagp = fetestexcept(excepts & FE_ALL_EXCEPT);
+ return 0;
+}
+
+int fesetexceptflag(const fexcept_t* flagp, int excepts) {
+ feclearexcept((~*flagp) & excepts);
+ feraiseexcept(*flagp & excepts);
+ return 0;
+}
+
+int feraiseexcept(int excepts) {
+ __asm__ __volatile__("csrs fflags, %0" : : "r"(excepts));
+ return 0;
+}
+
+int fetestexcept(int excepts) {
+ int flags;
+ __asm__ __volatile__("frflags %0" : "=r"(flags));
+ return flags & excepts;
+}
+
+int fegetround(void) {
+ int rm;
+ __asm__ __volatile__("frrm %0" : "=r"(rm));
+ return rm;
+}
+
+int fesetround(int round) {
+ if (round < FE_TONEAREST || round > FE_UPWARD) return -1;
+ __asm__ __volatile__("fsrm %z0" : : "r"(round));
+ return 0;
+}
+
+int feholdexcept(fenv_t* envp) {
+ fegetenv(envp);
+ feclearexcept(FE_ALL_EXCEPT);
+ return 0;
+}
+
+int feupdateenv(const fenv_t* envp) {
+ int excepts = fetestexcept(FE_ALL_EXCEPT);
+ fesetenv(envp);
+ feraiseexcept(excepts);
+ return 0;
+}
+
+int feenableexcept(int mask __unused) {
+ return -1;
+}
+
+int fedisableexcept(int mask __unused) {
+ return 0;
+}
+
+int fegetexcept(void) {
+ return 0;
+}
diff --git a/tests/fenv_test.cpp b/tests/fenv_test.cpp
index c5b5eca..ad34caa 100644
--- a/tests/fenv_test.cpp
+++ b/tests/fenv_test.cpp
@@ -117,6 +117,21 @@
ASSERT_EQ(FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT));
}
+TEST(fenv, fegetenv_fesetenv_rounding_mode) {
+ // Test that fegetenv()/fesetenv() includes the rounding mode.
+ fesetround(FE_DOWNWARD);
+ ASSERT_EQ(FE_DOWNWARD, fegetround());
+
+ fenv_t env;
+ fegetenv(&env);
+
+ fesetround(FE_UPWARD);
+ ASSERT_EQ(FE_UPWARD, fegetround());
+
+ fesetenv(&env);
+ ASSERT_EQ(FE_DOWNWARD, fegetround());
+}
+
TEST(fenv, feholdexcept_feupdateenv) {
// Set FE_OVERFLOW only.
feclearexcept(FE_ALL_EXCEPT);
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index 472aa20..c9e9a0c 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -224,13 +224,15 @@
}
#if defined(__arm__)
-#define __JB_SIGFLAG 0
+#define JB_SIGFLAG_OFFSET 0
#elif defined(__aarch64__)
-#define __JB_SIGFLAG 0
+#define JB_SIGFLAG_OFFSET 0
#elif defined(__i386__)
-#define __JB_SIGFLAG 8
+#define JB_SIGFLAG_OFFSET 8
+#elif defined(__riscv)
+#define JB_SIGFLAG_OFFSET 0
#elif defined(__x86_64)
-#define __JB_SIGFLAG 8
+#define JB_SIGFLAG_OFFSET 8
#endif
TEST_F(setjmp_DeathTest, setjmp_cookie) {
@@ -238,7 +240,7 @@
int value = setjmp(jb);
ASSERT_EQ(0, value);
- long* sigflag = reinterpret_cast<long*>(jb) + __JB_SIGFLAG;
+ long* sigflag = reinterpret_cast<long*>(jb) + JB_SIGFLAG_OFFSET;
// Make sure there's actually a cookie.
EXPECT_NE(0, *sigflag & ~1);