master
  1const builtin = @import("builtin");
  2const std = @import("../../std.zig");
  3const SYS = std.os.linux.SYS;
  4
  5pub fn syscall0(number: SYS) u32 {
  6    return asm volatile ("trap #0"
  7        : [ret] "={d0}" (-> u32),
  8        : [number] "{d0}" (@intFromEnum(number)),
  9        : .{ .memory = true });
 10}
 11
 12pub fn syscall1(number: SYS, arg1: u32) u32 {
 13    return asm volatile ("trap #0"
 14        : [ret] "={d0}" (-> u32),
 15        : [number] "{d0}" (@intFromEnum(number)),
 16          [arg1] "{d1}" (arg1),
 17        : .{ .memory = true });
 18}
 19
 20pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 {
 21    return asm volatile ("trap #0"
 22        : [ret] "={d0}" (-> u32),
 23        : [number] "{d0}" (@intFromEnum(number)),
 24          [arg1] "{d1}" (arg1),
 25          [arg2] "{d2}" (arg2),
 26        : .{ .memory = true });
 27}
 28
 29pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 {
 30    return asm volatile ("trap #0"
 31        : [ret] "={d0}" (-> u32),
 32        : [number] "{d0}" (@intFromEnum(number)),
 33          [arg1] "{d1}" (arg1),
 34          [arg2] "{d2}" (arg2),
 35          [arg3] "{d3}" (arg3),
 36        : .{ .memory = true });
 37}
 38
 39pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
 40    return asm volatile ("trap #0"
 41        : [ret] "={d0}" (-> u32),
 42        : [number] "{d0}" (@intFromEnum(number)),
 43          [arg1] "{d1}" (arg1),
 44          [arg2] "{d2}" (arg2),
 45          [arg3] "{d3}" (arg3),
 46          [arg4] "{d4}" (arg4),
 47        : .{ .memory = true });
 48}
 49
 50pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 {
 51    return asm volatile ("trap #0"
 52        : [ret] "={d0}" (-> u32),
 53        : [number] "{d0}" (@intFromEnum(number)),
 54          [arg1] "{d1}" (arg1),
 55          [arg2] "{d2}" (arg2),
 56          [arg3] "{d3}" (arg3),
 57          [arg4] "{d4}" (arg4),
 58          [arg5] "{d5}" (arg5),
 59        : .{ .memory = true });
 60}
 61
 62pub fn syscall6(
 63    number: SYS,
 64    arg1: u32,
 65    arg2: u32,
 66    arg3: u32,
 67    arg4: u32,
 68    arg5: u32,
 69    arg6: u32,
 70) u32 {
 71    return asm volatile ("trap #0"
 72        : [ret] "={d0}" (-> u32),
 73        : [number] "{d0}" (@intFromEnum(number)),
 74          [arg1] "{d1}" (arg1),
 75          [arg2] "{d2}" (arg2),
 76          [arg3] "{d3}" (arg3),
 77          [arg4] "{d4}" (arg4),
 78          [arg5] "{d5}" (arg5),
 79          [arg6] "{a0}" (arg6),
 80        : .{ .memory = true });
 81}
 82
 83pub fn clone() callconv(.naked) u32 {
 84    // __clone(func, stack, flags, arg, ptid, tls, ctid)
 85    //         +4,   +8,    +12,   +16, +20,  +24, +28
 86    //
 87    // syscall(SYS_clone, flags, stack, ptid, ctid, tls)
 88    //         d0,        d1,    d2,    d3,   d4,   d5
 89    asm volatile (
 90        \\ // Save callee-saved registers.
 91        \\ movem.l %%d2-%%d5, -(%%sp) // sp -= 16
 92        \\
 93        \\ // Save func and arg.
 94        \\ move.l 16+4(%%sp), %%a0
 95        \\ move.l 16+16(%%sp), %%a1
 96        \\
 97        \\ // d0 = syscall(d0, d1, d2, d3, d4, d5)
 98        \\ move.l #120, %%d0 // SYS_clone
 99        \\ move.l 16+12(%%sp), %%d1
100        \\ move.l 16+8(%%sp), %%d2
101        \\ move.l 16+20(%%sp), %%d3
102        \\ move.l 16+28(%%sp), %%d4
103        \\ move.l 16+24(%%sp), %%d5
104        \\ and.l #-4, %%d2 // Align the child stack pointer.
105        \\ trap #0
106        \\
107        \\ // Are we in the parent or child?
108        \\ tst.l %%d0
109        \\ beq 1f
110        \\ // Parent:
111        \\
112        \\ // Restore callee-saved registers and return.
113        \\ movem.l (%%sp)+, %%d2-%%d5 // sp += 16
114        \\ rts
115        \\
116        \\ // Child:
117        \\1:
118    );
119    if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
120        \\ .cfi_undefined %%pc
121    );
122    asm volatile (
123        \\ suba.l %%fp, %%fp
124        \\
125        \\ // d0 = func(a1)
126        \\ move.l %%a1, -(%%sp)
127        \\ jsr (%%a0)
128        \\
129        \\ // syscall(d0, d1)
130        \\ move.l %%d0, %%d1
131        \\ move.l #1, %%d0 // SYS_exit
132        \\ trap #0
133    );
134}
135
136pub const restore = restore_rt;
137
138pub fn restore_rt() callconv(.naked) noreturn {
139    asm volatile ("trap #0"
140        :
141        : [number] "{d0}" (@intFromEnum(SYS.rt_sigreturn)),
142    );
143}
144
145pub const blksize_t = i32;
146pub const nlink_t = u32;
147pub const time_t = i32;
148pub const mode_t = u32;
149pub const off_t = i64;
150pub const ino_t = u64;
151pub const dev_t = u64;
152pub const blkcnt_t = i64;
153
154pub const Stat = extern struct {
155    dev: dev_t,
156    __pad: i16,
157    __ino_truncated: i32,
158    mode: mode_t,
159    nlink: nlink_t,
160    uid: std.os.linux.uid_t,
161    gid: std.os.linux.gid_t,
162    rdev: dev_t,
163    __pad2: i16,
164    size: off_t,
165    blksize: blksize_t,
166    blocks: blkcnt_t,
167    atim: std.os.linux.timespec,
168    mtim: std.os.linux.timespec,
169    ctim: std.os.linux.timespec,
170    ino: ino_t,
171
172    pub fn atime(self: @This()) std.os.linux.timespec {
173        return self.atim;
174    }
175
176    pub fn mtime(self: @This()) std.os.linux.timespec {
177        return self.mtim;
178    }
179
180    pub fn ctime(self: @This()) std.os.linux.timespec {
181        return self.ctim;
182    }
183};
184
185// No VDSO used as of glibc 112a0ae18b831bf31f44d81b82666980312511d6.
186pub const VDSO = void;