add riscv64 architecture support
authorRich Felker <dalias@aerifal.cx>
Fri, 24 May 2019 14:46:08 +0000 (10:46 -0400)
committerRich Felker <dalias@aerifal.cx>
Fri, 14 Jun 2019 21:13:05 +0000 (17:13 -0400)
Author: Alex Suykov <alex.suykov@gmail.com>
Author: Aric Belsito <lluixhi@gmail.com>
Author: Drew DeVault <sir@cmpwn.com>
Author: Michael Clark <mjc@sifive.com>
Author: Michael Forney <mforney@mforney.org>
Author: Stefan O'Rear <sorear2@gmail.com>

This port has involved the work of many people over several years. I
have tried to ensure that everyone with substantial contributions has
been credited above; if any omissions are found they will be noted
later in an update to the authors/contributors list in the COPYRIGHT
file.

The version committed here comes from the riscv/riscv-musl repo's
commit 3fe7e2c75df78eef42dcdc352a55757729f451e2, with minor changes by
me for issues found during final review:

- a_ll/a_sc atomics are removed (according to the ISA spec, lr/sc
  are not safe to use in separate inline asm fragments)

- a_cas[_p] is fixed to be a memory barrier

- the call from the _start assembly into the C part of crt1/ldso is
  changed to allow for the possibility that the linker does not place
  them nearby each other.

- DTP_OFFSET is defined correctly so that local-dynamic TLS works

- reloc.h LDSO_ARCH logic is simplified and made explicit.

- unused, non-functional crti/n asm files are removed.

- an empty .sdata section is added to crt1 so that the
  __global_pointer reference is resolvable.

- indentation style errors in some asm files are fixed.

51 files changed:
arch/riscv64/atomic_arch.h [new file with mode: 0644]
arch/riscv64/bits/alltypes.h.in [new file with mode: 0644]
arch/riscv64/bits/endian.h [new file with mode: 0644]
arch/riscv64/bits/fcntl.h [new file with mode: 0644]
arch/riscv64/bits/fenv.h [new file with mode: 0644]
arch/riscv64/bits/float.h [new file with mode: 0644]
arch/riscv64/bits/ipc.h [new file with mode: 0644]
arch/riscv64/bits/limits.h [new file with mode: 0644]
arch/riscv64/bits/mman.h [new file with mode: 0644]
arch/riscv64/bits/msg.h [new file with mode: 0644]
arch/riscv64/bits/posix.h [new file with mode: 0644]
arch/riscv64/bits/reg.h [new file with mode: 0644]
arch/riscv64/bits/sem.h [new file with mode: 0644]
arch/riscv64/bits/setjmp.h [new file with mode: 0644]
arch/riscv64/bits/shm.h [new file with mode: 0644]
arch/riscv64/bits/signal.h [new file with mode: 0644]
arch/riscv64/bits/socket.h [new file with mode: 0644]
arch/riscv64/bits/stat.h [new file with mode: 0644]
arch/riscv64/bits/stdint.h [new file with mode: 0644]
arch/riscv64/bits/syscall.h.in [new file with mode: 0644]
arch/riscv64/bits/user.h [new file with mode: 0644]
arch/riscv64/crt_arch.h [new file with mode: 0644]
arch/riscv64/pthread_arch.h [new file with mode: 0644]
arch/riscv64/reloc.h [new file with mode: 0644]
arch/riscv64/syscall_arch.h [new file with mode: 0644]
configure
include/elf.h
src/fenv/riscv64/fenv-sf.c [new file with mode: 0644]
src/fenv/riscv64/fenv.S [new file with mode: 0644]
src/ldso/riscv64/dlsym.s [new file with mode: 0644]
src/linux/cache.c
src/math/riscv64/copysign.c [new file with mode: 0644]
src/math/riscv64/copysignf.c [new file with mode: 0644]
src/math/riscv64/fabs.c [new file with mode: 0644]
src/math/riscv64/fabsf.c [new file with mode: 0644]
src/math/riscv64/fma.c [new file with mode: 0644]
src/math/riscv64/fmaf.c [new file with mode: 0644]
src/math/riscv64/fmax.c [new file with mode: 0644]
src/math/riscv64/fmaxf.c [new file with mode: 0644]
src/math/riscv64/fmin.c [new file with mode: 0644]
src/math/riscv64/fminf.c [new file with mode: 0644]
src/math/riscv64/sqrt.c [new file with mode: 0644]
src/math/riscv64/sqrtf.c [new file with mode: 0644]
src/setjmp/riscv64/longjmp.S [new file with mode: 0644]
src/setjmp/riscv64/setjmp.S [new file with mode: 0644]
src/signal/riscv64/restore.s [new file with mode: 0644]
src/signal/riscv64/sigsetjmp.s [new file with mode: 0644]
src/thread/riscv64/__set_thread_area.s [new file with mode: 0644]
src/thread/riscv64/__unmapself.s [new file with mode: 0644]
src/thread/riscv64/clone.s [new file with mode: 0644]
src/thread/riscv64/syscall_cp.s [new file with mode: 0644]

