master
  1const builtin = @import("builtin");
  2const std = @import("../../std.zig");
  3const SYS = std.os.linux.SYS;
  4
  5pub fn syscall0(number: SYS) u64 {
  6    return asm volatile (
  7        \\ syscall
  8        \\ beq $a3, $zero, 1f
  9        \\ blez $v0, 1f
 10        \\ dsubu $v0, $zero, $v0
 11        \\1:
 12        : [ret] "={$2}" (-> u64),
 13        : [number] "{$2}" (@intFromEnum(number)),
 14        : .{ .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 });
 15}
 16
 17pub fn syscall_pipe(fd: *[2]i32) u64 {
 18    return asm volatile (
 19        \\ syscall
 20        \\ beq $a3, $zero, 1f
 21        \\ blez $v0, 2f
 22        \\ dsubu $v0, $zero, $v0
 23        \\ b 2f
 24        \\1:
 25        \\ sw $v0, 0($a0)
 26        \\ sw $v1, 4($a0)
 27        \\2:
 28        : [ret] "={$2}" (-> u64),
 29        : [number] "{$2}" (@intFromEnum(SYS.pipe)),
 30          [fd] "{$4}" (fd),
 31        : .{ .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 });
 32}
 33
 34pub fn syscall1(number: SYS, arg1: u64) u64 {
 35    return asm volatile (
 36        \\ syscall
 37        \\ beq $a3, $zero, 1f
 38        \\ blez $v0, 1f
 39        \\ dsubu $v0, $zero, $v0
 40        \\1:
 41        : [ret] "={$2}" (-> u64),
 42        : [number] "{$2}" (@intFromEnum(number)),
 43          [arg1] "{$4}" (arg1),
 44        : .{ .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 });
 45}
 46
 47pub fn syscall2(number: SYS, arg1: u64, arg2: u64) u64 {
 48    return asm volatile (
 49        \\ syscall
 50        \\ beq $a3, $zero, 1f
 51        \\ blez $v0, 1f
 52        \\ dsubu $v0, $zero, $v0
 53        \\1:
 54        : [ret] "={$2}" (-> u64),
 55        : [number] "{$2}" (@intFromEnum(number)),
 56          [arg1] "{$4}" (arg1),
 57          [arg2] "{$5}" (arg2),
 58        : .{ .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 });
 59}
 60
 61pub fn syscall3(number: SYS, arg1: u64, arg2: u64, arg3: u64) u64 {
 62    return asm volatile (
 63        \\ syscall
 64        \\ beq $a3, $zero, 1f
 65        \\ blez $v0, 1f
 66        \\ dsubu $v0, $zero, $v0
 67        \\1:
 68        : [ret] "={$2}" (-> u64),
 69        : [number] "{$2}" (@intFromEnum(number)),
 70          [arg1] "{$4}" (arg1),
 71          [arg2] "{$5}" (arg2),
 72          [arg3] "{$6}" (arg3),
 73        : .{ .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 });
 74}
 75
 76pub fn syscall4(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64) u64 {
 77    return asm volatile (
 78        \\ syscall
 79        \\ beq $a3, $zero, 1f
 80        \\ blez $v0, 1f
 81        \\ dsubu $v0, $zero, $v0
 82        \\1:
 83        : [ret] "={$2}" (-> u64),
 84        : [number] "{$2}" (@intFromEnum(number)),
 85          [arg1] "{$4}" (arg1),
 86          [arg2] "{$5}" (arg2),
 87          [arg3] "{$6}" (arg3),
 88          [arg4] "{$7}" (arg4),
 89        : .{ .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 });
 90}
 91
 92pub fn syscall5(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) u64 {
 93    return asm volatile (
 94        \\ syscall
 95        \\ beq $a3, $zero, 1f
 96        \\ blez $v0, 1f
 97        \\ dsubu $v0, $zero, $v0
 98        \\1:
 99        : [ret] "={$2}" (-> u64),
100        : [number] "{$2}" (@intFromEnum(number)),
101          [arg1] "{$4}" (arg1),
102          [arg2] "{$5}" (arg2),
103          [arg3] "{$6}" (arg3),
104          [arg4] "{$7}" (arg4),
105          [arg5] "{$8}" (arg5),
106        : .{ .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 });
107}
108
109pub fn syscall6(
110    number: SYS,
111    arg1: u64,
112    arg2: u64,
113    arg3: u64,
114    arg4: u64,
115    arg5: u64,
116    arg6: u64,
117) u64 {
118    return asm volatile (
119        \\ syscall
120        \\ beq $a3, $zero, 1f
121        \\ blez $v0, 1f
122        \\ dsubu $v0, $zero, $v0
123        \\1:
124        : [ret] "={$2}" (-> u64),
125        : [number] "{$2}" (@intFromEnum(number)),
126          [arg1] "{$4}" (arg1),
127          [arg2] "{$5}" (arg2),
128          [arg3] "{$6}" (arg3),
129          [arg4] "{$7}" (arg4),
130          [arg5] "{$8}" (arg5),
131          [arg6] "{$9}" (arg6),
132        : .{ .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 });
133}
134
135pub fn clone() callconv(.naked) u64 {
136    // __clone(func, stack, flags, arg, ptid, tls, ctid)
137    //         a0,   a1,    a2,    a3,  a4,   a5,  a6
138    //
139    // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
140    //         v0         a0,    a1,    a2,   a3,  a4
141    asm volatile (
142        \\ # Save function pointer and argument pointer on new thread stack
143        \\ and $a1, $a1, -16
144        \\ dsubu $a1, $a1, 16
145        \\ sd $a0, 0($a1)
146        \\ sd $a3, 8($a1)
147        \\
148        \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid)
149        \\ move $a0, $a2
150        \\ move $a2, $a4
151        \\ move $a3, $a5
152        \\ move $a4, $a6
153        \\ li $v0, 5055 # SYS_clone
154        \\ syscall
155        \\ beq $a3, $zero, 1f
156        \\ blez $v0, 2f
157        \\ dsubu $v0, $zero, $v0
158        \\ b 2f
159        \\1:
160        \\ beq $v0, $zero, 3f
161        \\2:
162        \\ jr $ra
163        \\3:
164    );
165    if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
166        \\ .cfi_undefined $ra
167    );
168    asm volatile (
169        \\ move $fp, $zero
170        \\ move $ra, $zero
171        \\
172        \\ ld $t9, 0($sp)
173        \\ ld $a0, 8($sp)
174        \\ jalr $t9
175        \\
176        \\ move $a0, $v0
177        \\ li $v0, 5058 # SYS_exit
178        \\ syscall
179    );
180}
181
182pub const VDSO = struct {
183    pub const CGT_SYM = "__vdso_clock_gettime";
184    pub const CGT_VER = "LINUX_2.6";
185};
186
187pub const blksize_t = u32;
188pub const nlink_t = u32;
189pub const time_t = i32;
190pub const mode_t = u32;
191pub const off_t = i64;
192pub const ino_t = u64;
193pub const dev_t = u64;
194pub const blkcnt_t = i64;
195
196// The `stat` definition used by the Linux kernel.
197pub const Stat = extern struct {
198    dev: dev_t,
199    __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32).
200    ino: ino_t,
201    mode: mode_t,
202    nlink: nlink_t,
203    uid: std.os.linux.uid_t,
204    gid: std.os.linux.gid_t,
205    rdev: dev_t,
206    __pad1: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32).
207    size: off_t,
208    atim: u32,
209    atim_nsec: u32,
210    mtim: u32,
211    mtim_nsec: u32,
212    ctim: u32,
213    ctim_nsec: u32,
214    blksize: blksize_t,
215    __pad3: u32,
216    blocks: blkcnt_t,
217
218    pub fn atime(self: @This()) std.os.linux.timespec {
219        return .{
220            .sec = self.atim,
221            .nsec = self.atim_nsec,
222        };
223    }
224
225    pub fn mtime(self: @This()) std.os.linux.timespec {
226        return .{
227            .sec = self.mtim,
228            .nsec = self.mtim_nsec,
229        };
230    }
231
232    pub fn ctime(self: @This()) std.os.linux.timespec {
233        return .{
234            .sec = self.ctim,
235            .nsec = self.ctim_nsec,
236        };
237    }
238};