linux_syscall/arch/x86/
syscall_asm.rs

1// Copyright (c) 2022 John Millikin <john@john-millikin.com>
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted.
5//
6// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
7// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
8// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
9// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
10// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
11// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
12// PERFORMANCE OF THIS SOFTWARE.
13//
14// SPDX-License-Identifier: 0BSD
15
16/// Linux syscall result for the `x86` architecture.
17#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
18#[must_use]
19pub struct Result(u32);
20
21impl Result {
22	#[inline]
23	pub const fn new(register_eax: u32) -> Self {
24		Self(register_eax)
25	}
26
27	#[inline]
28	pub const fn as_u32_unchecked(self) -> u32 {
29		self.0
30	}
31
32	#[inline]
33	pub const fn as_usize_unchecked(self) -> usize {
34		self.0 as usize
35	}
36}
37
38single_register_result32!(Result);
39
40#[cfg(not(doc))]
41#[macro_export]
42macro_rules! syscall {
43	($nr:expr $(,)?) => {{
44		let mut out_eax;
45		core::arch::asm!(
46			"int $0x80",
47			in("eax") u32::from(Into::<$crate::Syscall>::into($nr)),
48			lateout("eax") out_eax,
49			options(nostack),
50		);
51		$crate::arch::x86::Result::new(out_eax)
52	}};
53	($nr:expr, $a1:expr $(,)?) => {{
54		let mut out_eax;
55		core::arch::asm!(
56			"int $0x80",
57			in("eax") u32::from(Into::<$crate::Syscall>::into($nr)),
58			in("ebx") $a1,
59			lateout("eax") out_eax,
60			options(nostack),
61		);
62		$crate::arch::x86::Result::new(out_eax)
63	}};
64	($nr:expr, $a1:expr, $a2:expr $(,)?) => {{
65		let mut out_eax;
66		core::arch::asm!(
67			"int $0x80",
68			in("eax") u32::from(Into::<$crate::Syscall>::into($nr)),
69			in("ebx") $a1,
70			in("ecx") $a2,
71			lateout("eax") out_eax,
72			options(nostack),
73		);
74		$crate::arch::x86::Result::new(out_eax)
75	}};
76	($nr:expr, $a1:expr, $a2:expr, $a3:expr $(,)?) => {{
77		let mut out_eax;
78		core::arch::asm!(
79			"int $0x80",
80			in("eax") u32::from(Into::<$crate::Syscall>::into($nr)),
81			in("ebx") $a1,
82			in("ecx") $a2,
83			in("edx") $a3,
84			lateout("eax") out_eax,
85			options(nostack),
86		);
87		$crate::arch::x86::Result::new(out_eax)
88	}};
89	($nr:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr $(,)?) => {{
90		let in_esi = $a4;
91		let mut out_eax;
92		core::arch::asm!(
93			"push esi",
94			"mov esi, {0}",
95			"int $0x80",
96			"pop esi",
97			in(reg) in_esi,
98			in("eax") u32::from(Into::<$crate::Syscall>::into($nr)),
99			in("ebx") $a1,
100			in("ecx") $a2,
101			in("edx") $a3,
102			lateout("eax") out_eax,
103		);
104		$crate::arch::x86::Result::new(out_eax)
105	}};
106	($nr:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr $(,)?) => {{
107		let in_esi = $a4;
108		let mut out_eax;
109		core::arch::asm!(
110			"push esi",
111			"mov esi, {0}",
112			"int $0x80",
113			"pop esi",
114			in(reg) in_esi,
115			in("eax") u32::from(Into::<$crate::Syscall>::into($nr)),
116			in("ebx") $a1,
117			in("ecx") $a2,
118			in("edx") $a3,
119			in("edi") $a5,
120			lateout("eax") out_eax,
121		);
122		$crate::arch::x86::Result::new(out_eax)
123	}};
124	($nr:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr $(,)?) => {{
125		let in_esi = $a4;
126		let in_ebp = $a6;
127		let mut out_eax;
128		core::arch::asm!(
129			"push esi",
130			"push ebp",
131			"mov esi, {0}",
132			"mov ebp, {1}",
133			"int $0x80",
134			"pop ebp",
135			"pop esi",
136			in(reg) in_esi,
137			in(reg) in_ebp,
138			in("eax") u32::from(Into::<$crate::Syscall>::into($nr)),
139			in("ebx") $a1,
140			in("ecx") $a2,
141			in("edx") $a3,
142			in("edi") $a5,
143			lateout("eax") out_eax,
144		);
145		$crate::arch::x86::Result::new(out_eax)
146	}};
147}