diff --git a/arch/riscv64/atomic_arch.h b/arch/riscv64/atomic_arch.h
new file mode 100644 (file)
index 0000000..98f12fc
--- /dev/null
@@ -0,0 +1,34 @@
+#define a_barrier a_barrier
+static inline void a_barrier()
+{
+       __asm__ __volatile__ ("fence rw,rw" : : : "memory");
+}
+
+#define a_cas a_cas
+static inline int a_cas(volatile int *p, int t, int s)
+{
+       int old, tmp;
+       __asm__("\n1:   lr.w.aqrl %0, %2\n"
+               "       bne %0, %3, 1f\n"
+               "       sc.w.aqrl %1, %4, %2\n"
+               "       bnez %1, 1b\n"
+               "1:"
+               : "=&r"(old), "+r"(tmp), "+A"(*p)
+               : "r"(t), "r"(s));
+       return old;
+}
+
+#define a_cas_p a_cas_p
+static inline void *a_cas_p(volatile void *p, void *t, void *s)
+{
+       void *old;
+       int tmp;
+       __asm__("\n1:   lr.d.aqrl %0, %2\n"
+               "       bne %0, %3, 1f\n"
+               "       sc.d.aqrl %1, %4, %2\n"
+               "       bnez %1, 1b\n"
+               "1:"
+               : "=&r"(old), "+r"(tmp), "+A"(*(long *)p)
+               : "r"(t), "r"(s));
+       return old;
+}
diff --git a/arch/riscv64/bits/alltypes.h.in b/arch/riscv64/bits/alltypes.h.in
new file mode 100644 (file)
index 0000000..ae9ba41
--- /dev/null
@@ -0,0 +1,29 @@
+#define _Addr long
+#define _Int64 long
+#define _Reg long
+
+TYPEDEF __builtin_va_list va_list;
+TYPEDEF __builtin_va_list __isoc_va_list;
+
+#ifndef __cplusplus
+TYPEDEF int wchar_t;
+#endif
+
+TYPEDEF int blksize_t;
+TYPEDEF unsigned int nlink_t;
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
+
+TYPEDEF long time_t;
+TYPEDEF long suseconds_t;
+
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
+TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/arch/riscv64/bits/endian.h b/arch/riscv64/bits/endian.h
new file mode 100644 (file)
index 0000000..172c338
--- /dev/null
@@ -0,0 +1 @@
+#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/arch/riscv64/bits/fcntl.h b/arch/riscv64/bits/fcntl.h
new file mode 100644 (file)
index 0000000..ecb4d18
--- /dev/null
@@ -0,0 +1,38 @@
+#define O_CREAT        0100
+#define O_EXCL         0200
+#define O_NOCTTY       0400
+#define O_TRUNC       01000
+#define O_APPEND      02000
+#define O_NONBLOCK    04000
+#define O_DSYNC      010000
+#define O_SYNC     04010000
+#define O_RSYNC    04010000
+#define O_DIRECTORY 0200000
+#define O_NOFOLLOW  0400000
+#define O_CLOEXEC  02000000
+
+#define O_ASYNC      020000
+#define O_DIRECT     040000
+#define O_LARGEFILE 0100000
+#define O_NOATIME  01000000
+#define O_PATH    010000000
+#define O_TMPFILE 020200000
+#define O_NDELAY O_NONBLOCK
+
+#define F_DUPFD  0
+#define F_GETFD  1
+#define F_SETFD  2
+#define F_GETFL  3
+#define F_SETFL  4
+#define F_GETLK  5
+#define F_SETLK  6
+#define F_SETLKW 7
+#define F_SETOWN 8
+#define F_GETOWN 9
+#define F_SETSIG 10
+#define F_GETSIG 11
+
+#define F_SETOWN_EX 15
+#define F_GETOWN_EX 16
+
+#define F_GETOWNER_UIDS 17
diff --git a/arch/riscv64/bits/fenv.h b/arch/riscv64/bits/fenv.h
new file mode 100644 (file)
index 0000000..806ec40
--- /dev/null
@@ -0,0 +1,17 @@
+#define FE_INVALID      16
+#define FE_DIVBYZERO    8
+#define FE_OVERFLOW     4
+#define FE_UNDERFLOW    2
+#define FE_INEXACT      1
+
+#define FE_ALL_EXCEPT   31
+
+#define FE_TONEAREST    0
+#define FE_DOWNWARD     2
+#define FE_UPWARD       3
+#define FE_TOWARDZERO   1
+
+typedef unsigned int fexcept_t;
+typedef unsigned int fenv_t;
+
+#define FE_DFL_ENV      ((const fenv_t *) -1)
diff --git a/arch/riscv64/bits/float.h b/arch/riscv64/bits/float.h
new file mode 100644 (file)
index 0000000..719c790
--- /dev/null
@@ -0,0 +1,16 @@
+#define FLT_EVAL_METHOD 0
+
+#define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L
+#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
+#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
+#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
+
+#define LDBL_MANT_DIG 113
+#define LDBL_MIN_EXP (-16381)
+#define LDBL_MAX_EXP 16384
+
+#define LDBL_DIG 33
+#define LDBL_MIN_10_EXP (-4931)
+#define LDBL_MAX_10_EXP 4932
+
+#define DECIMAL_DIG 36
diff --git a/arch/riscv64/bits/ipc.h b/arch/riscv64/bits/ipc.h
new file mode 100644 (file)
index 0000000..6f3328a
--- /dev/null
@@ -0,0 +1,14 @@
+struct ipc_perm {
+       key_t __ipc_perm_key;
+       uid_t uid;
+       gid_t gid;
+       uid_t cuid;
+       gid_t cgid;
+       mode_t mode;
+       unsigned short __ipc_perm_seq;
+
+       unsigned long __pad1;
+       unsigned long __pad2;
+};
+
+#define IPC_64 0
diff --git a/arch/riscv64/bits/limits.h b/arch/riscv64/bits/limits.h
new file mode 100644 (file)
index 0000000..0226588
--- /dev/null
@@ -0,0 +1,7 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define LONG_BIT 64
+#endif
+
+#define LONG_MAX  0x7fffffffffffffffL
+#define LLONG_MAX  0x7fffffffffffffffLL
diff --git a/arch/riscv64/bits/mman.h b/arch/riscv64/bits/mman.h
new file mode 100644 (file)
index 0000000..3695057
--- /dev/null
@@ -0,0 +1 @@
+#define MAP_32BIT       0x40
diff --git a/arch/riscv64/bits/msg.h b/arch/riscv64/bits/msg.h
new file mode 100644 (file)
index 0000000..641e170
--- /dev/null
@@ -0,0 +1,13 @@
+struct msqid_ds {
+       struct ipc_perm msg_perm;
+       time_t msg_stime;
+       time_t msg_rtime;
+       time_t msg_ctime;
+       unsigned long msg_cbytes;
+       msgqnum_t msg_qnum;
+       msglen_t msg_qbytes;
+       pid_t msg_lspid;
+       pid_t msg_lrpid;
+       unsigned long __pad1;
+       unsigned long __pad2;
+};
diff --git a/arch/riscv64/bits/posix.h b/arch/riscv64/bits/posix.h
new file mode 100644 (file)
index 0000000..8068ce9
--- /dev/null
@@ -0,0 +1,2 @@
+#define _POSIX_V6_LP64_OFF64 1
+#define _POSIX_V7_LP64_OFF64 1
diff --git a/arch/riscv64/bits/reg.h b/arch/riscv64/bits/reg.h
new file mode 100644 (file)
index 0000000..c800788
--- /dev/null
@@ -0,0 +1,8 @@
+#undef __WORDSIZE
+#define __WORDSIZE 64
+#define REG_PC 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_TP 4
+#define REG_S0 8
+#define REG_A0 10
diff --git a/arch/riscv64/bits/sem.h b/arch/riscv64/bits/sem.h
new file mode 100644 (file)
index 0000000..5f93c12
--- /dev/null
@@ -0,0 +1,9 @@
+struct semid_ds {
+       struct ipc_perm sem_perm;
+       time_t sem_otime;
+       time_t sem_ctime;
+       unsigned short sem_nsems;
+       char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
+       time_t __unused3;
+       time_t __unused4;
+};
diff --git a/arch/riscv64/bits/setjmp.h b/arch/riscv64/bits/setjmp.h
new file mode 100644 (file)
index 0000000..ad7e401
--- /dev/null
@@ -0,0 +1 @@
+typedef unsigned long __jmp_buf[26];
diff --git a/arch/riscv64/bits/shm.h b/arch/riscv64/bits/shm.h
new file mode 100644 (file)
index 0000000..4c3c9fb
--- /dev/null
@@ -0,0 +1,25 @@
+#define SHMLBA 4096
+
+struct shmid_ds
+{
+       struct ipc_perm shm_perm;
+       size_t shm_segsz;
+       time_t shm_atime;
+       time_t shm_dtime;
+       time_t shm_ctime;
+       pid_t shm_cpid;
+       pid_t shm_lpid;
+       unsigned long shm_nattch;
+       unsigned long __pad1;
+       unsigned long __pad2;
+};
+
+struct shminfo {
+       unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
+};
+
+struct shm_info {
+       int __used_ids;
+       unsigned long shm_tot, shm_rss, shm_swp;
+       unsigned long __swap_attempts, __swap_successes;
+};
diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
new file mode 100644 (file)
index 0000000..4c94a8f
--- /dev/null
@@ -0,0 +1,112 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+# define MINSIGSTKSZ 2048
+# define SIGSTKSZ 8192
+#endif
+
+/* gregs[0] holds the program counter. */
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+typedef unsigned long greg_t;
+typedef unsigned long gregset_t[32];
+
+struct __riscv_f_ext_state {
+       unsigned int f[32];
+       unsigned int fcsr;
+};
+
+struct __riscv_d_ext_state {
+       unsigned long long f[32];
+       unsigned int fcsr;
+};
+
+struct __riscv_q_ext_state {
+       unsigned long long f[64] __attribute__((aligned(16)));
+       unsigned int fcsr;
+       unsigned int reserved[3];
+};
+
+union __riscv_fp_state {
+       struct __riscv_f_ext_state f;
+       struct __riscv_d_ext_state d;
+       struct __riscv_q_ext_state q;
+};
+
+typedef union __riscv_fp_state fpregset_t;
+
+typedef struct sigcontext {
+       gregset_t gregs;
+       fpregset_t fpregs;
+} mcontext_t;
+
+#else
+typedef struct {
+       unsigned long gregs[32];
+       unsigned long long fpregs[66];
+} mcontext_t;
+#endif
+
+struct sigaltstack {
+       void *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+};
+
+typedef struct __ucontext
+{
+       unsigned long uc_flags;
+       struct __ucontext *uc_link;
+       stack_t uc_stack;
+       sigset_t uc_sigmask;
+       mcontext_t uc_mcontext;
+} ucontext_t;
+
+#define SA_NOCLDSTOP 1
+#define SA_NOCLDWAIT 2
+#define SA_SIGINFO   4
+#define SA_ONSTACK   0x08000000
+#define SA_RESTART   0x10000000
+#define SA_NODEFER   0x40000000
+#define SA_RESETHAND 0x80000000
+#define SA_RESTORER  0x04000000
+
+#endif
+
+#define SIGHUP     1
+#define SIGINT     2
+#define SIGQUIT    3
+#define SIGILL     4
+#define SIGTRAP    5
+#define SIGABRT    6
+#define SIGIOT     SIGABRT
+#define SIGBUS     7
+#define SIGFPE     8
+#define SIGKILL    9
+#define SIGUSR1   10
+#define SIGSEGV   11
+#define SIGUSR2   12
+#define SIGPIPE   13
+#define SIGALRM   14
+#define SIGTERM   15
+#define SIGSTKFLT 16
+#define SIGCHLD   17
+#define SIGCONT   18
+#define SIGSTOP   19
+#define SIGTSTP   20
+#define SIGTTIN   21
+#define SIGTTOU   22
+#define SIGURG    23
+#define SIGXCPU   24
+#define SIGXFSZ   25
+#define SIGVTALRM 26
+#define SIGPROF   27
+#define SIGWINCH  28
+#define SIGIO     29
+#define SIGPOLL   SIGIO
+#define SIGPWR    30
+#define SIGSYS    31
+#define SIGUNUSED SIGSYS
+
+#define _NSIG     65
diff --git a/arch/riscv64/bits/socket.h b/arch/riscv64/bits/socket.h
new file mode 100644 (file)
index 0000000..aae537d
--- /dev/null
@@ -0,0 +1,19 @@
+#include <endian.h>
+
+struct msghdr {
+       void *msg_name;
+       socklen_t msg_namelen;
+       struct iovec *msg_iov;
+       int msg_iovlen, __pad1;
+       void *msg_control;
+       socklen_t msg_controllen;
+       int __pad2;
+       int msg_flags;
+};
+
+struct cmsghdr {
+       socklen_t cmsg_len;
+       int __pad1;
+       int cmsg_level;
+       int cmsg_type;
+};
diff --git a/arch/riscv64/bits/stat.h b/arch/riscv64/bits/stat.h
new file mode 100644 (file)
index 0000000..b7f4221
--- /dev/null
@@ -0,0 +1,18 @@
+struct stat {
+       dev_t st_dev;
+       ino_t st_ino;
+       mode_t st_mode;
+       nlink_t st_nlink;
+       uid_t st_uid;
+       gid_t st_gid;
+       dev_t st_rdev;
+       unsigned long __pad;
+       off_t st_size;
+       blksize_t st_blksize;
+       int __pad2;
+       blkcnt_t st_blocks;
+       struct timespec st_atim;
+       struct timespec st_mtim;
+       struct timespec st_ctim;
+       unsigned __unused[2];
+};
diff --git a/arch/riscv64/bits/stdint.h b/arch/riscv64/bits/stdint.h
new file mode 100644 (file)
index 0000000..1bb147f
--- /dev/null
@@ -0,0 +1,20 @@
+typedef int32_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+#define INT_FAST16_MIN  INT32_MIN
+#define INT_FAST32_MIN  INT32_MIN
+
+#define INT_FAST16_MAX  INT32_MAX
+#define INT_FAST32_MAX  INT32_MAX
+
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN      INT64_MIN
+#define INTPTR_MAX      INT64_MAX
+#define UINTPTR_MAX     UINT64_MAX
+#define PTRDIFF_MIN     INT64_MIN
+#define PTRDIFF_MAX     INT64_MAX
+#define SIZE_MAX        UINT64_MAX
diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in
new file mode 100644 (file)
index 0000000..03d7f86
--- /dev/null
@@ -0,0 +1,277 @@
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs 43
+#define __NR_fstatfs 44
+#define __NR_truncate 45
+#define __NR_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile 71
+#define __NR_pselect6 72
+#define __NR_ppoll 73
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_fstatat 79
+#define __NR_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_timerfd_settime 86
+#define __NR_timerfd_gettime 87
+#define __NR_utimensat 88
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_futex 98
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_nanosleep 101
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_gettime 108
+#define __NR_timer_getoverrun 109
+#define __NR_timer_settime 110
+#define __NR_timer_delete 111
+#define __NR_clock_settime 112
+#define __NR_clock_gettime 113
+#define __NR_clock_getres 114
+#define __NR_clock_nanosleep 115
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_sched_rr_get_interval 127
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigtimedwait 137
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrlimit 163
+#define __NR_setrlimit 164
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_gettimeofday 169
+#define __NR_settimeofday 170
+#define __NR_adjtimex 171
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_timedsend 182
+#define __NR_mq_timedreceive 183
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semtimedop 192
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap 222
+#define __NR_fadvise64 223
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_recvmmsg 243
+#define __NR_arch_specific_syscall 244
+#define __NR_wait4 260
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_clock_adjtime 266
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_sysriscv __NR_arch_specific_syscall
+#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
diff --git a/arch/riscv64/bits/user.h b/arch/riscv64/bits/user.h
new file mode 100644 (file)
index 0000000..bd0f0fc
--- /dev/null
@@ -0,0 +1,43 @@
+struct user_regs_struct {
+       unsigned long pc;
+       unsigned long ra;
+       unsigned long sp;
+       unsigned long gp;
+       unsigned long tp;
+       unsigned long t0;
+       unsigned long t1;
+       unsigned long t2;
+       unsigned long s0;
+       unsigned long s1;
+       unsigned long a0;
+       unsigned long a1;
+       unsigned long a2;
+       unsigned long a3;
+       unsigned long a4;
+       unsigned long a5;
+       unsigned long a6;
+       unsigned long a7;
+       unsigned long s2;
+       unsigned long s3;
+       unsigned long s4;
+       unsigned long s5;
+       unsigned long s6;
+       unsigned long s7;
+       unsigned long s8;
+       unsigned long s9;
+       unsigned long s10;
+       unsigned long s11;
+       unsigned long t3;
+       unsigned long t4;
+       unsigned long t5;
+       unsigned long t6;
+};
+
+struct user_fpregs_struct {
+       double f[32];
+       unsigned int fcsr;
+};
+
+#define ELF_NGREG 32
+typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+typedef struct user_fpregs_struct elf_fpregset_t;
diff --git a/arch/riscv64/crt_arch.h b/arch/riscv64/crt_arch.h
new file mode 100644 (file)
index 0000000..6b93fcf
--- /dev/null
@@ -0,0 +1,19 @@
+__asm__(
+".section .sdata,\"aw\"\n"
+".text\n"
+".global " START "\n"
+".type " START ",%function\n"
+START ":\n"
+".weak __global_pointer$\n"
+".hidden __global_pointer$\n"
+".option push\n"
+".option norelax\n\t"
+"lla gp, __global_pointer$\n"
+".option pop\n\t"
+"mv a0, sp\n"
+".weak _DYNAMIC\n"
+".hidden _DYNAMIC\n\t"
+"lla a1, _DYNAMIC\n\t"
+"andi sp, sp, -16\n\t"
+"tail " START "_c"
+);
diff --git a/arch/riscv64/pthread_arch.h b/arch/riscv64/pthread_arch.h
new file mode 100644 (file)
index 0000000..1268b72
--- /dev/null
@@ -0,0 +1,14 @@
+static inline struct pthread *__pthread_self()
+{
+       char *tp;
+       __asm__ __volatile__("mv %0, tp" : "=r"(tp));
+       return (void *)(tp - sizeof(struct pthread));
+}
+
+#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
+#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
+
+#define DTP_OFFSET 0x800
+
+#define MC_PC gregs[0]
diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h
new file mode 100644 (file)
index 0000000..1ca1381
--- /dev/null
@@ -0,0 +1,22 @@
+#if defined __riscv_float_abi_soft
+#define RISCV_FP_SUFFIX "-sf"
+#elif defined __riscv_float_abi_single
+#define RISCV_FP_SUFFIX "-sp"
+#elif defined __riscv_float_abi_double
+#define RISCV_FP_SUFFIX ""
+#endif
+
+#define LDSO_ARCH "riscv64" RISCV_FP_SUFFIX
+
+#define TPOFF_K 0
+
+#define REL_SYMBOLIC    R_RISCV_64
+#define REL_PLT         R_RISCV_JUMP_SLOT
+#define REL_RELATIVE    R_RISCV_RELATIVE
+#define REL_COPY        R_RISCV_COPY
+#define REL_DTPMOD      R_RISCV_TLS_DTPMOD64
+#define REL_DTPOFF      R_RISCV_TLS_DTPREL64
+#define REL_TPOFF       R_RISCV_TLS_TPREL64
+
+#define CRTJMP(pc,sp) __asm__ __volatile__( \
+       "mv sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" )
diff --git a/arch/riscv64/syscall_arch.h b/arch/riscv64/syscall_arch.h
new file mode 100644 (file)
index 0000000..1aaeb63
--- /dev/null
@@ -0,0 +1,76 @@
+#define __SYSCALL_LL_E(x) (x)
+#define __SYSCALL_LL_O(x) (x)
+
+#define __asm_syscall(...) \
+       __asm__ __volatile__ ("ecall\n\t" \
+       : "+r"(a0) : __VA_ARGS__ : "memory"); \
+       return a0; \
+
+static inline long __syscall0(long n)
+{
+       register long a7 __asm__("a7") = n;
+       register long a0 __asm__("a0");
+       __asm_syscall("r"(a7))
+}
+
+static inline long __syscall1(long n, long a)
+{
+       register long a7 __asm__("a7") = n;
+       register long a0 __asm__("a0") = a;
+       __asm_syscall("r"(a7), "0"(a0))
+}
+
+static inline long __syscall2(long n, long a, long b)
+{
+       register long a7 __asm__("a7") = n;
+       register long a0 __asm__("a0") = a;
+       register long a1 __asm__("a1") = b;
+       __asm_syscall("r"(a7), "0"(a0), "r"(a1))
+}
+
+static inline long __syscall3(long n, long a, long b, long c)
+{
+       register long a7 __asm__("a7") = n;
+       register long a0 __asm__("a0") = a;
+       register long a1 __asm__("a1") = b;
+       register long a2 __asm__("a2") = c;
+       __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
+}
+
+static inline long __syscall4(long n, long a, long b, long c, long d)
+{
+       register long a7 __asm__("a7") = n;
+       register long a0 __asm__("a0") = a;
+       register long a1 __asm__("a1") = b;
+       register long a2 __asm__("a2") = c;
+       register long a3 __asm__("a3") = d;
+       __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
+}
+
+static inline long __syscall5(long n, long a, long b, long c, long d, long e)
+{
+       register long a7 __asm__("a7") = n;
+       register long a0 __asm__("a0") = a;
+       register long a1 __asm__("a1") = b;
+       register long a2 __asm__("a2") = c;
+       register long a3 __asm__("a3") = d;
+       register long a4 __asm__("a4") = e;
+       __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
+}
+
+static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
+{
+       register long a7 __asm__("a7") = n;
+       register long a0 __asm__("a0") = a;
+       register long a1 __asm__("a1") = b;
+       register long a2 __asm__("a2") = c;
+       register long a3 __asm__("a3") = d;
+       register long a4 __asm__("a4") = e;
+       register long a5 __asm__("a5") = f;
+       __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
+}
+
+#define VDSO_USEFUL
+/* We don't have a clock_gettime function.
+#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT_VER "LINUX_2.6" */
index 2123ddce1f05d4f73871f09509a23e0c9eedc5d7..60e0b1fc9aec47954f7a88d53034bdbeeaee19e7 100755 (executable)
--- a/configure
+++ b/configure
@@ -322,6 +322,7 @@ microblaze*) ARCH=microblaze ;;
 or1k*) ARCH=or1k ;;
 powerpc64*|ppc64*) ARCH=powerpc64 ;;
 powerpc*|ppc*) ARCH=powerpc ;;
