From 8750266719007e666c0af6e66420f1ad579b0974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 02:14:50 +0200 Subject: [PATCH 01/45] std.start: remove unnecessary @plt in riscv _start assembly posixCallMainAndExit is a local symbol so it will never go through the PLT, and we wouldn't want it to either due to static PIE. --- lib/std/start.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index 6021da10325aa38a6be00d59ecc1d58634deba77..f477b9b5fa53788533b1e668f795b45c804fac77 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -332,7 +332,7 @@ fn _start() callconv(.naked) noreturn { \\ li ra, 0 \\ mv a0, sp \\ andi sp, sp, -16 - \\ tail %[posixCallMainAndExit]@plt + \\ tail %[posixCallMainAndExit] , .m68k => // Note that the - 8 is needed because pc in the jsr instruction points into the middle -- 2.54.0 From 1df99ba96a11fa8c16821018681683835cedb7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 02:41:04 +0200 Subject: [PATCH 02/45] std.start: fix csky _start assembly to be static PIE safe The jmpi form that was used here will rely on a literal pool entry containing a relocation. Instead, use @GOTOFF since we've already set up gb anyway. --- lib/std/start.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index f477b9b5fa53788533b1e668f795b45c804fac77..92482d6a9109d335f9f3ddb1784247d66e5a0302 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -276,14 +276,16 @@ fn _start() callconv(.naked) noreturn { // `_DYNAMIC` as well. // r8 = FP \\ grs t0, 1f - \\ 1: + \\1: \\ lrw gb, 1b@GOTPC \\ addu gb, t0 \\ movi r8, 0 \\ movi lr, 0 \\ mov a0, sp \\ andi sp, sp, -8 - \\ jmpi %[posixCallMainAndExit] + \\ lrw t1, %[posixCallMainAndExit]@GOTOFF + \\ addu t1, gb + \\ jmp t1 , .hexagon => // r29 = SP, r30 = FP, r31 = LR -- 2.54.0 From 9ca1d1e6b1e7eef01f59703f10d7d4dcb10dfcfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 02:44:02 +0200 Subject: [PATCH 03/45] std.start: fix alpha _start assembly to be static PIE safe jsr used in this way is a macro for ldq t12, (gp) jsr ra, (t12), with relocations on both instructions. br avoids this. --- lib/std/start.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index 92482d6a9109d335f9f3ddb1784247d66e5a0302..cef9f81dc13832ddd109004141bafa2e3e579c72 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -247,7 +247,7 @@ fn _start() callconv(.naked) noreturn { \\ mov $30, $16 \\ ldi $1, -16 \\ and $30, $30, $1 - \\ jsr $26, %[posixCallMainAndExit] + \\ br $31, %[posixCallMainAndExit] , .arc, .arceb => // ARC v1 and v2 had a very low stack alignment requirement of 4; v3 increased it to 16. -- 2.54.0 From dc169ff2b5183471110f84103c11c59f56309210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 02:53:14 +0200 Subject: [PATCH 04/45] std.start: fix stack alignment in mips n32 _start assembly It should be 16 for both N64 and N32; only O32 uses 8. --- lib/std/start.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index cef9f81dc13832ddd109004141bafa2e3e579c72..9e8ea47877453d7e7b079b2cbddb430c1e8a67af 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -401,7 +401,7 @@ fn _start() callconv(.naked) noreturn { \\ addu $t9, $t9, $gp \\ move $ra, $zero \\ move $a0, $sp - \\ and $sp, -8 + \\ and $sp, -16 \\ subu $sp, $sp, 16 \\ jalr $t9 , -- 2.54.0 From 3822af14071ec2ffe03427079c343549f0143d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 03:03:19 +0200 Subject: [PATCH 05/45] std: fix stack alignment instruction in csky _start and clone assembly andi zero-extends its operand so this usage doesn't assemble; use andni instead. --- lib/std/os/linux/csky.zig | 2 +- lib/std/start.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/csky.zig b/lib/std/os/linux/csky.zig index 9a0e854979d79614c8b40235d39e5e03f873bb04..4d456b08f210dce3f61da784333f067f341b8445 100644 --- a/lib/std/os/linux/csky.zig +++ b/lib/std/os/linux/csky.zig @@ -120,7 +120,7 @@ pub fn clone() callconv(.naked) u32 { \\ mov t0, r4 \\ mov t1, r7 \\ - \\ andi r1, r1, -8 + \\ andni r1, r1, 7 \\ \\ subi r1, 8 \\ stw r0, (r1, 0) diff --git a/lib/std/start.zig b/lib/std/start.zig index 9e8ea47877453d7e7b079b2cbddb430c1e8a67af..92e0df4ed4b938f64a01a2c9cd51494ae8271447 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -282,7 +282,7 @@ fn _start() callconv(.naked) noreturn { \\ movi r8, 0 \\ movi lr, 0 \\ mov a0, sp - \\ andi sp, sp, -8 + \\ andni sp, sp, 7 \\ lrw t1, %[posixCallMainAndExit]@GOTOFF \\ addu t1, gb \\ jmp t1 -- 2.54.0 From 3b947932abbb9f14710c64e3afa6fa88947d1ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 02:52:48 +0200 Subject: [PATCH 06/45] std: avoid pointless delay slots and lr writes in inline assembly And fill in some delay slots where we can't avoid them. --- lib/std/Thread.zig | 64 +++++++++++++++++------------------ lib/std/debug/cpu_context.zig | 5 +++ lib/std/os/linux/or1k.zig | 3 ++ lib/std/os/linux/tls.zig | 1 + lib/std/pie.zig | 2 ++ lib/std/start.zig | 18 +++++----- 6 files changed, 53 insertions(+), 40 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 0cc439d07da7d8a6c0de39a65bf83800ea9b6992..bd3f9e1f019fea9de6f06b8da4df47cdf11eaa0a 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1166,29 +1166,29 @@ const LinuxThreadImpl = struct { posix.sigprocmask(std.posix.SIG.BLOCK, &std.os.linux.sigfillset(), null); switch (target.cpu.arch) { .x86 => asm volatile ( - \\ movl $91, %%eax # SYS_munmap - \\ int $128 - \\ movl $1, %%eax # SYS_exit - \\ movl $0, %%ebx - \\ int $128 + \\ movl $91, %%eax # SYS_munmap + \\ int $128 + \\ movl $1, %%eax # SYS_exit + \\ movl $0, %%ebx + \\ int $128 : : [ptr] "{ebx}" (@intFromPtr(self.mapped.ptr)), [len] "{ecx}" (self.mapped.len), ), .x86_64 => asm volatile (switch (target.abi) { .gnux32, .muslx32, .x32 => - \\ movl $0x4000000b, %%eax # SYS_munmap - \\ syscall - \\ movl $0x4000003c, %%eax # SYS_exit - \\ xor %%rdi, %%rdi - \\ syscall + \\ movl $0x4000000b, %%eax # SYS_munmap + \\ syscall + \\ movl $0x4000003c, %%eax # SYS_exit + \\ xor %%rdi, %%rdi + \\ syscall , else => - \\ movl $11, %%eax # SYS_munmap - \\ syscall - \\ movl $60, %%eax # SYS_exit - \\ xor %%rdi, %%rdi - \\ syscall + \\ movl $11, %%eax # SYS_munmap + \\ syscall + \\ movl $60, %%eax # SYS_exit + \\ xor %%rdi, %%rdi + \\ syscall , } : @@ -1196,21 +1196,21 @@ const LinuxThreadImpl = struct { [len] "{rsi}" (self.mapped.len), ), .arm, .armeb, .thumb, .thumbeb => asm volatile ( - \\ mov r7, #91 // SYS_munmap - \\ svc 0 - \\ mov r7, #1 // SYS_exit - \\ mov r0, #0 - \\ svc 0 + \\ mov r7, #91 // SYS_munmap + \\ svc 0 + \\ mov r7, #1 // SYS_exit + \\ mov r0, #0 + \\ svc 0 : : [ptr] "{r0}" (@intFromPtr(self.mapped.ptr)), [len] "{r1}" (self.mapped.len), ), .aarch64, .aarch64_be => asm volatile ( - \\ mov x8, #215 // SYS_munmap - \\ svc 0 - \\ mov x8, #93 // SYS_exit - \\ mov x0, #0 - \\ svc 0 + \\ mov x8, #215 // SYS_munmap + \\ svc 0 + \\ mov x8, #93 // SYS_exit + \\ mov x0, #0 + \\ svc 0 : : [ptr] "{x0}" (@intFromPtr(self.mapped.ptr)), [len] "{x1}" (self.mapped.len), @@ -1236,21 +1236,21 @@ const LinuxThreadImpl = struct { [len] "{r1}" (self.mapped.len), ), .hexagon => asm volatile ( - \\ r6 = #215 // SYS_munmap - \\ trap0(#1) - \\ r6 = #93 // SYS_exit - \\ r0 = #0 - \\ trap0(#1) + \\ r6 = #215 // SYS_munmap + \\ trap0(#1) + \\ r6 = #93 // SYS_exit + \\ r0 = #0 + \\ trap0(#1) : : [ptr] "{r0}" (@intFromPtr(self.mapped.ptr)), [len] "{r1}" (self.mapped.len), ), .hppa => asm volatile ( - \\ ldi 91, %%r20 /* SYS_munmap */ \\ ble 0x100(%%sr2, %%r0) - \\ ldi 1, %%r20 /* SYS_exit */ + \\ ldi 91, %%r20 /* SYS_munmap */ \\ ldi 0, %%r26 \\ ble 0x100(%%sr2, %%r0) + \\ ldi 1, %%r20 /* SYS_exit */ : : [ptr] "{r26}" (@intFromPtr(self.mapped.ptr)), [len] "{r25}" (self.mapped.len), diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index ab90b9b2c27e374ef56148334eb83fcc13d6ba75..6579ade9f4ca749170294c5a03cf91a9a4b7e3a8 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1039,6 +1039,7 @@ const Mips = extern struct { \\ sd $fp, 240($t0) \\ sd $ra, 248($t0) \\ bal 1f + \\ nop \\1: \\ sd $ra, 256($t0) \\ .set pop @@ -1080,6 +1081,7 @@ const Mips = extern struct { \\ sw $fp, 120($t4) \\ sw $ra, 124($t4) \\ bal 1f + \\ nop \\1: \\ sw $ra, 128($t4) \\ .set pop @@ -1164,6 +1166,7 @@ const Or1k = extern struct { \\ l.sw 120(r15), r30 \\ l.sw 124(r15), r31 \\ l.jal 1f + \\ l.nop \\1: \\ l.sw 128(r15), r9 : @@ -1558,6 +1561,7 @@ const Sparc = extern struct { \\ stx %i6, [%l0 + 240] \\ stx %i7, [%l0 + 248] \\ call 1f + \\ nop \\1: \\ stx %o7, [%l0 + 256] else @@ -1578,6 +1582,7 @@ const Sparc = extern struct { \\ std %i4, [%l0 + 112] \\ std %i6, [%l0 + 120] \\ call 1f + \\ nop \\1: \\ st %o7, [%l0 + 128] : diff --git a/lib/std/os/linux/or1k.zig b/lib/std/os/linux/or1k.zig index 2d27b49a8f4f44c4a8f601df3d108c8eedfe0f17..75dbef7623a4012cca599fd2d49cd3e9d49a6dcc 100644 --- a/lib/std/os/linux/or1k.zig +++ b/lib/std/os/linux/or1k.zig @@ -138,7 +138,9 @@ pub fn clone() callconv(.naked) u32 { \\ l.sys 1 \\ l.sfeqi r11, 0 \\ l.bf 1f + \\ l.nop \\ l.jr r9 + \\ l.nop \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( @@ -151,6 +153,7 @@ pub fn clone() callconv(.naked) u32 { \\ l.lwz r11, 0(r1) \\ l.lwz r3, 4(r1) \\ l.jalr r11 + \\ l.nop \\ \\ l.ori r3, r11, 0 \\ l.ori r11, r0, 93 # SYS_exit diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 81ccd5cb56eb90ff1d2d9582f45c6b22630a5173..798f5666311dbad2edbfd81bdd0e81c02c184019 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -295,6 +295,7 @@ pub fn setThreadPointer(addr: usize) void { .hppa => { asm volatile ( \\ ble 0xe0(%%sr2, %%r0) + \\ nop : : [addr] "={r26}" (addr), : .{ .r29 = true }); diff --git a/lib/std/pie.zig b/lib/std/pie.zig index bcec6acd590f391c56202ff897b364ee0d456554..60829b610d775816e00492428c48a6a0c31850ae 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -190,6 +190,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ .weak _DYNAMIC \\ .hidden _DYNAMIC \\ l.jal 1f + \\ l.nop \\ .word _DYNAMIC - . \\1: \\ l.lwz %[ret], 0(r9) @@ -245,6 +246,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ mov.l 1f, %[ret] \\ add r0, %[ret] \\ bra 2f + \\ nop \\1: \\ .balign 4 \\ .long DYNAMIC - . diff --git a/lib/std/start.zig b/lib/std/start.zig index 92e0df4ed4b938f64a01a2c9cd51494ae8271447..0e88eed1a478b09afc6490acffa9fca4c01b1fe2 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -295,7 +295,7 @@ fn _start() callconv(.naked) noreturn { \\ r29 = and(r29, #-8) \\ memw(r29 + #-8) = r29 \\ r29 = add(r29, #-8) - \\ call %[posixCallMainAndExit] + \\ jump %[posixCallMainAndExit] , .kvx => \\ make $fp = 0 @@ -327,7 +327,8 @@ fn _start() callconv(.naked) noreturn { \\ l.ori r9, r0, 0 \\ l.ori r3, r1, 0 \\ l.andi r1, r1, -4 - \\ l.jal %[posixCallMainAndExit] + \\ l.j %[posixCallMainAndExit] + \\ l.nop , .riscv32, .riscv32be, .riscv64, .riscv64be => \\ li fp, 0 @@ -356,7 +357,7 @@ fn _start() callconv(.naked) noreturn { \\ or %%r1, %%r0, %%r0 \\ or %%r2, %%r31, %%r0 \\ clr %%r31, %%r31, 4<0> - \\ br.n %[posixCallMainAndExit] + \\ br %[posixCallMainAndExit] , .microblaze, .microblazeel => // r1 = SP, r15 = LR, r19 = FP, r20 = GP @@ -366,7 +367,7 @@ fn _start() callconv(.naked) noreturn { \\ addi r20, r20, _GLOBAL_OFFSET_TABLE_ + 8 \\ ori r5, r1, 0 \\ andi r1, r1, -4 - \\ brlid r15, %[posixCallMainAndExit] + \\ bri %[posixCallMainAndExit] , .mips, .mipsel => \\ move $fp, $zero @@ -385,7 +386,7 @@ fn _start() callconv(.naked) noreturn { \\ move $a0, $sp \\ and $sp, -8 \\ subu $sp, $sp, 16 - \\ jalr $t9 + \\ jr $t9 , .mips64, .mips64el => switch (builtin.abi) { .gnuabin32, .muslabin32, .abin32 => @@ -403,7 +404,7 @@ fn _start() callconv(.naked) noreturn { \\ move $a0, $sp \\ and $sp, -16 \\ subu $sp, $sp, 16 - \\ jalr $t9 + \\ jr $t9 , else => \\ move $fp, $zero @@ -424,7 +425,7 @@ fn _start() callconv(.naked) noreturn { \\ move $a0, $sp \\ and $sp, -16 \\ dsubu $sp, $sp, 16 - \\ jalr $t9 + \\ jr $t9 , }, .powerpc, .powerpcle => @@ -476,7 +477,8 @@ fn _start() callconv(.naked) noreturn { \\ and r0, r15 \\ mov.l 2f, r1 \\1: - \\ bsrf r1 + \\ braf r1 + \\ nop \\2: \\ .balign 4 \\ .long %[posixCallMainAndExit]@PCREL - (1b + 4 - .) -- 2.54.0 From 2a155d75ac575c9a99918569249aecdf251e94d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 03:19:47 +0200 Subject: [PATCH 07/45] std: fix stack alignment in or1k _start and clone assembly l.andi zero-extends its operand so this would give the wrong result. Instead, use l.addi to materialize -4 and then l.and that. Rather unfortunate that the assembler doesn't reject this form. --- lib/std/os/linux/or1k.zig | 3 ++- lib/std/start.zig | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/or1k.zig b/lib/std/os/linux/or1k.zig index 75dbef7623a4012cca599fd2d49cd3e9d49a6dcc..a54b9bd43ff5464c29d920d222c4988440a267d7 100644 --- a/lib/std/os/linux/or1k.zig +++ b/lib/std/os/linux/or1k.zig @@ -124,7 +124,8 @@ pub fn clone() callconv(.naked) u32 { // r11 r3, r4, r5, r6, r7 asm volatile ( \\ # Save function pointer and argument pointer on new thread stack - \\ l.andi r4, r4, -4 + \\ l.addi r13, r0, -4 + \\ l.and r4, r4, r13 \\ l.addi r4, r4, -8 \\ l.sw 0(r4), r3 \\ l.sw 4(r4), r6 diff --git a/lib/std/start.zig b/lib/std/start.zig index 0e88eed1a478b09afc6490acffa9fca4c01b1fe2..c49453246fcc59f09d717fe08a9d000a418cd891 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -326,7 +326,8 @@ fn _start() callconv(.naked) noreturn { \\ l.ori r2, r0, 0 \\ l.ori r9, r0, 0 \\ l.ori r3, r1, 0 - \\ l.andi r1, r1, -4 + \\ l.addi r13, r0, -4 + \\ l.and r1, r1, r13 \\ l.j %[posixCallMainAndExit] \\ l.nop , -- 2.54.0 From ef4ce7def1d4868d1d54832fba473f84938e40be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 01:55:14 +0200 Subject: [PATCH 08/45] std: fix zeroing of lr in powerpc _start and clone assembly PowerPC assembly is wonderful because you can't tell at a glance whether an operand is an immediate integer or a register number. In this case, mtlr takes a register number, but we haven't zeroed r0, and it's not a hardwired zero register as on other architectures. Fix this by copying from r31 which we've just zeroed. --- lib/std/os/linux/powerpc.zig | 2 +- lib/std/os/linux/powerpc64.zig | 2 +- lib/std/start.zig | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig index 614c981f8ff891e2e3fed978b65866da9d9a6ab3..5bfaae2767ee33b4d0b1ff32ccafab0ed5f1a1b1 100644 --- a/lib/std/os/linux/powerpc.zig +++ b/lib/std/os/linux/powerpc.zig @@ -247,7 +247,7 @@ pub fn clone() callconv(.naked) u32 { ); asm volatile ( \\ li 31, 0 - \\ mtlr 0 + \\ mtlr 31 \\ \\ #call funcptr: move arg (d) into r3 \\ mr 3, 30 diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig index 89f3dbde7b3736d7cc021d55f0b9fb753f347789..5dd1fc9a9d8163ec50b37e58749a63d2eaf5312a 100644 --- a/lib/std/os/linux/powerpc64.zig +++ b/lib/std/os/linux/powerpc64.zig @@ -232,7 +232,7 @@ pub fn clone() callconv(.naked) u64 { ); asm volatile ( \\ li 31, 0 - \\ mtlr 0 + \\ mtlr 31 \\ \\ # call fn(arg) \\ ld 3, 16(1) diff --git a/lib/std/start.zig b/lib/std/start.zig index c49453246fcc59f09d717fe08a9d000a418cd891..ccfc572f0690ccbc254270b4d9c6c76bb66ccfa7 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -438,7 +438,7 @@ fn _start() callconv(.naked) noreturn { \\ stwu 1, -16(1) \\ stw 0, 0(1) \\ li 31, 0 - \\ mtlr 0 + \\ mtlr 31 \\ b %[posixCallMainAndExit] , .powerpc64, .powerpc64le => @@ -451,7 +451,7 @@ fn _start() callconv(.naked) noreturn { \\ li 0, 0 \\ stdu 0, -32(1) \\ li 31, 0 - \\ mtlr 0 + \\ mtlr 31 \\ b %[posixCallMainAndExit] \\ nop , -- 2.54.0 From 19a0cef7e8adfff9dea6f9672cc022ad267939ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 14:08:27 +0200 Subject: [PATCH 09/45] std.start: simplify sh _start assembly a bit A couple extra instructions, but this looks significantly less arcane. --- lib/std/start.zig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index ccfc572f0690ccbc254270b4d9c6c76bb66ccfa7..503de37118a60fabd7f45cf5d1ea7e362ee15e1e 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -476,13 +476,14 @@ fn _start() callconv(.naked) noreturn { \\ mov r15, r4 \\ mov #-4, r0 \\ and r0, r15 + \\ mova 2f, r0 \\ mov.l 2f, r1 - \\1: - \\ braf r1 + \\ add r0, r1 + \\ jmp @r1 \\ nop - \\2: \\ .balign 4 - \\ .long %[posixCallMainAndExit]@PCREL - (1b + 4 - .) + \\1: + \\ .long %[posixCallMainAndExit] - . , .sparc => // argc is stored after a register window (16 registers * 4 bytes). -- 2.54.0 From 82b9ba071f33f7404db5d987232493dd122e991a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 19:08:33 +0200 Subject: [PATCH 10/45] std.pie: fix alpha, csky, and microblaze assembly In hindsight, this approach was obviously not going to work since it's loading the unrelocated address of _DYNAMIC. Instead just use a PC-relative approach like other targets. --- lib/std/pie.zig | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 60829b610d775816e00492428c48a6a0c31850ae..a1bcc5c3dcbb3e9ab672a9236a1fb301da038ab9 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -83,7 +83,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ add %[ret], pc \\ b 2f \\1: - \\ .word _DYNAMIC-1b + \\ .word _DYNAMIC - 1b \\2: : [ret] "=r" (-> [*]const elf.Dyn), ), @@ -97,20 +97,29 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { ), // The compiler is not required to load the GP register, so do it ourselves. .alpha => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC \\ br $29, 1f \\1: \\ ldgp $29, 0($29) - \\ ldq %[ret], -0x8000($29) + \\ ldah %[ret], _DYNAMIC($29) !gprelhigh + \\ lda %[ret], _DYNAMIC(%[ret]) !gprellow : [ret] "=r" (-> [*]const elf.Dyn), : - : .{ .r26 = true, .r29 = true }), - // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first - // entry in the GOT is defined to hold the address of _DYNAMIC. + : .{ .r29 = true }), .csky => asm volatile ( - \\ mov %[ret], gb - \\ ldw %[ret], %[ret] + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ grs %[ret], 1f + \\ br 2f + \\1: + \\ .long _DYNAMIC - 1b + \\2: + \\ ldw r12, (%[ret], 0) + \\ addu %[ret], %[ret], r12 : [ret] "=r" (-> [*]const elf.Dyn), - ), + : + : .{ .r12 = true }), .hexagon => asm volatile ( \\ .weak _DYNAMIC \\ .hidden _DYNAMIC @@ -146,9 +155,17 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { : [ret] "=r" (-> [*]const elf.Dyn), ), .microblaze, .microblazeel => asm volatile ( - \\ lwi %[ret], r20, 0 + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ mfs %[ret], rpc + \\ bri 1f + \\ .word _DYNAMIC - . + 8 + \\1: + \\ lwi r18, %[ret], 8 + \\ add %[ret], %[ret], r18 : [ret] "=r" (-> [*]const elf.Dyn), - ), + : + : .{ .r18 = true }), .mips, .mipsel => asm volatile ( \\ .weak _DYNAMIC \\ .hidden _DYNAMIC -- 2.54.0 From ee1983a985c013905f23a95adbac77cbd6e578f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 19:13:18 +0200 Subject: [PATCH 11/45] std.pie: fix sparc assembly to actually load &_DYNAMIC It was loading &_GLOBAL_OFFSET_TABLE_[0] rather than &_DYNAMIC. I suspect that I committed this before actually finishing writing it. --- lib/std/pie.zig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index a1bcc5c3dcbb3e9ab672a9236a1fb301da038ab9..84f8d35e8c082063fba23846978bb6f6c6d12eaf 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -271,17 +271,17 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { : [ret] "=r" (-> [*]const elf.Dyn), : : .{ .r0 = true }), - // The compiler does not necessarily have any obligation to load the `l7` register (pointing - // to the GOT), so do it ourselves just in case. .sparc, .sparc64 => asm volatile ( - \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7 + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ sethi %%pc22(_DYNAMIC - 4), %[ret] \\ call 1f - \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7 + \\ add %[ret], %%pc10(_DYNAMIC + 4), %[ret] \\1: - \\ add %%l7, %%o7, %[ret] + \\ add %[ret], %%o7, %[ret] : [ret] "=r" (-> [*]const elf.Dyn), : - : .{ .l7 = true }), + : .{ .o7 = true }), .xtensa, .xtensaeb => asm volatile ( \\ .weak _DYNAMIC \\ .hidden _DYNAMIC -- 2.54.0 From 962b4bbebf484487d6ff71a957fcc3d0afda470b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 19:40:30 +0200 Subject: [PATCH 12/45] std.pie: fix potentially reading garbage in sh assembly The alignment should of course be applied to the label, not the contents after it. Also fix a silly typo (DYNAMIC -> _DYNAMIC). --- lib/std/pie.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 84f8d35e8c082063fba23846978bb6f6c6d12eaf..a5c63e0580dbd66b3f4b17e2ac108b0c8aea8e6b 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -264,9 +264,9 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ add r0, %[ret] \\ bra 2f \\ nop - \\1: \\ .balign 4 - \\ .long DYNAMIC - . + \\1: + \\ .long _DYNAMIC - . \\2: : [ret] "=r" (-> [*]const elf.Dyn), : -- 2.54.0 From 37d1bdb8a7b700b900dd83c8c5c85296f5c3c17a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 19:11:14 +0200 Subject: [PATCH 13/45] std.pie: fix potentially unaligned quadword load in powerpc64 assembly It probably happened to be quadword aligned by coincidence, or real hardware can cope with misaligned loads. Either way, we should just align it properly. --- lib/std/pie.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index a5c63e0580dbd66b3f4b17e2ac108b0c8aea8e6b..7bb0713bbdd5c23c271c1bbfdc7b0d96efc9b865 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -230,11 +230,13 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { .powerpc64, .powerpc64le => asm volatile ( \\ .weak _DYNAMIC \\ .hidden _DYNAMIC + \\ .balign 8 \\ bl 1f + \\ nop \\ .quad _DYNAMIC - . \\1: \\ mflr %[ret] - \\ ld 4, 0(%[ret]) + \\ ld 4, 4(%[ret]) \\ add %[ret], 4, %[ret] : [ret] "=r" (-> [*]const elf.Dyn), : -- 2.54.0 From 8dda65bba08a65a1df846ae68cfa31272e5ee1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 19:09:39 +0200 Subject: [PATCH 14/45] std.pie: fix register constraint in m68k assembly lea needs an address register as destination. --- lib/std/pie.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 7bb0713bbdd5c23c271c1bbfdc7b0d96efc9b865..c7218388745ad81f2a617e433843bf777162e5fe 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -152,7 +152,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ .hidden _DYNAMIC \\ lea _DYNAMIC - . - 8, %[ret] \\ lea (%[ret], %%pc), %[ret] - : [ret] "=r" (-> [*]const elf.Dyn), + : [ret] "=a" (-> [*]const elf.Dyn), ), .microblaze, .microblazeel => asm volatile ( \\ .weak _DYNAMIC -- 2.54.0 From 511a5c6e192e562b830c30b95820cb37321d98f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 19:10:30 +0200 Subject: [PATCH 15/45] std.pie: fix typo in xtensa assembly (add -> addi) --- lib/std/pie.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/pie.zig b/lib/std/pie.zig index c7218388745ad81f2a617e433843bf777162e5fe..988ecaa8d424931632ba21ee6f6b436f9402409a 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -295,7 +295,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ .balign 4 \\ .word _DYNAMIC - . \\1: - \\ add a0, a0, 1 + \\ addi a0, a0, 1 \\ l32i a8, a0, 0 \\ add %[ret], a0, a8 : [ret] "=a" (-> [*]const elf.Dyn), -- 2.54.0 From 71a0bc027304562f7c6ffc5acc95c3ee11c7cf1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 20:27:51 +0200 Subject: [PATCH 16/45] std.os.linux.alpha: fix some bugs in the clone assembly --- lib/std/os/linux/alpha.zig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/std/os/linux/alpha.zig b/lib/std/os/linux/alpha.zig index 20bf4bd14bbceacc74e2e9328dcfac74c7603b46..82baf15f167215bc94e6a2f705c1f1e34dc5cb04 100644 --- a/lib/std/os/linux/alpha.zig +++ b/lib/std/os/linux/alpha.zig @@ -295,8 +295,8 @@ pub fn clone() callconv(.naked) u64 { // a0 = $16, a1 = $17, a2 = $18, a3 = $19, // a4 = $20, a5 = $21, sp = $30, v0 = $0 \\ # Save function pointer and argument pointer on new thread stack - \\ ldi $1, -8 - \\ and $17, $17, $1 + \\ ldi $1, -16 + \\ and $17, $1, $17 \\ lda $17, -16($17) \\ stq $16, 0($17) \\ stq $19, 8($17) @@ -323,16 +323,16 @@ pub fn clone() callconv(.naked) u64 { \\ .cfi_undefined $26 ); asm volatile ( - // v0 = $0, t9 = $23, a0 = $16, ra = $26, sp = $30, fp = $15 + // v0 = $0, a0 = $16, ra = $26, sp = $30, fp = $15, pv = $27 \\ mov 0, $15 \\ - \\ ldq $23, 0($30) + \\ ldq $27, 0($30) \\ ldq $16, 8($30) \\ lda $30, 16($30) - \\ jsr $26, ($23) + \\ jsr $26, ($27) \\ \\ mov $0, $16 - \\ ldi $0, 1 # SYS_EXIT + \\ ldi $0, 1 # SYS_exit \\ callsys ); } @@ -341,7 +341,7 @@ pub fn restore() noreturn { asm volatile ( // v0 = $0, a0 = $16, sp = $30 \\ mov $30, $16 - \\ ldi $0, 103 # SIGRETURN + \\ ldi $0, 103 # SYS_sigreturn \\ callsys ); } @@ -350,7 +350,7 @@ pub fn restore_rt() noreturn { asm volatile ( // v0 = $0, a0 = $16, sp = $30 \\ mov $30, $16 - \\ ldi $0, 351 # RT_SIGRETURN + \\ ldi $0, 351 # SYS_rt_sigreturn \\ callsys ); } -- 2.54.0 From 96dbec5d816e9bac472302363efb42a5746cb9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 01:13:31 +0200 Subject: [PATCH 17/45] std.os.linux.csky: fix misleading comment in clone assembly --- lib/std/os/linux/csky.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/csky.zig b/lib/std/os/linux/csky.zig index 4d456b08f210dce3f61da784333f067f341b8445..91b6becad8e9418f9d106013597a8dbcad56e822 100644 --- a/lib/std/os/linux/csky.zig +++ b/lib/std/os/linux/csky.zig @@ -113,8 +113,8 @@ pub fn clone() callconv(.naked) u32 { // __clone(func, stack, flags, arg, ptid, tls, ctid) // r0, r1, r2, r3, +0, +4, +8 // - // syscall(SYS_clone, flags, stack, ptid, tls, ctid) - // r7 r0, r1, r2, r3, r4 + // syscall(SYS_clone, flags, stack, ptid, ctid, tls) + // r7 r0, r1, r2, r3, r4 asm volatile ( \\ // Preserve callee-saved registers. \\ mov t0, r4 -- 2.54.0 From c65e90d741b7f6016f907c4d1fd8717ab19240d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 17:48:24 +0200 Subject: [PATCH 18/45] std.os.linux.mips[64,n32]: remove workaround for buggy 2.x kernels I'm not sure Zig has ever supported kernels this old but we certainly don't now. --- lib/std/os/linux/mips.zig | 10 ---------- lib/std/os/linux/mips64.zig | 9 --------- lib/std/os/linux/mipsn32.zig | 10 ---------- 3 files changed, 29 deletions(-) diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig index ca1e59053dcb5636c599d018160087f1067a5db9..ce15e83d4bfafa9d6bbf355f5cbad21aefc6d353 100644 --- a/lib/std/os/linux/mips.zig +++ b/lib/std/os/linux/mips.zig @@ -10,7 +10,6 @@ pub fn syscall0( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -25,7 +24,6 @@ pub fn syscall1( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -42,7 +40,6 @@ pub fn syscall2( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -61,7 +58,6 @@ pub fn syscall3( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -82,7 +78,6 @@ pub fn syscall4( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -111,7 +106,6 @@ pub fn syscall5( \\ syscall \\ addu $sp, $sp, 24 \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -140,7 +134,6 @@ pub fn syscall6( \\ syscall \\ addu $sp, $sp, 24 \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -172,7 +165,6 @@ pub fn syscall7( \\ syscall \\ addu $sp, $sp, 32 \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -193,7 +185,6 @@ pub fn syscall_pipe( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 2f \\ subu $v0, $zero, $v0 \\ b 2f \\1: @@ -229,7 +220,6 @@ pub fn clone() callconv(.naked) u32 { \\ li $v0, 4120 # SYS_clone \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 2f \\ subu $v0, $zero, $v0 \\ b 2f \\1: diff --git a/lib/std/os/linux/mips64.zig b/lib/std/os/linux/mips64.zig index a9ed38257c8c9fb3f25e44b7792b7d8ad1c61d93..aee211ec8aa3aa77265a79c9055df39b606cf390 100644 --- a/lib/std/os/linux/mips64.zig +++ b/lib/std/os/linux/mips64.zig @@ -10,7 +10,6 @@ pub fn syscall0( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -25,7 +24,6 @@ pub fn syscall1( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -42,7 +40,6 @@ pub fn syscall2( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -61,7 +58,6 @@ pub fn syscall3( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -82,7 +78,6 @@ pub fn syscall4( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -105,7 +100,6 @@ pub fn syscall5( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -130,7 +124,6 @@ pub fn syscall6( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -150,7 +143,6 @@ pub fn syscall_pipe( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 2f \\ dsubu $v0, $zero, $v0 \\ b 2f \\1: @@ -184,7 +176,6 @@ pub fn clone() callconv(.naked) u64 { \\ li $v0, 5055 # SYS_clone \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 2f \\ dsubu $v0, $zero, $v0 \\ b 2f \\1: diff --git a/lib/std/os/linux/mipsn32.zig b/lib/std/os/linux/mipsn32.zig index bc1744242729cc3cbce3f7b07215753e564b9461..fa9b2cc298d3a5c70707bbb020cf0669ac73f7c5 100644 --- a/lib/std/os/linux/mipsn32.zig +++ b/lib/std/os/linux/mipsn32.zig @@ -10,7 +10,6 @@ pub fn syscall0( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -25,7 +24,6 @@ pub fn syscall1( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -42,7 +40,6 @@ pub fn syscall2( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -61,7 +58,6 @@ pub fn syscall3( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -82,7 +78,6 @@ pub fn syscall4( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -105,7 +100,6 @@ pub fn syscall5( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -130,7 +124,6 @@ pub fn syscall6( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ subu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u32), @@ -150,7 +143,6 @@ pub fn syscall_pipe( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 2f \\ subu $v0, $zero, $v0 \\ b 2f \\1: @@ -171,7 +163,6 @@ pub fn syscall_lseek( return asm volatile ( \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 1f \\ dsubu $v0, $zero, $v0 \\1: : [ret] "={$2}" (-> u64), @@ -203,7 +194,6 @@ pub fn clone() callconv(.naked) u32 { \\ li $v0, 6055 # SYS_clone \\ syscall \\ beq $a3, $zero, 1f - \\ blez $v0, 2f \\ subu $v0, $zero, $v0 \\ b 2f \\1: -- 2.54.0 From d8426e69c34768fda27c47078aafdec1f20f020b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 02:20:55 +0200 Subject: [PATCH 19/45] std.os.linux.powerpc: respect ABI backchain requirements in clone assembly The ABI says that a stack frame always starts with the backchain slot and the LR save slot. Actually respect that by storing the old stack pointer in the backchain slot and storing r29 and r30 in the locals area instead. --- lib/std/os/linux/powerpc.zig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig index 5bfaae2767ee33b4d0b1ff32ccafab0ed5f1a1b1..ae2574e52b07bd4856bfee02bf6fbeb7c1ae3e43 100644 --- a/lib/std/os/linux/powerpc.zig +++ b/lib/std/os/linux/powerpc.zig @@ -200,8 +200,9 @@ pub fn clone() callconv(.naked) u32 { asm volatile ( \\ # store non-volatile regs r29, r30 on stack in order to put our \\ # start func and its arg there - \\ stwu 29, -16(1) - \\ stw 30, 4(1) + \\ stwu 1, -16(1) + \\ stw 29, 8(1) + \\ stw 30, 12(1) \\ \\ # save r3 (func) into r29, and r6(arg) into r30 \\ mr 29, 3 @@ -234,8 +235,8 @@ pub fn clone() callconv(.naked) u32 { \\ \\ # if not 0, restore stack and return \\ beq cr7, 2f - \\ lwz 29, 0(1) - \\ lwz 30, 4(1) + \\ lwz 29, 8(1) + \\ lwz 30, 12(1) \\ addi 1, 1, 16 \\ blr \\ -- 2.54.0 From 89f6d00cad6bd833f8a14baa03c844a531e61d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 03:04:24 +0200 Subject: [PATCH 20/45] musl: set up a proper stack frame in the parent thread in powerpc clone() https://www.openwall.com/lists/musl/2026/08/09/1 --- lib/libc/musl/src/thread/powerpc/clone.s | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/libc/musl/src/thread/powerpc/clone.s b/lib/libc/musl/src/thread/powerpc/clone.s index 019fd62a95afc6e4cff64f0c5bce1e1d41ae33c8..29c0b2ef4e34a2b0ed04c42e6a43d1deddbb4d13 100644 --- a/lib/libc/musl/src/thread/powerpc/clone.s +++ b/lib/libc/musl/src/thread/powerpc/clone.s @@ -16,8 +16,9 @@ __clone: # 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) +stwu 1, -16(1) +stw 30, 8(1) +stw 31, 12(1) # save r3 (func) into r30, and r6(arg) into r31 mr 30, 3 @@ -51,8 +52,8 @@ cmpwi cr7, 3, 0 # if not 0, restore stack and return beq cr7, 2f -lwz 30, 0(1) -lwz 31, 4(1) +lwz 30, 8(1) +lwz 31, 12(1) addi 1, 1, 16 blr -- 2.54.0 From bf66a7d6b7f17a1404f65e1c53ca08ef4442cec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 01:40:19 +0200 Subject: [PATCH 21/45] std.os.linux.riscv32/64: align the child stack pointer in clone --- lib/std/os/linux/riscv32.zig | 1 + lib/std/os/linux/riscv64.zig | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/std/os/linux/riscv32.zig b/lib/std/os/linux/riscv32.zig index ceabe30a87116d5e1ae8114d6f5751c4e15139f4..cb1243a0ca892ab9a39226e11bc645c15704d22f 100644 --- a/lib/std/os/linux/riscv32.zig +++ b/lib/std/os/linux/riscv32.zig @@ -116,6 +116,7 @@ pub fn clone() callconv(.naked) u32 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // a7 a0, a1, a2, a3, a4 asm volatile ( + \\ andi a1, a1, -16 \\ # Save func and arg to stack \\ addi a1, a1, -8 \\ sw a0, 0(a1) diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig index 41dabbb47216c84af9e43ecbe8c89853aee7c584..accde6d5e6a06db1cfcd4be94f2165ff2c2b6cc4 100644 --- a/lib/std/os/linux/riscv64.zig +++ b/lib/std/os/linux/riscv64.zig @@ -116,6 +116,7 @@ pub fn clone() callconv(.naked) u64 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // a7 a0, a1, a2, a3, a4 asm volatile ( + \\ andi a1, a1, -16 \\ # Save func and arg to stack \\ addi a1, a1, -16 \\ sd a0, 0(a1) -- 2.54.0 From 39caa63800c161bc7e403f5636147b19ed48ef38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 01:40:41 +0200 Subject: [PATCH 22/45] std.os.linux.riscv32: fix child stack alignment violation in clone assembly Both LP64 and ILP32 calling conventions require the stack pointer to be aligned to a 16-byte boundary on function entry. --- lib/std/os/linux/riscv32.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/linux/riscv32.zig b/lib/std/os/linux/riscv32.zig index cb1243a0ca892ab9a39226e11bc645c15704d22f..16e39c50df60df12dbe86658a5c8c1ab68a16b16 100644 --- a/lib/std/os/linux/riscv32.zig +++ b/lib/std/os/linux/riscv32.zig @@ -118,7 +118,7 @@ pub fn clone() callconv(.naked) u32 { asm volatile ( \\ andi a1, a1, -16 \\ # Save func and arg to stack - \\ addi a1, a1, -8 + \\ addi a1, a1, -16 \\ sw a0, 0(a1) \\ sw a3, 4(a1) \\ -- 2.54.0 From 14f9ea5a0f1303f4ba6caed56d990c8981eb9657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 01:24:37 +0200 Subject: [PATCH 23/45] std.os.linux.sh: fix reg/disp order in clone assembly --- lib/std/os/linux/sh.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/sh.zig b/lib/std/os/linux/sh.zig index 02581ce183ddb67c2c2eda91cd57b88402d58217..bda7330343c722cdf211d6b17aa8edb250db48d3 100644 --- a/lib/std/os/linux/sh.zig +++ b/lib/std/os/linux/sh.zig @@ -167,8 +167,8 @@ pub fn clone() callconv(.naked) u32 { \\ mov #120, r3 ! SYS_clone \\ mov r6, r4 \\ mov.l @r15, r6 - \\ mov.l @(r15, 8), r7 - \\ mov.l @(r15, 4), r0 + \\ mov.l @(8, r15), r7 + \\ mov.l @(4, r15), r0 \\ trapa #31 \\ or r0, r0 \\ or r0, r0 -- 2.54.0 From 2fc37914da3ff32536394c58478a45844544beeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 02:00:46 +0200 Subject: [PATCH 24/45] std.os.linux.sparc: delete incorrect stack bias in clone assembly 32-bit doesn't have a stack bias; this was a copy/paste goof when I implemented the 32-bit clone code based on the 64-bit code. --- lib/std/os/linux/sparc.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/sparc.zig b/lib/std/os/linux/sparc.zig index c8addd36c45bfc08aff71672c2aeef42bb948f06..10d4b98b9a55a595bed8bc7c386edcedefcc9847 100644 --- a/lib/std/os/linux/sparc.zig +++ b/lib/std/os/linux/sparc.zig @@ -214,11 +214,11 @@ pub fn clone() callconv(.naked) u32 { \\ \\ # Align, and add some extra space for the initial frame \\ and %%i1, -8, %%i1 - \\ sub %%i1, 96 + 2047, %%o1 + \\ sub %%i1, 96, %%o1 \\ \\ mov %%i4, %%o2 \\ mov %%i5, %%o3 - \\ ld [%%fp + 92 + 2047], %%o4 + \\ ld [%%fp + 92], %%o4 \\ t 0x10 \\ bcs 1f \\ nop -- 2.54.0 From 6d2c427635dfcdbe5867c5af5194cbe175b85003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 03:35:05 +0200 Subject: [PATCH 25/45] std.os.linux: prefer inline asm with explicit materialization With https://codeberg.org/ziglang/zig/issues/35571 accepted, the form used in the stage2_c prongs is now the preferred form because it does not require the compiler to emit machine code behind the programmer's back. --- lib/std/os/linux/aarch64.zig | 19 +++++----------- lib/std/os/linux/arc.zig | 19 +++++----------- lib/std/os/linux/arm.zig | 38 ++++++++++--------------------- lib/std/os/linux/powerpc.zig | 38 ++++++++++--------------------- lib/std/os/linux/powerpc64.zig | 38 ++++++++++--------------------- lib/std/os/linux/s390x.zig | 38 ++++++++++--------------------- lib/std/os/linux/x32.zig | 19 +++++----------- lib/std/os/linux/x86.zig | 41 +++++++++++----------------------- lib/std/os/linux/x86_64.zig | 19 +++++----------- lib/std/os/linux/xtensa.zig | 19 +++++----------- 10 files changed, 91 insertions(+), 197 deletions(-) diff --git a/lib/std/os/linux/aarch64.zig b/lib/std/os/linux/aarch64.zig index 431097feccf104eba84a3f347fac6fe29ae1eb57..5381def39f634c526d0cef748c8e89306a494544 100644 --- a/lib/std/os/linux/aarch64.zig +++ b/lib/std/os/linux/aarch64.zig @@ -152,19 +152,12 @@ pub fn clone() callconv(.naked) u64 { pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ mov w8, %[number] - \\ svc #0 - : - : [number] "i" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ svc #0 - : - : [number] "{x8}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ mov w8, %[number] + \\ svc #0 + : + : [number] "i" (@backingInt(SYS.rt_sigreturn)), + ); } pub const VDSO = struct { diff --git a/lib/std/os/linux/arc.zig b/lib/std/os/linux/arc.zig index 8721de28f9922068d405cda98f4b64da474b69ab..e2c0785ffc53158eb4b6e17656bd4e95c155481f 100644 --- a/lib/std/os/linux/arc.zig +++ b/lib/std/os/linux/arc.zig @@ -153,19 +153,12 @@ pub fn clone() callconv(.naked) u32 { pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ mov r8, %[number] - \\ trap_s 0 - : - : [number] "I" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ trap_s 0 - : - : [number] "{r8}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ mov r8, %[number] + \\ trap_s 0 + : + : [number] "I" (@backingInt(SYS.rt_sigreturn)), + ); } pub const time_t = i64; diff --git a/lib/std/os/linux/arm.zig b/lib/std/os/linux/arm.zig index d198c03748a9ad119a477b0de580770d441396ea..7d7631b36c6380474e540f2c43d2c59900e319da 100644 --- a/lib/std/os/linux/arm.zig +++ b/lib/std/os/linux/arm.zig @@ -146,35 +146,21 @@ pub fn clone() callconv(.naked) u32 { } pub fn restore() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ mov r7, %[number] - \\ svc #0 - : - : [number] "I" (@backingInt(SYS.sigreturn)), - ), - else => asm volatile ( - \\ svc #0 - : - : [number] "{r7}" (@backingInt(SYS.sigreturn)), - ), - } + asm volatile ( + \\ mov r7, %[number] + \\ svc #0 + : + : [number] "I" (@backingInt(SYS.sigreturn)), + ); } pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ mov r7, %[number] - \\ svc #0 - : - : [number] "I" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ svc #0 - : - : [number] "{r7}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ mov r7, %[number] + \\ svc #0 + : + : [number] "I" (@backingInt(SYS.rt_sigreturn)), + ); } pub const VDSO = struct { diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig index ae2574e52b07bd4856bfee02bf6fbeb7c1ae3e43..6d47674234948a9a6e3fb0070507e852bf418656 100644 --- a/lib/std/os/linux/powerpc.zig +++ b/lib/std/os/linux/powerpc.zig @@ -263,35 +263,21 @@ pub fn clone() callconv(.naked) u32 { } pub fn restore() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ li 0, %[number] - \\ sc - : - : [number] "i" (@backingInt(SYS.sigreturn)), - ), - else => asm volatile ( - \\ sc - : - : [number] "{r0}" (@backingInt(SYS.sigreturn)), - ), - } + asm volatile ( + \\ li 0, %[number] + \\ sc + : + : [number] "i" (@backingInt(SYS.sigreturn)), + ); } pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ li 0, %[number] - \\ sc - : - : [number] "i" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ sc - : - : [number] "{r0}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ li 0, %[number] + \\ sc + : + : [number] "i" (@backingInt(SYS.rt_sigreturn)), + ); } pub const VDSO = struct { diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig index 5dd1fc9a9d8163ec50b37e58749a63d2eaf5312a..d6f488cad409bef8f7ab9ce082eda5e23ca7f35e 100644 --- a/lib/std/os/linux/powerpc64.zig +++ b/lib/std/os/linux/powerpc64.zig @@ -247,35 +247,21 @@ pub fn clone() callconv(.naked) u64 { } pub fn restore() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ li 0, %[number] - \\ sc - : - : [number] "i" (@backingInt(SYS.sigreturn)), - ), - else => asm volatile ( - \\ sc - : - : [number] "{r0}" (@backingInt(SYS.sigreturn)), - ), - } + asm volatile ( + \\ li 0, %[number] + \\ sc + : + : [number] "i" (@backingInt(SYS.sigreturn)), + ); } pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ li 0, %[number] - \\ sc - : - : [number] "i" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ sc - : - : [number] "{r0}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ li 0, %[number] + \\ sc + : + : [number] "i" (@backingInt(SYS.rt_sigreturn)), + ); } pub const VDSO = struct { diff --git a/lib/std/os/linux/s390x.zig b/lib/std/os/linux/s390x.zig index 3c44beeb8df7bb5d7f0d7d7fb13f3c35c840da01..4f90ad2081a613d8416464df25a98c8529b9d3a9 100644 --- a/lib/std/os/linux/s390x.zig +++ b/lib/std/os/linux/s390x.zig @@ -174,35 +174,21 @@ pub fn clone() callconv(.naked) u64 { } pub fn restore() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\lghi %%r1, %[number] - \\svc 0 - : - : [number] "K" (@backingInt(SYS.sigreturn)), - ), - else => asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.sigreturn)), - ), - } + asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.sigreturn)), + ); } pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\lghi %%r1, %[number] - \\svc 0 - : - : [number] "K" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.rt_sigreturn)), + ); } pub const time_t = i64; diff --git a/lib/std/os/linux/x32.zig b/lib/std/os/linux/x32.zig index 429aac82973def7599ecc441d35409d085e9b28f..19509018dd88783047346930ddff37d8b05887df 100644 --- a/lib/std/os/linux/x32.zig +++ b/lib/std/os/linux/x32.zig @@ -160,19 +160,12 @@ pub fn clone() callconv(.naked) u32 { pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ movl %[number], %%eax - \\ syscall - : - : [number] "i" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ syscall - : - : [number] "{rax}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ movl %[number], %%eax + \\ syscall + : + : [number] "i" (@backingInt(SYS.rt_sigreturn)), + ); } pub const time_t = i64; diff --git a/lib/std/os/linux/x86.zig b/lib/std/os/linux/x86.zig index 8145bf2826c780bcd0e5b85de341b6dc7d6b1281..4a1c593c121939fb58e4ce33cf1d9b2a11f260a2 100644 --- a/lib/std/os/linux/x86.zig +++ b/lib/std/os/linux/x86.zig @@ -186,37 +186,22 @@ pub fn clone() callconv(.naked) u32 { } pub fn restore() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ addl $4, %%esp - \\ movl %[number], %%eax - \\ int $0x80 - : - : [number] "i" (@backingInt(SYS.sigreturn)), - ), - else => asm volatile ( - \\ addl $4, %%esp - \\ int $0x80 - : - : [number] "{eax}" (@backingInt(SYS.sigreturn)), - ), - } + asm volatile ( + \\ addl $4, %%esp + \\ movl %[number], %%eax + \\ int $0x80 + : + : [number] "i" (@backingInt(SYS.sigreturn)), + ); } pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ movl %[number], %%eax - \\ int $0x80 - : - : [number] "i" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ int $0x80 - : - : [number] "{eax}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ movl %[number], %%eax + \\ int $0x80 + : + : [number] "i" (@backingInt(SYS.rt_sigreturn)), + ); } pub const VDSO = struct { diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig index ae5808921c648f93130b26009940acc9376e97f9..465a330156554a035b258bcf682fab24cb4fe7ba 100644 --- a/lib/std/os/linux/x86_64.zig +++ b/lib/std/os/linux/x86_64.zig @@ -146,19 +146,12 @@ pub fn clone() callconv(.naked) u64 { pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ movl %[number], %%eax - \\ syscall - : - : [number] "i" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ syscall - : - : [number] "{rax}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ movl %[number], %%eax + \\ syscall + : + : [number] "i" (@backingInt(SYS.rt_sigreturn)), + ); } pub const time_t = i64; diff --git a/lib/std/os/linux/xtensa.zig b/lib/std/os/linux/xtensa.zig index 839df53cace5d533c35bb986bcc08bcba8b5dd0c..0bda5a9331365dea6c333818b1624cbfd7aba444 100644 --- a/lib/std/os/linux/xtensa.zig +++ b/lib/std/os/linux/xtensa.zig @@ -173,19 +173,12 @@ pub fn clone() callconv(.naked) u32 { pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { - switch (builtin.zig_backend) { - .stage2_c => asm volatile ( - \\ movi a2, %[number] - \\ syscall - : - : [number] "I" (@backingInt(SYS.rt_sigreturn)), - ), - else => asm volatile ( - \\ syscall - : - : [number] "{a2}" (@backingInt(SYS.rt_sigreturn)), - ), - } + asm volatile ( + \\ movi a2, %[number] + \\ syscall + : + : [number] "I" (@backingInt(SYS.rt_sigreturn)), + ); } pub const VDSO = void; -- 2.54.0 From 516040582da20208d2026996c0ca9cf4c1fc20be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 17:05:48 +0200 Subject: [PATCH 26/45] std.os.linux: fix some bonkers indentation in inline assembly --- lib/std/os/linux/aarch64.zig | 42 +++++++-------- lib/std/os/linux/arc.zig | 46 ++++++++-------- lib/std/os/linux/arm.zig | 48 +++++++++-------- lib/std/os/linux/powerpc.zig | 14 ++--- lib/std/os/linux/powerpc64.zig | 80 +++++++++++++-------------- lib/std/os/linux/riscv32.zig | 50 ++++++++--------- lib/std/os/linux/riscv64.zig | 50 ++++++++--------- lib/std/os/linux/s390x.zig | 99 +++++++++++++++++----------------- lib/std/os/linux/x32.zig | 43 ++++++++------- lib/std/os/linux/x86.zig | 66 +++++++++++------------ lib/std/os/linux/x86_64.zig | 43 ++++++++------- 11 files changed, 290 insertions(+), 291 deletions(-) diff --git a/lib/std/os/linux/aarch64.zig b/lib/std/os/linux/aarch64.zig index 5381def39f634c526d0cef748c8e89306a494544..930b75bb322040189cbbddc0ccaaf2c5f7eb413d 100644 --- a/lib/std/os/linux/aarch64.zig +++ b/lib/std/os/linux/aarch64.zig @@ -116,36 +116,36 @@ pub fn clone() callconv(.naked) u64 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // x8, x0, x1, x2, x3, x4 asm volatile ( - \\ // align stack and save func,arg - \\ and x1,x1,#-16 - \\ stp x0,x3,[x1,#-16]! + \\ // align stack and save func,arg + \\ and x1,x1,#-16 + \\ stp x0,x3,[x1,#-16]! \\ - \\ // syscall - \\ uxtw x0,w2 - \\ mov x2,x4 - \\ mov x3,x5 - \\ mov x4,x6 - \\ mov x8,#220 // SYS_clone - \\ svc #0 + \\ // syscall + \\ uxtw x0,w2 + \\ mov x2,x4 + \\ mov x3,x5 + \\ mov x4,x6 + \\ mov x8,#220 // SYS_clone + \\ svc #0 \\ - \\ cbz x0,1f - \\ // parent - \\ ret + \\ cbz x0,1f + \\ // parent + \\ ret \\ - \\ // child + \\ // child \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined lr + \\ .cfi_undefined lr ); asm volatile ( - \\ mov fp, 0 - \\ mov lr, 0 + \\ mov fp, 0 + \\ mov lr, 0 \\ - \\ ldp x1,x0,[sp],#16 - \\ blr x1 - \\ mov x8,#93 // SYS_exit - \\ svc #0 + \\ ldp x1,x0,[sp],#16 + \\ blr x1 + \\ mov x8,#93 // SYS_exit + \\ svc #0 ); } diff --git a/lib/std/os/linux/arc.zig b/lib/std/os/linux/arc.zig index e2c0785ffc53158eb4b6e17656bd4e95c155481f..faef23963b6effd064af866192bcad3949aea2d1 100644 --- a/lib/std/os/linux/arc.zig +++ b/lib/std/os/linux/arc.zig @@ -116,37 +116,37 @@ pub fn clone() callconv(.naked) u32 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // r8 r0, r1, r2, r3, r4 asm volatile ( - \\ // Align stack pointer - \\ and r1, r1, -16 - \\ mov r10, r0 - \\ mov r11, r3 - \\ // Setup the arguments - \\ mov r0, r2 - \\ mov r2, r4 - \\ mov r3, r5 - \\ mov r4, r6 - \\ mov r8, 220 // SYS_clone - \\ trap_s 0 - \\ cmp r0, 0 - \\ beq 1f - \\ j [blink] - \\ // Child - \\ 1: + \\ // Align stack pointer + \\ and r1, r1, -16 + \\ mov r10, r0 + \\ mov r11, r3 + \\ // Setup the arguments + \\ mov r0, r2 + \\ mov r2, r4 + \\ mov r3, r5 + \\ mov r4, r6 + \\ mov r8, 220 // SYS_clone + \\ trap_s 0 + \\ cmp r0, 0 + \\ beq 1f + \\ j [blink] + \\ // Child + \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( \\ .cfi_undefined blink ); asm volatile ( - \\ mov fp, 0 - \\ mov blink, 0 + \\ mov fp, 0 + \\ mov blink, 0 \\ - \\ mov r0, r11 - \\ jl [r10] + \\ mov r0, r11 + \\ jl [r10] \\ - \\ // Exit - \\ mov r8, 93 // SYS_exit - \\ trap_s 0 + \\ // Exit + \\ mov r8, 93 // SYS_exit + \\ trap_s 0 ); } diff --git a/lib/std/os/linux/arm.zig b/lib/std/os/linux/arm.zig index 7d7631b36c6380474e540f2c43d2c59900e319da..522d1c925b5fc2e73377e8591a7a8ca72828ecde 100644 --- a/lib/std/os/linux/arm.zig +++ b/lib/std/os/linux/arm.zig @@ -116,32 +116,34 @@ pub fn clone() callconv(.naked) u32 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // r7 r0, r1, r2, r3, r4 asm volatile ( - \\ stmfd sp!,{r4,r5,r6,r7} - \\ mov r7,#120 // SYS_clone - \\ mov r6,r3 - \\ mov r5,r0 - \\ mov r0,r2 - \\ and r1,r1,#-16 - \\ ldr r2,[sp,#16] - \\ ldr r3,[sp,#20] - \\ ldr r4,[sp,#24] - \\ svc 0 - \\ tst r0,r0 - \\ beq 1f - \\ ldmfd sp!,{r4,r5,r6,r7} - \\ bx lr + \\ stmfd sp!,{r4,r5,r6,r7} + \\ mov r7,#120 // SYS_clone + \\ mov r6,r3 + \\ mov r5,r0 + \\ mov r0,r2 + \\ and r1,r1,#-16 + \\ ldr r2,[sp,#16] + \\ ldr r3,[sp,#20] + \\ ldr r4,[sp,#24] + \\ svc 0 + \\ tst r0,r0 + \\ beq 1f + \\ ldmfd sp!,{r4,r5,r6,r7} + \\ bx lr \\ - \\ // https://github.com/llvm/llvm-project/issues/115891 - \\1: mov r7, #0 - \\ mov r11, #0 - \\ mov lr, #0 + \\ // https://github.com/llvm/llvm-project/issues/115891 + \\1: + \\ mov r7, #0 + \\ mov r11, #0 + \\ mov lr, #0 \\ - \\ mov r0,r6 - \\ bl 3f - \\ mov r7,#1 // SYS_exit - \\ svc 0 + \\ mov r0,r6 + \\ bl 3f + \\ mov r7,#1 // SYS_exit + \\ svc 0 \\ - \\3: bx r5 + \\3: + \\ bx r5 ); } diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig index 6d47674234948a9a6e3fb0070507e852bf418656..b1ccf17b5594f4b60beb013f4b7f810e4f318705 100644 --- a/lib/std/os/linux/powerpc.zig +++ b/lib/std/os/linux/powerpc.zig @@ -16,7 +16,7 @@ pub fn syscall0( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u32), [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@backingInt(number)), @@ -33,7 +33,7 @@ pub fn syscall1( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u32), [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@backingInt(number)), @@ -53,7 +53,7 @@ pub fn syscall2( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u32), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -77,7 +77,7 @@ pub fn syscall3( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u32), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -105,7 +105,7 @@ pub fn syscall4( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u32), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -137,7 +137,7 @@ pub fn syscall5( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u32), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -173,7 +173,7 @@ pub fn syscall6( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u32), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig index d6f488cad409bef8f7ab9ce082eda5e23ca7f35e..92963a2efbe089d164c4d9296f7596552c1abcc4 100644 --- a/lib/std/os/linux/powerpc64.zig +++ b/lib/std/os/linux/powerpc64.zig @@ -16,7 +16,7 @@ pub fn syscall0( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u64), [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@backingInt(number)), @@ -33,7 +33,7 @@ pub fn syscall1( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u64), [r0_out] "={r0}" (r0_out), : [number] "{r0}" (@backingInt(number)), @@ -53,7 +53,7 @@ pub fn syscall2( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u64), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -77,7 +77,7 @@ pub fn syscall3( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u64), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -105,7 +105,7 @@ pub fn syscall4( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u64), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -137,7 +137,7 @@ pub fn syscall5( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u64), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -173,7 +173,7 @@ pub fn syscall6( \\ sc \\ bns+ 1f \\ neg 3, 3 - \\ 1: + \\1: : [ret] "={r3}" (-> u64), [r0_out] "={r0}" (r0_out), [r4_out] "={r4}" (r4_out), @@ -198,51 +198,51 @@ pub fn clone() callconv(.naked) u64 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // 0 3, 4, 5, 6, 7 asm volatile ( - \\ # create initial stack frame for new thread - \\ clrrdi 4, 4, 4 - \\ li 0, 0 - \\ stdu 0,-32(4) + \\ # create initial stack frame for new thread + \\ clrrdi 4, 4, 4 + \\ li 0, 0 + \\ stdu 0,-32(4) \\ - \\ # save fn and arg to child stack - \\ std 3, 8(4) - \\ std 6, 16(4) + \\ # save fn and arg to child stack + \\ std 3, 8(4) + \\ std 6, 16(4) \\ - \\ # shuffle args into correct registers and call SYS_clone - \\ mr 3, 5 - \\ #mr 4, 4 - \\ mr 5, 7 - \\ mr 6, 8 - \\ mr 7, 9 - \\ li 0, 120 # SYS_clone = 120 - \\ sc + \\ # shuffle args into correct registers and call SYS_clone + \\ mr 3, 5 + \\ #mr 4, 4 + \\ mr 5, 7 + \\ mr 6, 8 + \\ mr 7, 9 + \\ li 0, 120 # SYS_clone = 120 + \\ sc \\ - \\ # if error, negate return (errno) - \\ bns+ 1f - \\ neg 3, 3 + \\ # if error, negate return (errno) + \\ bns+ 1f + \\ neg 3, 3 \\ \\1: - \\ # if we're the parent, return - \\ cmpwi cr7, 3, 0 - \\ bnelr cr7 + \\ # if we're the parent, return + \\ cmpwi cr7, 3, 0 + \\ bnelr cr7 \\ - \\ # we're the child + \\ # we're the child ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined lr + \\ .cfi_undefined lr ); asm volatile ( - \\ li 31, 0 - \\ mtlr 31 + \\ li 31, 0 + \\ mtlr 31 \\ - \\ # call fn(arg) - \\ ld 3, 16(1) - \\ ld 12, 8(1) - \\ mtctr 12 - \\ bctrl + \\ # call fn(arg) + \\ ld 3, 16(1) + \\ ld 12, 8(1) + \\ mtctr 12 + \\ bctrl \\ - \\ # call SYS_exit. exit code is already in r3 from fn return value - \\ li 0, 1 # SYS_exit = 1 - \\ sc + \\ # call SYS_exit. exit code is already in r3 from fn return value + \\ li 0, 1 # SYS_exit = 1 + \\ sc ); } diff --git a/lib/std/os/linux/riscv32.zig b/lib/std/os/linux/riscv32.zig index 16e39c50df60df12dbe86658a5c8c1ab68a16b16..609e59151da3012b9de1061979767e3f94b0d3e6 100644 --- a/lib/std/os/linux/riscv32.zig +++ b/lib/std/os/linux/riscv32.zig @@ -116,41 +116,41 @@ pub fn clone() callconv(.naked) u32 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // a7 a0, a1, a2, a3, a4 asm volatile ( - \\ andi a1, a1, -16 - \\ # Save func and arg to stack - \\ addi a1, a1, -16 - \\ sw a0, 0(a1) - \\ sw a3, 4(a1) + \\ andi a1, a1, -16 + \\ # Save func and arg to stack + \\ addi a1, a1, -16 + \\ sw a0, 0(a1) + \\ sw a3, 4(a1) \\ - \\ # Call SYS_clone - \\ mv a0, a2 - \\ mv a2, a4 - \\ mv a3, a5 - \\ mv a4, a6 - \\ li a7, 220 # SYS_clone - \\ ecall + \\ # Call SYS_clone + \\ mv a0, a2 + \\ mv a2, a4 + \\ mv a3, a5 + \\ mv a4, a6 + \\ li a7, 220 # SYS_clone + \\ ecall \\ - \\ beqz a0, 1f - \\ # Parent - \\ ret + \\ beqz a0, 1f + \\ # Parent + \\ ret \\ - \\ # Child + \\ # Child \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined ra + \\ .cfi_undefined ra ); asm volatile ( - \\ mv fp, zero - \\ mv ra, zero + \\ mv fp, zero + \\ mv ra, zero \\ - \\ lw a1, 0(sp) - \\ lw a0, 4(sp) - \\ jalr a1 + \\ lw a1, 0(sp) + \\ lw a0, 4(sp) + \\ jalr a1 \\ - \\ # Exit - \\ li a7, 93 # SYS_exit - \\ ecall + \\ # Exit + \\ li a7, 93 # SYS_exit + \\ ecall ); } diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig index accde6d5e6a06db1cfcd4be94f2165ff2c2b6cc4..3d3ce7dba36dd759c5124efaebcfd6c74c588bcb 100644 --- a/lib/std/os/linux/riscv64.zig +++ b/lib/std/os/linux/riscv64.zig @@ -116,41 +116,41 @@ pub fn clone() callconv(.naked) u64 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // a7 a0, a1, a2, a3, a4 asm volatile ( - \\ andi a1, a1, -16 - \\ # Save func and arg to stack - \\ addi a1, a1, -16 - \\ sd a0, 0(a1) - \\ sd a3, 8(a1) + \\ andi a1, a1, -16 + \\ # Save func and arg to stack + \\ addi a1, a1, -16 + \\ sd a0, 0(a1) + \\ sd a3, 8(a1) \\ - \\ # Call SYS_clone - \\ mv a0, a2 - \\ mv a2, a4 - \\ mv a3, a5 - \\ mv a4, a6 - \\ li a7, 220 # SYS_clone - \\ ecall + \\ # Call SYS_clone + \\ mv a0, a2 + \\ mv a2, a4 + \\ mv a3, a5 + \\ mv a4, a6 + \\ li a7, 220 # SYS_clone + \\ ecall \\ - \\ beqz a0, 1f - \\ # Parent - \\ ret + \\ beqz a0, 1f + \\ # Parent + \\ ret \\ - \\ # Child + \\ # Child \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined ra + \\ .cfi_undefined ra ); asm volatile ( - \\ mv fp, zero - \\ mv ra, zero + \\ mv fp, zero + \\ mv ra, zero \\ - \\ ld a1, 0(sp) - \\ ld a0, 8(sp) - \\ jalr a1 + \\ ld a1, 0(sp) + \\ ld a0, 8(sp) + \\ jalr a1 \\ - \\ # Exit - \\ li a7, 93 # SYS_exit - \\ ecall + \\ # Exit + \\ li a7, 93 # SYS_exit + \\ ecall ); } diff --git a/lib/std/os/linux/s390x.zig b/lib/std/os/linux/s390x.zig index 4f90ad2081a613d8416464df25a98c8529b9d3a9..beebd97c1a89d9c6cb96a890b1fd74fd9a444337 100644 --- a/lib/std/os/linux/s390x.zig +++ b/lib/std/os/linux/s390x.zig @@ -111,72 +111,71 @@ pub fn syscall6( pub fn clone() callconv(.naked) u64 { asm volatile ( - \\# 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; + \\ # 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) + \\ # 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) + \\ # 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) + \\ # 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 + \\ # 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) + \\ # restore call-saved register + \\ lg %%r6, 48(%%r15) \\ - \\# if error or if we're the parent, return - \\ltgr %%r2, %%r2 - \\bnzr %%r14 + \\ # if error or if we're the parent, return + \\ ltgr %%r2, %%r2 + \\ bnzr %%r14 \\ - \\# we're the child + \\ # we're the child ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\.cfi_undefined %%r14 + \\ .cfi_undefined %%r14 ); asm volatile ( - \\lghi %%r11, 0 - \\lghi %%r14, 0 + \\ lghi %%r11, 0 + \\ lghi %%r14, 0 \\ - \\# 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 + \\ # 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 ); } pub fn restore() callconv(.naked) noreturn { asm volatile ( - \\lghi %%r1, %[number] - \\svc 0 + \\ lghi %%r1, %[number] + \\ svc 0 : : [number] "K" (@backingInt(SYS.sigreturn)), ); @@ -184,8 +183,8 @@ pub fn restore() callconv(.naked) noreturn { pub fn restore_rt() callconv(.naked) noreturn { asm volatile ( - \\lghi %%r1, %[number] - \\svc 0 + \\ lghi %%r1, %[number] + \\ svc 0 : : [number] "K" (@backingInt(SYS.rt_sigreturn)), ); diff --git a/lib/std/os/linux/x32.zig b/lib/std/os/linux/x32.zig index 19509018dd88783047346930ddff37d8b05887df..0e6d6b6c19aed9c378f8034a845ec2f7a66d9665 100644 --- a/lib/std/os/linux/x32.zig +++ b/lib/std/os/linux/x32.zig @@ -125,35 +125,34 @@ pub fn syscall_lseek( pub fn clone() callconv(.naked) u32 { asm volatile ( - \\ movl $0x40000038,%%eax // SYS_clone - \\ mov %%rdi,%%r11 - \\ mov %%rdx,%%rdi - \\ mov %%r8,%%rdx - \\ mov %%r9,%%r8 - \\ mov 8(%%rsp),%%r10d - \\ mov %%r11,%%r9 - \\ and $-16,%%rsi - \\ sub $8,%%rsi - \\ mov %%rcx,(%%rsi) - \\ syscall - \\ test %%eax,%%eax - \\ jz 1f - \\ ret + \\ movl $0x40000038,%%eax // SYS_clone + \\ mov %%rdi,%%r11 + \\ mov %%rdx,%%rdi + \\ mov %%r8,%%rdx + \\ mov %%r9,%%r8 + \\ mov 8(%%rsp),%%r10d + \\ mov %%r11,%%r9 + \\ and $-16,%%rsi + \\ sub $8,%%rsi + \\ mov %%rcx,(%%rsi) + \\ syscall + \\ test %%eax,%%eax + \\ jz 1f + \\ ret \\ \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined %%rip + \\ .cfi_undefined %%rip ); asm volatile ( - \\ xor %%ebp,%%ebp - \\ - \\ pop %%rdi - \\ call *%%r9 - \\ mov %%eax,%%edi - \\ movl $0x4000003c,%%eax // SYS_exit - \\ syscall + \\ xor %%ebp,%%ebp \\ + \\ pop %%rdi + \\ call *%%r9 + \\ mov %%eax,%%edi + \\ movl $0x4000003c,%%eax // SYS_exit + \\ syscall ); } diff --git a/lib/std/os/linux/x86.zig b/lib/std/os/linux/x86.zig index 4a1c593c121939fb58e4ce33cf1d9b2a11f260a2..1537deb7751794f01973e5629614cd803ffc7bf7 100644 --- a/lib/std/os/linux/x86.zig +++ b/lib/std/os/linux/x86.zig @@ -142,46 +142,46 @@ pub fn clone() callconv(.naked) u32 { // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // eax, ebx, ecx, edx, esi, edi asm volatile ( - \\ pushl %%ebp - \\ movl %%esp,%%ebp - \\ pushl %%ebx - \\ pushl %%esi - \\ pushl %%edi - \\ // Setup the arguments - \\ movl 16(%%ebp),%%ebx - \\ movl 12(%%ebp),%%ecx - \\ andl $-16,%%ecx - \\ subl $20,%%ecx - \\ movl 20(%%ebp),%%eax - \\ movl %%eax,4(%%ecx) - \\ movl 8(%%ebp),%%eax - \\ movl %%eax,0(%%ecx) - \\ movl 24(%%ebp),%%edx - \\ movl 28(%%ebp),%%esi - \\ movl 32(%%ebp),%%edi - \\ movl $120,%%eax // SYS_clone - \\ int $128 - \\ testl %%eax,%%eax - \\ jz 1f - \\ popl %%edi - \\ popl %%esi - \\ popl %%ebx - \\ popl %%ebp - \\ retl + \\ pushl %%ebp + \\ movl %%esp,%%ebp + \\ pushl %%ebx + \\ pushl %%esi + \\ pushl %%edi + \\ // Setup the arguments + \\ movl 16(%%ebp),%%ebx + \\ movl 12(%%ebp),%%ecx + \\ andl $-16,%%ecx + \\ subl $20,%%ecx + \\ movl 20(%%ebp),%%eax + \\ movl %%eax,4(%%ecx) + \\ movl 8(%%ebp),%%eax + \\ movl %%eax,0(%%ecx) + \\ movl 24(%%ebp),%%edx + \\ movl 28(%%ebp),%%esi + \\ movl 32(%%ebp),%%edi + \\ movl $120,%%eax // SYS_clone + \\ int $128 + \\ testl %%eax,%%eax + \\ jz 1f + \\ popl %%edi + \\ popl %%esi + \\ popl %%ebx + \\ popl %%ebp + \\ retl \\ \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined %%eip + \\ .cfi_undefined %%eip ); asm volatile ( - \\ xorl %%ebp,%%ebp + \\ xorl %%ebp,%%ebp \\ - \\ popl %%eax - \\ calll *%%eax - \\ movl %%eax,%%ebx - \\ movl $1,%%eax // SYS_exit - \\ int $128 + \\ popl %%eax + \\ calll *%%eax + \\ movl %%eax,%%ebx + \\ movl $1,%%eax // SYS_exit + \\ int $128 ); } diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig index 465a330156554a035b258bcf682fab24cb4fe7ba..9764941fbe5e774c081435b0d7378fd89ad1d083 100644 --- a/lib/std/os/linux/x86_64.zig +++ b/lib/std/os/linux/x86_64.zig @@ -111,35 +111,34 @@ pub fn syscall6( pub fn clone() callconv(.naked) u64 { asm volatile ( - \\ movl $56,%%eax // SYS_clone - \\ movq %%rdi,%%r11 - \\ movq %%rdx,%%rdi - \\ movq %%r8,%%rdx - \\ movq %%r9,%%r8 - \\ movq 8(%%rsp),%%r10 - \\ movq %%r11,%%r9 - \\ andq $-16,%%rsi - \\ subq $8,%%rsi - \\ movq %%rcx,(%%rsi) - \\ syscall - \\ testq %%rax,%%rax - \\ jz 1f - \\ retq + \\ movl $56,%%eax // SYS_clone + \\ movq %%rdi,%%r11 + \\ movq %%rdx,%%rdi + \\ movq %%r8,%%rdx + \\ movq %%r9,%%r8 + \\ movq 8(%%rsp),%%r10 + \\ movq %%r11,%%r9 + \\ andq $-16,%%rsi + \\ subq $8,%%rsi + \\ movq %%rcx,(%%rsi) + \\ syscall + \\ testq %%rax,%%rax + \\ jz 1f + \\ retq \\ \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined %%rip + \\ .cfi_undefined %%rip ); asm volatile ( - \\ xorl %%ebp,%%ebp - \\ - \\ popq %%rdi - \\ callq *%%r9 - \\ movl %%eax,%%edi - \\ movl $60,%%eax // SYS_exit - \\ syscall + \\ xorl %%ebp,%%ebp \\ + \\ popq %%rdi + \\ callq *%%r9 + \\ movl %%eax,%%edi + \\ movl $60,%%eax // SYS_exit + \\ syscall ); } -- 2.54.0 From f0292b57033ce2063c51f01fcd24937b81eb3699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 03:49:05 +0200 Subject: [PATCH 27/45] std.Thread: remove mips o32 workaround in LinuxThreadImpl.freeAndExit() Our minimum kernel version was released several years after this kernel bug was fixed. On top of that, it's a hacky workaround that depends on abicalls to work. Well past time to get rid of it. --- lib/std/Thread.zig | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index bd3f9e1f019fea9de6f06b8da4df47cdf11eaa0a..473aa308f242cf1d24dc7b66d4e237fec6b7d03a 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1275,12 +1275,7 @@ const LinuxThreadImpl = struct { : [ptr] "{r5}" (@intFromPtr(self.mapped.ptr)), [len] "{r6}" (self.mapped.len), ), - // We set `sp` to the address of the current function as a workaround for a Linux - // kernel bug that caused syscalls to return EFAULT if the stack pointer is invalid. - // The bug was introduced in 46e12c07b3b9603c60fc1d421ff18618241cb081 and fixed in - // 7928eb0370d1133d0d8cd2f5ddfca19c309079d5. .mips, .mipsel => asm volatile ( - \\ move $sp, $t9 \\ li $v0, 4091 # SYS_munmap \\ syscall \\ li $v0, 4001 # SYS_exit -- 2.54.0 From 5102fe31bdc030dc6549f8dc2612c9ba981bc2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 03:51:56 +0200 Subject: [PATCH 28/45] std.Thread: fix typo in or1k LinuxThreadImpl.freeAndExit() --- lib/std/Thread.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 473aa308f242cf1d24dc7b66d4e237fec6b7d03a..b975daee75af365f87915bdaf1bc81be56ad5839 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1309,7 +1309,7 @@ const LinuxThreadImpl = struct { \\ l.ori r11, r0, 215 # SYS_munmap \\ l.sys 1 \\ l.ori r11, r0, 93 # SYS_exit - \\ l.ori r3, r0, r0 + \\ l.ori r3, r0, 0 \\ l.sys 1 : : [ptr] "{r3}" (@intFromPtr(self.mapped.ptr)), -- 2.54.0 From 5cbafcfd56862d9042b2446b0cac9d07d4d141a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 03:52:30 +0200 Subject: [PATCH 29/45] std.Thread: remove pointless clobbers in LinuxThreadImpl.freeAndExit() The function is noreturn and destroys the thread; clobbers serve no purpose. Also remove a pointless blr in the powerpc prong. --- lib/std/Thread.zig | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index b975daee75af365f87915bdaf1bc81be56ad5839..3c79bc68d4e9c09066d5b74a23a1dbf738a5258a 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1316,30 +1316,29 @@ const LinuxThreadImpl = struct { [len] "{r4}" (self.mapped.len), ), .powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile ( - \\ li 0, 91 # SYS_munmap - \\ sc - \\ li 0, 1 # SYS_exit - \\ li 3, 0 - \\ sc - \\ blr + \\ li 0, 91 # SYS_munmap + \\ sc + \\ li 0, 1 # SYS_exit + \\ li 3, 0 + \\ sc : : [ptr] "{r3}" (@intFromPtr(self.mapped.ptr)), [len] "{r4}" (self.mapped.len), ), .riscv32, .riscv64 => asm volatile ( - \\ li a7, 215 # SYS_munmap - \\ ecall - \\ li a7, 93 # SYS_exit - \\ mv a0, zero - \\ ecall + \\ li a7, 215 # SYS_munmap + \\ ecall + \\ li a7, 93 # SYS_exit + \\ mv a0, zero + \\ ecall : : [ptr] "{a0}" (@intFromPtr(self.mapped.ptr)), [len] "{a1}" (self.mapped.len), ), .s390x => asm volatile ( - \\ svc 91 # SYS_munmap - \\ lghi %%r2, 0 - \\ svc 1 # SYS_exit + \\ svc 91 # SYS_munmap + \\ lghi %%r2, 0 + \\ svc 1 # SYS_exit : : [ptr] "{r2}" (@intFromPtr(self.mapped.ptr)), [len] "{r3}" (self.mapped.len), @@ -1379,7 +1378,7 @@ const LinuxThreadImpl = struct { : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), [len] "{g2}" (self.mapped.len), [stack] "{g3}" (&sparc_exit_stack), - : .{ .memory = true }), + ), .sparc64 => asm volatile ( \\ // Ensure that the kernel only has to flush the current register window. \\ flushw @@ -1398,7 +1397,7 @@ const LinuxThreadImpl = struct { : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), [len] "{g2}" (self.mapped.len), [stack] "{g3}" (&sparc_exit_stack), - : .{ .memory = true }), + ), .loongarch32, .loongarch64 => asm volatile ( \\ ori $a7, $zero, 215 # SYS_munmap \\ syscall 0 # call munmap @@ -1408,7 +1407,7 @@ const LinuxThreadImpl = struct { : : [ptr] "{r4}" (@intFromPtr(self.mapped.ptr)), [len] "{r5}" (self.mapped.len), - : .{ .memory = true }), + ), .csky => asm volatile ( \\ movi r7, 215 # SYS_munmap \\ trap 0 @@ -1418,7 +1417,7 @@ const LinuxThreadImpl = struct { : : [ptr] "{r0}" (@intFromPtr(self.mapped.ptr)), [len] "{r1}" (self.mapped.len), - : .{ .memory = true }), + ), .xtensa, .xtensaeb => asm volatile ( \\ movi a2, 81 // SYS_munmap \\ syscall @@ -1428,7 +1427,7 @@ const LinuxThreadImpl = struct { : : [ptr] "{a6}" (@intFromPtr(self.mapped.ptr)), [len] "{a3}" (self.mapped.len), - : .{ .memory = true }), + ), else => |cpu_arch| @compileError("Unsupported linux arch: " ++ @tagName(cpu_arch)), } unreachable; -- 2.54.0 From 0d947ae87a2280d6f4acec16cf2307d11aed03e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:08:36 +0200 Subject: [PATCH 30/45] std.debug: use a different register number for pc on sparc Also report the floating-point registers as unsupported rather than invalid. --- lib/std/debug/Dwarf.zig | 2 +- lib/std/debug/cpu_context.zig | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 2d6e2204a340effe84ef4d2c00f1b87ea5cc1a5c..525e9ce078882cc4fb8013762e323579a1d05126 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1462,7 +1462,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .powerpc, .powerpcle, .powerpc64, .powerpc64le => 67, .riscv32, .riscv32be, .riscv64, .riscv64be => 65, .s390x => 65, - .sparc, .sparc64 => 32, + .sparc, .sparc64 => 65, .ve => 144, .x86 => 8, .x86_64 => 16, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 6579ade9f4ca749170294c5a03cf91a9a4b7e3a8..a0c50743465ccfcc0a68dd91589a6fade3da7e28 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1613,7 +1613,11 @@ const Sparc = extern struct { 8...15 => return @ptrCast(&ctx.o[register_num - 8]), 16...23 => return @ptrCast(&ctx.l[register_num - 16]), 24...31 => return @ptrCast(&ctx.i[register_num - 24]), - 32 => return @ptrCast(&ctx.pc), + 65 => return @ptrCast(&ctx.pc), + + 32...63 => return error.UnsupportedRegister, // F0-F31 + 64 => return error.UnsupportedRegister, // Y + 72...87 => return error.UnsupportedRegister, // D0-D15 else => return error.InvalidRegister, } -- 2.54.0 From 39f0cf90e5f761187a67b88741efcf0049baa959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:10:03 +0200 Subject: [PATCH 31/45] std.debug.cpu_context.Alpha: fix current assembly not saving r31 It's always zero, but we shouldn't leave that element of the array undefined. --- lib/std/debug/cpu_context.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index a0c50743465ccfcc0a68dd91589a6fade3da7e28..5a4cfb32cef8bda3afa6c489dd1be1453b67769e 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -349,6 +349,7 @@ const Alpha = extern struct { \\ stq $28, 0x0e0($0) \\ stq $29, 0x0e8($0) \\ stq $30, 0x0f0($0) + \\ stq $31, 0x0f8($0) \\ \\ br $1, 1f \\1: -- 2.54.0 From d9e11f4f3143e5739c5444302d4e7f4701a86d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:15:57 +0200 Subject: [PATCH 32/45] std.debug.cpu_context.Arm: make current assembly work in Thumb-1 --- lib/std/debug/cpu_context.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 5a4cfb32cef8bda3afa6c489dd1be1453b67769e..6cd81d2575b0366c5af3064d292070fdee039009 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -464,10 +464,11 @@ const Arm = struct { \\ stm r0, {r0-r12} \\ str r13, [r0, #0x34] \\ str r14, [r0, #0x38] - \\ str r15, [r0, #0x3c] + \\ mov r1, pc + \\ str r1, [r0, #0x3c] : : [r] "{r0}" (&ctx.r), - : .{ .memory = true }); + : .{ .r1 = true, .memory = true }); return ctx; } -- 2.54.0 From 225deb64e9891c555db2b55d9f4f8c16d9262139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:16:51 +0200 Subject: [PATCH 33/45] std.debug.cpu_context.Kvx: fix pc/ra being swapped vs current assembly --- lib/std/debug/cpu_context.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 6cd81d2575b0366c5af3064d292070fdee039009..e85a842bf49f559ca1765a89c9c66756af2d5a73 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -638,8 +638,8 @@ const Hexagon = extern struct { /// This is an `extern struct` so that inline assembly in `current` can use field offsets. const Kvx = extern struct { r: [64]Gpr, + pc: Gpr, ra: Gpr, - pc: Gpr, pub const Gpr = u64; -- 2.54.0 From 4a9c642b64a7f24e9a57a0c8f45961a28dd871e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:17:52 +0200 Subject: [PATCH 34/45] std.debug.cpu_context.Lanai: fix typos --- lib/std/debug/cpu_context.zig | 66 +++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index e85a842bf49f559ca1765a89c9c66756af2d5a73..0aa269f38b5d777d0b576e1e71e2e038e3b6a023 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -718,38 +718,38 @@ const Lanai = extern struct { pub inline fn current() Lanai { var ctx: Lanai = undefined; asm volatile ( - \\ st %%r0, 0[r9] - \\ st %%r1, 4[r9] - \\ st %%r2, 8[r9] - \\ st %%r3, 12[r9] - \\ st %%r4, 16[r9] - \\ st %%r5, 20[r9] - \\ st %%r6, 24[r9] - \\ st %%r7, 28[r9] - \\ st %%r8, 32[r9] - \\ st %%r9, 36[r9] - \\ st %%r10, 40[r9] - \\ st %%r11, 44[r9] - \\ st %%r12, 48[r9] - \\ st %%r13, 52[r9] - \\ st %%r14, 56[r9] - \\ st %%r15, 60[r9] - \\ st %%r16, 64[r9] - \\ st %%r17, 68[r9] - \\ st %%r18, 72[r9] - \\ st %%r19, 76[r9] - \\ st %%r20, 80[r9] - \\ st %%r21, 84[r9] - \\ st %%r22, 88[r9] - \\ st %%r23, 92[r9] - \\ st %%r24, 96[r9] - \\ st %%r25, 100[r9] - \\ st %%r26, 104[r9] - \\ st %%r27, 108[r9] - \\ st %%r28, 112[r9] - \\ st %%r29, 116[r9] - \\ st %%r30, 120[r9] - \\ st %%r31, 124[r9] + \\ st %%r0, 0[%%r9] + \\ st %%r1, 4[%%r9] + \\ st %%r2, 8[%%r9] + \\ st %%r3, 12[%%r9] + \\ st %%r4, 16[%%r9] + \\ st %%r5, 20[%%r9] + \\ st %%r6, 24[%%r9] + \\ st %%r7, 28[%%r9] + \\ st %%r8, 32[%%r9] + \\ st %%r9, 36[%%r9] + \\ st %%r10, 40[%%r9] + \\ st %%r11, 44[%%r9] + \\ st %%r12, 48[%%r9] + \\ st %%r13, 52[%%r9] + \\ st %%r14, 56[%%r9] + \\ st %%r15, 60[%%r9] + \\ st %%r16, 64[%%r9] + \\ st %%r17, 68[%%r9] + \\ st %%r18, 72[%%r9] + \\ st %%r19, 76[%%r9] + \\ st %%r20, 80[%%r9] + \\ st %%r21, 84[%%r9] + \\ st %%r22, 88[%%r9] + \\ st %%r23, 92[%%r9] + \\ st %%r24, 96[%%r9] + \\ st %%r25, 100[%%r9] + \\ st %%r26, 104[%%r9] + \\ st %%r27, 108[%%r9] + \\ st %%r28, 112[%%r9] + \\ st %%r29, 116[%%r9] + \\ st %%r30, 120[%%r9] + \\ st %%r31, 124[%%r9] : : [ctx] "{r9}" (&ctx), : .{ .memory = true }); @@ -765,7 +765,7 @@ const Lanai = extern struct { pub fn dwarfRegisterBytes(ctx: *Lanai, register_num: u16) DwarfRegisterError![]u8 { switch (register_num) { - 0...31 => return @ptrCast(&ctx.s[register_num]), + 0...31 => return @ptrCast(&ctx.r[register_num]), else => return error.InvalidRegister, } -- 2.54.0 From f376cbc37b38794857e63bffc3766ad5cb8482c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:19:11 +0200 Subject: [PATCH 35/45] std.debug.cpu_context.Sparc: align to 8 bytes to make std on 32-bit safe Otherwise we might get SIGBUS due to misalignment. --- lib/std/debug/cpu_context.zig | 102 +++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 0aa269f38b5d777d0b576e1e71e2e038e3b6a023..578f840f8cb60a86a90b4f12d9e8c1c32bc0d335 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1517,7 +1517,7 @@ const S390x = extern struct { /// This is an `extern struct` so that inline assembly in `current` can use field offsets. const Sparc = extern struct { - g: [8]Gpr, + g: [8]Gpr align(8), // Align to make `std` safe on 32-bit. o: [8]Gpr, l: [8]Gpr, i: [8]Gpr, @@ -1530,63 +1530,63 @@ const Sparc = extern struct { var ctx: Sparc = undefined; asm volatile (if (Gpr == u64) - \\ stx %g0, [%l0 + 0] - \\ stx %g1, [%l0 + 8] - \\ stx %g2, [%l0 + 16] - \\ stx %g3, [%l0 + 24] - \\ stx %g4, [%l0 + 32] - \\ stx %g5, [%l0 + 40] - \\ stx %g6, [%l0 + 48] - \\ stx %g7, [%l0 + 56] - \\ stx %o0, [%l0 + 64] - \\ stx %o1, [%l0 + 72] - \\ stx %o2, [%l0 + 80] - \\ stx %o3, [%l0 + 88] - \\ stx %o4, [%l0 + 96] - \\ stx %o5, [%l0 + 104] - \\ stx %o6, [%l0 + 112] - \\ stx %o7, [%l0 + 120] - \\ stx %l0, [%l0 + 128] - \\ stx %l1, [%l0 + 136] - \\ stx %l2, [%l0 + 144] - \\ stx %l3, [%l0 + 152] - \\ stx %l4, [%l0 + 160] - \\ stx %l5, [%l0 + 168] - \\ stx %l6, [%l0 + 176] - \\ stx %l7, [%l0 + 184] - \\ stx %i0, [%l0 + 192] - \\ stx %i1, [%l0 + 200] - \\ stx %i2, [%l0 + 208] - \\ stx %i3, [%l0 + 216] - \\ stx %i4, [%l0 + 224] - \\ stx %i5, [%l0 + 232] - \\ stx %i6, [%l0 + 240] - \\ stx %i7, [%l0 + 248] + \\ stx %%g0, [%%l0 + 0] + \\ stx %%g1, [%%l0 + 8] + \\ stx %%g2, [%%l0 + 16] + \\ stx %%g3, [%%l0 + 24] + \\ stx %%g4, [%%l0 + 32] + \\ stx %%g5, [%%l0 + 40] + \\ stx %%g6, [%%l0 + 48] + \\ stx %%g7, [%%l0 + 56] + \\ stx %%o0, [%%l0 + 64] + \\ stx %%o1, [%%l0 + 72] + \\ stx %%o2, [%%l0 + 80] + \\ stx %%o3, [%%l0 + 88] + \\ stx %%o4, [%%l0 + 96] + \\ stx %%o5, [%%l0 + 104] + \\ stx %%o6, [%%l0 + 112] + \\ stx %%o7, [%%l0 + 120] + \\ stx %%l0, [%%l0 + 128] + \\ stx %%l1, [%%l0 + 136] + \\ stx %%l2, [%%l0 + 144] + \\ stx %%l3, [%%l0 + 152] + \\ stx %%l4, [%%l0 + 160] + \\ stx %%l5, [%%l0 + 168] + \\ stx %%l6, [%%l0 + 176] + \\ stx %%l7, [%%l0 + 184] + \\ stx %%i0, [%%l0 + 192] + \\ stx %%i1, [%%l0 + 200] + \\ stx %%i2, [%%l0 + 208] + \\ stx %%i3, [%%l0 + 216] + \\ stx %%i4, [%%l0 + 224] + \\ stx %%i5, [%%l0 + 232] + \\ stx %%i6, [%%l0 + 240] + \\ stx %%i7, [%%l0 + 248] \\ call 1f \\ nop \\1: - \\ stx %o7, [%l0 + 256] + \\ stx %%o7, [%%l0 + 256] else - \\ std %g0, [%l0 + 0] - \\ std %g2, [%l0 + 8] - \\ std %g4, [%l0 + 16] - \\ std %g6, [%l0 + 24] - \\ std %o0, [%l0 + 32] - \\ std %o2, [%l0 + 40] - \\ std %o4, [%l0 + 48] - \\ std %o6, [%l0 + 56] - \\ std %l0, [%l0 + 64] - \\ std %l2, [%l0 + 72] - \\ std %l4, [%l0 + 80] - \\ std %l6, [%l0 + 88] - \\ std %i0, [%l0 + 96] - \\ std %i2, [%l0 + 104] - \\ std %i4, [%l0 + 112] - \\ std %i6, [%l0 + 120] + \\ std %%g0, [%%l0 + 0] + \\ std %%g2, [%%l0 + 8] + \\ std %%g4, [%%l0 + 16] + \\ std %%g6, [%%l0 + 24] + \\ std %%o0, [%%l0 + 32] + \\ std %%o2, [%%l0 + 40] + \\ std %%o4, [%%l0 + 48] + \\ std %%o6, [%%l0 + 56] + \\ std %%l0, [%%l0 + 64] + \\ std %%l2, [%%l0 + 72] + \\ std %%l4, [%%l0 + 80] + \\ std %%l6, [%%l0 + 88] + \\ std %%i0, [%%l0 + 96] + \\ std %%i2, [%%l0 + 104] + \\ std %%i4, [%%l0 + 112] + \\ std %%i6, [%%l0 + 120] \\ call 1f \\ nop \\1: - \\ st %o7, [%l0 + 128] + \\ st %%o7, [%%l0 + 128] : : [ctx] "{l0}" (&ctx), : .{ .o7 = true, .memory = true }); -- 2.54.0 From 19de614e9d69c44c8b8bf94b4a941740cb4e228a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:20:13 +0200 Subject: [PATCH 36/45] std.debug.cpu_context.Ve: simplify getting ic in current assembly Turns out the architecture has an instruction that just... gives you the ic. Revolutionary! --- lib/std/debug/cpu_context.zig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 578f840f8cb60a86a90b4f12d9e8c1c32bc0d335..7b8ddaba805e31cd7877a517a6844a94ee2c3f34 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1700,9 +1700,8 @@ const Ve = extern struct { \\ st %%s61, 488(, %%s8) \\ st %%s62, 496(, %%s8) \\ st %%s63, 504(, %%s8) - \\ br.l 1f - \\1: - \\ st %%lr, 512(, %%s8) + \\ sic %%s10 + \\ st %%s10, 512(, %%s8) : : [ctx] "{s8}" (&ctx), : .{ .s10 = true, .memory = true }); -- 2.54.0 From 9e9047b7e8f4fd55cd8a525ba64e4830dc8fe1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 05:22:26 +0200 Subject: [PATCH 37/45] std.debug.cpu_context.X86_16: fix register number for ip to match eip on X86 --- lib/std/debug/cpu_context.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 7b8ddaba805e31cd7877a517a6844a94ee2c3f34..07bb43a4fa2997a61ea5b2286132de2c427ce648 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1768,7 +1768,7 @@ const X86_16 = struct { switch (register_num) { 4 => return @ptrCast(ctx.regs.getPtr(.sp)), 5 => return @ptrCast(ctx.regs.getPtr(.bp)), - 6 => return @ptrCast(ctx.regs.getPtr(.ip)), + 8 => return @ptrCast(ctx.regs.getPtr(.ip)), 41 => return @ptrCast(ctx.regs.getPtr(.cs)), 42 => return @ptrCast(ctx.regs.getPtr(.ss)), else => return error.InvalidRegister, -- 2.54.0 From fb578f3d17e839f0454cee4832baf2d4c95c4bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:08:06 +0200 Subject: [PATCH 38/45] std.atomic: use pause on mips r2+ in spinLoopHint --- lib/std/atomic.zig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig index afbb9137be5148f830dd2fb1cfc3eb5b3535e0b8..d5a7403b092225c33adf976a68ae7e5021b958e5 100644 --- a/lib/std/atomic.zig +++ b/lib/std/atomic.zig @@ -392,6 +392,14 @@ pub inline fn spinLoopHint() void { .hexagon, => asm volatile ("pause(#1)"), + .mips, + .mipsel, + .mips64, + .mips64el, + => if (comptime builtin.cpu.has(.mips, .mips32r2)) { + asm volatile ("pause"); + }, + .riscv32, .riscv32be, .riscv64, -- 2.54.0 From 0125c27363f8b36d17ce53fee33a7e807c9ce167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:08:27 +0200 Subject: [PATCH 39/45] std.atomic: use rd %ccr, %g0 on sparc v9 in spinLoopHint --- lib/std/atomic.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig index d5a7403b092225c33adf976a68ae7e5021b958e5..814d87ae261a094d74e828de10a89ac8a2c804f2 100644 --- a/lib/std/atomic.zig +++ b/lib/std/atomic.zig @@ -408,6 +408,12 @@ pub inline fn spinLoopHint() void { asm volatile ("pause"); }, + .sparc, + .sparc64, + => if (comptime builtin.cpu.hasAny(.sparc, &.{ .v8plus, .v9 })) { + asm volatile ("rd %%ccr, %%g0"); + }, + else => {}, } } -- 2.54.0 From b29a6e3925311d01296156992cc71c1c8f39b07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:08:52 +0200 Subject: [PATCH 40/45] std.atomic: fix conditions for using yield on arm/thumb in spinLoopHint --- lib/std/atomic.zig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig index 814d87ae261a094d74e828de10a89ac8a2c804f2..abc7b06f0adbfb51e58d33492282780564c06e3a 100644 --- a/lib/std/atomic.zig +++ b/lib/std/atomic.zig @@ -377,13 +377,16 @@ pub inline fn spinLoopHint() void { .aarch64_be, => asm volatile ("isb"), - // `yield` was introduced in v6k but is also available on v6m. // https://www.keil.com/support/man/docs/armasm/armasm_dom1361289926796.htm .arm, .armeb, + => if (comptime builtin.cpu.has(.arm, .has_v6k)) { + asm volatile ("yield"); + }, + .thumb, .thumbeb, - => if (comptime builtin.cpu.hasAny(.arm, &.{ .has_v6k, .has_v6m })) { + => if (comptime builtin.cpu.hasAny(.arm, &.{ .has_v6m, .thumb2 })) { asm volatile ("yield"); }, -- 2.54.0 From bc5cd402211ba274328ce6f4287201ca5c013473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:10:35 +0200 Subject: [PATCH 41/45] std.os.linux.tls: fix operand order for sh setThreadPointer/getThreadPointer assembly --- lib/std/os/linux/tls.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 798f5666311dbad2edbfd81bdd0e81c02c184019..6c7ea2f6b3844034932e5bb1c4a9089869f571ca 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -358,7 +358,7 @@ pub fn setThreadPointer(addr: usize) void { }, .sh, .sheb => { asm volatile ( - \\ ldc gbr, %[addr] + \\ ldc %[addr], gbr : : [addr] "r" (addr), ); @@ -450,7 +450,7 @@ pub fn getThreadPointer() usize { : [ret] "=r" (-> usize), ), .sh, .sheb => asm ( - \\ stc %[ret], gbr + \\ stc gbr, %[ret] : [ret] "=r" (-> usize), ), .sparc, .sparc64 => asm ( -- 2.54.0 From 0873d786b63dd1995cbff6bbb7045d2443306c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:11:10 +0200 Subject: [PATCH 42/45] std.os.linux.tls: fix m68k getThreadPointer to use syscall0 instead of syscall1 --- lib/std/os/linux/tls.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 6c7ea2f6b3844034932e5bb1c4a9089869f571ca..2aa2c4a208cabd1c77f330dbc350363b55987fa4 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -418,7 +418,7 @@ pub fn getThreadPointer() usize { \\ move %[ret], $tp : [ret] "=r" (-> usize), ), - .m68k => linux.syscall1(.get_thread_area), + .m68k => linux.syscall0(.get_thread_area), .mips, .mipsel, .mips64, .mips64el => asm ( \\ rdhwr %[ret], $29 : [ret] "=r" (-> usize), -- 2.54.0 From 01cadcae1c3061d8a8726b3c4e23dbb6ad113433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:15:23 +0200 Subject: [PATCH 43/45] std.os.linux.tls: always inline set_thread_area syscall in m68k setThreadPointer As for the rest. --- lib/std/os/linux/tls.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 2aa2c4a208cabd1c77f330dbc350363b55987fa4..731703d30979e3d7dba00259861cfa69a094d7a3 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -282,7 +282,7 @@ pub fn setThreadPointer(addr: usize) void { assert(rc == 0); }, .m68k => { - const rc = linux.syscall1(.set_thread_area, addr); + const rc = @call(.always_inline, linux.syscall1, .{ .set_thread_area, addr }); assert(rc == 0); }, .hexagon => { -- 2.54.0 From 52b8d3421e347871ffe16cbda30141183fd5e624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:13:39 +0200 Subject: [PATCH 44/45] std.os.linux.tls: fix alpha setThreadPointer assembly not indicating its r16 clobber --- lib/std/os/linux/tls.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 731703d30979e3d7dba00259861cfa69a094d7a3..1c1558be2291ec7129d87d2ff63e602991a4396e 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -261,10 +261,9 @@ pub fn setThreadPointer(addr: usize) void { }, .alpha => { asm volatile ( - \\ lda $16, 0(%[addr]) \\ wruniq : - : [addr] "r" (addr), + : [addr] "{$16}" (addr), ); }, .arc, .arceb => { -- 2.54.0 From 8217f26ef8ddab9eb02a9d380d6509c39ac2d0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 9 Aug 2026 16:30:33 +0200 Subject: [PATCH 45/45] std.os.linux.tls: fix a typo and a mistake in hppa setThreadPointer assembly * addr is an input, not an output. * ble clobbers r31, not r29. --- lib/std/os/linux/tls.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 1c1558be2291ec7129d87d2ff63e602991a4396e..aed76fc0cb2ee83318e5c0e2d72b0016cf44eb91 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -296,8 +296,8 @@ pub fn setThreadPointer(addr: usize) void { \\ ble 0xe0(%%sr2, %%r0) \\ nop : - : [addr] "={r26}" (addr), - : .{ .r29 = true }); + : [addr] "{r26}" (addr), + : .{ .r31 = true }); }, .loongarch32, .loongarch64 => { asm volatile ( -- 2.54.0