diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index ce5eec59f5..df9e822c07 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -43,7 +43,10 @@ const arch_bits = switch (native_arch) { .loongarch64 => @import("linux/loongarch64.zig"), .m68k => @import("linux/m68k.zig"), .mips, .mipsel => @import("linux/mips.zig"), - .mips64, .mips64el => @import("linux/mips64.zig"), + .mips64, .mips64el => switch (builtin.abi) { + .gnuabin32, .muslabin32 => @import("linux/mipsn32.zig"), + else => @import("linux/mips64.zig"), + }, .powerpc, .powerpcle => @import("linux/powerpc.zig"), .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), .s390x => @import("linux/s390x.zig"), diff --git a/lib/std/os/linux/mipsn32.zig b/lib/std/os/linux/mipsn32.zig new file mode 100644 index 0000000000..59a4cf0549 --- /dev/null +++ b/lib/std/os/linux/mipsn32.zig @@ -0,0 +1,271 @@ +// 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; + +pub fn syscall0(number: SYS) u32 { + return asm volatile ( + \\ syscall + \\ beq $7, $zero, 1f + \\ blez $2, 1f + \\ dsubu $2, $0, $2 + \\ 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 }); +} + +pub fn syscall_pipe(fd: *[2]i32) u32 { + return asm volatile ( + \\ .set noat + \\ .set noreorder + \\ syscall + \\ beq $7, $zero, 1f + \\ nop + \\ b 2f + \\ subu $2, $0, $2 + \\ 1: + \\ sw $2, 0($4) + \\ sw $3, 4($4) + \\ 2: + : [ret] "={$2}" (-> u32), + : [number] "{$2}" (@intFromEnum(SYS.pipe)), + [fd] "{$4}" (fd), + : .{ .r1 = true, .r3 = 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 }); +} + +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: + : [ret] "={$2}" (-> u32), + : [number] "{$2}" (@intFromEnum(number)), + [arg1] "{$4}" (arg1), + : .{ .r1 = true, .r3 = 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 }); +} + +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: + : [ret] "={$2}" (-> u32), + : [number] "{$2}" (@intFromEnum(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + : .{ .r1 = true, .r3 = 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 }); +} + +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: + : [ret] "={$2}" (-> u32), + : [number] "{$2}" (@intFromEnum(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + : .{ .r1 = true, .r3 = 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 }); +} + +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: + : [ret] "={$2}" (-> u32), + : [number] "{$2}" (@intFromEnum(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + [arg4] "{$7}" (arg4), + : .{ .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 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: + : [ret] "={$2}" (-> u32), + : [number] "{$2}" (@intFromEnum(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + [arg4] "{$7}" (arg4), + [arg5] "{$8}" (arg5), + : .{ .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 syscall6( + number: SYS, + arg1: u32, + arg2: u32, + arg3: u32, + arg4: u32, + arg5: u32, + arg6: 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), + : .{ .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 + // + // syscall(SYS_clone, flags, stack, ptid, tls, ctid) + // 2 4, 5, 6, 7, 8 + 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) + \\ # 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 + \\ syscall + \\ beq $7, $0, 1f + \\ nop + \\ jr $ra + \\ dsubu $2, $0, $2 + \\1: + \\ beq $2, $0, 1f + \\ nop + \\ jr $ra + \\ nop + \\1: + ); + if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( + \\ .cfi_undefined $ra + ); + asm volatile ( + \\ 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 + \\ syscall + ); +} + +pub const VDSO = struct { + pub const CGT_SYM = "__vdso_clock_gettime"; + pub const CGT_VER = "LINUX_2.6"; +}; + +pub const blksize_t = u32; +pub const nlink_t = u32; +pub const time_t = i32; +pub const mode_t = u32; +pub const off_t = i64; +pub const ino_t = u64; +pub const dev_t = u64; +pub const blkcnt_t = i64; + +// The `stat` definition used by the Linux kernel. +pub const Stat = extern struct { + dev: dev_t, + __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: std.os.linux.uid_t, + gid: std.os.linux.gid_t, + rdev: dev_t, + __pad1: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). + size: off_t, + atim: u32, + atim_nsec: u32, + mtim: u32, + mtim_nsec: u32, + ctim: u32, + ctim_nsec: u32, + blksize: blksize_t, + __pad3: u32, + blocks: blkcnt_t, + + pub fn atime(self: @This()) std.os.linux.timespec { + return .{ + .sec = self.atim, + .nsec = self.atim_nsec, + }; + } + + pub fn mtime(self: @This()) std.os.linux.timespec { + return .{ + .sec = self.mtim, + .nsec = self.mtim_nsec, + }; + } + + pub fn ctime(self: @This()) std.os.linux.timespec { + return .{ + .sec = self.ctim, + .nsec = self.ctim_nsec, + }; + } +};