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 \\ t 0x10
12 \\ bcc 1f
13 \\ nop
14 \\ neg %%o0
15 \\1:
16 : [ret] "={o0}" (-> u32),
17 : [number] "{g1}" (@backingInt(number)),
18 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
19}
20
21pub fn syscall1(
22 number: SYS,
23 arg1: syscall_arg_t,
24) u32 {
25 return asm volatile (
26 \\ t 0x10
27 \\ bcc 1f
28 \\ nop
29 \\ neg %%o0
30 \\1:
31 : [ret] "={o0}" (-> u32),
32 : [number] "{g1}" (@backingInt(number)),
33 [arg1] "{o0}" (arg1),
34 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
35}
36
37pub fn syscall2(
38 number: SYS,
39 arg1: syscall_arg_t,
40 arg2: syscall_arg_t,
41) u32 {
42 return asm volatile (
43 \\ t 0x10
44 \\ bcc 1f
45 \\ nop
46 \\ neg %%o0
47 \\1:
48 : [ret] "={o0}" (-> u32),
49 : [number] "{g1}" (@backingInt(number)),
50 [arg1] "{o0}" (arg1),
51 [arg2] "{o1}" (arg2),
52 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
53}
54
55pub fn syscall3(
56 number: SYS,
57 arg1: syscall_arg_t,
58 arg2: syscall_arg_t,
59 arg3: syscall_arg_t,
60) u32 {
61 return asm volatile (
62 \\ t 0x10
63 \\ bcc 1f
64 \\ nop
65 \\ neg %%o0
66 \\1:
67 : [ret] "={o0}" (-> u32),
68 : [number] "{g1}" (@backingInt(number)),
69 [arg1] "{o0}" (arg1),
70 [arg2] "{o1}" (arg2),
71 [arg3] "{o2}" (arg3),
72 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
73}
74
75pub fn syscall4(
76 number: SYS,
77 arg1: syscall_arg_t,
78 arg2: syscall_arg_t,
79 arg3: syscall_arg_t,
80 arg4: syscall_arg_t,
81) u32 {
82 return asm volatile (
83 \\ t 0x10
84 \\ bcc 1f
85 \\ nop
86 \\ neg %%o0
87 \\1:
88 : [ret] "={o0}" (-> u32),
89 : [number] "{g1}" (@backingInt(number)),
90 [arg1] "{o0}" (arg1),
91 [arg2] "{o1}" (arg2),
92 [arg3] "{o2}" (arg3),
93 [arg4] "{o3}" (arg4),
94 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
95}
96
97pub fn syscall5(
98 number: SYS,
99 arg1: syscall_arg_t,
100 arg2: syscall_arg_t,
101 arg3: syscall_arg_t,
102 arg4: syscall_arg_t,
103 arg5: syscall_arg_t,
104) u32 {
105 return asm volatile (
106 \\ t 0x10
107 \\ bcc 1f
108 \\ nop
109 \\ neg %%o0
110 \\1:
111 : [ret] "={o0}" (-> u32),
112 : [number] "{g1}" (@backingInt(number)),
113 [arg1] "{o0}" (arg1),
114 [arg2] "{o1}" (arg2),
115 [arg3] "{o2}" (arg3),
116 [arg4] "{o3}" (arg4),
117 [arg5] "{o4}" (arg5),
118 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = 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 \\ t 0x10
132 \\ bcc 1f
133 \\ nop
134 \\ neg %%o0
135 \\1:
136 : [ret] "={o0}" (-> u32),
137 : [number] "{g1}" (@backingInt(number)),
138 [arg1] "{o0}" (arg1),
139 [arg2] "{o1}" (arg2),
140 [arg3] "{o2}" (arg3),
141 [arg4] "{o3}" (arg4),
142 [arg5] "{o4}" (arg5),
143 [arg6] "{o5}" (arg6),
144 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
145}
146
147pub fn syscall_pipe(
148 fd: *[2]std.os.linux.fd_t,
149) u32 {
150 return asm volatile (
151 \\ mov %[arg], %%g3
152 \\ t 0x10
153 \\ bcc 1f
154 \\ nop
155 \\ # Return the error code
156 \\ ba 2f
157 \\ neg %%o0
158 \\1:
159 \\ st %%o0, [%%g3+0]
160 \\ st %%o1, [%%g3+4]
161 \\ clr %%o0
162 \\2:
163 : [ret] "={o0}" (-> u32),
164 : [number] "{g1}" (@backingInt(SYS.pipe)),
165 [arg] "r" (fd),
166 : .{ .memory = true, .g3 = true });
167}
168
169pub fn syscall_fork() u32 {
170 // Linux/sparc fork() returns two values in %o0 and %o1:
171 // - On the parent's side, %o0 is the child's PID and %o1 is 0.
172 // - On the child's side, %o0 is the parent's PID and %o1 is 1.
173 // We need to clear the child's %o0 so that the return values
174 // conform to the libc convention.
175 return asm volatile (
176 \\ t 0x10
177 \\ bcc 1f
178 \\ nop
179 \\ ba 2f
180 \\ neg %%o0
181 \\1:
182 \\ # Clear the child's %%o0
183 \\ dec %%o1
184 \\ and %%o1, %%o0, %%o0
185 \\2:
186 : [ret] "={o0}" (-> u32),
187 : [number] "{g1}" (@backingInt(SYS.fork)),
188 : .{ .memory = true, .xcc = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
189}
190
191pub fn clone() callconv(.naked) u32 {
192 // __clone(func, stack, flags, arg, ptid, tls, ctid)
193 // i0, i1, i2, i3, i4, i5, sp
194 //
195 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
196 // g1 o0, o1, o2, o3, o4
197 asm volatile (
198 \\ save %%sp, -96, %%sp
199 \\
200 \\ // clone() on SPARC can fail with EFAULT if %%sp points to uncommitted memory, so flush
201 \\ // all register windows up to this point to ensure that the kernel has enough committed
202 \\ // memory for its stack frame.
203 \\ save %%sp, -96, %%sp
204 \\ t 0x3
205 \\ restore
206 \\
207 \\ # Save the func pointer and the arg pointer
208 \\ mov %%i0, %%g2
209 \\ mov %%i3, %%g3
210 \\
211 \\ # Shuffle the arguments
212 \\ mov 217, %%g1 // SYS_clone
213 \\ mov %%i2, %%o0
214 \\
215 \\ # Align, and add some extra space for the initial frame
216 \\ and %%i1, -8, %%i1
217 \\ sub %%i1, 96, %%o1
218 \\
219 \\ mov %%i4, %%o2
220 \\ mov %%i5, %%o3
221 \\ ld [%%fp + 92], %%o4
222 \\ t 0x10
223 \\ bcs 1f
224 \\ nop
225 \\ # The child pid is returned in o0 while o1 tells if this
226 \\ # process is the child (=1) or the parent (=0).
227 \\ tst %%o1
228 \\ bne 2f
229 \\ nop
230 \\
231 \\ # Parent process, return the child pid
232 \\ mov %%o0, %%i0
233 \\ ret
234 \\ restore
235 \\
236 \\1:
237 \\ # The syscall failed
238 \\ sub %%g0, %%o0, %%i0
239 \\ ret
240 \\ restore
241 \\
242 \\2:
243 \\ # Child process
244 );
245 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
246 \\ .cfi_undefined %%i7
247 );
248 asm volatile (
249 \\ mov %%g0, %%fp
250 \\ mov %%g0, %%i7
251 \\
252 \\ # call func(arg)
253 \\ call %%g2
254 \\ mov %%g3, %%o0
255 \\ # Exit
256 \\ mov 1, %%g1 // SYS_exit
257 \\ t 0x10
258 );
259}
260
261pub const restore = restore_rt;
262
263pub fn restore_rt() callconv(.naked) noreturn {
264 asm volatile (
265 \\ nop
266 \\ nop
267 );
268 asm volatile (
269 \\ t 0x10
270 :
271 : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),
272 );
273}
274
275pub const VDSO = struct {
276 pub const CGT_SYM = "__vdso_clock_gettime";
277 pub const CGT_VER = "LINUX_2.6";
278};
279
280pub const time_t = i32;