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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 | |