1 /* Assembly macros for RISC-V. 2 Copyright (C) 2011-2018 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_RISCV_SYSDEP_H 20 #define _LINUX_RISCV_SYSDEP_H 1 21 22 #include <sysdeps/unix/sysv/linux/generic/sysdep.h> 23 #include <tls.h> 24 25 #undef SYS_ify 26 #define SYS_ify(syscall_name) __NR_##syscall_name 27 28 #if __WORDSIZE == 32 29 30 /* Workarounds for generic code needing to handle 64-bit time_t. */ 31 32 /* Fix sysdeps/unix/sysv/linux/clock_getcpuclockid.c. */ 33 #define __NR_clock_getres __NR_clock_getres_time64 34 /* Fix sysdeps/nptl/lowlevellock-futex.h. */ 35 #define __NR_futex __NR_futex_time64 36 /* Fix sysdeps/unix/sysv/linux/pause.c. */ 37 #define __NR_ppoll __NR_ppoll_time64 38 /* Fix sysdeps/unix/sysv/linux/select.c. */ 39 #define __NR_pselect6 __NR_pselect6_time64 40 /* Fix sysdeps/unix/sysv/linux/recvmmsg.c. */ 41 #define __NR_recvmmsg __NR_recvmmsg_time64 42 /* Fix sysdeps/unix/sysv/linux/sigtimedwait.c. */ 43 #define __NR_rt_sigtimedwait __NR_rt_sigtimedwait_time64 44 /* Fix sysdeps/unix/sysv/linux/semtimedop.c. */ 45 #define __NR_semtimedop __NR_semtimedop_time64 46 /* Hack sysdeps/unix/sysv/linux/generic/utimes.c. */ 47 #define __NR_utimensat __NR_utimensat_time64 48 49 #endif /* __WORDSIZE == 32 */ 50 51 #ifdef __ASSEMBLER__ 52 53 # include <sys/asm.h> 54 55 # define ENTRY(name) LEAF(name) 56 57 # define L(label) .L ## label 58 59 /* Performs a system call, handling errors by setting errno. Linux indicates 60 errors by setting a0 to a value between -1 and -4095. */ 61 # undef PSEUDO 62 # define PSEUDO(name, syscall_name, args) \ 63 .text; \ 64 .align 2; \ 65 ENTRY (name); \ 66 li a7, SYS_ify (syscall_name); \ 67 scall; \ 68 li a7, -4096; \ 69 bgtu a0, a7, .Lsyscall_error ## name; 70 71 # undef PSEUDO_END 72 # define PSEUDO_END(sym) \ 73 SYSCALL_ERROR_HANDLER (sym) \ 74 ret; \ 75 END (sym) 76 77 # if !IS_IN (libc) 78 # if RTLD_PRIVATE_ERRNO 79 # define SYSCALL_ERROR_HANDLER(name) \ 80 .Lsyscall_error ## name: \ 81 li t1, -4096; \ 82 neg a0, a0; \ 83 sw a0, rtld_errno, t1; \ 84 li a0, -1; 85 # elif defined (__PIC__) 86 # define SYSCALL_ERROR_HANDLER(name) \ 87 .Lsyscall_error ## name: \ 88 la.tls.ie t1, errno; \ 89 add t1, t1, tp; \ 90 neg a0, a0; \ 91 sw a0, 0(t1); \ 92 li a0, -1; 93 # else 94 # define SYSCALL_ERROR_HANDLER(name) \ 95 .Lsyscall_error ## name: \ 96 lui t1, %tprel_hi(errno); \ 97 add t1, t1, tp, %tprel_add(errno); \ 98 neg a0, a0; \ 99 sw a0, %tprel_lo(errno)(t1); \ 100 li a0, -1; 101 # endif 102 # else 103 # define SYSCALL_ERROR_HANDLER(name) \ 104 .Lsyscall_error ## name: \ 105 j __syscall_error; 106 # endif 107 108 /* Performs a system call, not setting errno. */ 109 # undef PSEUDO_NEORRNO 110 # define PSEUDO_NOERRNO(name, syscall_name, args) \ 111 .align 2; \ 112 ENTRY (name); \ 113 li a7, SYS_ify (syscall_name); \ 114 scall; 115 116 # undef PSEUDO_END_NOERRNO 117 # define PSEUDO_END_NOERRNO(name) \ 118 END (name) 119 120 # undef ret_NOERRNO 121 # define ret_NOERRNO ret 122 123 /* Perfroms a system call, returning the error code. */ 124 # undef PSEUDO_ERRVAL 125 # define PSEUDO_ERRVAL(name, syscall_name, args) \ 126 PSEUDO_NOERRNO (name, syscall_name, args) \ 127 neg a0, a0; 128 129 # undef PSEUDO_END_ERRVAL 130 # define PSEUDO_END_ERRVAL(name) \ 131 END (name) 132 133 # undef ret_ERRVAL 134 # define ret_ERRVAL ret 135 136 #else /* !__ASSEMBLER__ */ 137 138 # if __WORDSIZE == 64 139 # define VDSO_NAME "LINUX_4.15" 140 # define VDSO_HASH 182943605 141 142 /* List of system calls which are supported as vsyscalls only 143 for RV64. */ 144 # define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres" 145 # define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime" 146 # define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday" 147 # else 148 # define VDSO_NAME "LINUX_5.4" 149 # define VDSO_HASH 61765876 150 151 /* RV32 does not support the gettime VDSO syscalls. */ 152 # endif 153 154 /* List of system calls which are supported as vsyscalls (for RV32 and 155 RV64). */ 156 # define HAVE_GETCPU_VSYSCALL "__vdso_getcpu" 157 158 # undef HAVE_INTERNAL_BRK_ADDR_SYMBOL 159 # define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 160 161 # define INTERNAL_SYSCALL(name, nr, args...) \ 162 internal_syscall##nr (SYS_ify (name), args) 163 164 # define INTERNAL_SYSCALL_NCS(number, nr, args...) \ 165 internal_syscall##nr (number, args) 166 167 # define internal_syscall0(number, dummy...) \ 168 ({ \ 169 long int _sys_result; \ 170 \ 171 { \ 172 register long int __a7 asm ("a7") = number; \ 173 register long int __a0 asm ("a0"); \ 174 __asm__ volatile ( \ 175 "scall\n\t" \ 176 : "=r" (__a0) \ 177 : "r" (__a7) \ 178 : __SYSCALL_CLOBBERS); \ 179 _sys_result = __a0; \ 180 } \ 181 _sys_result; \ 182 }) 183 184 # define internal_syscall1(number, arg0) \ 185 ({ \ 186 long int _sys_result; \ 187 long int _arg0 = (long int) (arg0); \ 188 \ 189 { \ 190 register long int __a7 asm ("a7") = number; \ 191 register long int __a0 asm ("a0") = _arg0; \ 192 __asm__ volatile ( \ 193 "scall\n\t" \ 194 : "+r" (__a0) \ 195 : "r" (__a7) \ 196 : __SYSCALL_CLOBBERS); \ 197 _sys_result = __a0; \ 198 } \ 199 _sys_result; \ 200 }) 201 202 # define internal_syscall2(number, arg0, arg1) \ 203 ({ \ 204 long int _sys_result; \ 205 long int _arg0 = (long int) (arg0); \ 206 long int _arg1 = (long int) (arg1); \ 207 \ 208 { \ 209 register long int __a7 asm ("a7") = number; \ 210 register long int __a0 asm ("a0") = _arg0; \ 211 register long int __a1 asm ("a1") = _arg1; \ 212 __asm__ volatile ( \ 213 "scall\n\t" \ 214 : "+r" (__a0) \ 215 : "r" (__a7), "r" (__a1) \ 216 : __SYSCALL_CLOBBERS); \ 217 _sys_result = __a0; \ 218 } \ 219 _sys_result; \ 220 }) 221 222 # define internal_syscall3(number, arg0, arg1, arg2) \ 223 ({ \ 224 long int _sys_result; \ 225 long int _arg0 = (long int) (arg0); \ 226 long int _arg1 = (long int) (arg1); \ 227 long int _arg2 = (long int) (arg2); \ 228 \ 229 { \ 230 register long int __a7 asm ("a7") = number; \ 231 register long int __a0 asm ("a0") = _arg0; \ 232 register long int __a1 asm ("a1") = _arg1; \ 233 register long int __a2 asm ("a2") = _arg2; \ 234 __asm__ volatile ( \ 235 "scall\n\t" \ 236 : "+r" (__a0) \ 237 : "r" (__a7), "r" (__a1), "r" (__a2) \ 238 : __SYSCALL_CLOBBERS); \ 239 _sys_result = __a0; \ 240 } \ 241 _sys_result; \ 242 }) 243 244 # define internal_syscall4(number, arg0, arg1, arg2, arg3) \ 245 ({ \ 246 long int _sys_result; \ 247 long int _arg0 = (long int) (arg0); \ 248 long int _arg1 = (long int) (arg1); \ 249 long int _arg2 = (long int) (arg2); \ 250 long int _arg3 = (long int) (arg3); \ 251 \ 252 { \ 253 register long int __a7 asm ("a7") = number; \ 254 register long int __a0 asm ("a0") = _arg0; \ 255 register long int __a1 asm ("a1") = _arg1; \ 256 register long int __a2 asm ("a2") = _arg2; \ 257 register long int __a3 asm ("a3") = _arg3; \ 258 __asm__ volatile ( \ 259 "scall\n\t" \ 260 : "+r" (__a0) \ 261 : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3) \ 262 : __SYSCALL_CLOBBERS); \ 263 _sys_result = __a0; \ 264 } \ 265 _sys_result; \ 266 }) 267 268 # define internal_syscall5(number, arg0, arg1, arg2, arg3, arg4) \ 269 ({ \ 270 long int _sys_result; \ 271 long int _arg0 = (long int) (arg0); \ 272 long int _arg1 = (long int) (arg1); \ 273 long int _arg2 = (long int) (arg2); \ 274 long int _arg3 = (long int) (arg3); \ 275 long int _arg4 = (long int) (arg4); \ 276 \ 277 { \ 278 register long int __a7 asm ("a7") = number; \ 279 register long int __a0 asm ("a0") = _arg0; \ 280 register long int __a1 asm ("a1") = _arg1; \ 281 register long int __a2 asm ("a2") = _arg2; \ 282 register long int __a3 asm ("a3") = _arg3; \ 283 register long int __a4 asm ("a4") = _arg4; \ 284 __asm__ volatile ( \ 285 "scall\n\t" \ 286 : "+r" (__a0) \ 287 : "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r" (__a4) \ 288 : __SYSCALL_CLOBBERS); \ 289 _sys_result = __a0; \ 290 } \ 291 _sys_result; \ 292 }) 293 294 # define internal_syscall6(number, arg0, arg1, arg2, arg3, arg4, arg5) \ 295 ({ \ 296 long int _sys_result; \ 297 long int _arg0 = (long int) (arg0); \ 298 long int _arg1 = (long int) (arg1); \ 299 long int _arg2 = (long int) (arg2); \ 300 long int _arg3 = (long int) (arg3); \ 301 long int _arg4 = (long int) (arg4); \ 302 long int _arg5 = (long int) (arg5); \ 303 \ 304 { \ 305 register long int __a7 asm ("a7") = number; \ 306 register long int __a0 asm ("a0") = _arg0; \ 307 register long int __a1 asm ("a1") = _arg1; \ 308 register long int __a2 asm ("a2") = _arg2; \ 309 register long int __a3 asm ("a3") = _arg3; \ 310 register long int __a4 asm ("a4") = _arg4; \ 311 register long int __a5 asm ("a5") = _arg5; \ 312 __asm__ volatile ( \ 313 "scall\n\t" \ 314 : "+r" (__a0) \ 315 : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3), \ 316 "r" (__a4), "r" (__a5) \ 317 : __SYSCALL_CLOBBERS); \ 318 _sys_result = __a0; \ 319 } \ 320 _sys_result; \ 321 }) 322 323 # define internal_syscall7(number, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ 324 ({ \ 325 long int _sys_result; \ 326 long int _arg0 = (long int) (arg0); \ 327 long int _arg1 = (long int) (arg1); \ 328 long int _arg2 = (long int) (arg2); \ 329 long int _arg3 = (long int) (arg3); \ 330 long int _arg4 = (long int) (arg4); \ 331 long int _arg5 = (long int) (arg5); \ 332 long int _arg6 = (long int) (arg6); \ 333 \ 334 { \ 335 register long int __a7 asm ("a7") = number; \ 336 register long int __a0 asm ("a0") = _arg0; \ 337 register long int __a1 asm ("a1") = _arg1; \ 338 register long int __a2 asm ("a2") = _arg2; \ 339 register long int __a3 asm ("a3") = _arg3; \ 340 register long int __a4 asm ("a4") = _arg4; \ 341 register long int __a5 asm ("a5") = _arg5; \ 342 register long int __a6 asm ("a6") = _arg6; \ 343 __asm__ volatile ( \ 344 "scall\n\t" \ 345 : "+r" (__a0) \ 346 : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3), \ 347 "r" (__a4), "r" (__a5), "r" (__a6) \ 348 : __SYSCALL_CLOBBERS); \ 349 _sys_result = __a0; \ 350 } \ 351 _sys_result; \ 352 }) 353 354 # define __SYSCALL_CLOBBERS "memory" 355 356 extern long int __syscall_error (long int neg_errno); 357 358 #endif /* ! __ASSEMBLER__ */ 359 360 /* Pointer mangling is not supported. */ 361 #define PTR_MANGLE(var) (void) (var) 362 #define PTR_DEMANGLE(var) (void) (var) 363 364 #endif /* linux/riscv/sysdep.h */ 365