[02/12] RISC-V: ABI Implementation

Message ID 20170614183048.11040-3-palmer@dabbelt.com
State New, archived
Headers

Commit Message

Palmer Dabbelt June 14, 2017, 6:30 p.m. UTC
  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
  

Comments

Joseph Myers June 14, 2017, 8:33 p.m. UTC | #1
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 June 20, 2017, 12:57 a.m. UTC | #2
On Wed, 14 Jun 2017 13:33:04 PDT (-0700), joseph@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
  

Patch

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 <ralf@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 */