1251034Sed//===-- sanitizer_syscall_linux_x86_64.inc ----------------------*- C++ -*-===//
2251034Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6251034Sed//
7251034Sed//===----------------------------------------------------------------------===//
8251034Sed//
9251034Sed// Implementations of internal_syscall and internal_iserror for Linux/x86_64.
10251034Sed//
11251034Sed//===----------------------------------------------------------------------===//
12251034Sed
13276789Sdim#define SYSCALL(name) __NR_ ## name
14276789Sdim
15251034Sedstatic uptr internal_syscall(u64 nr) {
16251034Sed  u64 retval;
17274201Sdim  asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11",
18274201Sdim               "memory", "cc");
19251034Sed  return retval;
20251034Sed}
21251034Sed
22251034Sedtemplate <typename T1>
23251034Sedstatic uptr internal_syscall(u64 nr, T1 arg1) {
24251034Sed  u64 retval;
25251034Sed  asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) :
26274201Sdim               "rcx", "r11", "memory", "cc");
27251034Sed  return retval;
28251034Sed}
29251034Sed
30251034Sedtemplate <typename T1, typename T2>
31251034Sedstatic uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) {
32251034Sed  u64 retval;
33251034Sed  asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
34274201Sdim               "S"((u64)arg2) : "rcx", "r11", "memory", "cc");
35251034Sed  return retval;
36251034Sed}
37251034Sed
38251034Sedtemplate <typename T1, typename T2, typename T3>
39251034Sedstatic uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) {
40251034Sed  u64 retval;
41251034Sed  asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
42274201Sdim               "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11", "memory", "cc");
43251034Sed  return retval;
44251034Sed}
45251034Sed
46251034Sedtemplate <typename T1, typename T2, typename T3, typename T4>
47251034Sedstatic uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
48251034Sed  u64 retval;
49251034Sed  asm volatile("mov %5, %%r10;"
50251034Sed               "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
51251034Sed               "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) :
52274201Sdim               "rcx", "r11", "r10", "memory", "cc");
53251034Sed  return retval;
54251034Sed}
55251034Sed
56251034Sedtemplate <typename T1, typename T2, typename T3, typename T4, typename T5>
57251034Sedstatic uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
58251034Sed                             T5 arg5) {
59251034Sed  u64 retval;
60251034Sed  asm volatile("mov %5, %%r10;"
61251034Sed               "mov %6, %%r8;"
62251034Sed               "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
63251034Sed               "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) :
64274201Sdim               "rcx", "r11", "r10", "r8", "memory", "cc");
65251034Sed  return retval;
66251034Sed}
67251034Sed
68251034Sedtemplate <typename T1, typename T2, typename T3, typename T4, typename T5,
69251034Sed          typename T6>
70251034Sedstatic uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
71251034Sed                             T5 arg5, T6 arg6) {
72251034Sed  u64 retval;
73251034Sed  asm volatile("mov %5, %%r10;"
74251034Sed               "mov %6, %%r8;"
75251034Sed               "mov %7, %%r9;"
76251034Sed               "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
77251034Sed               "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5),
78274201Sdim               "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9",
79274201Sdim               "memory", "cc");
80251034Sed  return retval;
81251034Sed}
82251034Sed
83251034Sedbool internal_iserror(uptr retval, int *rverrno) {
84251034Sed  if (retval >= (uptr)-4095) {
85251034Sed    if (rverrno)
86251034Sed      *rverrno = -retval;
87251034Sed    return true;
88251034Sed  }
89251034Sed  return false;
90251034Sed}
91