diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 707a1b840a..be8237107c 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -42,6 +42,7 @@ const arch_bits = switch (native_arch) { .gnuabin32, .muslabin32 => @import("linux/mipsn32.zig"), else => @import("linux/mips64.zig"), }, + .or1k => @import("linux/or1k.zig"), .powerpc, .powerpcle => @import("linux/powerpc.zig"), .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), .riscv32 => @import("linux/riscv32.zig"), @@ -273,7 +274,7 @@ pub const MAP = switch (native_arch) { UNINITIALIZED: bool = false, _: u5 = 0, }, - .hexagon, .m68k, .s390x => packed struct(u32) { + .hexagon, .m68k, .or1k, .s390x => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, @@ -444,7 +445,7 @@ pub const O = switch (native_arch) { TMPFILE: bool = false, _23: u9 = 0, }, - .hexagon, .s390x => packed struct(u32) { + .hexagon, .or1k, .s390x => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, @@ -1931,7 +1932,7 @@ pub fn sigaction(sig: u8, noalias act: ?*const Sigaction, noalias oact: ?*Sigact const mask_size = @sizeOf(@TypeOf(ksa.mask)); if (act) |new| { - if (native_arch == .hexagon or is_loongarch or is_mips or is_riscv) { + if (native_arch == .hexagon or is_loongarch or is_mips or native_arch == .or1k or is_riscv) { ksa = .{ .handler = new.handler.handler, .flags = new.flags, @@ -3747,7 +3748,7 @@ pub const SA = if (is_mips) struct { pub const ONSTACK = 0x1; pub const NODEFER = 0x20; pub const RESTORER = 0x04000000; -} else if (native_arch == .hexagon or is_loongarch or is_riscv) struct { +} else if (native_arch == .hexagon or is_loongarch or native_arch == .or1k or is_riscv) struct { pub const NOCLDSTOP = 1; pub const NOCLDWAIT = 2; pub const SIGINFO = 4; @@ -5828,7 +5829,7 @@ pub const k_sigaction = switch (native_arch) { handler: k_sigaction_funcs.handler, mask: sigset_t, }, - .hexagon, .loongarch32, .loongarch64, .riscv32, .riscv64 => extern struct { + .hexagon, .loongarch32, .loongarch64, .or1k, .riscv32, .riscv64 => extern struct { handler: k_sigaction_funcs.handler, flags: c_ulong, mask: sigset_t, @@ -6161,6 +6162,7 @@ pub const MINSIGSTKSZ = switch (native_arch) { .mipsel, .mips64, .mips64el, + .or1k, .powerpc, .powerpcle, .riscv32, @@ -6195,6 +6197,7 @@ pub const SIGSTKSZ = switch (native_arch) { .mipsel, .mips64, .mips64el, + .or1k, .powerpc, .powerpcle, .riscv32, @@ -9744,6 +9747,7 @@ pub const AUDIT = struct { .gnuabin32, .muslabin32 => .MIPSEL64N32, else => .MIPSEL64, }, + .or1k => .OPENRISC, .powerpc => .PPC, .powerpc64 => .PPC64, .powerpc64le => .PPC64LE, diff --git a/lib/std/os/linux/or1k.zig b/lib/std/os/linux/or1k.zig new file mode 100644 index 0000000000..1054e52d19 --- /dev/null +++ b/lib/std/os/linux/or1k.zig @@ -0,0 +1,173 @@ +const builtin = @import("builtin"); +const std = @import("../../std.zig"); +const SYS = std.os.linux.SYS; + +pub fn syscall0(number: SYS) u32 { + return asm volatile ( + \\ l.sys 1 + : [ret] "={r11}" (-> u32), + : [number] "{r11}" (@intFromEnum(number)), + : .{ .r3 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true }); +} + +pub fn syscall1(number: SYS, arg1: u32) u32 { + return asm volatile ( + \\ l.sys 1 + : [ret] "={r11}" (-> u32), + : [number] "{r11}" (@intFromEnum(number)), + [arg1] "{r3}" (arg1), + : .{ .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true }); +} + +pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 { + return asm volatile ( + \\ l.sys 1 + : [ret] "={r11}" (-> u32), + : [number] "{r11}" (@intFromEnum(number)), + [arg1] "{r3}" (arg1), + [arg2] "{r4}" (arg2), + : .{ .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true }); +} + +pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 { + return asm volatile ( + \\ l.sys 1 + : [ret] "={r11}" (-> u32), + : [number] "{r11}" (@intFromEnum(number)), + [arg1] "{r3}" (arg1), + [arg2] "{r4}" (arg2), + [arg3] "{r5}" (arg3), + : .{ .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true }); +} + +pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 { + return asm volatile ( + \\ l.sys 1 + : [ret] "={r11}" (-> u32), + : [number] "{r11}" (@intFromEnum(number)), + [arg1] "{r3}" (arg1), + [arg2] "{r4}" (arg2), + [arg3] "{r5}" (arg3), + [arg4] "{r6}" (arg4), + : .{ .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true }); +} + +pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 { + return asm volatile ( + \\ l.sys 1 + : [ret] "={r11}" (-> u32), + : [number] "{r11}" (@intFromEnum(number)), + [arg1] "{r3}" (arg1), + [arg2] "{r4}" (arg2), + [arg3] "{r5}" (arg3), + [arg4] "{r6}" (arg4), + [arg5] "{r7}" (arg5), + : .{ .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true }); +} + +pub fn syscall6( + number: SYS, + arg1: u32, + arg2: u32, + arg3: u32, + arg4: u32, + arg5: u32, + arg6: u32, +) u32 { + return asm volatile ( + \\ l.sys 1 + : [ret] "={r11}" (-> u32), + : [number] "{r11}" (@intFromEnum(number)), + [arg1] "{r3}" (arg1), + [arg2] "{r4}" (arg2), + [arg3] "{r5}" (arg3), + [arg4] "{r6}" (arg4), + [arg5] "{r7}" (arg5), + [arg6] "{r8}" (arg6), + : .{ .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true }); +} + +pub fn clone() callconv(.naked) u32 { + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // r3, r4, r5, r6, r7, r8, +0 + // + // syscall(SYS_clone, flags, stack, ptid, tls, ctid) + // 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 r4, r4, -8 + \\ l.sw 0(r4), r3 + \\ l.sw 4(r4), r6 + \\ + \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) + \\ l.ori r11, r0, 220 # SYS_clone + \\ l.ori r3, r5, 0 + \\ l.ori r5, r7, 0 + \\ l.ori r6, r8, 0 + \\ l.lwz r7, 0(r1) + \\ l.sys 1 + \\ l.sfeqi r11, 0 + \\ l.bf 1f + \\ l.jr r9 + \\1: + ); + if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( + \\ .cfi_undefined r9 + ); + asm volatile ( + \\ l.ori r2, r0, 0 + \\ l.ori r9, r0, 0 + \\ + \\ l.lwz r11, 0(r1) + \\ l.lwz r3, 4(r1) + \\ l.jalr r11 + \\ + \\ l.ori r3, r11, 0 + \\ l.ori r11, r0, 93 # SYS_exit + \\ l.sys 1 + ); +} + +pub const VDSO = void; + +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 `stat64` definition used by the Linux kernel. +pub const Stat = extern struct { + dev: dev_t, + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: std.os.linux.uid_t, + gid: std.os.linux.gid_t, + rdev: dev_t, + _pad0: [2]u32, + size: off_t, + blksize: blksize_t, + _pad1: u32, + blocks: blkcnt_t, + atim: std.os.linux.timespec, + mtim: std.os.linux.timespec, + ctim: std.os.linux.timespec, + _pad2: [2]u32, + + pub fn atime(self: @This()) std.os.linux.timespec { + return self.atim; + } + + pub fn mtime(self: @This()) std.os.linux.timespec { + return self.mtim; + } + + pub fn ctime(self: @This()) std.os.linux.timespec { + return self.ctim; + } +};