From cf2ee4ae2c6608261e849f0d75209669d435624c Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 27 Nov 2020 18:51:50 +0700 Subject: [PATCH 1/3] Add sparc64 long double mapping --- src/stage1/codegen.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 6a02f2912b..b449fb2fea 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); From 41c40f4bbec35ac260b6a7af6b0db0dafccb56ca Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 27 Nov 2020 23:02:22 +0700 Subject: [PATCH 2/3] Fix fork() on Linux/sparc64 fork() on Linux/sparc64 seems to return its result in two registers, with %o0 always holding the current process' PID, and the parent/child status returned in %o1. Add some glue code to convert those into the libc-style return value. --- lib/std/os/linux.zig | 4 +++- lib/std/os/linux/sparc64.zig | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) 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..20fdc275dd 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -21,6 +21,23 @@ pub fn syscall_pipe(fd: *[2]i32) usize { ); } +pub fn syscall_fork() usize { + return asm volatile ( + \\ t 0x6d + \\ bcc,pt %%xcc, 1f + \\ nop + \\ ba 2f + \\ neg %%o0 + \\ 1: + \\ 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 From f10bff9ffb452eaf22af8dd85412653ac8bd1081 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 28 Nov 2020 13:24:24 +0700 Subject: [PATCH 3/3] Add a comment to explain the fork return values on sparc64 --- lib/std/os/linux/sparc64.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index 20fdc275dd..902940071e 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -22,6 +22,11 @@ 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 @@ -29,6 +34,7 @@ pub fn syscall_fork() usize { \\ ba 2f \\ neg %%o0 \\ 1: + \\ # Clear the child's %%o0 \\ dec %%o1 \\ and %%o1, %%o0, %%o0 \\ 2: