1//===------------ inline implementation of x86_64 syscalls ----------------===//
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%%begin()
10
11#include "src/__support/common.h"
12
13#define SYSCALL_CLOBBER_LIST "rcx", "r11", "memory"
14
15namespace __llvm_libc {
16
17__attribute__((always_inline)) inline long syscall(long __number) {
18  long retcode;
19  LIBC_INLINE_ASM("syscall"
20                  : "=a"(retcode)
21                  : "a"(__number)
22                  : SYSCALL_CLOBBER_LIST);
23  return retcode;
24}
25
26__attribute__((always_inline)) inline long syscall(long __number, long __arg1) {
27  long retcode;
28  LIBC_INLINE_ASM("syscall"
29                  : "=a"(retcode)
30                  : "a"(__number), "D"(__arg1)
31                  : SYSCALL_CLOBBER_LIST);
32  return retcode;
33}
34
35__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
36                                                   long __arg2) {
37  long retcode;
38  LIBC_INLINE_ASM("syscall"
39                  : "=a"(retcode)
40                  : "a"(__number), "D"(__arg1), "S"(__arg2)
41                  : SYSCALL_CLOBBER_LIST);
42  return retcode;
43}
44
45__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
46                                                   long __arg2, long __arg3) {
47  long retcode;
48  LIBC_INLINE_ASM("syscall"
49                  : "=a"(retcode)
50                  : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3)
51                  : SYSCALL_CLOBBER_LIST);
52  return retcode;
53}
54
55__attribute__((always_inline)) inline long
56syscall(long __number, long __arg1, long __arg2, long __arg3, long __arg4) {
57  long retcode;
58  register long r10 __asm__("r10") = __arg4;
59  LIBC_INLINE_ASM("syscall"
60                  : "=a"(retcode)
61                  : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3),
62                    "r"(r10)
63                  : SYSCALL_CLOBBER_LIST);
64  return retcode;
65}
66
67__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
68                                                   long __arg2, long __arg3,
69                                                   long __arg4, long __arg5) {
70  long retcode;
71  register long r10 __asm__("r10") = __arg4;
72  register long r8 __asm__("r8") = __arg5;
73  LIBC_INLINE_ASM("syscall"
74                  : "=a"(retcode)
75                  : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3),
76                    "r"(r10), "r"(r8)
77                  : SYSCALL_CLOBBER_LIST);
78  return retcode;
79}
80
81__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
82                                                   long __arg2, long __arg3,
83                                                   long __arg4, long __arg5,
84                                                   long __arg6) {
85  long retcode;
86  register long r10 __asm__("r10") = __arg4;
87  register long r8 __asm__("r8") = __arg5;
88  register long r9 __asm__("r9") = __arg6;
89  LIBC_INLINE_ASM("syscall"
90                  : "=a"(retcode)
91                  : "a"(__number), "D"(__arg1), "S"(__arg2), "d"(__arg3),
92                    "r"(r10), "r"(r8), "r"(r9)
93                  : SYSCALL_CLOBBER_LIST);
94  return retcode;
95}
96
97template <typename... Ts>
98__attribute__((always_inline)) inline long syscall(long __number, Ts... ts) {
99  static_assert(sizeof...(Ts) <= 6, "Too many arguments for syscall");
100  return syscall(__number, (long)ts...);
101}
102
103
104#undef SYSCALL_CLOBBER_LIST
105
106} // namespace __llvm_libc
107