diff options
Diffstat (limited to 'libc-top-half/musl/src/thread/s390x/clone.s')
-rw-r--r-- | libc-top-half/musl/src/thread/s390x/clone.s | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/thread/s390x/clone.s b/libc-top-half/musl/src/thread/s390x/clone.s new file mode 100644 index 0000000..2125f20 --- /dev/null +++ b/libc-top-half/musl/src/thread/s390x/clone.s @@ -0,0 +1,54 @@ +.text +.global __clone +.hidden __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; + + # preserve call-saved register used as syscall arg + stg %r6, 48(%r15) + + # 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 + + # restore call-saved register + lg %r6, 48(%r15) + + # 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 |