1326943Sdim//===-- sanitizer_syscall_linux_arm.inc -------------------------*- C++ -*-===// 2326943Sdim// 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 6326943Sdim// 7326943Sdim//===----------------------------------------------------------------------===// 8326943Sdim// 9326943Sdim// Implementations of internal_syscall and internal_iserror for Linux/arm. 10326943Sdim// 11326943Sdim//===----------------------------------------------------------------------===// 12326943Sdim 13326943Sdim#define SYSCALL(name) __NR_ ## name 14326943Sdim 15326943Sdimstatic uptr __internal_syscall(u32 nr) { 16326943Sdim register u32 r8 asm("r7") = nr; 17326943Sdim register u32 r0 asm("r0"); 18326943Sdim asm volatile("swi #0" 19326943Sdim : "=r"(r0) 20326943Sdim : "r"(r8) 21326943Sdim : "memory", "cc"); 22326943Sdim return r0; 23326943Sdim} 24326943Sdim#define __internal_syscall0(n) \ 25326943Sdim (__internal_syscall)(n) 26326943Sdim 27326943Sdimstatic uptr __internal_syscall(u32 nr, u32 arg1) { 28326943Sdim register u32 r8 asm("r7") = nr; 29326943Sdim register u32 r0 asm("r0") = arg1; 30326943Sdim asm volatile("swi #0" 31326943Sdim : "=r"(r0) 32326943Sdim : "r"(r8), "0"(r0) 33326943Sdim : "memory", "cc"); 34326943Sdim return r0; 35326943Sdim} 36326943Sdim#define __internal_syscall1(n, a1) \ 37326943Sdim (__internal_syscall)(n, (u32)(a1)) 38326943Sdim 39326943Sdimstatic uptr __internal_syscall(u32 nr, u32 arg1, long arg2) { 40326943Sdim register u32 r8 asm("r7") = nr; 41326943Sdim register u32 r0 asm("r0") = arg1; 42326943Sdim register u32 r1 asm("r1") = arg2; 43326943Sdim asm volatile("swi #0" 44326943Sdim : "=r"(r0) 45326943Sdim : "r"(r8), "0"(r0), "r"(r1) 46326943Sdim : "memory", "cc"); 47326943Sdim return r0; 48326943Sdim} 49326943Sdim#define __internal_syscall2(n, a1, a2) \ 50326943Sdim (__internal_syscall)(n, (u32)(a1), (long)(a2)) 51326943Sdim 52326943Sdimstatic uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3) { 53326943Sdim register u32 r8 asm("r7") = nr; 54326943Sdim register u32 r0 asm("r0") = arg1; 55326943Sdim register u32 r1 asm("r1") = arg2; 56326943Sdim register u32 r2 asm("r2") = arg3; 57326943Sdim asm volatile("swi #0" 58326943Sdim : "=r"(r0) 59326943Sdim : "r"(r8), "0"(r0), "r"(r1), "r"(r2) 60326943Sdim : "memory", "cc"); 61326943Sdim return r0; 62326943Sdim} 63326943Sdim#define __internal_syscall3(n, a1, a2, a3) \ 64326943Sdim (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3)) 65326943Sdim 66326943Sdimstatic uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3, 67326943Sdim u32 arg4) { 68326943Sdim register u32 r8 asm("r7") = nr; 69326943Sdim register u32 r0 asm("r0") = arg1; 70326943Sdim register u32 r1 asm("r1") = arg2; 71326943Sdim register u32 r2 asm("r2") = arg3; 72326943Sdim register u32 r3 asm("r3") = arg4; 73326943Sdim asm volatile("swi #0" 74326943Sdim : "=r"(r0) 75326943Sdim : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3) 76326943Sdim : "memory", "cc"); 77326943Sdim return r0; 78326943Sdim} 79326943Sdim#define __internal_syscall4(n, a1, a2, a3, a4) \ 80326943Sdim (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4)) 81326943Sdim 82326943Sdimstatic uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3, 83326943Sdim u32 arg4, long arg5) { 84326943Sdim register u32 r8 asm("r7") = nr; 85326943Sdim register u32 r0 asm("r0") = arg1; 86326943Sdim register u32 r1 asm("r1") = arg2; 87326943Sdim register u32 r2 asm("r2") = arg3; 88326943Sdim register u32 r3 asm("r3") = arg4; 89326943Sdim register u32 r4 asm("r4") = arg5; 90326943Sdim asm volatile("swi #0" 91326943Sdim : "=r"(r0) 92326943Sdim : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4) 93326943Sdim : "memory", "cc"); 94326943Sdim return r0; 95326943Sdim} 96326943Sdim#define __internal_syscall5(n, a1, a2, a3, a4, a5) \ 97326943Sdim (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \ 98326943Sdim (u32)(a5)) 99326943Sdim 100326943Sdimstatic uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3, 101326943Sdim u32 arg4, long arg5, long arg6) { 102326943Sdim register u32 r8 asm("r7") = nr; 103326943Sdim register u32 r0 asm("r0") = arg1; 104326943Sdim register u32 r1 asm("r1") = arg2; 105326943Sdim register u32 r2 asm("r2") = arg3; 106326943Sdim register u32 r3 asm("r3") = arg4; 107326943Sdim register u32 r4 asm("r4") = arg5; 108326943Sdim register u32 r5 asm("r5") = arg6; 109326943Sdim asm volatile("swi #0" 110326943Sdim : "=r"(r0) 111326943Sdim : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5) 112326943Sdim : "memory", "cc"); 113326943Sdim return r0; 114326943Sdim} 115326943Sdim#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \ 116326943Sdim (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \ 117326943Sdim (u32)(a5), (long)(a6)) 118326943Sdim 119326943Sdim#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n 120326943Sdim#define __SYSCALL_NARGS(...) \ 121326943Sdim __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, ) 122326943Sdim#define __SYSCALL_CONCAT_X(a, b) a##b 123326943Sdim#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b) 124326943Sdim#define __SYSCALL_DISP(b, ...) \ 125326943Sdim __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) 126326943Sdim 127326943Sdim#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__) 128326943Sdim 129326943Sdim// Helper function used to avoid cobbler errno. 130326943Sdimbool internal_iserror(uptr retval, int *rverrno) { 131326943Sdim if (retval >= (uptr)-4095) { 132326943Sdim if (rverrno) 133326943Sdim *rverrno = -retval; 134326943Sdim return true; 135326943Sdim } 136326943Sdim return false; 137326943Sdim} 138