summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-05-24 10:46:08 -0400
committerRich Felker <dalias@aerifal.cx>2019-06-14 17:13:05 -0400
commit0a48860c27a8eb291bcc7616ea9eb073dc660cab (patch)
tree6021d6d18943d7b883e38e2f3e20a3b81d916fc5 /src
parent5fc43798250255455e4b5f9b08000bd3102274d9 (diff)
downloadmusl-0a48860c27a8eb291bcc7616ea9eb073dc660cab.tar.gz
add riscv64 architecture support
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.
Diffstat (limited to 'src')
-rw-r--r--src/fenv/riscv64/fenv-sf.c3
-rw-r--r--src/fenv/riscv64/fenv.S53
-rw-r--r--src/ldso/riscv64/dlsym.s6
-rw-r--r--src/linux/cache.c33
-rw-r--r--src/math/riscv64/copysign.c15
-rw-r--r--src/math/riscv64/copysignf.c15
-rw-r--r--src/math/riscv64/fabs.c15
-rw-r--r--src/math/riscv64/fabsf.c15
-rw-r--r--src/math/riscv64/fma.c15
-rw-r--r--src/math/riscv64/fmaf.c15
-rw-r--r--src/math/riscv64/fmax.c15
-rw-r--r--src/math/riscv64/fmaxf.c15
-rw-r--r--src/math/riscv64/fmin.c15
-rw-r--r--src/math/riscv64/fminf.c15
-rw-r--r--src/math/riscv64/sqrt.c15
-rw-r--r--src/math/riscv64/sqrtf.c15
-rw-r--r--src/setjmp/riscv64/longjmp.S42
-rw-r--r--src/setjmp/riscv64/setjmp.S41
-rw-r--r--src/signal/riscv64/restore.s8
-rw-r--r--src/signal/riscv64/sigsetjmp.s23
-rw-r--r--src/thread/riscv64/__set_thread_area.s6
-rw-r--r--src/thread/riscv64/__unmapself.s7
-rw-r--r--src/thread/riscv64/clone.s34
-rw-r--r--src/thread/riscv64/syscall_cp.s29
24 files changed, 465 insertions, 0 deletions
diff --git a/src/fenv/riscv64/fenv-sf.c b/src/fenv/riscv64/fenv-sf.c
new file mode 100644
index 00000000..ecd3cb5c
--- /dev/null
+++ b/src/fenv/riscv64/fenv-sf.c
@@ -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
index 00000000..f149003d
--- /dev/null
+++ b/src/fenv/riscv64/fenv.S
@@ -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
index 00000000..2bafd72d
--- /dev/null
+++ b/src/ldso/riscv64/dlsym.s
@@ -0,0 +1,6 @@
+.global dlsym
+.hidden __dlsym
+.type dlsym, %function
+dlsym:
+ mv a2, ra
+ tail __dlsym
diff --git a/src/linux/cache.c b/src/linux/cache.c
index 84a138a4..0eb051c2 100644
--- a/src/linux/cache.c
+++ b/src/linux/cache.c
@@ -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
index 00000000..c7854178
--- /dev/null
+++ b/src/math/riscv64/copysign.c
@@ -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
index 00000000..a125611a
--- /dev/null
+++ b/src/math/riscv64/copysignf.c
@@ -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
index 00000000..5290b6f0
--- /dev/null
+++ b/src/math/riscv64/fabs.c
@@ -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
index 00000000..f5032e35
--- /dev/null
+++ b/src/math/riscv64/fabsf.c
@@ -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
index 00000000..99b05713
--- /dev/null
+++ b/src/math/riscv64/fma.c
@@ -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
index 00000000..f9dc47ed
--- /dev/null
+++ b/src/math/riscv64/fmaf.c
@@ -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
index 00000000..023709cd
--- /dev/null
+++ b/src/math/riscv64/fmax.c
@@ -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
index 00000000..863d2bd1
--- /dev/null
+++ b/src/math/riscv64/fmaxf.c
@@ -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
index 00000000..a4e3b067
--- /dev/null
+++ b/src/math/riscv64/fmin.c
@@ -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
index 00000000..32156e80
--- /dev/null
+++ b/src/math/riscv64/fminf.c
@@ -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
index 00000000..867a504c
--- /dev/null
+++ b/src/math/riscv64/sqrt.c
@@ -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
index 00000000..610c2cf8
--- /dev/null
+++ b/src/math/riscv64/sqrtf.c
@@ -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
index 00000000..41e2d210
--- /dev/null
+++ b/src/setjmp/riscv64/longjmp.S
@@ -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
index 00000000..51249672
--- /dev/null
+++ b/src/setjmp/riscv64/setjmp.S
@@ -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
index 00000000..40012c75
--- /dev/null
+++ b/src/signal/riscv64/restore.s
@@ -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
index 00000000..f9bc162a
--- /dev/null
+++ b/src/signal/riscv64/sigsetjmp.s
@@ -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
index 00000000..828154d2
--- /dev/null
+++ b/src/thread/riscv64/__set_thread_area.s
@@ -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
index 00000000..2849119c
--- /dev/null
+++ b/src/thread/riscv64/__unmapself.s
@@ -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
index 00000000..db908248
--- /dev/null
+++ b/src/thread/riscv64/clone.s
@@ -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
index 00000000..eeef6391
--- /dev/null
+++ b/src/thread/riscv64/syscall_cp.s
@@ -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