diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 56e9d45a08..dbb9225aa2 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -112,7 +112,9 @@ pub fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*: } pub fn fork() usize { - if (@hasField(SYS, "fork")) { + if (comptime builtin.arch.isSPARC()) { + return syscall_fork(); + } else if (@hasField(SYS, "fork")) { return syscall0(.fork); } else { return syscall2(.clone, SIGCHLD, 0); diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index eefa4d60fd..902940071e 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -21,6 +21,29 @@ pub fn syscall_pipe(fd: *[2]i32) usize { ); } +pub fn syscall_fork() usize { + // Linux/sparc64 fork() returns two values in %o0 and %o1: + // - On the parent's side, %o0 is the child's PID and %o1 is 0. + // - On the child's side, %o0 is the parent's PID and %o1 is 1. + // We need to clear the child's %o0 so that the return values + // conform to the libc convention. + return asm volatile ( + \\ t 0x6d + \\ bcc,pt %%xcc, 1f + \\ nop + \\ ba 2f + \\ neg %%o0 + \\ 1: + \\ # Clear the child's %%o0 + \\ dec %%o1 + \\ and %%o1, %%o0, %%o0 + \\ 2: + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(SYS.fork)) + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" + ); +} + pub fn syscall0(number: SYS) usize { return asm volatile ( \\ t 0x6d diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index d308522943..bc55aa1936 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -8640,6 +8640,9 @@ static void define_builtin_types(CodeGen *g) { case ZigLLVM_ppc64le: add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble); break; + case ZigLLVM_sparcv9: + add_fp_entry(g, "c_longdouble", 128, LLVMFP128Type(), &g->builtin_types.entry_c_longdouble); + break; case ZigLLVM_avr: // It's either a float or a double, depending on a toolchain switch add_fp_entry(g, "c_longdouble", 64, LLVMDoubleType(), &g->builtin_types.entry_c_longdouble);