zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit b8d776928a0b0092830ee632b1c57c8bcf9391ea (tree)
parent f3da54f53c1db1484b00657de18e3677358549cd
Author: Alex Rønne Petersen <alex@alexrp.com>
Date:   Sat, 18 Oct 2025 01:56:20 +0200

std: make all MIPS inline asm safe for MIPS I

MIPS I has load hazards so we need to insert nops in a few places. This is not a
problem for MIPS II and later.

While doing this, I also touched up all the inline asm to use ABI register
aliases and a consistent formatting convention. Also fixed a few places that
didn't properly check if the syscall return value should be negated.

Diffstat:
Mlib/std/os/linux/mips.zig | 162++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mlib/std/os/linux/mips64.zig | 131+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mlib/std/os/linux/mipsn32.zig | 131+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mlib/std/pie.zig | 5+++--
Mlib/std/start.zig | 26++++++++++++++------------
5 files changed, 223 insertions(+), 232 deletions(-)

diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig @@ -5,10 +5,10 @@ const SYS = std.os.linux.SYS; pub fn syscall0(number: SYS) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), : .{ .r1 = true, .r3 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); @@ -16,17 +16,15 @@ pub fn syscall0(number: SYS) u32 { pub fn syscall_pipe(fd: *[2]i32) u32 { return asm volatile ( - \\ .set noat - \\ .set noreorder \\ syscall - \\ beq $7, $zero, 1f - \\ nop + \\ beq $a3, $zero, 1f + \\ blez $v0, 2f + \\ subu $v0, $zero, $v0 \\ b 2f - \\ subu $2, $0, $2 - \\ 1: - \\ sw $2, 0($4) - \\ sw $3, 4($4) - \\ 2: + \\1: + \\ sw $v0, 0($a0) + \\ sw $v1, 4($a0) + \\2: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(SYS.pipe)), [fd] "{$4}" (fd), @@ -36,10 +34,10 @@ pub fn syscall_pipe(fd: *[2]i32) u32 { pub fn syscall1(number: SYS, arg1: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -49,10 +47,10 @@ pub fn syscall1(number: SYS, arg1: u32) u32 { pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -63,10 +61,10 @@ pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 { pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -78,10 +76,10 @@ pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 { pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -91,17 +89,19 @@ pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 { : .{ .r1 = true, .r3 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); } +// NOTE: The o32 calling convention requires the callee to reserve 16 bytes for +// the first four arguments even though they're passed in $a0-$a3. + pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 { return asm volatile ( - \\ .set noat \\ subu $sp, $sp, 24 \\ sw %[arg5], 16($sp) \\ syscall \\ addu $sp, $sp, 24 - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -112,9 +112,6 @@ pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u : .{ .r1 = true, .r3 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); } -// NOTE: The o32 calling convention requires the callee to reserve 16 bytes for -// the first four arguments even though they're passed in $a0-$a3. - pub fn syscall6( number: SYS, arg1: u32, @@ -125,16 +122,15 @@ pub fn syscall6( arg6: u32, ) u32 { return asm volatile ( - \\ .set noat \\ subu $sp, $sp, 24 \\ sw %[arg5], 16($sp) \\ sw %[arg6], 20($sp) \\ syscall \\ addu $sp, $sp, 24 - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -157,17 +153,16 @@ pub fn syscall7( arg7: u32, ) u32 { return asm volatile ( - \\ .set noat \\ subu $sp, $sp, 32 \\ sw %[arg5], 16($sp) \\ sw %[arg6], 20($sp) \\ sw %[arg7], 24($sp) \\ syscall \\ addu $sp, $sp, 32 - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ subu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -182,52 +177,51 @@ pub fn syscall7( pub fn clone() callconv(.naked) u32 { // __clone(func, stack, flags, arg, ptid, tls, ctid) - // 3, 4, 5, 6, 7, 8, 9 + // a0, a1, a2, a3, +0, +4, +8 // // syscall(SYS_clone, flags, stack, ptid, tls, ctid) - // 2 4, 5, 6, 7, 8 + // v0 a0, a1, a2, a3, +0 asm volatile ( - \\ # Save function pointer and argument pointer on new thread stack - \\ and $5, $5, -8 - \\ subu $5, $5, 16 - \\ sw $4, 0($5) - \\ sw $7, 4($5) - \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) - \\ move $4, $6 - \\ lw $6, 16($sp) - \\ lw $7, 20($sp) - \\ lw $9, 24($sp) - \\ subu $sp, $sp, 16 - \\ sw $9, 16($sp) - \\ li $2, 4120 # SYS_clone - \\ syscall - \\ beq $7, $0, 1f - \\ nop - \\ addu $sp, $sp, 16 - \\ jr $ra - \\ subu $2, $0, $2 - \\1: - \\ beq $2, $0, 1f - \\ nop - \\ addu $sp, $sp, 16 - \\ jr $ra - \\ nop + \\ # Save function pointer and argument pointer on new thread stack + \\ and $a1, $a1, -8 + \\ subu $a1, $a1, 16 + \\ sw $a0, 0($a1) + \\ sw $a3, 4($a1) + \\ + \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) + \\ move $a0, $a2 + \\ lw $a2, 16($sp) + \\ lw $a3, 20($sp) + \\ lw $t1, 24($sp) + \\ subu $sp, $sp, 16 + \\ sw $t1, 16($sp) + \\ li $v0, 4120 # SYS_clone + \\ syscall + \\ beq $a3, $zero, 1f + \\ blez $v0, 2f + \\ subu $v0, $zero, $v0 + \\ b 2f \\1: + \\ beq $v0, $zero, 3f + \\2: + \\ addu $sp, $sp, 16 + \\ jr $ra + \\3: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( - \\ .cfi_undefined $ra + \\ .cfi_undefined $ra ); asm volatile ( - \\ move $fp, $zero - \\ move $ra, $zero + \\ move $fp, $zero + \\ move $ra, $zero \\ - \\ lw $25, 0($sp) - \\ lw $4, 4($sp) - \\ jalr $25 - \\ nop - \\ move $4, $2 - \\ li $2, 4001 # SYS_exit - \\ syscall + \\ lw $t9, 0($sp) + \\ lw $a0, 4($sp) + \\ jalr $t9 + \\ + \\ move $a0, $v0 + \\ li $v0, 4001 # SYS_exit + \\ syscall ); } diff --git a/lib/std/os/linux/mips64.zig b/lib/std/os/linux/mips64.zig @@ -5,10 +5,10 @@ const SYS = std.os.linux.SYS; pub fn syscall0(number: SYS) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), : .{ .r1 = true, .r3 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); @@ -16,17 +16,15 @@ pub fn syscall0(number: SYS) u64 { pub fn syscall_pipe(fd: *[2]i32) u64 { return asm volatile ( - \\ .set noat - \\ .set noreorder \\ syscall - \\ beq $7, $zero, 1f - \\ nop + \\ beq $a3, $zero, 1f + \\ blez $v0, 2f + \\ dsubu $v0, $zero, $v0 \\ b 2f - \\ subu $2, $0, $2 - \\ 1: - \\ sw $2, 0($4) - \\ sw $3, 4($4) - \\ 2: + \\1: + \\ sw $v0, 0($a0) + \\ sw $v1, 4($a0) + \\2: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(SYS.pipe)), [fd] "{$4}" (fd), @@ -36,11 +34,10 @@ pub fn syscall_pipe(fd: *[2]i32) u64 { pub fn syscall1(number: SYS, arg1: u64) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ nop - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -50,10 +47,10 @@ pub fn syscall1(number: SYS, arg1: u64) u64 { pub fn syscall2(number: SYS, arg1: u64, arg2: u64) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -64,10 +61,10 @@ pub fn syscall2(number: SYS, arg1: u64, arg2: u64) u64 { pub fn syscall3(number: SYS, arg1: u64, arg2: u64, arg3: u64) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -79,10 +76,10 @@ pub fn syscall3(number: SYS, arg1: u64, arg2: u64, arg3: u64) u64 { pub fn syscall4(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -95,10 +92,10 @@ pub fn syscall4(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64) u64 { pub fn syscall5(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -120,10 +117,10 @@ pub fn syscall6( ) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -147,10 +144,10 @@ pub fn syscall7( ) u64 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u64), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -165,33 +162,33 @@ pub fn syscall7( pub fn clone() callconv(.naked) u64 { // __clone(func, stack, flags, arg, ptid, tls, ctid) - // 3, 4, 5, 6, 7, 8, 9 + // a0, a1, a2, a3, a4, a5, a6 // // syscall(SYS_clone, flags, stack, ptid, tls, ctid) - // 2 4, 5, 6, 7, 8 + // v0 a0, a1, a2, a3, a4 asm volatile ( \\ # Save function pointer and argument pointer on new thread stack - \\ and $5, $5, -16 - \\ dsubu $5, $5, 16 - \\ sd $4, 0($5) - \\ sd $7, 8($5) + \\ and $a1, $a1, -16 + \\ dsubu $a1, $a1, 16 + \\ sd $a0, 0($a1) + \\ sd $a3, 8($a1) + \\ \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) - \\ move $4, $6 - \\ move $6, $8 - \\ move $7, $9 - \\ move $8, $10 - \\ li $2, 5055 # SYS_clone + \\ move $a0, $a2 + \\ move $a2, $a4 + \\ move $a3, $a5 + \\ move $a4, $a6 + \\ li $v0, 5055 # SYS_clone \\ syscall - \\ beq $7, $0, 1f - \\ nop - \\ jr $ra - \\ dsubu $2, $0, $2 + \\ beq $a3, $zero, 1f + \\ blez $v0, 2f + \\ dsubu $v0, $zero, $v0 + \\ b 2f \\1: - \\ beq $2, $0, 1f - \\ nop + \\ beq $v0, $zero, 3f + \\2: \\ jr $ra - \\ nop - \\1: + \\3: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( \\ .cfi_undefined $ra @@ -200,12 +197,12 @@ pub fn clone() callconv(.naked) u64 { \\ move $fp, $zero \\ move $ra, $zero \\ - \\ ld $25, 0($sp) - \\ ld $4, 8($sp) - \\ jalr $25 - \\ nop - \\ move $4, $2 - \\ li $2, 5058 # SYS_exit + \\ ld $t9, 0($sp) + \\ ld $a0, 8($sp) + \\ jalr $t9 + \\ + \\ move $a0, $v0 + \\ li $v0, 5058 # SYS_exit \\ syscall ); } diff --git a/lib/std/os/linux/mipsn32.zig b/lib/std/os/linux/mipsn32.zig @@ -7,10 +7,10 @@ const SYS = std.os.linux.SYS; pub fn syscall0(number: SYS) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), : .{ .r1 = true, .r3 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); @@ -18,17 +18,15 @@ pub fn syscall0(number: SYS) u32 { pub fn syscall_pipe(fd: *[2]i32) u32 { return asm volatile ( - \\ .set noat - \\ .set noreorder \\ syscall - \\ beq $7, $zero, 1f - \\ nop + \\ beq $a3, $zero, 1f + \\ blez $v0, 2f + \\ dsubu $v0, $zero, $v0 \\ b 2f - \\ subu $2, $0, $2 - \\ 1: - \\ sw $2, 0($4) - \\ sw $3, 4($4) - \\ 2: + \\1: + \\ sw $v0, 0($a0) + \\ sw $v1, 4($a0) + \\2: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(SYS.pipe)), [fd] "{$4}" (fd), @@ -38,11 +36,10 @@ pub fn syscall_pipe(fd: *[2]i32) u32 { pub fn syscall1(number: SYS, arg1: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ nop - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -52,10 +49,10 @@ pub fn syscall1(number: SYS, arg1: u32) u32 { pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -66,10 +63,10 @@ pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 { pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -81,10 +78,10 @@ pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 { pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -97,10 +94,10 @@ pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 { pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -122,10 +119,10 @@ pub fn syscall6( ) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -149,10 +146,10 @@ pub fn syscall7( ) u32 { return asm volatile ( \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: + \\ beq $a3, $zero, 1f + \\ blez $v0, 1f + \\ dsubu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -167,33 +164,33 @@ pub fn syscall7( pub fn clone() callconv(.naked) u32 { // __clone(func, stack, flags, arg, ptid, tls, ctid) - // 3, 4, 5, 6, 7, 8, 9 + // a0, a1, a2, a3, a4, a5, a6 // // syscall(SYS_clone, flags, stack, ptid, tls, ctid) - // 2 4, 5, 6, 7, 8 + // v0 a0, a1, a2, a3, a4 asm volatile ( \\ # Save function pointer and argument pointer on new thread stack - \\ and $5, $5, -16 - \\ dsubu $5, $5, 16 - \\ sd $4, 0($5) - \\ sd $7, 8($5) + \\ and $a1, $a1, -16 + \\ dsubu $a1, $a1, 16 + \\ sd $a0, 0($a1) + \\ sd $a3, 8($a1) + \\ \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) - \\ move $4, $6 - \\ move $6, $8 - \\ move $7, $9 - \\ move $8, $10 - \\ li $2, 5055 # SYS_clone + \\ move $a0, $a2 + \\ move $a2, $a4 + \\ move $a3, $a5 + \\ move $a4, $a6 + \\ li $v0, 5055 # SYS_clone \\ syscall - \\ beq $7, $0, 1f - \\ nop - \\ jr $ra - \\ dsubu $2, $0, $2 + \\ beq $a3, $zero, 1f + \\ blez $v0, 2f + \\ dsubu $v0, $zero, $v0 + \\ b 2f \\1: - \\ beq $2, $0, 1f - \\ nop + \\ beq $v0, $zero, 3f + \\2: \\ jr $ra - \\ nop - \\1: + \\3: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( \\ .cfi_undefined $ra @@ -202,12 +199,12 @@ pub fn clone() callconv(.naked) u32 { \\ move $fp, $zero \\ move $ra, $zero \\ - \\ ld $25, 0($sp) - \\ ld $4, 8($sp) - \\ jalr $25 - \\ nop - \\ move $4, $2 - \\ li $2, 5058 # SYS_exit + \\ ld $t9, 0($sp) + \\ ld $a0, 8($sp) + \\ jalr $t9 + \\ + \\ move $a0, $v0 + \\ li $v0, 5058 # SYS_exit \\ syscall ); } diff --git a/lib/std/pie.zig b/lib/std/pie.zig @@ -121,8 +121,9 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ .hidden _DYNAMIC \\ bal 1f \\ .gpword _DYNAMIC - \\ 1: + \\1: \\ lw %[ret], 0($ra) + \\ nop \\ addu %[ret], %[ret], $gp : [ret] "=r" (-> [*]const elf.Dyn), : @@ -133,7 +134,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ .balign 8 \\ bal 1f \\ .gpdword _DYNAMIC - \\ 1: + \\1: \\ ld %[ret], 0($ra) \\ daddu %[ret], %[ret], $gp : [ret] "=r" (-> [*]const elf.Dyn), diff --git a/lib/std/start.zig b/lib/std/start.zig @@ -325,24 +325,26 @@ fn _start() callconv(.naked) noreturn { \\ jsr (%%pc, %%a0) , .mips, .mipsel => - \\ move $fp, $0 + \\ move $fp, $zero \\ bal 1f \\ .gpword . \\ .gpword %[posixCallMainAndExit] - \\ 1: + \\1: // The `gp` register on MIPS serves a similar purpose to `r2` (ToC pointer) on PPC64. \\ lw $gp, 0($ra) + \\ nop \\ subu $gp, $ra, $gp - \\ lw $25, 4($ra) - \\ addu $25, $25, $gp - \\ move $ra, $0 + \\ lw $t9, 4($ra) + \\ nop + \\ addu $t9, $t9, $gp + \\ move $ra, $zero \\ move $a0, $sp \\ and $sp, -8 \\ subu $sp, $sp, 16 - \\ jalr $25 + \\ jalr $t9 , .mips64, .mips64el => - \\ move $fp, $0 + \\ move $fp, $zero // This is needed because early MIPS versions don't support misaligned loads. Without // this directive, the hidden `nop` inserted to fill the delay slot after `bal` would // cause the two doublewords to be aligned to 4 bytes instead of 8. @@ -350,17 +352,17 @@ fn _start() callconv(.naked) noreturn { \\ bal 1f \\ .gpdword . \\ .gpdword %[posixCallMainAndExit] - \\ 1: + \\1: // The `gp` register on MIPS serves a similar purpose to `r2` (ToC pointer) on PPC64. \\ ld $gp, 0($ra) \\ dsubu $gp, $ra, $gp - \\ ld $25, 8($ra) - \\ daddu $25, $25, $gp - \\ move $ra, $0 + \\ ld $t9, 8($ra) + \\ daddu $t9, $t9, $gp + \\ move $ra, $zero \\ move $a0, $sp \\ and $sp, -16 \\ dsubu $sp, $sp, 16 - \\ jalr $25 + \\ jalr $t9 , .powerpc, .powerpcle => // Set up the initial stack frame, and clear the back chain pointer.