1//===-- sanitizer_syscall_linux_hexagon.inc ---------------------*- 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// Implementations of internal_syscall and internal_iserror for Linux/hexagon. 10// 11//===----------------------------------------------------------------------===// 12 13#define SYSCALL(name) __NR_##name 14 15#define __internal_syscall_LL_E(x) \ 16 ((union { \ 17 long long ll; \ 18 long l[2]; \ 19 }){.ll = x}) \ 20 .l[0], \ 21 ((union { \ 22 long long ll; \ 23 long l[2]; \ 24 }){.ll = x}) \ 25 .l[1] 26#define __internal_syscall_LL_O(x) 0, __SYSCALL_LL_E((x)) 27 28#define __asm_syscall(...) \ 29 do { \ 30 __asm__ __volatile__("trap0(#1)" : "=r"(r0) : __VA_ARGS__ : "memory"); \ 31 return r0; \ 32 } while (0) 33 34#define __internal_syscall0(n) (__internal_syscall)(n) 35 36static uptr __internal_syscall(long n) { 37 register u32 r6 __asm__("r6") = n; 38 register u32 r0 __asm__("r0"); 39 __asm_syscall("r"(r6)); 40} 41 42#define __internal_syscall1(n, a1) (__internal_syscall)(n, (long)(a1)) 43 44static uptr __internal_syscall(long n, long a) { 45 register u32 r6 __asm__("r6") = n; 46 register u32 r0 __asm__("r0") = a; 47 __asm_syscall("r"(r6), "0"(r0)); 48} 49 50#define __internal_syscall2(n, a1, a2) \ 51 (__internal_syscall)(n, (long)(a1), (long)(a2)) 52 53static uptr __internal_syscall(long n, long a, long b) { 54 register u32 r6 __asm__("r6") = n; 55 register u32 r0 __asm__("r0") = a; 56 register u32 r1 __asm__("r1") = b; 57 __asm_syscall("r"(r6), "0"(r0), "r"(r1)); 58} 59 60#define __internal_syscall3(n, a1, a2, a3) \ 61 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3)) 62 63static uptr __internal_syscall(long n, long a, long b, long c) { 64 register u32 r6 __asm__("r6") = n; 65 register u32 r0 __asm__("r0") = a; 66 register u32 r1 __asm__("r1") = b; 67 register u32 r2 __asm__("r2") = c; 68 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2)); 69} 70 71#define __internal_syscall4(n, a1, a2, a3, a4) \ 72 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4)) 73 74static uptr __internal_syscall(long n, long a, long b, long c, long d) { 75 register u32 r6 __asm__("r6") = n; 76 register u32 r0 __asm__("r0") = a; 77 register u32 r1 __asm__("r1") = b; 78 register u32 r2 __asm__("r2") = c; 79 register u32 r3 __asm__("r3") = d; 80 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3)); 81} 82 83#define __internal_syscall5(n, a1, a2, a3, a4, a5) \ 84 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \ 85 (long)(a5)) 86 87static uptr __internal_syscall(long n, long a, long b, long c, long d, long e) { 88 register u32 r6 __asm__("r6") = n; 89 register u32 r0 __asm__("r0") = a; 90 register u32 r1 __asm__("r1") = b; 91 register u32 r2 __asm__("r2") = c; 92 register u32 r3 __asm__("r3") = d; 93 register u32 r4 __asm__("r4") = e; 94 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)); 95} 96 97#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \ 98 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \ 99 (long)(a5), (long)(a6)) 100 101static uptr __internal_syscall(long n, long a, long b, long c, long d, long e, 102 long f) { 103 register u32 r6 __asm__("r6") = n; 104 register u32 r0 __asm__("r0") = a; 105 register u32 r1 __asm__("r1") = b; 106 register u32 r2 __asm__("r2") = c; 107 register u32 r3 __asm__("r3") = d; 108 register u32 r4 __asm__("r4") = e; 109 register u32 r5 __asm__("r5") = f; 110 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); 111} 112 113#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n 114#define __SYSCALL_NARGS(...) \ 115 __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, ) 116#define __SYSCALL_CONCAT_X(a, b) a##b 117#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b) 118#define __SYSCALL_DISP(b, ...) \ 119 __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) 120 121#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__) 122 123// Helper function used to avoid clobbering of errno. 124bool internal_iserror(uptr retval, int *rverrno) { 125 if (retval >= (uptr)-4095) { 126 if (rverrno) 127 *rverrno = -retval; 128 return true; 129 } 130 return false; 131} 132