1 /* Assembly macros for C-SKY.
2 Copyright (C) 2018-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #ifndef _LINUX_CSKY_SYSDEP_H
20 #define _LINUX_CSKY_SYSDEP_H 1
22 /* There is some commonality. */
23 #include <sysdeps/unix/sysv/linux/generic/sysdep.h>
24 #include <sysdeps/unix/sysv/linux/sysdep.h>
25 #include <sysdeps/csky/sysdep.h>
27 /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
28 #include <dl-sysdep.h>
32 /* In order to get __set_errno() definition in INLINE_SYSCALL. */
38 #define SYS_ify(syscall_name) (__NR_##syscall_name)
41 /* Linux uses a negative return value to indicate syscall errors,
42 unlike most Unices, which use the condition codes' carry flag.
44 Since version 2.1 the return value of a system call might be
45 negative even if the call succeeded. E.g., the `lseek' system call
46 might return a large offset. Therefore we must not anymore test
47 for < 0, but test for a real error by making sure the value in R0
48 is a real error number. Linus said he will make sure the no syscall
49 returns a value in -1 .. -4095 as a valid result so we can safely
53 # define PSEUDO(name, syscall_name, args) \
56 DO_CALL (syscall_name, args);
61 lrw gb, .Lgetpc@GOTPC; \
73 lrw a2, SYSCALL_ERROR@PLT; \
106 # define PSEUDO_RET \
114 # define ret PSEUDO_RET
117 # define PSEUDO_END(name) \
119 SYSCALL_ERROR_HANDLER; \
122 # undef PSEUDO_NOERRNO
123 # define PSEUDO_NOERRNO(name, syscall_name, args) \
126 DO_CALL (syscall_name, args)
128 # define PSEUDO_RET_NOERRNO rts
131 # define ret_NOERRNO PSEUDO_RET_NOERRNO
133 # undef PSEUDO_END_NOERRNO
134 # define PSEUDO_END_NOERRNO(name) END (name)
136 /* The function has to return the error code. */
137 # undef PSEUDO_ERRVAL
138 # define PSEUDO_ERRVAL(name, syscall_name, args) \
141 DO_CALL (syscall_name, args); \
145 # undef PSEUDO_END_ERRVAL
146 # define PSEUDO_END_ERRVAL(name) END (name)
148 # define ret_ERRVAL rts
151 # define SYSCALL_ERROR __local_syscall_error
152 # if RTLD_PRIVATE_ERRNO
154 # define SYSCALL_ERROR_HANDLER \
155 __local_syscall_error: \
156 lrw a1, rtld_errno@PLT; \
164 # define SYSCALL_ERROR_HANDLER \
165 __local_syscall_error: \
166 lrw a1, rtld_errno; \
171 # endif /* __PIC__ */
172 # else /* !RTLD_PRIVATE_ERRNO */
174 # define SYSCALL_ERROR_HANDLER \
175 __local_syscall_error: \
179 lrw a1, __errno_location@PLT; \
183 ldw a1, (sp, 0); /* load errno*/ \
192 # define SYSCALL_ERROR_HANDLER \
193 __local_syscall_error: \
197 lrw a1, __errno_location; \
199 ldw a1, (sp, 0); /* load errno */ \
207 # endif /* __PIC__ */
208 # endif/* RTLD_PRIVATE_ERROR */
210 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
211 # define SYSCALL_ERROR __syscall_error
212 # endif/* IS_IN (libc) */
216 # define DO_CALL(syscall_name, args) \
218 lrw r7, SYS_ify(syscall_name); \
225 cfi_adjust_cfa_offset (8); \
227 cfi_rel_offset (r7, 0);
230 # define DOARGS_1 DOARGS_0
232 # define DOARGS_2 DOARGS_0
234 # define DOARGS_3 DOARGS_0
236 # define DOARGS_4 DOARGS_0
240 cfi_adjust_cfa_offset (8); \
242 cfi_rel_offset (7, 0); \
244 cfi_rel_offset (4, 4); \
249 cfi_adjust_cfa_offset (16); \
251 cfi_rel_offset (7, 0); \
253 cfi_rel_offset (4, 4); \
255 cfi_rel_offset (5, 8); \
260 # define UNDOARGS_0 \
264 cfi_adjust_cfa_offset (-8);
267 # define UNDOARGS_1 UNDOARGS_0
269 # define UNDOARGS_2 UNDOARGS_0
271 # define UNDOARGS_3 UNDOARGS_0
273 # define UNDOARGS_4 UNDOARGS_0
275 # define UNDOARGS_5 \
281 cfi_adjust_cfa_offset (-8);
284 # define UNDOARGS_6 \
292 cfi_adjust_cfa_offset (-16);
294 #else /* not __ASSEMBLER__ */
296 # undef INTERNAL_SYSCALL_RAW
297 # define INTERNAL_SYSCALL_RAW0(name, dummy...) \
298 ({unsigned int __sys_result; \
300 register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
302 __asm__ __volatile__ ("trap 0 \n\t" \
306 __sys_result = _a1; \
308 (int) __sys_result; })
310 # define INTERNAL_SYSCALL_RAW1(name, arg1) \
311 ({unsigned int __sys_result; \
312 register int _tmp_arg1 = (int)(arg1); \
314 register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
317 __asm__ __volatile__ ("trap 0 \n\t" \
319 : "r" (_nr), "r" (_a1) \
321 __sys_result = _a1; \
323 (int) __sys_result; })
325 # define INTERNAL_SYSCALL_RAW2(name, arg1, arg2) \
326 ({unsigned int __sys_result; \
327 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
329 register int _nr __asm__ ("r7"); \
330 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
331 _a1 = _tmp_arg1, _a2 = _tmp_arg2; \
333 __asm__ __volatile__ ("trap 0 \n\t" \
335 : "r" (_nr), "r" (_a1), "r" (_a2) \
337 __sys_result = _a1; \
339 (int) __sys_result; })
341 # define INTERNAL_SYSCALL_RAW3(name, arg1, arg2, arg3) \
342 ({unsigned int __sys_result; \
343 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
344 register int _tmp_arg3 = (int)(arg3); \
346 register int _nr __asm__ ("r7"); \
347 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
348 register int _a3 __asm__ ("a2"); \
353 __asm__ __volatile__ ("trap 0 \n\t" \
355 : "r" (_nr), "r" (_a1), "r" (_a2), \
358 __sys_result = _a1; \
360 (int) __sys_result; })
362 # define INTERNAL_SYSCALL_RAW4(name, arg1, arg2, arg3, arg4) \
363 ({unsigned int __sys_result; \
364 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
365 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
367 register int _nr __asm__ ("r7"); \
368 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
369 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
370 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
373 __asm__ __volatile__ ("trap 0 \n\t" \
375 : "r" (_nr), "r" (_a1), "r" (_a2), \
376 "r" (_a3), "r" (_a4) \
378 __sys_result = _a1; \
380 (int) __sys_result; })
382 # define INTERNAL_SYSCALL_RAW5(name, arg1, arg2, arg3, arg4, \
384 ({unsigned int __sys_result; \
385 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
386 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
387 register int _tmp_arg5 = (int)(arg5); \
389 register int _nr __asm__ ("r7"); \
390 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
391 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
392 register int _a5 __asm__ ("r4"); \
393 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
394 _a4 = _tmp_arg4, _a5 = _tmp_arg5; \
396 __asm__ __volatile__ ("trap 0 \n\t" \
398 : "r" (_nr), "r" (_a1), "r" (_a2), \
399 "r" (_a3), "r" (_a4), "r" (_a5) \
401 __sys_result = _a1; \
403 (int) __sys_result; })
405 # define INTERNAL_SYSCALL_RAW6(name, arg1, arg2, arg3, arg4, \
407 ({unsigned int __sys_result; \
408 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
409 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
410 register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
412 register int _nr __asm__ ("r7"); \
413 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
414 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
415 register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
416 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
417 _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
419 __asm__ __volatile__ ("trap 0 \n\t" \
421 : "r" (_nr), "r" (_a1), "r" (_a2), \
422 "r" (_a3), "r" (_a4), "r" (_a5), \
425 __sys_result = _a1; \
427 (int) __sys_result; })
429 # define INTERNAL_SYSCALL_RAW7(name, arg1, arg2, arg3, arg4, \
431 ({unsigned int __sys_result; \
432 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
433 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
434 register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
435 register int _tmp_arg7 = (int)(arg7); \
437 register int _nr __asm__ ("r7"); \
438 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
439 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
440 register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
441 register int _a7 __asm__ ("r6"); \
442 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
443 _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
446 __asm__ __volatile__ ("trap 0 \n\t" \
448 : "r" (_nr), "r" (_a1), "r" (_a2), \
449 "r" (_a3), "r" (_a4), "r" (_a5), \
450 "r" (_a6), "r" (_a7) \
452 __sys_result = _a1; \
454 (int) __sys_result; })
456 # undef INTERNAL_SYSCALL
457 # define INTERNAL_SYSCALL(name, nr, args...) \
458 INTERNAL_SYSCALL_RAW##nr(SYS_ify(name), args)
460 # undef INTERNAL_SYSCALL_NCS
461 # define INTERNAL_SYSCALL_NCS(number, nr, args...) \
462 INTERNAL_SYSCALL_RAW##nr (number, args)
464 #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
465 #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
467 #endif /* __ASSEMBLER__ */
469 /* Pointer mangling support. */
471 || (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
472 # ifdef __ASSEMBLER__
473 # define PTR_MANGLE(dst, src, guard) \
476 lrw guard, 1b@GOTPC; \
478 lrw guard, __pointer_chk_guard_local@GOT; \
479 ldr.w guard, (t0, guard << 0); \
480 ldw guard, (guard, 0); \
482 # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
483 # define PTR_MANGLE2(dst, src, guard) \
485 # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
487 extern uintptr_t __pointer_chk_guard_local
;
488 # define PTR_MANGLE(var) \
489 (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
490 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
493 # ifdef __ASSEMBLER__
494 # define PTR_MANGLE(dst, src, guard) \
497 lrw guard, 1b@GOTPC; \
499 lrw guard, __pointer_chk_guard@GOT; \
500 ldr.w guard, (t0, guard << 0); \
501 ldw guard, (guard, 0); \
503 # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
504 # define PTR_MANGLE2(dst, src, guard) \
506 # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
508 extern uintptr_t __pointer_chk_guard
;
509 # define PTR_MANGLE(var) \
510 (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
511 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
515 #endif /* linux/csky/sysdep.h */