+riscv64*) ARCH=riscv64 ;;
 sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
 s390x*) ARCH=s390x ;;
 unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
@@ -654,6 +655,11 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
 trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
 fi
 
+if test "$ARCH" = "riscv64" ; then
+trycppif __riscv_float_abi_soft "$t" && SUBARCH=${SUBARCH}-sf
+trycppif __riscv_float_abi_single "$t" && SUBARCH=${SUBARCH}-sp
+fi
+
 if test "$ARCH" = "sh" ; then
 tryflag CFLAGS_AUTO -Wa,--isa=any
 trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
index aad522e484508f98b9e7dd322227c0c7330d77bb..41e6e0c365e2a9561b190b8f4bc967d45637cfe9 100644 (file)
@@ -3226,6 +3226,62 @@ enum
 #define R_BPF_NONE             0
 #define R_BPF_MAP_FD           1
 
+#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
+
+#define R_RISCV_BRANCH          16
+#define R_RISCV_JAL             17
+#define R_RISCV_CALL            18
+#define R_RISCV_CALL_PLT        19
+#define R_RISCV_GOT_HI20        20
+#define R_RISCV_TLS_GOT_HI20    21
+#define R_RISCV_TLS_GD_HI20     22
+#define R_RISCV_PCREL_HI20      23
+#define R_RISCV_PCREL_LO12_I    24
+#define R_RISCV_PCREL_LO12_S    25
+#define R_RISCV_HI20            26
+#define R_RISCV_LO12_I          27
+#define R_RISCV_LO12_S          28
+#define R_RISCV_TPREL_HI20      29
+#define R_RISCV_TPREL_LO12_I    30
+#define R_RISCV_TPREL_LO12_S    31
+#define R_RISCV_TPREL_ADD       32
+#define R_RISCV_ADD8            33
+#define R_RISCV_ADD16           34
+#define R_RISCV_ADD32           35
+#define R_RISCV_ADD64           36
+#define R_RISCV_SUB8            37
+#define R_RISCV_SUB16           38
+#define R_RISCV_SUB32           39
+#define R_RISCV_SUB64           40
+#define R_RISCV_GNU_VTINHERIT   41
+#define R_RISCV_GNU_VTENTRY     42
+#define R_RISCV_ALIGN           43
+#define R_RISCV_RVC_BRANCH      44
+#define R_RISCV_RVC_JUMP        45
+#define R_RISCV_RVC_LUI         46
+#define R_RISCV_GPREL_I         47
+#define R_RISCV_GPREL_S         48
+#define R_RISCV_TPREL_I         49
+#define R_RISCV_TPREL_S         50
+#define R_RISCV_RELAX           51
+#define R_RISCV_SUB6            52
+#define R_RISCV_SET6            53
+#define R_RISCV_SET8            54
+#define R_RISCV_SET16           55
+#define R_RISCV_SET32           56
+#define R_RISCV_32_PCREL        57
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/fenv/riscv64/fenv-sf.c b/src/fenv/riscv64/fenv-sf.c
new file mode 100644 (file)
index 0000000..ecd3cb5
--- /dev/null
@@ -0,0 +1,3 @@
+#ifndef __riscv_flen
+#include "../fenv.c"
+#endif
diff --git a/src/fenv/riscv64/fenv.S b/src/fenv/riscv64/fenv.S
new file mode 100644 (file)
index 0000000..f149003
--- /dev/null
@@ -0,0 +1,53 @@
+#ifdef __riscv_flen
+
+.global feclearexcept
+.type feclearexcept, %function
+feclearexcept:
+       csrc fflags, a0
+       li a0, 0
+       ret
+
+.global feraiseexcept
+.type feraiseexcept, %function
+feraiseexcept:
+       csrs fflags, a0
+       li a0, 0
+       ret
+
+.global fetestexcept
+.type fetestexcept, %function
+fetestexcept:
+       frflags t0
+       and a0, t0, a0
+       ret
+
+.global fegetround
+.type fegetround, %function
+fegetround:
+       frrm a0
+       ret
+
+.global __fesetround
+.type __fesetround, %function
+__fesetround:
+       fsrm t0, a0
+       li a0, 0
+       ret
+
+.global fegetenv
+.type fegetenv, %function
+fegetenv:
+       frcsr t0
+       sw t0, 0(a0)
+       li a0, 0
+       ret
+
+.global fesetenv
+.type fesetenv, %function
+fesetenv:
+       lw t1, 0(a0)
+       fscsr t0, t1
+       li a0, 0
+       ret
+
+#endif
diff --git a/src/ldso/riscv64/dlsym.s b/src/ldso/riscv64/dlsym.s
new file mode 100644 (file)
index 0000000..2bafd72
--- /dev/null
@@ -0,0 +1,6 @@
+.global dlsym
+.hidden __dlsym
+.type dlsym, %function
+dlsym:
+       mv a2, ra
+       tail __dlsym
index 84a138a4158692d037b1c8aa56ea5d04b0d07ca6..0eb051c2d4acecbce4ca780413f125369ffecf14 100644 (file)
@@ -1,4 +1,6 @@
+#include <errno.h>
 #include "syscall.h"
