1use crate::syscalls::types::SyscallResult;
2
3use core::arch::asm;
4
5#[macro_export]
10macro_rules! syscall {
11 ($num: expr, $($arg: expr),*) => {{
12 #[allow(unused_imports)]
13 use $crate::syscalls::call::JoinTuples;
14 use $crate::syscalls::call::SyscallCaller;
15 #[allow(unused_imports)]
16 use $crate::syscalls::types::IntoSyscallArg;
17
18 let args = ();
19 $(
20 let args = args.join_tuple($arg.into_syscall_arg());
21 )*
22 SyscallCaller::<{ $num as u16 }, _>::new(args).call()
23 }};
24}
25
26pub use syscall;
27
28pub struct SyscallCaller<const NUM: u16, T> {
29 args: T,
30}
31
32impl<const NUM: u16, T> SyscallCaller<NUM, T> {
33 pub const fn new(args: T) -> Self {
34 Self { args }
35 }
36}
37
38impl<const NUM: u16> SyscallCaller<NUM, ()> {
39 #[inline(always)]
40 pub fn call(self) -> SyscallResult {
41 syscall0::<NUM>()
42 }
43}
44
45impl<const NUM: u16> SyscallCaller<NUM, (usize,)> {
46 #[inline(always)]
47 pub fn call(self) -> SyscallResult {
48 syscall1::<NUM>(self.args.0)
49 }
50}
51
52impl<const NUM: u16> SyscallCaller<NUM, (usize, usize)> {
53 #[inline(always)]
54 pub fn call(self) -> SyscallResult {
55 syscall2::<NUM>(self.args.0, self.args.1)
56 }
57}
58
59impl<const NUM: u16> SyscallCaller<NUM, (usize, usize, usize)> {
60 #[inline(always)]
61 pub fn call(self) -> SyscallResult {
62 syscall3::<NUM>(self.args.0, self.args.1, self.args.2)
63 }
64}
65
66impl<const NUM: u16> SyscallCaller<NUM, (usize, usize, usize, usize)> {
67 #[inline(always)]
68 pub fn call(self) -> SyscallResult {
69 syscall4::<NUM>(self.args.0, self.args.1, self.args.2, self.args.3)
70 }
71}
72
73impl<const NUM: u16> SyscallCaller<NUM, (usize, usize, usize, usize, usize)> {
74 #[inline(always)]
75 pub fn call(self) -> SyscallResult {
76 syscall5::<NUM>(
77 self.args.0,
78 self.args.1,
79 self.args.2,
80 self.args.3,
81 self.args.4,
82 )
83 }
84}
85
86#[doc(hidden)]
87#[inline(always)]
88pub fn syscall0<const NUM: u16>() -> SyscallResult {
89 let result: u16;
90 unsafe {
91 #[cfg(target_arch = "x86_64")]
92 asm!(
93 "int 0x80",
94 in("rax") NUM as usize,
95 lateout("rax") result,
96 );
97 #[cfg(target_arch = "aarch64")]
98 asm!(
99 "svc #{num}",
100 num = const NUM,
101 lateout("x0") result
102 );
103 core::mem::transmute(result)
104 }
105}
106
107#[doc(hidden)]
108#[inline(always)]
109pub fn syscall1<const NUM: u16>(arg1: usize) -> SyscallResult {
110 let result: u16;
111 unsafe {
112 #[cfg(target_arch = "x86_64")]
113 asm!(
114 "int 0x80",
115 in("rax") NUM as usize,
116 in("rdi") arg1,
117 lateout("rax") result,
118 );
119 #[cfg(target_arch = "aarch64")]
120 asm!(
121 "svc #{num}",
122 num = const NUM,
123 in("x0") arg1,
124 lateout("x0") result
125 );
126 core::mem::transmute(result)
127 }
128}
129
130#[doc(hidden)]
131#[inline(always)]
132pub fn syscall2<const NUM: u16>(arg1: usize, arg2: usize) -> SyscallResult {
133 let result: u16;
134 unsafe {
135 #[cfg(target_arch = "x86_64")]
136 asm!(
137 "int 0x80",
138 in("rax") NUM as usize,
139 in("rdi") arg1,
140 in("rsi") arg2,
141 lateout("rax") result,
142 );
143 #[cfg(target_arch = "aarch64")]
144 asm!(
145 "svc #{num}",
146 num = const NUM,
147 in("x0") arg1,
148 in("x1") arg2,
149 lateout("x0") result
150 );
151 core::mem::transmute(result)
152 }
153}
154
155#[doc(hidden)]
156#[inline(always)]
157pub fn syscall3<const NUM: u16>(arg1: usize, arg2: usize, arg3: usize) -> SyscallResult {
158 let result: u16;
159 unsafe {
160 #[cfg(target_arch = "x86_64")]
161 asm!(
162 "int 0x80",
163 in("rax") NUM as usize,
164 in("rdi") arg1,
165 in("rsi") arg2,
166 in("rdx") arg3,
167 lateout("rax") result,
168 );
169 #[cfg(target_arch = "aarch64")]
170 asm!(
171 "svc #{num}",
172 num = const NUM,
173 in("x0") arg1,
174 in("x1") arg2,
175 in("x2") arg3,
176 lateout("x0") result
177 );
178 core::mem::transmute(result)
179 }
180}
181
182#[doc(hidden)]
183#[inline(always)]
184pub fn syscall4<const NUM: u16>(
185 arg1: usize,
186 arg2: usize,
187 arg3: usize,
188 arg4: usize,
189) -> SyscallResult {
190 let result: u16;
191 unsafe {
192 #[cfg(target_arch = "x86_64")]
193 asm!(
194 "int 0x80",
195 in("rax") NUM as usize,
196 in("rdi") arg1,
197 in("rsi") arg2,
198 in("rdx") arg3,
199 in("rcx") arg4,
200 lateout("rax") result,
201 );
202
203 #[cfg(target_arch = "aarch64")]
204 asm!(
205 "svc #{num}",
206 num = const NUM,
207 in("x0") arg1,
208 in("x1") arg2,
209 in("x2") arg3,
210 in("x3") arg4,
211 lateout("x0") result
212 );
213 core::mem::transmute(result)
214 }
215}
216
217#[doc(hidden)]
218#[inline(always)]
219pub fn syscall5<const NUM: u16>(
220 arg1: usize,
221 arg2: usize,
222 arg3: usize,
223 arg4: usize,
224 arg5: usize,
225) -> SyscallResult {
226 let result: u16;
227 unsafe {
228 #[cfg(target_arch = "x86_64")]
229 asm!(
230 "int 0x80",
231 in("rax") NUM as usize,
232 in("rdi") arg1,
233 in("rsi") arg2,
234 in("rdx") arg3,
235 in("rcx") arg4,
236 in("r8") arg5,
237 lateout("rax") result,
238 );
239 #[cfg(target_arch = "aarch64")]
240 asm!(
241 "svc #{num}",
242 num = const NUM,
243 in("x0") arg1,
244 in("x1") arg2,
245 in("x2") arg3,
246 in("x3") arg4,
247 in("x4") arg5,
248 lateout("x0") result
249 );
250 core::mem::transmute(result)
251 }
252}
253
254pub trait JoinTuples<JoinWith> {
255 type Output;
256 fn join_tuple(self, other: JoinWith) -> Self::Output;
257}
258
259macro_rules! impl_join_single {
260 ($($T:ident)*,$($O:ident)*) => {
261 impl<$($T,)* $($O,)*> JoinTuples<($($O,)*)> for ($($T,)*) {
262 type Output = ($($T,)* $($O,)*);
263 fn join_tuple(self, other: ($($O,)*) ) -> Self::Output {
264 #[allow(non_snake_case)]
265 let ($($T,)*) = self;
266 #[allow(non_snake_case)]
267 let ($($O,)*) = other;
268 ($($T,)* $($O,)*)
269 }
270 }
271 };
272}
273macro_rules! impl_join {
274 ($($T:ident)*,$($O:ident)*) => {
275 impl_join_single!($($T)*,$($O)*);
276 impl_join_single!($($O)*,$($T)*);
277 };
278}
279
280macro_rules! impl_join_nothing {
281 ($($T:ident)*) => {
282
283 impl<$($T,)*> JoinTuples<()> for ($($T,)*) {
284 type Output = ($($T,)*);
285 fn join_tuple(self, _other: ()) -> Self::Output {
286 self
287 }
288 }
289
290 impl<$($T,)*> JoinTuples<($($T,)*)> for () {
291 type Output = ($($T,)*);
292 fn join_tuple(self, other: ($($T,)*)) -> Self::Output {
293 _ = self;
294 other
295 }
296 }
297 };
298}
299
300impl_join_nothing!(A);
302impl_join_single!(A, B);
303impl_join_nothing!(A B);
304impl_join_single!(A B, C D);
305impl_join!(A B, C);
307impl_join_nothing!(A B C);
308impl_join!(A B C, D);
310impl_join_nothing!(A B C D);
311impl_join!(A B C D, E);
313impl_join_nothing!(A B C D E);
314impl_join!(A B C, D E);