1 /* Copyright (C) 2011-2018 Free Software Foundation, Inc. 2 3 The GNU C Library is free software; you can redistribute it and/or 4 modify it under the terms of the GNU Lesser General Public 5 License as published by the Free Software Foundation; either 6 version 2.1 of the License, or (at your option) any later version. 7 8 The GNU C Library is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public 14 License along with the GNU C Library. If not, see 15 <http://www.gnu.org/licenses/>. */ 16 17 #ifndef _BITS_SYSCALLS_H 18 #define _BITS_SYSCALLS_H 19 #ifndef _SYSCALL_H 20 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead." 21 #endif 22 23 /* Define a macro which expands inline into the wrapper code for a system 24 call. */ 25 # undef INLINE_SYSCALL 26 # define INLINE_SYSCALL(name, nr, args...) \ 27 ({ \ 28 INTERNAL_SYSCALL_DECL (_sc_err); \ 29 unsigned long _sc_val = INTERNAL_SYSCALL (name, _sc_err, nr, args); \ 30 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sc_val, _sc_err), 0)) \ 31 { \ 32 __set_errno (INTERNAL_SYSCALL_ERRNO (_sc_val, _sc_err)); \ 33 _sc_val = -1; \ 34 } \ 35 (long) _sc_val; \ 36 }) 37 38 #undef INTERNAL_SYSCALL 39 #define INTERNAL_SYSCALL(name, err, nr, args...) \ 40 internal_syscall##nr (SYS_ify (name), err, args) 41 42 #undef INTERNAL_SYSCALL_NCS 43 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ 44 internal_syscall##nr (number, err, args) 45 46 #undef INTERNAL_SYSCALL_DECL 47 #define INTERNAL_SYSCALL_DECL(err) int err 48 49 #undef INTERNAL_SYSCALL_ERROR_P 50 #define INTERNAL_SYSCALL_ERROR_P(val, err) ({ (void) (val); (err) != 0; }) 51 52 #undef INTERNAL_SYSCALL_ERRNO 53 #define INTERNAL_SYSCALL_ERRNO(val, err) ({ (void) (val); (err); }) 54 55 #define internal_syscall0(num, err, dummy...) \ 56 ({ \ 57 long _sys_result, __SYSCALL_CLOBBER_DECLS; \ 58 __asm__ __volatile__ ( \ 59 "swint1" \ 60 : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ 61 : "R10" (num) \ 62 : __SYSCALL_CLOBBERS); \ 63 _sys_result; \ 64 }) 65 66 #define internal_syscall1(num, err, arg0) \ 67 ({ \ 68 long _sys_result, __SYSCALL_CLOBBER_DECLS; \ 69 __asm__ __volatile__ ( \ 70 "swint1" \ 71 : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ 72 : "R10" (num), "R00" (arg0) \ 73 : __SYSCALL_CLOBBERS); \ 74 _sys_result; \ 75 }) 76 77 #define internal_syscall2(num, err, arg0, arg1) \ 78 ({ \ 79 long _sys_result, __SYSCALL_CLOBBER_DECLS; \ 80 __asm__ __volatile__ ( \ 81 "swint1" \ 82 : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ 83 : "R10" (num), "R00" (arg0), "R01" (arg1) \ 84 : __SYSCALL_CLOBBERS); \ 85 _sys_result; \ 86 }) 87 88 #define internal_syscall3(num, err, arg0, arg1, arg2) \ 89 ({ \ 90 long _sys_result, __SYSCALL_CLOBBER_DECLS; \ 91 __asm__ __volatile__ ( \ 92 "swint1" \ 93 : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ 94 : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2) \ 95 : __SYSCALL_CLOBBERS); \ 96 _sys_result; \ 97 }) 98 99 #define internal_syscall4(num, err, arg0, arg1, arg2, arg3) \ 100 ({ \ 101 long _sys_result, __SYSCALL_CLOBBER_DECLS; \ 102 __asm__ __volatile__ ( \ 103 "swint1" \ 104 : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ 105 : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \ 106 "R03" (arg3) \ 107 : __SYSCALL_CLOBBERS); \ 108 _sys_result; \ 109 }) 110 111 #define internal_syscall5(num, err, arg0, arg1, arg2, arg3, arg4) \ 112 ({ \ 113 long _sys_result, __SYSCALL_CLOBBER_DECLS; \ 114 __asm__ __volatile__ ( \ 115 "swint1" \ 116 : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ 117 : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \ 118 "R03" (arg3), "R04" (arg4) \ 119 : __SYSCALL_CLOBBERS); \ 120 _sys_result; \ 121 }) 122 123 #define internal_syscall6(num, err, arg0, arg1, arg2, arg3, arg4, arg5) \ 124 ({ \ 125 long _sys_result, __SYSCALL_CLOBBER_DECLS; \ 126 __asm__ __volatile__ ( \ 127 "swint1" \ 128 : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ 129 : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \ 130 "R03" (arg3), "R04" (arg4), "R05" (arg5) \ 131 : __SYSCALL_CLOBBERS); \ 132 _sys_result; \ 133 }) 134 135 #undef __SYSCALL_CLOBBERS 136 #define __SYSCALL_CLOBBERS \ 137 "r6", "r7", \ 138 "r8", "r9", "r11", "r12", "r13", "r14", "r15", \ 139 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ 140 "r24", "r25", "r26", "r27", "r28", "r29", "memory" 141 142 /* gcc doesn't seem to allow an input operand to be clobbered, so we 143 fake it with dummy outputs. */ 144 #define __SYSCALL_CLOBBER_DECLS \ 145 _clobber_r2, _clobber_r3, _clobber_r4, _clobber_r5, _clobber_r10 146 147 #define __SYSCALL_CLOBBER_OUTPUTS \ 148 "=R02" (_clobber_r2), "=R03" (_clobber_r3), "=R04" (_clobber_r4), \ 149 "=R05" (_clobber_r5), "=R10" (_clobber_r10) 150 151 #endif 152