diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fenv/s390x/fenv.c | 55 | ||||
-rw-r--r-- | src/internal/s390x/syscall.s | 15 | ||||
-rw-r--r-- | src/process/s390x/vfork.s | 8 | ||||
-rw-r--r-- | src/setjmp/s390x/longjmp.s | 23 | ||||
-rw-r--r-- | src/setjmp/s390x/setjmp.s | 25 | ||||
-rw-r--r-- | src/signal/s390x/restore.s | 9 | ||||
-rw-r--r-- | src/signal/s390x/sigsetjmp.s | 23 | ||||
-rw-r--r-- | src/thread/s390x/__set_thread_area.s | 9 | ||||
-rw-r--r-- | src/thread/s390x/__tls_get_offset.s | 17 | ||||
-rw-r--r-- | src/thread/s390x/__unmapself.s | 6 | ||||
-rw-r--r-- | src/thread/s390x/clone.s | 47 | ||||
-rw-r--r-- | src/thread/s390x/syscall_cp.s | 32 |
12 files changed, 269 insertions, 0 deletions
diff --git a/src/fenv/s390x/fenv.c b/src/fenv/s390x/fenv.c new file mode 100644 index 00000000..9a3488d7 --- /dev/null +++ b/src/fenv/s390x/fenv.c @@ -0,0 +1,55 @@ +#include <fenv.h> + +static inline unsigned get_fpc(void) +{ + unsigned fpc; + __asm__ __volatile__("efpc %0" : "=r"(fpc)); + return fpc; +} + +static inline void set_fpc(unsigned fpc) +{ + __asm__ __volatile__("sfpc %0" :: "r"(fpc)); +} + +int feclearexcept(int mask) +{ + mask &= FE_ALL_EXCEPT; + set_fpc(get_fpc() & ~mask); + return 0; +} + +int feraiseexcept(int mask) +{ + mask &= FE_ALL_EXCEPT; + set_fpc(get_fpc() | mask); + return 0; +} + +int fetestexcept(int mask) +{ + return get_fpc() & mask & FE_ALL_EXCEPT; +} + +int fegetround(void) +{ + return get_fpc() & 3; +} + +int __fesetround(int r) +{ + set_fpc(get_fpc() & ~3L | r); + return 0; +} + +int fegetenv(fenv_t *envp) +{ + *envp = get_fpc(); + return 0; +} + +int fesetenv(const fenv_t *envp) +{ + set_fpc(envp != FE_DFL_ENV ? *envp : 0); + return 0; +} diff --git a/src/internal/s390x/syscall.s b/src/internal/s390x/syscall.s new file mode 100644 index 00000000..2322bc36 --- /dev/null +++ b/src/internal/s390x/syscall.s @@ -0,0 +1,15 @@ +.global __syscall +.hidden __syscall +.type __syscall, %function +__syscall: + stg %r7, 56(%r15) + lgr %r1, %r2 + lgr %r2, %r3 + lgr %r3, %r4 + lgr %r4, %r5 + lgr %r5, %r6 + lg %r6, 160(%r15) + lg %r7, 168(%r15) + svc 0 + lg %r7, 56(%r15) + br %r14 diff --git a/src/process/s390x/vfork.s b/src/process/s390x/vfork.s new file mode 100644 index 00000000..05956e81 --- /dev/null +++ b/src/process/s390x/vfork.s @@ -0,0 +1,8 @@ + .global __vfork + .weak vfork + .type __vfork,%function + .type vfork,%function +__vfork: +vfork: + svc 190 + jg __syscall_ret diff --git a/src/setjmp/s390x/longjmp.s b/src/setjmp/s390x/longjmp.s new file mode 100644 index 00000000..b2310f8a --- /dev/null +++ b/src/setjmp/s390x/longjmp.s @@ -0,0 +1,23 @@ + .global _longjmp + .global longjmp + .type _longjmp,@function + .type longjmp,@function +_longjmp: +longjmp: + +1: + lmg %r6, %r15, 0(%r2) + + ld %f8, 10*8(%r2) + ld %f9, 11*8(%r2) + ld %f10, 12*8(%r2) + ld %f11, 13*8(%r2) + ld %f12, 14*8(%r2) + ld %f13, 15*8(%r2) + ld %f14, 16*8(%r2) + ld %f15, 17*8(%r2) + + ltgr %r2, %r3 + bnzr %r14 + lhi %r2, 1 + br %r14 diff --git a/src/setjmp/s390x/setjmp.s b/src/setjmp/s390x/setjmp.s new file mode 100644 index 00000000..afae1b67 --- /dev/null +++ b/src/setjmp/s390x/setjmp.s @@ -0,0 +1,25 @@ + .global ___setjmp + .hidden ___setjmp + .global __setjmp + .global _setjmp + .global setjmp + .type __setjmp,@function + .type _setjmp,@function + .type setjmp,@function +___setjmp: +__setjmp: +_setjmp: +setjmp: + stmg %r6, %r15, 0(%r2) + + std %f8, 10*8(%r2) + std %f9, 11*8(%r2) + std %f10, 12*8(%r2) + std %f11, 13*8(%r2) + std %f12, 14*8(%r2) + std %f13, 15*8(%r2) + std %f14, 16*8(%r2) + std %f15, 17*8(%r2) + + lghi %r2, 0 + br %r14 diff --git a/src/signal/s390x/restore.s b/src/signal/s390x/restore.s new file mode 100644 index 00000000..79beb68f --- /dev/null +++ b/src/signal/s390x/restore.s @@ -0,0 +1,9 @@ + .global __restore + .type __restore,%function +__restore: + svc 119 #__NR_sigreturn + + .global __restore_rt + .type __restore_rt,%function +__restore_rt: + svc 173 # __NR_rt_sigreturn diff --git a/src/signal/s390x/sigsetjmp.s b/src/signal/s390x/sigsetjmp.s new file mode 100644 index 00000000..72dfc25d --- /dev/null +++ b/src/signal/s390x/sigsetjmp.s @@ -0,0 +1,23 @@ + .global sigsetjmp + .global __sigsetjmp + .type sigsetjmp,%function + .type __sigsetjmp,%function + .hidden ___setjmp +sigsetjmp: +__sigsetjmp: + ltgr %r3, %r3 + bz ___setjmp + + stg %r14, 18*8(%r2) + stg %r6, 20*8(%r2) + lgr %r6, %r2 + + brasl %r14, ___setjmp + + lgr %r3, %r2 + lgr %r2, %r6 + lg %r14, 18*8(%r2) + lg %r6, 20*8(%r2) + +.hidden __sigsetjmp_tail + jg __sigsetjmp_tail diff --git a/src/thread/s390x/__set_thread_area.s b/src/thread/s390x/__set_thread_area.s new file mode 100644 index 00000000..fd412913 --- /dev/null +++ b/src/thread/s390x/__set_thread_area.s @@ -0,0 +1,9 @@ +.text +.global __set_thread_area +.type __set_thread_area, %function +__set_thread_area: + sar %a1, %r2 + srlg %r2, %r2, 32 + sar %a0, %r2 + lghi %r2, 0 + br %r14 diff --git a/src/thread/s390x/__tls_get_offset.s b/src/thread/s390x/__tls_get_offset.s new file mode 100644 index 00000000..8ee92de8 --- /dev/null +++ b/src/thread/s390x/__tls_get_offset.s @@ -0,0 +1,17 @@ + .global __tls_get_offset + .type __tls_get_offset,%function +__tls_get_offset: + stmg %r14, %r15, 112(%r15) + aghi %r15, -160 + + la %r2, 0(%r2, %r12) + brasl %r14, __tls_get_addr + + ear %r1, %a0 + sllg %r1, %r1, 32 + ear %r1, %a1 + + sgr %r2, %r1 + + lmg %r14, %r15, 272(%r15) + br %r14 diff --git a/src/thread/s390x/__unmapself.s b/src/thread/s390x/__unmapself.s new file mode 100644 index 00000000..48b312cd --- /dev/null +++ b/src/thread/s390x/__unmapself.s @@ -0,0 +1,6 @@ +.text +.global __unmapself +.type __unmapself, @function +__unmapself: + svc 91 # SYS_munmap + svc 1 # SYS_exit diff --git a/src/thread/s390x/clone.s b/src/thread/s390x/clone.s new file mode 100644 index 00000000..3e08c213 --- /dev/null +++ b/src/thread/s390x/clone.s @@ -0,0 +1,47 @@ +.text +.global __clone +.type __clone, %function +__clone: + # int clone( + # fn, a = r2 + # stack, b = r3 + # flags, c = r4 + # arg, d = r5 + # ptid, e = r6 + # tls, f = *(r15+160) + # ctid) g = *(r15+168) + # + # pseudo C code: + # tid = syscall(SYS_clone,b,c,e,g,f); + # if (!tid) syscall(SYS_exit, a(d)); + # return tid; + + # create initial stack frame for new thread + nill %r3, 0xfff8 + aghi %r3, -160 + lghi %r0, 0 + stg %r0, 0(%r3) + + # save fn and arg to child stack + stg %r2, 8(%r3) + stg %r5, 16(%r3) + + # shuffle args into correct registers and call SYS_clone + lgr %r2, %r3 + lgr %r3, %r4 + lgr %r4, %r6 + lg %r5, 168(%r15) + lg %r6, 160(%r15) + svc 120 + + # if error or if we're the parent, return + ltgr %r2, %r2 + bnzr %r14 + + # we're the child. call fn(arg) + lg %r1, 8(%r15) + lg %r2, 16(%r15) + basr %r14, %r1 + + # call SYS_exit. exit code is already in r2 from fn return value + svc 1 diff --git a/src/thread/s390x/syscall_cp.s b/src/thread/s390x/syscall_cp.s new file mode 100644 index 00000000..c1da40de --- /dev/null +++ b/src/thread/s390x/syscall_cp.s @@ -0,0 +1,32 @@ + .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 + .text + .type __syscall_cp_asm,%function +__syscall_cp_asm: +__cp_begin: + icm %r2, 15, 0(%r2) + jne __cp_cancel + + stg %r7, 56(%r15) + lgr %r1, %r3 + lgr %r2, %r4 + lgr %r3, %r5 + lgr %r4, %r6 + lg %r5, 160(%r15) + lg %r6, 168(%r15) + lg %r7, 176(%r15) + svc 0 + +__cp_end: + lg %r7, 56(%r15) + br %r14 + +__cp_cancel: + jg __cancel |