1 //! x86-64 Linux system calls.
2 
3 use crate::backend::reg::{
4     ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
5 };
6 use core::arch::asm;
7 
8 #[cfg(target_pointer_width = "32")]
9 compile_error!("x32 is not yet supported");
10 
11 #[inline]
syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0>12 pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
13     let r0;
14     asm!(
15         "syscall",
16         inlateout("rax") nr.to_asm() => r0,
17         lateout("rcx") _,
18         lateout("r11") _,
19         options(nostack, preserves_flags, readonly)
20     );
21     FromAsm::from_asm(r0)
22 }
23 
24 #[inline]
syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0>25 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
26     let r0;
27     asm!(
28         "syscall",
29         inlateout("rax") nr.to_asm() => r0,
30         in("rdi") a0.to_asm(),
31         lateout("rcx") _,
32         lateout("r11") _,
33         options(nostack, preserves_flags)
34     );
35     FromAsm::from_asm(r0)
36 }
37 
38 #[inline]
syscall1_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, ) -> RetReg<R0>39 pub(in crate::backend) unsafe fn syscall1_readonly(
40     nr: SyscallNumber<'_>,
41     a0: ArgReg<'_, A0>,
42 ) -> RetReg<R0> {
43     let r0;
44     asm!(
45         "syscall",
46         inlateout("rax") nr.to_asm() => r0,
47         in("rdi") a0.to_asm(),
48         lateout("rcx") _,
49         lateout("r11") _,
50         options(nostack, preserves_flags, readonly)
51     );
52     FromAsm::from_asm(r0)
53 }
54 
55 #[inline]
syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> !56 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
57     asm!(
58         "syscall",
59         in("rax") nr.to_asm(),
60         in("rdi") a0.to_asm(),
61         options(nostack, noreturn)
62     )
63 }
64 
65 #[inline]
syscall2( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>66 pub(in crate::backend) unsafe fn syscall2(
67     nr: SyscallNumber<'_>,
68     a0: ArgReg<'_, A0>,
69     a1: ArgReg<'_, A1>,
70 ) -> RetReg<R0> {
71     let r0;
72     asm!(
73         "syscall",
74         inlateout("rax") nr.to_asm() => r0,
75         in("rdi") a0.to_asm(),
76         in("rsi") a1.to_asm(),
77         lateout("rcx") _,
78         lateout("r11") _,
79         options(nostack, preserves_flags)
80     );
81     FromAsm::from_asm(r0)
82 }
83 
84 #[inline]
syscall2_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>85 pub(in crate::backend) unsafe fn syscall2_readonly(
86     nr: SyscallNumber<'_>,
87     a0: ArgReg<'_, A0>,
88     a1: ArgReg<'_, A1>,
89 ) -> RetReg<R0> {
90     let r0;
91     asm!(
92         "syscall",
93         inlateout("rax") nr.to_asm() => r0,
94         in("rdi") a0.to_asm(),
95         in("rsi") a1.to_asm(),
96         lateout("rcx") _,
97         lateout("r11") _,
98         options(nostack, preserves_flags, readonly)
99     );
100     FromAsm::from_asm(r0)
101 }
102 
103 #[inline]
syscall3( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>104 pub(in crate::backend) unsafe fn syscall3(
105     nr: SyscallNumber<'_>,
106     a0: ArgReg<'_, A0>,
107     a1: ArgReg<'_, A1>,
108     a2: ArgReg<'_, A2>,
109 ) -> RetReg<R0> {
110     let r0;
111     asm!(
112         "syscall",
113         inlateout("rax") nr.to_asm() => r0,
114         in("rdi") a0.to_asm(),
115         in("rsi") a1.to_asm(),
116         in("rdx") a2.to_asm(),
117         lateout("rcx") _,
118         lateout("r11") _,
119         options(nostack, preserves_flags)
120     );
121     FromAsm::from_asm(r0)
122 }
123 
124 #[inline]
syscall3_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>125 pub(in crate::backend) unsafe fn syscall3_readonly(
126     nr: SyscallNumber<'_>,
127     a0: ArgReg<'_, A0>,
128     a1: ArgReg<'_, A1>,
129     a2: ArgReg<'_, A2>,
130 ) -> RetReg<R0> {
131     let r0;
132     asm!(
133         "syscall",
134         inlateout("rax") nr.to_asm() => r0,
135         in("rdi") a0.to_asm(),
136         in("rsi") a1.to_asm(),
137         in("rdx") a2.to_asm(),
138         lateout("rcx") _,
139         lateout("r11") _,
140         options(nostack, preserves_flags, readonly)
141     );
142     FromAsm::from_asm(r0)
143 }
144 
145 #[inline]
syscall4( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>146 pub(in crate::backend) unsafe fn syscall4(
147     nr: SyscallNumber<'_>,
148     a0: ArgReg<'_, A0>,
149     a1: ArgReg<'_, A1>,
150     a2: ArgReg<'_, A2>,
151     a3: ArgReg<'_, A3>,
152 ) -> RetReg<R0> {
153     let r0;
154     asm!(
155         "syscall",
156         inlateout("rax") nr.to_asm() => r0,
157         in("rdi") a0.to_asm(),
158         in("rsi") a1.to_asm(),
159         in("rdx") a2.to_asm(),
160         in("r10") a3.to_asm(),
161         lateout("rcx") _,
162         lateout("r11") _,
163         options(nostack, preserves_flags)
164     );
165     FromAsm::from_asm(r0)
166 }
167 
168 #[inline]
syscall4_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>169 pub(in crate::backend) unsafe fn syscall4_readonly(
170     nr: SyscallNumber<'_>,
171     a0: ArgReg<'_, A0>,
172     a1: ArgReg<'_, A1>,
173     a2: ArgReg<'_, A2>,
174     a3: ArgReg<'_, A3>,
175 ) -> RetReg<R0> {
176     let r0;
177     asm!(
178         "syscall",
179         inlateout("rax") nr.to_asm() => r0,
180         in("rdi") a0.to_asm(),
181         in("rsi") a1.to_asm(),
182         in("rdx") a2.to_asm(),
183         in("r10") a3.to_asm(),
184         lateout("rcx") _,
185         lateout("r11") _,
186         options(nostack, preserves_flags, readonly)
187     );
188     FromAsm::from_asm(r0)
189 }
190 
191 #[inline]
syscall5( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>192 pub(in crate::backend) unsafe fn syscall5(
193     nr: SyscallNumber<'_>,
194     a0: ArgReg<'_, A0>,
195     a1: ArgReg<'_, A1>,
196     a2: ArgReg<'_, A2>,
197     a3: ArgReg<'_, A3>,
198     a4: ArgReg<'_, A4>,
199 ) -> RetReg<R0> {
200     let r0;
201     asm!(
202         "syscall",
203         inlateout("rax") nr.to_asm() => r0,
204         in("rdi") a0.to_asm(),
205         in("rsi") a1.to_asm(),
206         in("rdx") a2.to_asm(),
207         in("r10") a3.to_asm(),
208         in("r8") a4.to_asm(),
209         lateout("rcx") _,
210         lateout("r11") _,
211         options(nostack, preserves_flags)
212     );
213     FromAsm::from_asm(r0)
214 }
215 
216 #[inline]
syscall5_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>217 pub(in crate::backend) unsafe fn syscall5_readonly(
218     nr: SyscallNumber<'_>,
219     a0: ArgReg<'_, A0>,
220     a1: ArgReg<'_, A1>,
221     a2: ArgReg<'_, A2>,
222     a3: ArgReg<'_, A3>,
223     a4: ArgReg<'_, A4>,
224 ) -> RetReg<R0> {
225     let r0;
226     asm!(
227         "syscall",
228         inlateout("rax") nr.to_asm() => r0,
229         in("rdi") a0.to_asm(),
230         in("rsi") a1.to_asm(),
231         in("rdx") a2.to_asm(),
232         in("r10") a3.to_asm(),
233         in("r8") a4.to_asm(),
234         lateout("rcx") _,
235         lateout("r11") _,
236         options(nostack, preserves_flags, readonly)
237     );
238     FromAsm::from_asm(r0)
239 }
240 
241 #[inline]
syscall6( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>242 pub(in crate::backend) unsafe fn syscall6(
243     nr: SyscallNumber<'_>,
244     a0: ArgReg<'_, A0>,
245     a1: ArgReg<'_, A1>,
246     a2: ArgReg<'_, A2>,
247     a3: ArgReg<'_, A3>,
248     a4: ArgReg<'_, A4>,
249     a5: ArgReg<'_, A5>,
250 ) -> RetReg<R0> {
251     let r0;
252     asm!(
253         "syscall",
254         inlateout("rax") nr.to_asm() => r0,
255         in("rdi") a0.to_asm(),
256         in("rsi") a1.to_asm(),
257         in("rdx") a2.to_asm(),
258         in("r10") a3.to_asm(),
259         in("r8") a4.to_asm(),
260         in("r9") a5.to_asm(),
261         lateout("rcx") _,
262         lateout("r11") _,
263         options(nostack, preserves_flags)
264     );
265     FromAsm::from_asm(r0)
266 }
267 
268 #[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>269 pub(in crate::backend) unsafe fn syscall6_readonly(
270     nr: SyscallNumber<'_>,
271     a0: ArgReg<'_, A0>,
272     a1: ArgReg<'_, A1>,
273     a2: ArgReg<'_, A2>,
274     a3: ArgReg<'_, A3>,
275     a4: ArgReg<'_, A4>,
276     a5: ArgReg<'_, A5>,
277 ) -> RetReg<R0> {
278     let r0;
279     asm!(
280         "syscall",
281         inlateout("rax") nr.to_asm() => r0,
282         in("rdi") a0.to_asm(),
283         in("rsi") a1.to_asm(),
284         in("rdx") a2.to_asm(),
285         in("r10") a3.to_asm(),
286         in("r8") a4.to_asm(),
287         in("r9") a5.to_asm(),
288         lateout("rcx") _,
289         lateout("r11") _,
290         options(nostack, preserves_flags, readonly)
291     );
292     FromAsm::from_asm(r0)
293 }
294