+#include "atomic.h"
 
 #ifdef SYS_cacheflush
 int _flush_cache(void *addr, int len, int op)
@@ -15,3 +17,34 @@ int __cachectl(void *addr, int len, int op)
 }
 weak_alias(__cachectl, cachectl);
 #endif
+
+#ifdef SYS_riscv_flush_icache
+
+#define VDSO_FLUSH_ICACHE_SYM "__vdso_flush_icache"
+#define VDSO_FLUSH_ICACHE_VER "LINUX_4.5"
+
+static void *volatile vdso_func;
+
+static int flush_icache_init(void *start, void *end, unsigned long int flags)
+{
+       void *p = __vdsosym(VDSO_FLUSH_ICACHE_VER, VDSO_FLUSH_ICACHE_SYM);
+       int (*f)(void *, void *, unsigned long int) =
+               (int (*)(void *, void *, unsigned long int))p;
+       a_cas_p(&vdso_func, (void *)flush_icache_init, p);
+       return f ? f(start, end, flags) : -ENOSYS;
+}
+
+static void *volatile vdso_func = (void *)flush_icache_init;
+
+int __riscv_flush_icache(void *start, void *end, unsigned long int flags) 
+{
+       int (*f)(void *, void *, unsigned long int) =
+               (int (*)(void *, void *, unsigned long int))vdso_func;
+       if (f) {
+               int r = f(start, end, flags);
+               if (!r) return r;
+               if (r != -ENOSYS) return __syscall_ret(r);
+       }
+}
+weak_alias(__riscv_flush_icache, riscv_flush_icache);
+#endif
diff --git a/src/math/riscv64/copysign.c b/src/math/riscv64/copysign.c
new file mode 100644 (file)
index 0000000..c785417
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 64
+
+double copysign(double x, double y)
+{
+       __asm__ ("fsgnj.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
+       return x;
+}
+
+#else
+
+#include "../copysign.c"
+
+#endif
diff --git a/src/math/riscv64/copysignf.c b/src/math/riscv64/copysignf.c
new file mode 100644 (file)
index 0000000..a125611
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 32
+
+float copysignf(float x, float y)
+{
+       __asm__ ("fsgnj.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
+       return x;
+}
+
+#else
+
+#include "../copysignf.c"
+
+#endif
diff --git a/src/math/riscv64/fabs.c b/src/math/riscv64/fabs.c
new file mode 100644 (file)
index 0000000..5290b6f
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 64
+
+double fabs(double x)
+{
+       __asm__ ("fabs.d %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../fabs.c"
+
+#endif
diff --git a/src/math/riscv64/fabsf.c b/src/math/riscv64/fabsf.c
new file mode 100644 (file)
index 0000000..f5032e3
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 32
+
+float fabsf(float x)
+{
+       __asm__ ("fabs.s %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../fabsf.c"
+
+#endif
diff --git a/src/math/riscv64/fma.c b/src/math/riscv64/fma.c
new file mode 100644 (file)
index 0000000..99b0571
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 64
+
+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;
+}
+
+#else
+
+#include "../fma.c"
+
+#endif
diff --git a/src/math/riscv64/fmaf.c b/src/math/riscv64/fmaf.c
new file mode 100644 (file)
index 0000000..f9dc47e
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 32
+
+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;
+}
+
+#else
+
+#include "../fmaf.c"
+
+#endif
diff --git a/src/math/riscv64/fmax.c b/src/math/riscv64/fmax.c
new file mode 100644 (file)
index 0000000..023709c
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 64
+
+double fmax(double x, double y)
+{
+       __asm__ ("fmax.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
+       return x;
+}
+
+#else
+
+#include "../fmax.c"
+
+#endif
diff --git a/src/math/riscv64/fmaxf.c b/src/math/riscv64/fmaxf.c
new file mode 100644 (file)
index 0000000..863d2bd
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 32
+
+float fmaxf(float x, float y)
+{
+       __asm__ ("fmax.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
+       return x;
+}
+
+#else
+
+#include "../fmaxf.c"
+
+#endif
diff --git a/src/math/riscv64/fmin.c b/src/math/riscv64/fmin.c
new file mode 100644 (file)
index 0000000..a4e3b06
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 64
+
+double fmin(double x, double y)
+{
+       __asm__ ("fmin.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
+       return x;
+}
+
+#else
+
+#include "../fmin.c"
+
+#endif
diff --git a/src/math/riscv64/fminf.c b/src/math/riscv64/fminf.c
new file mode 100644 (file)
index 0000000..32156e8
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 32
+
+float fminf(float x, float y)
+{
+       __asm__ ("fmin.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
+       return x;
+}
+
+#else
+
+#include "../fminf.c"
+
+#endif
diff --git a/src/math/riscv64/sqrt.c b/src/math/riscv64/sqrt.c
new file mode 100644 (file)
index 0000000..867a504
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 64
+
+double sqrt(double x)
+{
+       __asm__ ("fsqrt.d %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../sqrt.c"
+
+#endif
diff --git a/src/math/riscv64/sqrtf.c b/src/math/riscv64/sqrtf.c
new file mode 100644 (file)
index 0000000..610c2cf
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#if __riscv_flen >= 32
+
+float sqrtf(float x)
+{
+       __asm__ ("fsqrt.s %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../sqrtf.c"
+
+#endif
diff --git a/src/setjmp/riscv64/longjmp.S b/src/setjmp/riscv64/longjmp.S
new file mode 100644 (file)
index 0000000..41e2d21
--- /dev/null
@@ -0,0 +1,42 @@
+.global __longjmp
+.global _longjmp
+.global longjmp
+.type __longjmp, %function
+.type _longjmp,  %function
+.type longjmp,   %function
+__longjmp:
+_longjmp:
+longjmp:
+       ld s0,    0(a0)
+       ld s1,    8(a0)
+       ld s2,    16(a0)
+       ld s3,    24(a0)
+       ld s4,    32(a0)
+       ld s5,    40(a0)
+       ld s6,    48(a0)
+       ld s7,    56(a0)
+       ld s8,    64(a0)
+       ld s9,    72(a0)
+       ld s10,   80(a0)
+       ld s11,   88(a0)
+       ld sp,    96(a0)
+       ld ra,    104(a0)
+
+#ifndef __riscv_float_abi_soft
+       fld fs0,  112(a0)
+       fld fs1,  120(a0)
+       fld fs2,  128(a0)
+       fld fs3,  136(a0)
+       fld fs4,  144(a0)
+       fld fs5,  152(a0)
+       fld fs6,  160(a0)
+       fld fs7,  168(a0)
+       fld fs8,  176(a0)
+       fld fs9,  184(a0)
+       fld fs10, 192(a0)
+       fld fs11, 200(a0)
+#endif
+
+       seqz a0, a1
+       add a0, a0, a1
+       ret
diff --git a/src/setjmp/riscv64/setjmp.S b/src/setjmp/riscv64/setjmp.S
new file mode 100644 (file)
index 0000000..5124967
--- /dev/null
@@ -0,0 +1,41 @@
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp, %function
+.type _setjmp,  %function
+.type setjmp,   %function
+__setjmp:
+_setjmp:
+setjmp:
+       sd s0,    0(a0)
+       sd s1,    8(a0)
+       sd s2,    16(a0)
+       sd s3,    24(a0)
+       sd s4,    32(a0)
+       sd s5,    40(a0)
+       sd s6,    48(a0)
+       sd s7,    56(a0)
+       sd s8,    64(a0)
+       sd s9,    72(a0)
+       sd s10,   80(a0)
+       sd s11,   88(a0)
+       sd sp,    96(a0)
+       sd ra,    104(a0)
+
+#ifndef __riscv_float_abi_soft
+       fsd fs0,  112(a0)
+       fsd fs1,  120(a0)
+       fsd fs2,  128(a0)
+       fsd fs3,  136(a0)
+       fsd fs4,  144(a0)
+       fsd fs5,  152(a0)
+       fsd fs6,  160(a0)
+       fsd fs7,  168(a0)
+       fsd fs8,  176(a0)
+       fsd fs9,  184(a0)
+       fsd fs10, 192(a0)
+       fsd fs11, 200(a0)
+#endif
+
+       li a0, 0
+       ret
diff --git a/src/signal/riscv64/restore.s b/src/signal/riscv64/restore.s
new file mode 100644 (file)
index 0000000..40012c7
--- /dev/null
@@ -0,0 +1,8 @@
+.global __restore
+.type __restore, %function
+__restore:
+.global __restore_rt
+.type __restore_rt, %function
+__restore_rt:
+       li a7, 139 # SYS_rt_sigreturn
+       ecall
diff --git a/src/signal/riscv64/sigsetjmp.s b/src/signal/riscv64/sigsetjmp.s
new file mode 100644 (file)
index 0000000..f9bc162
--- /dev/null
@@ -0,0 +1,23 @@
+.global sigsetjmp
+.global __sigsetjmp
+.type sigsetjmp, %function
+.type __sigsetjmp, %function
+sigsetjmp:
+__sigsetjmp:
+       bnez a1, 1f
+       tail setjmp
+1:
+
+       sd ra, 208(a0)
+       sd s0, 224(a0)
+       mv s0, a0
+
+       call setjmp
+
+       mv a1, a0
+       mv a0, s0
+       ld s0, 224(a0)
+       ld ra, 208(a0)
+
+.hidden __sigsetjmp_tail
+       tail __sigsetjmp_tail
diff --git a/src/thread/riscv64/__set_thread_area.s b/src/thread/riscv64/__set_thread_area.s
new file mode 100644 (file)
index 0000000..828154d
--- /dev/null
@@ -0,0 +1,6 @@
+.global __set_thread_area
+.type   __set_thread_area, %function
+__set_thread_area:
+       mv tp, a0
+       li a0, 0
+       ret
diff --git a/src/thread/riscv64/__unmapself.s b/src/thread/riscv64/__unmapself.s
new file mode 100644 (file)
index 0000000..2849119
--- /dev/null
@@ -0,0 +1,7 @@
+.global __unmapself
+.type __unmapself, %function
+__unmapself:
+       li a7, 215 # SYS_munmap
+       ecall
+       li a7, 93  # SYS_exit
+       ecall
diff --git a/src/thread/riscv64/clone.s b/src/thread/riscv64/clone.s
new file mode 100644 (file)
index 0000000..db90824
--- /dev/null
@@ -0,0 +1,34 @@
+# __clone(func, stack, flags, arg, ptid, tls, ctid)
+#           a0,    a1,    a2,  a3,   a4,  a5,   a6
+
+# syscall(SYS_clone, flags, stack, ptid, tls, ctid)
+#                a7     a0,    a1,   a2,  a3,   a4
+
+.global __clone
+.type  __clone, %function
+__clone:
+       # Save func and arg to stack
+       addi a1, a1, -16
+       sd a0, 0(a1)
+       sd a3, 8(a1)
+
+       # Call SYS_clone
+       mv a0, a2
+       mv a2, a4
+       mv a3, a5
+       mv a4, a6
+       li a7, 220 # SYS_clone
+       ecall
+
+       beqz a0, 1f
+       # Parent
+       ret
+
+       # Child
+1:      ld a1, 0(sp)
+       ld a0, 8(sp)
+       jalr a1
+
+       # Exit
+       li a7, 93 # SYS_exit
+       ecall
diff --git a/src/thread/riscv64/syscall_cp.s b/src/thread/riscv64/syscall_cp.s
new file mode 100644 (file)
index 0000000..eeef639
--- /dev/null
@@ -0,0 +1,29 @@
+.global __cp_begin
+.hidden __cp_begin
+.global __cp_end
+.hidden __cp_end
+.global __cp_cancel
+.hidden __cp_cancel
+.hidden __cancel
+.global __syscall_cp_asm
+.hidden __syscall_cp_asm
+.type __syscall_cp_asm, %function
+__syscall_cp_asm:
+__cp_begin:
+       lw t0, 0(a0)
+       bnez t0, __cp_cancel
+
+       mv t0, a1
+       mv a0, a2
+       mv a1, a3
+       mv a2, a4
+       mv a3, a5
+       mv a4, a6
+       mv a5, a7
+       ld a6, 0(sp)
+       mv a7, t0
+       ecall
+__cp_end:
+       ret
+__cp_cancel:
+       tail __cancel