1 /* Assembler macros for Nios II. 2 Copyright (C) 2000-2021 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 #ifndef _LINUX_NIOS2_SYSDEP_H 20 #define _LINUX_NIOS2_SYSDEP_H 1 21 22 #include <sysdeps/unix/sysdep.h> 23 #include <sysdeps/nios2/sysdep.h> 24 #include <sysdeps/unix/sysv/linux/generic/sysdep.h> 25 26 /* For RTLD_PRIVATE_ERRNO. */ 27 #include <dl-sysdep.h> 28 29 #include <tls.h> 30 31 /* For Linux we can use the system call table in the header file 32 /usr/include/asm/unistd.h 33 of the kernel. But these symbols do not follow the SYS_* syntax 34 so we have to redefine the `SYS_ify' macro here. */ 35 #undef SYS_ify 36 #define SYS_ify(syscall_name) __NR_##syscall_name 37 38 #ifdef __ASSEMBLER__ 39 40 #undef SYSCALL_ERROR_LABEL 41 #define SYSCALL_ERROR_LABEL __local_syscall_error 42 43 #undef PSEUDO 44 #define PSEUDO(name, syscall_name, args) \ 45 ENTRY (name) \ 46 DO_CALL (syscall_name, args) \ 47 bne r7, zero, SYSCALL_ERROR_LABEL; \ 48 49 #undef PSEUDO_END 50 #define PSEUDO_END(name) \ 51 SYSCALL_ERROR_HANDLER \ 52 END (name) 53 54 #undef PSEUDO_NOERRNO 55 #define PSEUDO_NOERRNO(name, syscall_name, args) \ 56 ENTRY (name) \ 57 DO_CALL (syscall_name, args) 58 59 #undef PSEUDO_END_NOERRNO 60 #define PSEUDO_END_NOERRNO(name) \ 61 END (name) 62 63 #undef ret_NOERRNO 64 #define ret_NOERRNO ret 65 66 #undef DO_CALL 67 #define DO_CALL(syscall_name, args) \ 68 DOARGS_##args \ 69 movi r2, SYS_ify(syscall_name); \ 70 trap; 71 72 #if defined(__PIC__) || defined(PIC) 73 74 # if RTLD_PRIVATE_ERRNO 75 76 # define SYSCALL_ERROR_HANDLER \ 77 SYSCALL_ERROR_LABEL: \ 78 nextpc r3; \ 79 1: \ 80 movhi r8, %hiadj(rtld_errno - 1b); \ 81 addi r8, r8, %lo(rtld_errno - 1b); \ 82 add r3, r3, r8; \ 83 stw r2, 0(r3); \ 84 movi r2, -1; \ 85 ret; 86 87 # else 88 89 # if IS_IN (libc) 90 # define SYSCALL_ERROR_ERRNO __libc_errno 91 # else 92 # define SYSCALL_ERROR_ERRNO errno 93 # endif 94 # define SYSCALL_ERROR_HANDLER \ 95 SYSCALL_ERROR_LABEL: \ 96 nextpc r3; \ 97 1: \ 98 movhi r8, %hiadj(_gp_got - 1b); \ 99 addi r8, r8, %lo(_gp_got - 1b); \ 100 add r3, r3, r8; \ 101 ldw r3, %tls_ie(SYSCALL_ERROR_ERRNO)(r3); \ 102 add r3, r23, r3; \ 103 stw r2, 0(r3); \ 104 movi r2, -1; \ 105 ret; 106 107 # endif 108 109 #else 110 111 /* We can use a single error handler in the static library. */ 112 #define SYSCALL_ERROR_HANDLER \ 113 SYSCALL_ERROR_LABEL: \ 114 jmpi __syscall_error; 115 116 #endif 117 118 #define DOARGS_0 /* nothing */ 119 #define DOARGS_1 /* nothing */ 120 #define DOARGS_2 /* nothing */ 121 #define DOARGS_3 /* nothing */ 122 #define DOARGS_4 /* nothing */ 123 #define DOARGS_5 ldw r8, 0(sp); 124 #define DOARGS_6 ldw r9, 4(sp); ldw r8, 0(sp); 125 126 /* The function has to return the error code. */ 127 #undef PSEUDO_ERRVAL 128 #define PSEUDO_ERRVAL(name, syscall_name, args) \ 129 ENTRY (name) \ 130 DO_CALL (syscall_name, args) 131 132 #undef PSEUDO_END_ERRVAL 133 #define PSEUDO_END_ERRVAL(name) \ 134 END (name) 135 136 #define ret_ERRVAL ret 137 138 #else /* __ASSEMBLER__ */ 139 140 /* In order to get __set_errno() definition in INLINE_SYSCALL. */ 141 #include <errno.h> 142 143 #undef INTERNAL_SYSCALL_RAW 144 #define INTERNAL_SYSCALL_RAW(name, nr, args...) \ 145 ({ unsigned int _sys_result; \ 146 { \ 147 /* Load argument values in temporary variables 148 to perform side effects like function calls 149 before the call-used registers are set. */ \ 150 LOAD_ARGS_##nr (args) \ 151 LOAD_REGS_##nr \ 152 register int _r2 asm ("r2") = (int)(name); \ 153 register int _err asm ("r7"); \ 154 asm volatile ("trap" \ 155 : "+r" (_r2), "=r" (_err) \ 156 : ASM_ARGS_##nr \ 157 : __SYSCALL_CLOBBERS); \ 158 _sys_result = _err != 0 ? -_r2 : _r2; \ 159 } \ 160 (int) _sys_result; }) 161 162 #undef INTERNAL_SYSCALL 163 #define INTERNAL_SYSCALL(name, nr, args...) \ 164 INTERNAL_SYSCALL_RAW(SYS_ify(name), nr, args) 165 166 #undef INTERNAL_SYSCALL_NCS 167 #define INTERNAL_SYSCALL_NCS(number, nr, args...) \ 168 INTERNAL_SYSCALL_RAW(number, nr, args) 169 170 #define LOAD_ARGS_0() 171 #define LOAD_REGS_0 172 #define ASM_ARGS_0 173 #define LOAD_ARGS_1(a1) \ 174 LOAD_ARGS_0 () \ 175 int __arg1 = (int) (a1); 176 #define LOAD_REGS_1 \ 177 register int _r4 asm ("r4") = __arg1; \ 178 LOAD_REGS_0 179 #define ASM_ARGS_1 "r" (_r4) 180 #define LOAD_ARGS_2(a1, a2) \ 181 LOAD_ARGS_1 (a1) \ 182 int __arg2 = (int) (a2); 183 #define LOAD_REGS_2 \ 184 register int _r5 asm ("r5") = __arg2; \ 185 LOAD_REGS_1 186 #define ASM_ARGS_2 ASM_ARGS_1, "r" (_r5) 187 #define LOAD_ARGS_3(a1, a2, a3) \ 188 LOAD_ARGS_2 (a1, a2) \ 189 int __arg3 = (int) (a3); 190 #define LOAD_REGS_3 \ 191 register int _r6 asm ("r6") = __arg3; \ 192 LOAD_REGS_2 193 #define ASM_ARGS_3 ASM_ARGS_2, "r" (_r6) 194 #define LOAD_ARGS_4(a1, a2, a3, a4) \ 195 LOAD_ARGS_3 (a1, a2, a3) \ 196 int __arg4 = (int) (a4); 197 #define LOAD_REGS_4 \ 198 register int _r7 asm ("r7") = __arg4; \ 199 LOAD_REGS_3 200 #define ASM_ARGS_4 ASM_ARGS_3, "r" (_r7) 201 #define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ 202 LOAD_ARGS_4 (a1, a2, a3, a4) \ 203 int __arg5 = (int) (a5); 204 #define LOAD_REGS_5 \ 205 register int _r8 asm ("r8") = __arg5; \ 206 LOAD_REGS_4 207 #define ASM_ARGS_5 ASM_ARGS_4, "r" (_r8) 208 #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ 209 LOAD_ARGS_5 (a1, a2, a3, a4, a5) \ 210 int __arg6 = (int) (a6); 211 #define LOAD_REGS_6 \ 212 register int _r9 asm ("r9") = __arg6; \ 213 LOAD_REGS_5 214 #define ASM_ARGS_6 ASM_ARGS_5, "r" (_r9) 215 216 #define __SYSCALL_CLOBBERS "memory" 217 218 #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL 219 #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 220 221 #endif /* __ASSEMBLER__ */ 222 223 /* Pointer mangling support. */ 224 #if IS_IN (rtld) 225 /* We cannot use the thread descriptor because in ld.so we use setjmp 226 earlier than the descriptor is initialized. */ 227 #else 228 # ifdef __ASSEMBLER__ 229 # define PTR_MANGLE_GUARD(guard) ldw guard, POINTER_GUARD(r23) 230 # define PTR_MANGLE(dst, src, guard) xor dst, src, guard 231 # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard) 232 # else 233 # define PTR_MANGLE(var) \ 234 (var) = (__typeof (var)) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ()) 235 # define PTR_DEMANGLE(var) PTR_MANGLE (var) 236 # endif 237 #endif 238 239 240 #endif /* linux/nios2/sysdep.h */ 241