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 (
7 \\ syscall
8 \\ beq $a3, $zero, 1f
9 \\ blez $v0, 1f
10 \\ subu $v0, $zero, $v0
11 \\1:
12 : [ret] "={$2}" (-> u32),
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) u32 {
18 return asm volatile (
19 \\ syscall
20 \\ beq $a3, $zero, 1f
21 \\ blez $v0, 2f
22 \\ subu $v0, $zero, $v0
23 \\ b 2f
24 \\1:
25 \\ sw $v0, 0($a0)
26 \\ sw $v1, 4($a0)
27 \\2:
28 : [ret] "={$2}" (-> u32),
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: u32) u32 {
35 return asm volatile (
36 \\ syscall
37 \\ beq $a3, $zero, 1f
38 \\ blez $v0, 1f
39 \\ subu $v0, $zero, $v0
40 \\1:
41 : [ret] "={$2}" (-> u32),
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: u32, arg2: u32) u32 {
48 return asm volatile (
49 \\ syscall
50 \\ beq $a3, $zero, 1f
51 \\ blez $v0, 1f
52 \\ subu $v0, $zero, $v0
53 \\1:
54 : [ret] "={$2}" (-> u32),
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: u32, arg2: u32, arg3: u32) u32 {
62 return asm volatile (
63 \\ syscall
64 \\ beq $a3, $zero, 1f
65 \\ blez $v0, 1f
66 \\ subu $v0, $zero, $v0
67 \\1:
68 : [ret] "={$2}" (-> u32),
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: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
77 return asm volatile (
78 \\ syscall
79 \\ beq $a3, $zero, 1f
80 \\ blez $v0, 1f
81 \\ subu $v0, $zero, $v0
82 \\1:
83 : [ret] "={$2}" (-> u32),
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
92// NOTE: The o32 calling convention requires the callee to reserve 16 bytes for
93// the first four arguments even though they're passed in $a0-$a3.
94
95pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 {
96 return asm volatile (
97 \\ subu $sp, $sp, 24
98 \\ sw %[arg5], 16($sp)
99 \\ syscall
100 \\ addu $sp, $sp, 24
101 \\ beq $a3, $zero, 1f
102 \\ blez $v0, 1f
103 \\ subu $v0, $zero, $v0
104 \\1:
105 : [ret] "={$2}" (-> u32),
106 : [number] "{$2}" (@intFromEnum(number)),
107 [arg1] "{$4}" (arg1),
108 [arg2] "{$5}" (arg2),
109 [arg3] "{$6}" (arg3),
110 [arg4] "{$7}" (arg4),
111 [arg5] "r" (arg5),
112 : .{ .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 });
113}
114
115pub fn syscall6(
116 number: SYS,
117 arg1: u32,
118 arg2: u32,
119 arg3: u32,
120 arg4: u32,
121 arg5: u32,
122 arg6: u32,
123) u32 {
124 return asm volatile (
125 \\ subu $sp, $sp, 24
126 \\ sw %[arg5], 16($sp)
127 \\ sw %[arg6], 20($sp)
128 \\ syscall
129 \\ addu $sp, $sp, 24
130 \\ beq $a3, $zero, 1f
131 \\ blez $v0, 1f
132 \\ subu $v0, $zero, $v0
133 \\1:
134 : [ret] "={$2}" (-> u32),
135 : [number] "{$2}" (@intFromEnum(number)),
136 [arg1] "{$4}" (arg1),
137 [arg2] "{$5}" (arg2),
138 [arg3] "{$6}" (arg3),
139 [arg4] "{$7}" (arg4),
140 [arg5] "r" (arg5),
141 [arg6] "r" (arg6),
142 : .{ .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 });
143}
144
145pub fn syscall7(
146 number: SYS,
147 arg1: u32,
148 arg2: u32,
149 arg3: u32,
150 arg4: u32,
151 arg5: u32,
152 arg6: u32,
153 arg7: u32,
154) u32 {
155 return asm volatile (
156 \\ subu $sp, $sp, 32
157 \\ sw %[arg5], 16($sp)
158 \\ sw %[arg6], 20($sp)
159 \\ sw %[arg7], 24($sp)
160 \\ syscall
161 \\ addu $sp, $sp, 32
162 \\ beq $a3, $zero, 1f
163 \\ blez $v0, 1f
164 \\ subu $v0, $zero, $v0
165 \\1:
166 : [ret] "={$2}" (-> u32),
167 : [number] "{$2}" (@intFromEnum(number)),
168 [arg1] "{$4}" (arg1),
169 [arg2] "{$5}" (arg2),
170 [arg3] "{$6}" (arg3),
171 [arg4] "{$7}" (arg4),
172 [arg5] "r" (arg5),
173 [arg6] "r" (arg6),
174 [arg7] "r" (arg7),
175 : .{ .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 });
176}
177
178pub fn clone() callconv(.naked) u32 {
179 // __clone(func, stack, flags, arg, ptid, tls, ctid)
180 // a0, a1, a2, a3, +0, +4, +8
181 //
182 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
183 // v0 a0, a1, a2, a3, +0
184 asm volatile (
185 \\ # Save function pointer and argument pointer on new thread stack
186 \\ and $a1, $a1, -8
187 \\ subu $a1, $a1, 16
188 \\ sw $a0, 0($a1)
189 \\ sw $a3, 4($a1)
190 \\
191 \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid)
192 \\ move $a0, $a2
193 \\ lw $a2, 16($sp)
194 \\ lw $a3, 20($sp)
195 \\ lw $t1, 24($sp)
196 \\ subu $sp, $sp, 16
197 \\ sw $t1, 16($sp)
198 \\ li $v0, 4120 # SYS_clone
199 \\ syscall
200 \\ beq $a3, $zero, 1f
201 \\ blez $v0, 2f
202 \\ subu $v0, $zero, $v0
203 \\ b 2f
204 \\1:
205 \\ beq $v0, $zero, 3f
206 \\2:
207 \\ addu $sp, $sp, 16
208 \\ jr $ra
209 \\3:
210 );
211 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
212 \\ .cfi_undefined $ra
213 );
214 asm volatile (
215 \\ move $fp, $zero
216 \\ move $ra, $zero
217 \\
218 \\ lw $t9, 0($sp)
219 \\ lw $a0, 4($sp)
220 \\ jalr $t9
221 \\
222 \\ move $a0, $v0
223 \\ li $v0, 4001 # SYS_exit
224 \\ syscall
225 );
226}
227
228pub const VDSO = struct {
229 pub const CGT_SYM = "__vdso_clock_gettime";
230 pub const CGT_VER = "LINUX_2.6";
231};
232
233pub const blksize_t = u32;
234pub const nlink_t = u32;
235pub const time_t = i32;
236pub const mode_t = u32;
237pub const off_t = i64;
238pub const ino_t = u64;
239pub const dev_t = u64;
240pub const blkcnt_t = i64;
241
242// The `stat64` definition used by the Linux kernel.
243pub const Stat = extern struct {
244 dev: dev_t,
245 __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32).
246 ino: ino_t,
247 mode: mode_t,
248 nlink: nlink_t,
249 uid: std.os.linux.uid_t,
250 gid: std.os.linux.gid_t,
251 rdev: dev_t,
252 __pad1: [2]u32,
253 size: off_t,
254 atim: std.os.linux.timespec,
255 mtim: std.os.linux.timespec,
256 ctim: std.os.linux.timespec,
257 blksize: blksize_t,
258 __pad3: u32,
259 blocks: blkcnt_t,
260
261 pub fn atime(self: @This()) std.os.linux.timespec {
262 return self.atim;
263 }
264
265 pub fn mtime(self: @This()) std.os.linux.timespec {
266 return self.mtim;
267 }
268
269 pub fn ctime(self: @This()) std.os.linux.timespec {
270 return self.ctim;
271 }
272};