1 //===---------- inline implementation of x86_64 syscalls ----------* C++ *-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_X86_64_SYSCALL_H 10 #define LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_X86_64_SYSCALL_H 11 12 #include "src/__support/common.h" 13 14 #define SYSCALL_CLOBBER_LIST "rcx", "r11", "memory" 15 16 namespace __llvm_libc { 17 18 __attribute__((always_inline)) inline long syscall(long __number) { 19 long retcode; 20 LIBC_INLINE_ASM("syscall" 21 : "=a"(retcode) 22 : "a"(__number) 23 : SYSCALL_CLOBBER_LIST); 24 return retcode; 25 } 26 27 __attribute__((always_inline)) inline long syscall(long __number, long __arg1) { 28 long retcode; 29 LIBC_INLINE_ASM("syscall" 30 : "=a"(retcode) 31 : "a"(__number), "D"(__arg1) 32 : SYSCALL_CLOBBER_LIST); 33 return retcode; 34 } 35 36 __attribute__((always_inline)) inline long syscall(long __number, long __arg1, 37 long __arg2) { 38 long retcode; 39 LIBC_INLINE_ASM("syscall" 40 : "=a"(retcode) 41 : "a"(__number), "D"(__arg1), "S"(__arg2) 42 : SYSCALL_CLOBBER_LIST); 43 return retcode; 44 } 45 46 __attribute__((always_inline)) inline long syscall(long __number, long __arg1, 47 long __arg2, long __arg3) { 48 long retcode; 49 LIBC_INLINE_ASM("syscall" 50 : "=a"(retcode) 51 : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3) 52 : SYSCALL_CLOBBER_LIST); 53 return retcode; 54 } 55 56 __attribute__((always_inline)) inline long 57 syscall(long __number, long __arg1, long __arg2, long __arg3, long __arg4) { 58 long retcode; 59 register long r10 __asm__("r10") = __arg4; 60 LIBC_INLINE_ASM("syscall" 61 : "=a"(retcode) 62 : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3), 63 "r"(r10) 64 : SYSCALL_CLOBBER_LIST); 65 return retcode; 66 } 67 68 __attribute__((always_inline)) inline long syscall(long __number, long __arg1, 69 long __arg2, long __arg3, 70 long __arg4, long __arg5) { 71 long retcode; 72 register long r10 __asm__("r10") = __arg4; 73 register long r8 __asm__("r8") = __arg5; 74 LIBC_INLINE_ASM("syscall" 75 : "=a"(retcode) 76 : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3), 77 "r"(r10), "r"(r8) 78 : SYSCALL_CLOBBER_LIST); 79 return retcode; 80 } 81 82 __attribute__((always_inline)) inline long syscall(long __number, long __arg1, 83 long __arg2, long __arg3, 84 long __arg4, long __arg5, 85 long __arg6) { 86 long retcode; 87 register long r10 __asm__("r10") = __arg4; 88 register long r8 __asm__("r8") = __arg5; 89 register long r9 __asm__("r9") = __arg6; 90 LIBC_INLINE_ASM("syscall" 91 : "=a"(retcode) 92 : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3), 93 "r"(r10), "r"(r8), "r"(r9) 94 : SYSCALL_CLOBBER_LIST); 95 return retcode; 96 } 97 98 template <typename... Ts> 99 __attribute__((always_inline)) inline long syscall(long __number, Ts... ts) { 100 static_assert(sizeof...(Ts) <= 6, "Too many arguments for syscall"); 101 return syscall(__number, (long)ts...); 102 } 103 104 #undef SYSCALL_CLOBBER_LIST 105 106 } // namespace __llvm_libc 107 108 #endif // LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_X86_64_SYSCALL_H 109