diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index 51cbafc133..4e1b237d0d 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -491,6 +491,71 @@ fn clone() callconv(.Naked) void { \\ syscall ); }, + .powerpc => { + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // 3, 4, 5, 6, 7, 8, 9 + + // syscall(SYS_clone, flags, stack, ptid, tls, ctid) + // 0 3, 4, 5, 6, 7 + asm volatile ( + \\# store non-volatile regs r30, r31 on stack in order to put our + \\# start func and its arg there + \\stwu 30, -16(1) + \\stw 31, 4(1) + \\ + \\# save r3 (func) into r30, and r6(arg) into r31 + \\mr 30, 3 + \\mr 31, 6 + \\ + \\# create initial stack frame for new thread + \\clrrwi 4, 4, 4 + \\li 0, 0 + \\stwu 0, -16(4) + \\ + \\#move c into first arg + \\mr 3, 5 + \\#mr 4, 4 + \\mr 5, 7 + \\mr 6, 8 + \\mr 7, 9 + \\ + \\# move syscall number into r0 + \\li 0, 120 + \\ + \\sc + \\ + \\# check for syscall error + \\bns+ 1f # jump to label 1 if no summary overflow. + \\#else + \\neg 3, 3 #negate the result (errno) + \\1: + \\# compare sc result with 0 + \\cmpwi cr7, 3, 0 + \\ + \\# if not 0, jump to end + \\bne cr7, 2f + \\ + \\#else: we're the child + \\#call funcptr: move arg (d) into r3 + \\mr 3, 31 + \\#move r30 (funcptr) into CTR reg + \\mtctr 30 + \\# call CTR reg + \\bctrl + \\# mov SYS_exit into r0 (the exit param is already in r3) + \\li 0, 1 + \\sc + \\ + \\2: + \\ + \\# restore stack + \\lwz 30, 0(1) + \\lwz 31, 4(1) + \\addi 1, 1, 16 + \\ + \\blr + ); + }, .powerpc64, .powerpc64le => { // __clone(func, stack, flags, arg, ptid, tls, ctid) // 3, 4, 5, 6, 7, 8, 9