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 ("syscall"
11 : [ret] "={a2}" (-> u32),
12 : [number] "{a2}" (@backingInt(number)),
13 : .{ .memory = true });
14}
15
16pub fn syscall1(
17 number: SYS,
18 arg1: syscall_arg_t,
19) u32 {
20 return asm volatile ("syscall"
21 : [ret] "={a2}" (-> u32),
22 : [number] "{a2}" (@backingInt(number)),
23 [arg1] "{a6}" (arg1),
24 : .{ .memory = true });
25}
26
27pub fn syscall2(
28 number: SYS,
29 arg1: syscall_arg_t,
30 arg2: syscall_arg_t,
31) u32 {
32 return asm volatile ("syscall"
33 : [ret] "={a2}" (-> u32),
34 : [number] "{a2}" (@backingInt(number)),
35 [arg1] "{a6}" (arg1),
36 [arg2] "{a3}" (arg2),
37 : .{ .memory = true });
38}
39
40pub fn syscall3(
41 number: SYS,
42 arg1: syscall_arg_t,
43 arg2: syscall_arg_t,
44 arg3: syscall_arg_t,
45) u32 {
46 return asm volatile ("syscall"
47 : [ret] "={a2}" (-> u32),
48 : [number] "{a2}" (@backingInt(number)),
49 [arg1] "{a6}" (arg1),
50 [arg2] "{a3}" (arg2),
51 [arg3] "{a4}" (arg3),
52 : .{ .memory = true });
53}
54
55pub fn syscall4(
56 number: SYS,
57 arg1: syscall_arg_t,
58 arg2: syscall_arg_t,
59 arg3: syscall_arg_t,
60 arg4: syscall_arg_t,
61) u32 {
62 return asm volatile ("syscall"
63 : [ret] "={a2}" (-> u32),
64 : [number] "{a2}" (@backingInt(number)),
65 [arg1] "{a6}" (arg1),
66 [arg2] "{a3}" (arg2),
67 [arg3] "{a4}" (arg3),
68 [arg4] "{a5}" (arg4),
69 : .{ .memory = true });
70}
71
72pub fn syscall5(
73 number: SYS,
74 arg1: syscall_arg_t,
75 arg2: syscall_arg_t,
76 arg3: syscall_arg_t,
77 arg4: syscall_arg_t,
78 arg5: syscall_arg_t,
79) u32 {
80 return asm volatile ("syscall"
81 : [ret] "={a2}" (-> u32),
82 : [number] "{a2}" (@backingInt(number)),
83 [arg1] "{a6}" (arg1),
84 [arg2] "{a3}" (arg2),
85 [arg3] "{a4}" (arg3),
86 [arg4] "{a5}" (arg4),
87 [arg5] "{a8}" (arg5),
88 : .{ .memory = true });
89}
90
91pub fn syscall6(
92 number: SYS,
93 arg1: syscall_arg_t,
94 arg2: syscall_arg_t,
95 arg3: syscall_arg_t,
96 arg4: syscall_arg_t,
97 arg5: syscall_arg_t,
98 arg6: syscall_arg_t,
99) u32 {
100 return asm volatile ("syscall"
101 : [ret] "={a2}" (-> u32),
102 : [number] "{a2}" (@backingInt(number)),
103 [arg1] "{a6}" (arg1),
104 [arg2] "{a3}" (arg2),
105 [arg3] "{a4}" (arg3),
106 [arg4] "{a5}" (arg4),
107 [arg5] "{a8}" (arg5),
108 [arg6] "{a9}" (arg6),
109 : .{ .memory = true });
110}
111
112pub fn clone() callconv(.naked) u32 {
113 // __clone(func, stack, flags, arg, ptid, tls, ctid)
114 // a2, a3, a4, a5, a6, a7, +16
115 //
116 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
117 // a2 a6, a3, a4, a5, a8
118 if (builtin.abi != .call0) asm volatile (
119 \\ entry sp, 16
120 );
121 asm volatile (
122 \\ movi a8, -16
123 \\ and a3, a3, a8
124 \\
125 \\ mov a9, a2
126 \\ mov a10, a5
127 \\
128 \\ mov a5, a7
129 \\ mov a8, a6
130 \\ mov a6, a4
131 \\ mov a4, a8
132 );
133 if (builtin.abi == .call0) asm volatile (
134 \\ l32i a8, sp, 0
135 ) else asm volatile (
136 \\ l32i a8, sp, 16
137 );
138 asm volatile (
139 \\ movi a2, 116 // SYS_clone
140 \\ syscall
141 );
142 if (builtin.abi == .call0) asm volatile (
143 \\ beqz a2, 1f
144 \\ // parent
145 \\ ret
146 \\
147 \\ // child
148 \\1:
149 \\ movi a15, 0
150 \\ movi a0, 0
151 \\
152 \\ mov a2, a10
153 \\ callx0 a9
154 ) else asm volatile (
155 \\ beqz a2, 1f
156 \\ // parent
157 \\ retw
158 \\
159 \\ // child
160 \\1:
161 \\ movi a7, 0
162 \\ movi a0, 0
163 \\
164 \\ mov a6, a10
165 \\ callx4 a9
166 );
167 asm volatile (
168 \\ movi a2, 118 // SYS_exit
169 \\ syscall
170 );
171}
172
173pub const restore = restore_rt;
174
175pub fn restore_rt() callconv(.naked) noreturn {
176 asm volatile (
177 \\ movi a2, %[number]
178 \\ syscall
179 :
180 : [number] "I" (@backingInt(SYS.rt_sigreturn)),
181 );
182}
183
184pub const VDSO = void;
185
186pub const time_t = i32;