diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig index c8e03a1b04..a77ecab16b 100644 --- a/lib/std/os/linux/powerpc.zig +++ b/lib/std/os/linux/powerpc.zig @@ -15,84 +15,125 @@ const sockaddr = linux.sockaddr; const timespec = linux.timespec; pub fn syscall0(number: SYS) usize { + // r0 is both an input register and a clobber. musl and glibc achieve this with + // a "+" constraint, which isn't supported in Zig, so instead we separately list + // r0 as both an input and an output. (Listing it as an input and a clobber would + // cause the C backend to emit invalid code; see #25209.) + var r0_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@intFromEnum(number)), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall1(number: SYS, arg1: usize) usize { + // r0 is both an input and a clobber. + var r0_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; + var r6_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), + [r6_out] "={r6}" (r6_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), [arg4] "{r6}" (arg4), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; + var r6_out: usize = undefined; + var r7_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), + [r6_out] "={r6}" (r6_out), + [r7_out] "={r7}" (r7_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), [arg4] "{r6}" (arg4), [arg5] "{r7}" (arg5), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall6( @@ -104,12 +145,25 @@ pub fn syscall6( arg5: usize, arg6: usize, ) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; + var r6_out: usize = undefined; + var r7_out: usize = undefined; + var r8_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), + [r6_out] "={r6}" (r6_out), + [r7_out] "={r7}" (r7_out), + [r8_out] "={r8}" (r8_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), @@ -117,7 +171,7 @@ pub fn syscall6( [arg4] "{r6}" (arg4), [arg5] "{r7}" (arg5), [arg6] "{r8}" (arg6), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn clone() callconv(.naked) usize { diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig index ff07ac9180..1e42dc88c8 100644 --- a/lib/std/os/linux/powerpc64.zig +++ b/lib/std/os/linux/powerpc64.zig @@ -15,84 +15,125 @@ const sockaddr = linux.sockaddr; const timespec = linux.timespec; pub fn syscall0(number: SYS) usize { + // r0 is both an input register and a clobber. musl and glibc achieve this with + // a "+" constraint, which isn't supported in Zig, so instead we separately list + // r0 as both an input and an output. (Listing it as an input and a clobber would + // cause the C backend to emit invalid code; see #25209.) + var r0_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@intFromEnum(number)), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall1(number: SYS, arg1: usize) usize { + // r0 is both an input and a clobber. + var r0_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; + var r6_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), + [r6_out] "={r6}" (r6_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), [arg4] "{r6}" (arg4), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; + var r6_out: usize = undefined; + var r7_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), + [r6_out] "={r6}" (r6_out), + [r7_out] "={r7}" (r7_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), [arg4] "{r6}" (arg4), [arg5] "{r7}" (arg5), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn syscall6( @@ -104,12 +145,25 @@ pub fn syscall6( arg5: usize, arg6: usize, ) usize { + // These registers are both inputs and clobbers. + var r0_out: usize = undefined; + var r4_out: usize = undefined; + var r5_out: usize = undefined; + var r6_out: usize = undefined; + var r7_out: usize = undefined; + var r8_out: usize = undefined; return asm volatile ( \\ sc \\ bns+ 1f \\ neg 3, 3 \\ 1: : [ret] "={r3}" (-> usize), + [r0_out] "={r0}" (r0_out), + [r4_out] "={r4}" (r4_out), + [r5_out] "={r5}" (r5_out), + [r6_out] "={r6}" (r6_out), + [r7_out] "={r7}" (r7_out), + [r8_out] "={r8}" (r8_out), : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), @@ -117,7 +171,7 @@ pub fn syscall6( [arg4] "{r6}" (arg4), [arg5] "{r7}" (arg5), [arg6] "{r8}" (arg6), - : .{ .memory = true, .cr0 = true, .r0 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); + : .{ .memory = true, .cr0 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .ctr = true, .xer = true }); } pub fn clone() callconv(.naked) usize {