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 \\ callsys
8 \\ beq $19, 1f
9 \\ negq $0, $0
10 \\1:
11 : [ret] "={$0}" (-> u64),
12 : [number] "{$0}" (number),
13 : .{
14 .r1 = true,
15 .r2 = true,
16 .r3 = true,
17 .r4 = true,
18 .r5 = true,
19 .r6 = true,
20 .r7 = true,
21 .r8 = true,
22 .r22 = true,
23 .r23 = true,
24 .r24 = true,
25 .r25 = true,
26 .r27 = true,
27 .r28 = true,
28 .memory = true,
29 .r16 = true,
30 .r17 = true,
31 .r18 = true,
32 .r20 = true,
33 .r21 = true,
34 });
35}
36
37pub fn syscall1(number: SYS, arg1: u64) u64 {
38 // These registers are both inputs and clobbers.
39 var r16_out: u64 = undefined;
40 return asm volatile (
41 \\ callsys
42 \\ beq $19, 1f
43 \\ negq $0, $0
44 \\1:
45 : [ret] "={$0}" (-> u64),
46 [r16_out] "={$16}" (r16_out),
47 : [number] "{$0}" (number),
48 [arg1] "{$16}" (arg1),
49 : .{
50 .r1 = true,
51 .r2 = true,
52 .r3 = true,
53 .r4 = true,
54 .r5 = true,
55 .r6 = true,
56 .r7 = true,
57 .r8 = true,
58 .r22 = true,
59 .r23 = true,
60 .r24 = true,
61 .r25 = true,
62 .r27 = true,
63 .r28 = true,
64 .memory = true,
65 .r17 = true,
66 .r18 = true,
67 .r20 = true,
68 .r21 = true,
69 });
70}
71
72pub fn syscall2(number: SYS, arg1: u64, arg2: u64) u64 {
73 // These registers are both inputs and clobbers.
74 var r16_out: u64 = undefined;
75 var r17_out: u64 = undefined;
76 return asm volatile (
77 \\ callsys
78 \\ beq $19, 1f
79 \\ negq $0, $0
80 \\1:
81 : [ret] "={$0}" (-> u64),
82 [r16_out] "={$16}" (r16_out),
83 [r17_out] "={$17}" (r17_out),
84 : [number] "{$0}" (number),
85 [arg1] "{$16}" (arg1),
86 [arg2] "{$17}" (arg2),
87 : .{
88 .r1 = true,
89 .r2 = true,
90 .r3 = true,
91 .r4 = true,
92 .r5 = true,
93 .r6 = true,
94 .r7 = true,
95 .r8 = true,
96 .r22 = true,
97 .r23 = true,
98 .r24 = true,
99 .r25 = true,
100 .r27 = true,
101 .r28 = true,
102 .memory = true,
103 .r18 = true,
104 .r20 = true,
105 .r21 = true,
106 });
107}
108
109pub fn syscall3(number: SYS, arg1: u64, arg2: u64, arg3: u64) u64 {
110 // These registers are both inputs and clobbers.
111 var r16_out: u64 = undefined;
112 var r17_out: u64 = undefined;
113 var r18_out: u64 = undefined;
114 return asm volatile (
115 \\ callsys
116 \\ beq $19, 1f
117 \\ negq $0, $0
118 \\1:
119 : [ret] "={$0}" (-> u64),
120 [r16_out] "={$16}" (r16_out),
121 [r17_out] "={$17}" (r17_out),
122 [r18_out] "={$18}" (r18_out),
123 : [number] "{$0}" (number),
124 [arg1] "{$16}" (arg1),
125 [arg2] "{$17}" (arg2),
126 [arg3] "{$18}" (arg3),
127 : .{
128 .r1 = true,
129 .r2 = true,
130 .r3 = true,
131 .r4 = true,
132 .r5 = true,
133 .r6 = true,
134 .r7 = true,
135 .r8 = true,
136 .r22 = true,
137 .r23 = true,
138 .r24 = true,
139 .r25 = true,
140 .r27 = true,
141 .r28 = true,
142 .memory = true,
143 .r20 = true,
144 .r21 = true,
145 });
146}
147
148pub fn syscall4(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64) u64 {
149 // These registers are both inputs and clobbers.
150 var r16_out: u64 = undefined;
151 var r17_out: u64 = undefined;
152 var r18_out: u64 = undefined;
153 var r19_out: u64 = undefined;
154 return asm volatile (
155 \\ callsys
156 \\ beq $19, 1f
157 \\ negq $0, $0
158 \\1:
159 : [ret] "={$0}" (-> u64),
160 [r16_out] "={$16}" (r16_out),
161 [r17_out] "={$17}" (r17_out),
162 [r18_out] "={$18}" (r18_out),
163 [r19_out] "={$19}" (r19_out),
164 : [number] "{$0}" (number),
165 [arg1] "{$16}" (arg1),
166 [arg2] "{$17}" (arg2),
167 [arg3] "{$18}" (arg3),
168 [arg4] "{$19}" (arg4),
169 : .{
170 .r1 = true,
171 .r2 = true,
172 .r3 = true,
173 .r4 = true,
174 .r5 = true,
175 .r6 = true,
176 .r7 = true,
177 .r8 = true,
178 .r22 = true,
179 .r23 = true,
180 .r24 = true,
181 .r25 = true,
182 .r27 = true,
183 .r28 = true,
184 .memory = true,
185 .r20 = true,
186 .r21 = true,
187 });
188}
189
190pub fn syscall5(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) u64 {
191 // These registers are both inputs and clobbers.
192 var r16_out: u64 = undefined;
193 var r17_out: u64 = undefined;
194 var r18_out: u64 = undefined;
195 var r19_out: u64 = undefined;
196 var r20_out: u64 = undefined;
197 return asm volatile (
198 \\ callsys
199 \\ beq $19, 1f
200 \\ negq $0, $0
201 \\1:
202 : [ret] "={$0}" (-> u64),
203 [r16_out] "={$16}" (r16_out),
204 [r17_out] "={$17}" (r17_out),
205 [r18_out] "={$18}" (r18_out),
206 [r19_out] "={$19}" (r19_out),
207 [r20_out] "={$20}" (r20_out),
208 : [number] "{$0}" (number),
209 [arg1] "{$16}" (arg1),
210 [arg2] "{$17}" (arg2),
211 [arg3] "{$18}" (arg3),
212 [arg4] "{$19}" (arg4),
213 [arg5] "{$20}" (arg5),
214 : .{
215 .r1 = true,
216 .r2 = true,
217 .r3 = true,
218 .r4 = true,
219 .r5 = true,
220 .r6 = true,
221 .r7 = true,
222 .r8 = true,
223 .r22 = true,
224 .r23 = true,
225 .r24 = true,
226 .r25 = true,
227 .r27 = true,
228 .r28 = true,
229 .memory = true,
230 .r21 = true,
231 });
232}
233
234pub fn syscall6(
235 number: SYS,
236 arg1: u64,
237 arg2: u64,
238 arg3: u64,
239 arg4: u64,
240 arg5: u64,
241 arg6: u64,
242) u64 {
243 // These registers are both inputs and clobbers.
244 var r16_out: u64 = undefined;
245 var r17_out: u64 = undefined;
246 var r18_out: u64 = undefined;
247 var r19_out: u64 = undefined;
248 var r20_out: u64 = undefined;
249 var r21_out: u64 = undefined;
250 return asm volatile (
251 \\ callsys
252 \\ beq $19, 1f
253 \\ negq $0, $0
254 \\1:
255 : [ret] "={$0}" (-> u64),
256 [r16_out] "={$16}" (r16_out),
257 [r17_out] "={$17}" (r17_out),
258 [r18_out] "={$18}" (r18_out),
259 [r19_out] "={$19}" (r19_out),
260 [r20_out] "={$20}" (r20_out),
261 [r21_out] "={$21}" (r21_out),
262 : [number] "{$0}" (number),
263 [arg1] "{$16}" (arg1),
264 [arg2] "{$17}" (arg2),
265 [arg3] "{$18}" (arg3),
266 [arg4] "{$19}" (arg4),
267 [arg5] "{$20}" (arg5),
268 [arg6] "{$21}" (arg6),
269 : .{
270 .r1 = true,
271 .r2 = true,
272 .r3 = true,
273 .r4 = true,
274 .r5 = true,
275 .r6 = true,
276 .r7 = true,
277 .r8 = true,
278 .r22 = true,
279 .r23 = true,
280 .r24 = true,
281 .r25 = true,
282 .r27 = true,
283 .r28 = true,
284 .memory = true,
285 });
286}
287
288pub fn clone() callconv(.naked) u64 {
289 // __clone(func, stack, flags, arg, ptid, tls, ctid)
290 // a0, a1, a2, a3, a4, a5, +0
291 //
292 // syscall(SYS_clone, flags, stack, ptid, ctid, tls)
293 // v0 a0, a1, a2, a3, a4
294 asm volatile (
295 // a0 = $16, a1 = $17, a2 = $18, a3 = $19,
296 // a4 = $20, a5 = $21, sp = $30, v0 = $0
297 \\ # Save function pointer and argument pointer on new thread stack
298 \\ ldi $1, -16
299 \\ and $17, $1, $17
300 \\ lda $17, -16($17)
301 \\ stq $16, 0($17)
302 \\ stq $19, 8($17)
303 \\
304 \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,ctid,tls)
305 \\ mov $18, $16
306 \\ mov $20, $18
307 \\ ldq $19, 0($30)
308 \\ mov $21, $20
309 \\
310 \\ # Actual syscall
311 \\ ldi $0, 312 # SYS_clone
312 \\ callsys
313 \\ beq $19, 1f
314 \\ negq $0, $0
315 \\ ret
316 \\1:
317 \\ beq $0, 2f
318 \\ ret
319 \\2:
320 );
321 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
322 // ra = $26
323 \\ .cfi_undefined $26
324 );
325 asm volatile (
326 // v0 = $0, a0 = $16, ra = $26, sp = $30, fp = $15, pv = $27
327 \\ mov 0, $15
328 \\
329 \\ ldq $27, 0($30)
330 \\ ldq $16, 8($30)
331 \\ lda $30, 16($30)
332 \\ jsr $26, ($27)
333 \\
334 \\ mov $0, $16
335 \\ ldi $0, 1 # SYS_exit
336 \\ callsys
337 );
338}
339
340pub fn restore() noreturn {
341 asm volatile (
342 // v0 = $0, a0 = $16, sp = $30
343 \\ mov $30, $16
344 \\ ldi $0, 103 # SYS_sigreturn
345 \\ callsys
346 );
347}
348
349pub fn restore_rt() noreturn {
350 asm volatile (
351 // v0 = $0, a0 = $16, sp = $30
352 \\ mov $30, $16
353 \\ ldi $0, 351 # SYS_rt_sigreturn
354 \\ callsys
355 );
356}
357
358pub const VDSO = void;