1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const SYS = std.os.linux.SYS;
4
5pub const syscall_arg_t = u64;
6
7pub fn syscall0(
8 number: SYS,
9) u64 {
10 return asm volatile (
11 \\ t 0x6d
12 \\ bcc,pt %%xcc, 1f
13 \\ nop
14 \\ neg %%o0
15 \\1:
16 : [ret] "={o0}" (-> u64),
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) u64 {
25 return asm volatile (
26 \\ t 0x6d
27 \\ bcc,pt %%xcc, 1f
28 \\ nop
29 \\ neg %%o0
30 \\1:
31 : [ret] "={o0}" (-> u64),
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) u64 {
42 return asm volatile (
43 \\ t 0x6d
44 \\ bcc,pt %%xcc, 1f
45 \\ nop
46 \\ neg %%o0
47 \\1:
48 : [ret] "={o0}" (-> u64),
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) u64 {
61 return asm volatile (
62 \\ t 0x6d
63 \\ bcc,pt %%xcc, 1f
64 \\ nop
65 \\ neg %%o0
66 \\1:
67 : [ret] "={o0}" (-> u64),
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) u64 {
82 return asm volatile (
83 \\ t 0x6d
84 \\ bcc,pt %%xcc, 1f
85 \\ nop
86 \\ neg %%o0
87 \\1:
88 : [ret] "={o0}" (-> u64),
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) u64 {
105 return asm volatile (
106 \\ t 0x6d
107 \\ bcc,pt %%xcc, 1f
108 \\ nop
109 \\ neg %%o0
110 \\1:
111 : [ret] "={o0}" (-> u64),
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) u64 {
130 return asm volatile (
131 \\ t 0x6d
132 \\ bcc,pt %%xcc, 1f
133 \\ nop
134 \\ neg %%o0
135 \\1:
136 : [ret] "={o0}" (-> u64),
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) u64 {
150 return asm volatile (
151 \\ mov %[arg], %%g3
152 \\ t 0x6d
153 \\ bcc,pt %%xcc, 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}" (-> u64),
164 : [number] "{g1}" (@backingInt(SYS.pipe)),
165 [arg] "r" (fd),
166 : .{ .memory = true, .g3 = true });
167}
168
169pub fn syscall_fork() u64 {
170 // Linux/sparc64 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 0x6d
177 \\ bcc,pt %%xcc, 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}" (-> u64),
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) u64 {
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, -192, %%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, -192, %%sp
204 \\ flushw
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, -16, %%i1
217 \\ sub %%i1, 192 + 2047, %%o1
218 \\
219 \\ mov %%i4, %%o2
220 \\ mov %%i5, %%o3
221 \\ ldx [%%fp + 176 + 2047], %%o4
222 \\ t 0x6d
223 \\ bcs,pn %%xcc, 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 \\ brnz %%o1, 2f
228 \\ nop
229 \\
230 \\ # Parent process, return the child pid
231 \\ mov %%o0, %%i0
232 \\ ret
233 \\ restore
234 \\
235 \\1:
236 \\ # The syscall failed
237 \\ sub %%g0, %%o0, %%i0
238 \\ ret
239 \\ restore
240 \\
241 \\2:
242 \\ # Child process
243 );
244 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
245 \\ .cfi_undefined %%i7
246 );
247 asm volatile (
248 \\ mov %%g0, %%fp
249 \\ mov %%g0, %%i7
250 \\
251 \\ # call func(arg)
252 \\ call %%g2
253 \\ mov %%g3, %%o0
254 \\ # Exit
255 \\ mov 1, %%g1 // SYS_exit
256 \\ t 0x6d
257 );
258}
259
260pub const restore = restore_rt;
261
262pub fn restore_rt() callconv(.naked) noreturn {
263 asm volatile (
264 \\ nop
265 \\ nop
266 );
267 asm volatile (
268 \\ t 0x6d
269 :
270 : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),
271 );
272}
273
274pub const VDSO = struct {
275 pub const CGT_SYM = "__vdso_clock_gettime";
276 pub const CGT_VER = "LINUX_2.6";
277};
278
279pub const time_t = i64;