1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const SYS = std.os.linux.SYS;
4
5pub const syscall_arg_t = u32;
6
7pub fn syscall0(
8 number: SYS,
9) u32 {
10 return asm volatile (
11 \\ syscall
12 \\ beq $a3, $zero, 1f
13 \\ subu $v0, $zero, $v0
14 \\1:
15 : [ret] "={$2}" (-> u32),
16 : [number] "{$2}" (@backingInt(number)),
17 : .{ .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 });
18}
19
20pub fn syscall1(
21 number: SYS,
22 arg1: syscall_arg_t,
23) u32 {
24 return asm volatile (
25 \\ syscall
26 \\ beq $a3, $zero, 1f
27 \\ subu $v0, $zero, $v0
28 \\1:
29 : [ret] "={$2}" (-> u32),
30 : [number] "{$2}" (@backingInt(number)),
31 [arg1] "{$4}" (arg1),
32 : .{ .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 });
33}
34
35pub fn syscall2(
36 number: SYS,
37 arg1: syscall_arg_t,
38 arg2: syscall_arg_t,
39) u32 {
40 return asm volatile (
41 \\ syscall
42 \\ beq $a3, $zero, 1f
43 \\ subu $v0, $zero, $v0
44 \\1:
45 : [ret] "={$2}" (-> u32),
46 : [number] "{$2}" (@backingInt(number)),
47 [arg1] "{$4}" (arg1),
48 [arg2] "{$5}" (arg2),
49 : .{ .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 });
50}
51
52pub fn syscall3(
53 number: SYS,
54 arg1: syscall_arg_t,
55 arg2: syscall_arg_t,
56 arg3: syscall_arg_t,
57) u32 {
58 return asm volatile (
59 \\ syscall
60 \\ beq $a3, $zero, 1f
61 \\ subu $v0, $zero, $v0
62 \\1:
63 : [ret] "={$2}" (-> u32),
64 : [number] "{$2}" (@backingInt(number)),
65 [arg1] "{$4}" (arg1),
66 [arg2] "{$5}" (arg2),
67 [arg3] "{$6}" (arg3),
68 : .{ .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 });
69}
70
71pub fn syscall4(
72 number: SYS,
73 arg1: syscall_arg_t,
74 arg2: syscall_arg_t,
75 arg3: syscall_arg_t,
76 arg4: syscall_arg_t,
77) u32 {
78 return asm volatile (
79 \\ syscall
80 \\ beq $a3, $zero, 1f
81 \\ subu $v0, $zero, $v0
82 \\1:
83 : [ret] "={$2}" (-> u32),
84 : [number] "{$2}" (@backingInt(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(
96 number: SYS,
97 arg1: syscall_arg_t,
98 arg2: syscall_arg_t,
99 arg3: syscall_arg_t,
100 arg4: syscall_arg_t,
101 arg5: syscall_arg_t,
102) u32 {
103 return asm volatile (
104 \\ subu $sp, $sp, 24
105 \\ sw %[arg5], 16($sp)
106 \\ syscall
107 \\ addu $sp, $sp, 24
108 \\ beq $a3, $zero, 1f
109 \\ subu $v0, $zero, $v0
110 \\1:
111 : [ret] "={$2}" (-> u32),
112 : [number] "{$2}" (@backingInt(number)),
113 [arg1] "{$4}" (arg1),
114 [arg2] "{$5}" (arg2),
115 [arg3] "{$6}" (arg3),
116 [arg4] "{$7}" (arg4),
117 [arg5] "r" (arg5),
118 : .{ .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 });
119}
120
121pub fn syscall6(
122 number: SYS,
123 arg1: syscall_arg_t,
124 arg2: syscall_arg_t,
125 arg3: syscall_arg_t,
126 arg4: syscall_arg_t,
127 arg5: syscall_arg_t,
128 arg6: syscall_arg_t,
129) u32 {
130 return asm volatile (
131 \\ subu $sp, $sp, 24
132 \\ sw %[arg5], 16($sp)
133 \\ sw %[arg6], 20($sp)
134 \\ syscall
135 \\ addu $sp, $sp, 24
136 \\ beq $a3, $zero, 1f
137 \\ subu $v0, $zero, $v0
138 \\1:
139 : [ret] "={$2}" (-> u32),
140 : [number] "{$2}" (@backingInt(number)),
141 [arg1] "{$4}" (arg1),
142 [arg2] "{$5}" (arg2),
143 [arg3] "{$6}" (arg3),
144 [arg4] "{$7}" (arg4),
145 [arg5] "r" (arg5),
146 [arg6] "r" (arg6),
147 : .{ .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 });
148}
149
150pub fn syscall7(
151 number: SYS,
152 arg1: syscall_arg_t,
153 arg2: syscall_arg_t,
154 arg3: syscall_arg_t,
155 arg4: syscall_arg_t,
156 arg5: syscall_arg_t,
157 arg6: syscall_arg_t,
158 arg7: syscall_arg_t,
159) u32 {
160 return asm volatile (
161 \\ subu $sp, $sp, 32
162 \\ sw %[arg5], 16($sp)
163 \\ sw %[arg6], 20($sp)
164 \\ sw %[arg7], 24($sp)
165 \\ syscall
166 \\ addu $sp, $sp, 32
167 \\ beq $a3, $zero, 1f
168 \\ subu $v0, $zero, $v0
169 \\1:
170 : [ret] "={$2}" (-> u32),
171 : [number] "{$2}" (@backingInt(number)),
172 [arg1] "{$4}" (arg1),
173 [arg2] "{$5}" (arg2),
174 [arg3] "{$6}" (arg3),
175 [arg4] "{$7}" (arg4),
176 [arg5] "r" (arg5),
177 [arg6] "r" (arg6),
178 [arg7] "r" (arg7),
179 : .{ .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 });
180}
181
182pub fn syscall_pipe(
183 fd: *[2]std.os.linux.fd_t,
184) u32 {
185 return asm volatile (
186 \\ syscall
187 \\ beq $a3, $zero, 1f
188 \\ subu $v0, $zero, $v0
189 \\ b 2f
190 \\1:
191 \\ sw $v0, 0($a0)
192 \\ sw $v1, 4($a0)
193 \\2:
194 : [ret] "={$2}" (-> u32),
195 : [number] "{$2}" (@backingInt(SYS.pipe)),
196 [fd] "{$4}" (fd),
197 : .{ .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 });
198}
199
200pub fn clone() callconv(.naked) u32 {
201 // __clone(func, stack, flags, arg, ptid, tls, ctid)
202 // a0, a1, a2, a3, +0, +4, +8
203 //
204 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
205 // v0 a0, a1, a2, a3, +0
206 asm volatile (
207 \\ # Save function pointer and argument pointer on new thread stack
208 \\ and $a1, $a1, -8
209 \\ subu $a1, $a1, 16
210 \\ sw $a0, 0($a1)
211 \\ sw $a3, 4($a1)
212 \\
213 \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid)
214 \\ move $a0, $a2
215 \\ lw $a2, 16($sp)
216 \\ lw $a3, 20($sp)
217 \\ lw $t1, 24($sp)
218 \\ subu $sp, $sp, 16
219 \\ sw $t1, 16($sp)
220 \\ li $v0, 4120 # SYS_clone
221 \\ syscall
222 \\ beq $a3, $zero, 1f
223 \\ subu $v0, $zero, $v0
224 \\ b 2f
225 \\1:
226 \\ beq $v0, $zero, 3f
227 \\2:
228 \\ addu $sp, $sp, 16
229 \\ jr $ra
230 \\3:
231 );
232 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
233 \\ .cfi_undefined $ra
234 );
235 asm volatile (
236 \\ move $fp, $zero
237 \\ move $ra, $zero
238 \\
239 \\ lw $t9, 0($sp)
240 \\ lw $a0, 4($sp)
241 \\ jalr $t9
242 \\
243 \\ move $a0, $v0
244 \\ li $v0, 4001 # SYS_exit
245 \\ syscall
246 );
247}
248
249pub const VDSO = struct {
250 pub const CGT_SYM = "__vdso_clock_gettime";
251 pub const CGT_VER = "LINUX_2.6";
252};
253
254pub const time_t = i32;