1 //! powerpc64le Linux system calls.
2 //!
3 //! On powerpc64le, Linux indicates success or failure using `cr0.SO` rather
4 //! than by returning a negative error code as most other architectures do. In
5 //! theory we could immediately translate this into a `Result`, and it'd save a
6 //! few branches. And in theory we could have specialized sequences for use
7 //! with syscalls that are known to never fail. However, those would require
8 //! more extensive changes in rustix's platform-independent code. For now, we
9 //! check the flag and negate the error value to make PowerPC64 look like other
10 //! architectures.
11 
12 use crate::backend::reg::{
13     ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
14 };
15 use core::arch::asm;
16 
17 #[inline]
syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0>18 pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
19     let r0;
20     asm!(
21         "sc",
22         "bns 0f",
23         "neg 3, 3",
24         "0:",
25         inlateout("r0") nr.to_asm() => _,
26         lateout("r3") r0,
27         lateout("r4") _,
28         lateout("r5") _,
29         lateout("r6") _,
30         lateout("r7") _,
31         lateout("r8") _,
32         lateout("r9") _,
33         lateout("r10") _,
34         lateout("r11") _,
35         lateout("r12") _,
36         lateout("cr0") _,
37         options(nostack, preserves_flags, readonly)
38     );
39     FromAsm::from_asm(r0)
40 }
41 
42 #[inline]
syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0>43 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
44     let r0;
45     asm!(
46         "sc",
47         "bns 0f",
48         "neg 3, 3",
49         "0:",
50         inlateout("r0") nr.to_asm() => _,
51         inlateout("r3") a0.to_asm() => r0,
52         lateout("r4") _,
53         lateout("r5") _,
54         lateout("r6") _,
55         lateout("r7") _,
56         lateout("r8") _,
57         lateout("r9") _,
58         lateout("r10") _,
59         lateout("r11") _,
60         lateout("r12") _,
61         lateout("cr0") _,
62         options(nostack, preserves_flags)
63     );
64     FromAsm::from_asm(r0)
65 }
66 
67 #[inline]
syscall1_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, ) -> RetReg<R0>68 pub(in crate::backend) unsafe fn syscall1_readonly(
69     nr: SyscallNumber<'_>,
70     a0: ArgReg<'_, A0>,
71 ) -> RetReg<R0> {
72     let r0;
73     asm!(
74         "sc",
75         "bns 0f",
76         "neg 3, 3",
77         "0:",
78         inlateout("r0") nr.to_asm() => _,
79         inlateout("r3") a0.to_asm() => r0,
80         lateout("r4") _,
81         lateout("r5") _,
82         lateout("r6") _,
83         lateout("r7") _,
84         lateout("r8") _,
85         lateout("r9") _,
86         lateout("r10") _,
87         lateout("r11") _,
88         lateout("r12") _,
89         lateout("cr0") _,
90         options(nostack, preserves_flags, readonly)
91     );
92     FromAsm::from_asm(r0)
93 }
94 
95 #[inline]
syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> !96 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
97     asm!(
98         "sc",
99         in("r0") nr.to_asm(),
100         in("r3") a0.to_asm(),
101         options(nostack, noreturn)
102     )
103 }
104 
105 #[inline]
syscall2( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>106 pub(in crate::backend) unsafe fn syscall2(
107     nr: SyscallNumber<'_>,
108     a0: ArgReg<'_, A0>,
109     a1: ArgReg<'_, A1>,
110 ) -> RetReg<R0> {
111     let r0;
112     asm!(
113         "sc",
114         "bns 0f",
115         "neg 3, 3",
116         "0:",
117         inlateout("r0") nr.to_asm() => _,
118         inlateout("r3") a0.to_asm() => r0,
119         inlateout("r4") a1.to_asm() => _,
120         lateout("r5") _,
121         lateout("r6") _,
122         lateout("r7") _,
123         lateout("r8") _,
124         lateout("r9") _,
125         lateout("r10") _,
126         lateout("r11") _,
127         lateout("r12") _,
128         lateout("cr0") _,
129         options(nostack, preserves_flags)
130     );
131     FromAsm::from_asm(r0)
132 }
133 
134 #[inline]
syscall2_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>135 pub(in crate::backend) unsafe fn syscall2_readonly(
136     nr: SyscallNumber<'_>,
137     a0: ArgReg<'_, A0>,
138     a1: ArgReg<'_, A1>,
139 ) -> RetReg<R0> {
140     let r0;
141     asm!(
142         "sc",
143         "bns 0f",
144         "neg 3, 3",
145         "0:",
146         inlateout("r0") nr.to_asm() => _,
147         inlateout("r3") a0.to_asm() => r0,
148         inlateout("r4") a1.to_asm() => _,
149         lateout("r5") _,
150         lateout("r6") _,
151         lateout("r7") _,
152         lateout("r8") _,
153         lateout("r9") _,
154         lateout("r10") _,
155         lateout("r11") _,
156         lateout("r12") _,
157         lateout("cr0") _,
158         options(nostack, preserves_flags, readonly)
159     );
160     FromAsm::from_asm(r0)
161 }
162 
163 #[inline]
syscall3( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>164 pub(in crate::backend) unsafe fn syscall3(
165     nr: SyscallNumber<'_>,
166     a0: ArgReg<'_, A0>,
167     a1: ArgReg<'_, A1>,
168     a2: ArgReg<'_, A2>,
169 ) -> RetReg<R0> {
170     let r0;
171     asm!(
172         "sc",
173         "bns 0f",
174         "neg 3, 3",
175         "0:",
176         inlateout("r0") nr.to_asm() => _,
177         inlateout("r3") a0.to_asm() => r0,
178         inlateout("r4") a1.to_asm() => _,
179         inlateout("r5") a2.to_asm() => _,
180         lateout("r6") _,
181         lateout("r7") _,
182         lateout("r8") _,
183         lateout("r9") _,
184         lateout("r10") _,
185         lateout("r11") _,
186         lateout("r12") _,
187         lateout("cr0") _,
188         options(nostack, preserves_flags)
189     );
190     FromAsm::from_asm(r0)
191 }
192 
193 #[inline]
syscall3_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>194 pub(in crate::backend) unsafe fn syscall3_readonly(
195     nr: SyscallNumber<'_>,
196     a0: ArgReg<'_, A0>,
197     a1: ArgReg<'_, A1>,
198     a2: ArgReg<'_, A2>,
199 ) -> RetReg<R0> {
200     let r0;
201     asm!(
202         "sc",
203         "bns 0f",
204         "neg 3, 3",
205         "0:",
206         inlateout("r0") nr.to_asm() => _,
207         inlateout("r3") a0.to_asm() => r0,
208         inlateout("r4") a1.to_asm() => _,
209         inlateout("r5") a2.to_asm() => _,
210         lateout("r6") _,
211         lateout("r7") _,
212         lateout("r8") _,
213         lateout("r9") _,
214         lateout("r10") _,
215         lateout("r11") _,
216         lateout("r12") _,
217         lateout("cr0") _,
218         options(nostack, preserves_flags, readonly)
219     );
220     FromAsm::from_asm(r0)
221 }
222 
223 #[inline]
syscall4( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>224 pub(in crate::backend) unsafe fn syscall4(
225     nr: SyscallNumber<'_>,
226     a0: ArgReg<'_, A0>,
227     a1: ArgReg<'_, A1>,
228     a2: ArgReg<'_, A2>,
229     a3: ArgReg<'_, A3>,
230 ) -> RetReg<R0> {
231     let r0;
232     asm!(
233         "sc",
234         "bns 0f",
235         "neg 3, 3",
236         "0:",
237         inlateout("r0") nr.to_asm() => _,
238         inlateout("r3") a0.to_asm() => r0,
239         inlateout("r4") a1.to_asm() => _,
240         inlateout("r5") a2.to_asm() => _,
241         inlateout("r6") a3.to_asm() => _,
242         lateout("r7") _,
243         lateout("r8") _,
244         lateout("r9") _,
245         lateout("r10") _,
246         lateout("r11") _,
247         lateout("r12") _,
248         lateout("cr0") _,
249         options(nostack, preserves_flags)
250     );
251     FromAsm::from_asm(r0)
252 }
253 
254 #[inline]
syscall4_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>255 pub(in crate::backend) unsafe fn syscall4_readonly(
256     nr: SyscallNumber<'_>,
257     a0: ArgReg<'_, A0>,
258     a1: ArgReg<'_, A1>,
259     a2: ArgReg<'_, A2>,
260     a3: ArgReg<'_, A3>,
261 ) -> RetReg<R0> {
262     let r0;
263     asm!(
264         "sc",
265         "bns 0f",
266         "neg 3, 3",
267         "0:",
268         inlateout("r0") nr.to_asm() => _,
269         inlateout("r3") a0.to_asm() => r0,
270         inlateout("r4") a1.to_asm() => _,
271         inlateout("r5") a2.to_asm() => _,
272         inlateout("r6") a3.to_asm() => _,
273         lateout("r7") _,
274         lateout("r8") _,
275         lateout("r9") _,
276         lateout("r10") _,
277         lateout("r11") _,
278         lateout("r12") _,
279         lateout("cr0") _,
280         options(nostack, preserves_flags, readonly)
281     );
282     FromAsm::from_asm(r0)
283 }
284 
285 #[inline]
syscall5( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>286 pub(in crate::backend) unsafe fn syscall5(
287     nr: SyscallNumber<'_>,
288     a0: ArgReg<'_, A0>,
289     a1: ArgReg<'_, A1>,
290     a2: ArgReg<'_, A2>,
291     a3: ArgReg<'_, A3>,
292     a4: ArgReg<'_, A4>,
293 ) -> RetReg<R0> {
294     let r0;
295     asm!(
296         "sc",
297         "bns 0f",
298         "neg 3, 3",
299         "0:",
300         inlateout("r0") nr.to_asm() => _,
301         inlateout("r3") a0.to_asm() => r0,
302         inlateout("r4") a1.to_asm() => _,
303         inlateout("r5") a2.to_asm() => _,
304         inlateout("r6") a3.to_asm() => _,
305         inlateout("r7") a4.to_asm() => _,
306         lateout("r8") _,
307         lateout("r9") _,
308         lateout("r10") _,
309         lateout("r11") _,
310         lateout("r12") _,
311         lateout("cr0") _,
312         options(nostack, preserves_flags)
313     );
314     FromAsm::from_asm(r0)
315 }
316 
317 #[inline]
syscall5_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>318 pub(in crate::backend) unsafe fn syscall5_readonly(
319     nr: SyscallNumber<'_>,
320     a0: ArgReg<'_, A0>,
321     a1: ArgReg<'_, A1>,
322     a2: ArgReg<'_, A2>,
323     a3: ArgReg<'_, A3>,
324     a4: ArgReg<'_, A4>,
325 ) -> RetReg<R0> {
326     let r0;
327     asm!(
328         "sc",
329         "bns 0f",
330         "neg 3, 3",
331         "0:",
332         inlateout("r0") nr.to_asm() => _,
333         inlateout("r3") a0.to_asm() => r0,
334         inlateout("r4") a1.to_asm() => _,
335         inlateout("r5") a2.to_asm() => _,
336         inlateout("r6") a3.to_asm() => _,
337         inlateout("r7") a4.to_asm() => _,
338         lateout("r8") _,
339         lateout("r9") _,
340         lateout("r10") _,
341         lateout("r11") _,
342         lateout("r12") _,
343         lateout("cr0") _,
344         options(nostack, preserves_flags, readonly)
345     );
346     FromAsm::from_asm(r0)
347 }
348 
349 #[inline]
syscall6( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>350 pub(in crate::backend) unsafe fn syscall6(
351     nr: SyscallNumber<'_>,
352     a0: ArgReg<'_, A0>,
353     a1: ArgReg<'_, A1>,
354     a2: ArgReg<'_, A2>,
355     a3: ArgReg<'_, A3>,
356     a4: ArgReg<'_, A4>,
357     a5: ArgReg<'_, A5>,
358 ) -> RetReg<R0> {
359     let r0;
360     asm!(
361         "sc",
362         "bns 0f",
363         "neg 3, 3",
364         "0:",
365         inlateout("r0") nr.to_asm() => _,
366         inlateout("r3") a0.to_asm() => r0,
367         inlateout("r4") a1.to_asm() => _,
368         inlateout("r5") a2.to_asm() => _,
369         inlateout("r6") a3.to_asm() => _,
370         inlateout("r7") a4.to_asm() => _,
371         inlateout("r8") a5.to_asm() => _,
372         lateout("r9") _,
373         lateout("r10") _,
374         lateout("r11") _,
375         lateout("r12") _,
376         lateout("cr0") _,
377         options(nostack, preserves_flags)
378     );
379     FromAsm::from_asm(r0)
380 }
381 
382 #[inline]
syscall6_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>383 pub(in crate::backend) unsafe fn syscall6_readonly(
384     nr: SyscallNumber<'_>,
385     a0: ArgReg<'_, A0>,
386     a1: ArgReg<'_, A1>,
387     a2: ArgReg<'_, A2>,
388     a3: ArgReg<'_, A3>,
389     a4: ArgReg<'_, A4>,
390     a5: ArgReg<'_, A5>,
391 ) -> RetReg<R0> {
392     let r0;
393     asm!(
394         "sc",
395         "bns 0f",
396         "neg 3, 3",
397         "0:",
398         inlateout("r0") nr.to_asm() => _,
399         inlateout("r3") a0.to_asm() => r0,
400         inlateout("r4") a1.to_asm() => _,
401         inlateout("r5") a2.to_asm() => _,
402         inlateout("r6") a3.to_asm() => _,
403         inlateout("r7") a4.to_asm() => _,
404         inlateout("r8") a5.to_asm() => _,
405         lateout("r9") _,
406         lateout("r10") _,
407         lateout("r11") _,
408         lateout("r12") _,
409         lateout("cr0") _,
410         options(nostack, preserves_flags, readonly)
411     );
412     FromAsm::from_asm(r0)
413 }
414