riscv64 setjmp.

Signed-off-by: Mao Han <han_mao@linux.alibaba.com>
Signed-off-by: Xia Lifang <lifang_xia@linux.alibaba.com>
Signed-off-by: Chen Guoyin <chenguoyin.cgy@linux.alibaba.com>
Signed-off-by: Wang Chen <wangchen20@iscas.ac.cn>
Signed-off-by: Lu Xufan <luxufan@iscas.ac.cn>
Test: m
Change-Id: I02cf117f67bda74516e4de8cd6f4c05efdb9a85b
diff --git a/libc/Android.bp b/libc/Android.bp
index c438ee0..de564a7 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -924,6 +924,7 @@
             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",
             ],
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/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