rustix/backend/linux_raw/arch/
x86_64.rs

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