diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 6cc377b5bd..c299fb626c 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1191,12 +1191,22 @@ const LinuxThreadImpl = struct { : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), : .{ .memory = true }), - .x86_64 => asm volatile ( - \\ movq $11, %%rax # SYS_munmap - \\ syscall - \\ movq $60, %%rax # SYS_exit - \\ movq $1, %%rdi - \\ syscall + .x86_64 => asm volatile (switch (target.abi) { + .gnux32, .muslx32 => + \\ 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 + , + } : : [ptr] "{rdi}" (@intFromPtr(self.mapped.ptr)), [len] "{rsi}" (self.mapped.len), @@ -1242,26 +1252,38 @@ const LinuxThreadImpl = struct { // The bug was introduced in 46e12c07b3b9603c60fc1d421ff18618241cb081 and fixed in // 7928eb0370d1133d0d8cd2f5ddfca19c309079d5. .mips, .mipsel => asm volatile ( - \\ move $sp, $25 - \\ li $2, 4091 # SYS_munmap - \\ move $4, %[ptr] - \\ move $5, %[len] - \\ syscall - \\ li $2, 4001 # SYS_exit - \\ li $4, 0 - \\ syscall + \\ move $sp, $t9 + \\ li $v0, 4091 # SYS_munmap + \\ move $a0, %[ptr] + \\ move $a1, %[len] + \\ syscall + \\ li $v0, 4001 # SYS_exit + \\ li $a0, 0 + \\ syscall : : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), : .{ .memory = true }), - .mips64, .mips64el => asm volatile ( - \\ li $2, 5011 # SYS_munmap - \\ move $4, %[ptr] - \\ move $5, %[len] - \\ syscall - \\ li $2, 5058 # SYS_exit - \\ li $4, 0 - \\ syscall + .mips64, .mips64el => asm volatile (switch (target.abi) { + .gnuabin32, .muslabin32 => + \\ li $v0, 6011 # SYS_munmap + \\ move $a0, %[ptr] + \\ move $a1, %[len] + \\ syscall + \\ li $v0, 6058 # SYS_exit + \\ li $a0, 0 + \\ syscall + , + else => + \\ li $v0, 5011 # SYS_munmap + \\ move $a0, %[ptr] + \\ move $a1, %[len] + \\ syscall + \\ li $v0, 5058 # SYS_exit + \\ li $a0, 0 + \\ syscall + , + } : : [ptr] "r" (@intFromPtr(self.mapped.ptr)), [len] "r" (self.mapped.len), diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig index 7468396a09..3bd7790bd5 100644 --- 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 index 187a093c43..82ad6184f1 100644 --- 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), @@ -135,63 +132,35 @@ pub fn syscall6( : .{ .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 }); } -pub fn syscall7( - number: SYS, - arg1: u64, - arg2: u64, - arg3: u64, - arg4: u64, - arg5: u64, - arg6: u64, - arg7: u64, -) u64 { - return asm volatile ( - \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: - : [ret] "={$2}" (-> u64), - : [number] "{$2}" (@intFromEnum(number)), - [arg1] "{$4}" (arg1), - [arg2] "{$5}" (arg2), - [arg3] "{$6}" (arg3), - [arg4] "{$7}" (arg4), - [arg5] "{$8}" (arg5), - [arg6] "{$9}" (arg6), - [arg7] "{$10}" (arg7), - : .{ .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 }); -} - 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 +169,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 index 59a4cf0549..584edf7c80 100644 --- a/lib/std/os/linux/mipsn32.zig +++ b/lib/std/os/linux/mipsn32.zig @@ -1,5 +1,3 @@ -// TODO: A lot of this file is very likely wrong. - const builtin = @import("builtin"); const std = @import("../../std.zig"); const SYS = std.os.linux.SYS; @@ -7,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 - \\ dsubu $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 }); @@ -18,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), @@ -38,11 +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 - \\ nop - \\ dsubu $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), @@ -52,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 - \\ dsubu $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), @@ -66,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 - \\ dsubu $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), @@ -81,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 - \\ dsubu $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), @@ -97,10 +92,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 + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -122,10 +117,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 + \\ subu $v0, $zero, $v0 + \\1: : [ret] "={$2}" (-> u32), : [number] "{$2}" (@intFromEnum(number)), [arg1] "{$4}" (arg1), @@ -137,63 +132,35 @@ pub fn syscall6( : .{ .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 }); } -pub fn syscall7( - number: SYS, - arg1: u32, - arg2: u32, - arg3: u32, - arg4: u32, - arg5: u32, - arg6: u32, - arg7: u32, -) u32 { - return asm volatile ( - \\ syscall - \\ beq $7, $zero, 1f - \\ blez $2, 1f - \\ dsubu $2, $0, $2 - \\ 1: - : [ret] "={$2}" (-> u32), - : [number] "{$2}" (@intFromEnum(number)), - [arg1] "{$4}" (arg1), - [arg2] "{$5}" (arg2), - [arg3] "{$6}" (arg3), - [arg4] "{$7}" (arg4), - [arg5] "{$8}" (arg5), - [arg6] "{$9}" (arg6), - [arg7] "{$10}" (arg7), - : .{ .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 }); -} - 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 + \\ 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 $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, 6055 # SYS_clone \\ syscall - \\ beq $7, $0, 1f - \\ nop - \\ jr $ra - \\ dsubu $2, $0, $2 + \\ beq $a3, $zero, 1f + \\ blez $v0, 2f + \\ subu $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 +169,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, 4($sp) + \\ jalr $t9 + \\ + \\ move $a0, $v0 + \\ li $v0, 6058 # SYS_exit \\ syscall ); } diff --git a/lib/std/os/linux/x32.zig b/lib/std/os/linux/x32.zig index 4335fac04b..ac596844d6 100644 --- a/lib/std/os/linux/x32.zig +++ b/lib/std/os/linux/x32.zig @@ -1,5 +1,3 @@ -// TODO: A lot of this file is very likely wrong. - const builtin = @import("builtin"); const std = @import("../../std.zig"); const SYS = std.os.linux.SYS; @@ -84,20 +82,20 @@ pub fn syscall6( pub fn clone() callconv(.naked) u32 { 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) + \\ movl $0x40000038,%%eax // SYS_clone + \\ mov %%rdi,%%r11 + \\ mov %%rdx,%%rdi + \\ mov %%r8,%%rdx + \\ mov %%r9,%%r8 + \\ mov 8(%%rsp),%%r10 + \\ mov %%r11,%%r9 + \\ and $-16,%%rsi + \\ sub $8,%%rsi + \\ mov %%rcx,(%%rsi) \\ syscall - \\ testq %%rax,%%rax + \\ test %%eax,%%eax \\ jz 1f - \\ retq + \\ ret \\ \\1: ); @@ -105,12 +103,12 @@ pub fn clone() callconv(.naked) u32 { \\ .cfi_undefined %%rip ); asm volatile ( - \\ xorl %%ebp,%%ebp + \\ xor %%ebp,%%ebp \\ - \\ popq %%rdi - \\ callq *%%r9 - \\ movl %%eax,%%edi - \\ movl $60,%%eax // SYS_exit + \\ pop %%rdi + \\ call *%%r9 + \\ mov %%eax,%%edi + \\ movl $0x4000003c,%%eax // SYS_exit \\ syscall \\ ); diff --git a/lib/std/pie.zig b/lib/std/pie.zig index b497d6ed44..de8c63fc87 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -121,24 +121,38 @@ 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), : : .{ .lr = true }), - .mips64, .mips64el => asm volatile ( - \\ .weak _DYNAMIC - \\ .hidden _DYNAMIC - \\ .balign 8 - \\ bal 1f - \\ .gpdword _DYNAMIC - \\ 1: - \\ ld %[ret], 0($ra) - \\ daddu %[ret], %[ret], $gp - : [ret] "=r" (-> [*]const elf.Dyn), - : - : .{ .lr = true }), + .mips64, .mips64el => switch (builtin.abi) { + .gnuabin32, .muslabin32 => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ bal 1f + \\ .gpword _DYNAMIC + \\1: + \\ lw %[ret], 0($ra) + \\ addu %[ret], %[ret], $gp + : [ret] "=r" (-> [*]const elf.Dyn), + : + : .{ .lr = true }), + else => asm volatile ( + \\ .weak _DYNAMIC + \\ .hidden _DYNAMIC + \\ .balign 8 + \\ bal 1f + \\ .gpdword _DYNAMIC + \\1: + \\ ld %[ret], 0($ra) + \\ daddu %[ret], %[ret], $gp + : [ret] "=r" (-> [*]const elf.Dyn), + : + : .{ .lr = true }), + }, .powerpc, .powerpcle => asm volatile ( \\ .weak _DYNAMIC \\ .hidden _DYNAMIC diff --git a/lib/std/start.zig b/lib/std/start.zig index 60ddae43ac..299823a127 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -325,43 +325,64 @@ 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 - , - .mips64, .mips64el => - \\ move $fp, $0 - // 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. - \\ .balign 8 - \\ bal 1f - \\ .gpdword . - \\ .gpdword %[posixCallMainAndExit] - \\ 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 - \\ move $a0, $sp - \\ and $sp, -16 - \\ dsubu $sp, $sp, 16 - \\ jalr $25 + \\ jalr $t9 , + .mips64, .mips64el => switch (builtin.abi) { + .gnuabin32, .muslabin32 => + \\ move $fp, $zero + \\ bal 1f + \\ .gpword . + \\ .gpword %[posixCallMainAndExit] + \\1: + // The `gp` register on MIPS serves a similar purpose to `r2` (ToC pointer) on PPC64. + \\ lw $gp, 0($ra) + \\ subu $gp, $ra, $gp + \\ lw $t9, 4($ra) + \\ addu $t9, $t9, $gp + \\ move $ra, $zero + \\ move $a0, $sp + \\ and $sp, -8 + \\ subu $sp, $sp, 16 + \\ jalr $t9 + , + else => + \\ 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. + \\ .balign 8 + \\ bal 1f + \\ .gpdword . + \\ .gpdword %[posixCallMainAndExit] + \\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 $t9, 8($ra) + \\ daddu $t9, $t9, $gp + \\ move $ra, $zero + \\ move $a0, $sp + \\ and $sp, -16 + \\ dsubu $sp, $sp, 16 + \\ jalr $t9 + , + }, .powerpc, .powerpcle => // Set up the initial stack frame, and clear the back chain pointer. // r1 = SP, r31 = FP