123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- /* Assembly macros for C-SKY.
- Copyright (C) 2018-2019 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
- <http://www.gnu.org/licenses/>. */
- #ifndef _LINUX_CSKY_SYSDEP_H
- #define _LINUX_CSKY_SYSDEP_H 1
- /* There is some commonality. */
- #include <sysdeps/unix/sysv/linux/generic/sysdep.h>
- #include <sysdeps/unix/sysv/linux/sysdep.h>
- #include <sysdeps/csky/sysdep.h>
- /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
- #include <dl-sysdep.h>
- #include <tls.h>
- /* In order to get __set_errno() definition in INLINE_SYSCALL. */
- #ifndef __ASSEMBLER__
- # include <errno.h>
- #endif
- #undef SYS_ify
- #define SYS_ify(syscall_name) (__NR_##syscall_name)
- #ifdef __ASSEMBLER__
- /* Linux uses a negative return value to indicate syscall errors,
- unlike most Unices, which use the condition codes' carry flag.
- Since version 2.1 the return value of a system call might be
- negative even if the call succeeded. E.g., the `lseek' system call
- might return a large offset. Therefore we must not anymore test
- for < 0, but test for a real error by making sure the value in R0
- is a real error number. Linus said he will make sure the no syscall
- returns a value in -1 .. -4095 as a valid result so we can safely
- test with -4095. */
- # undef PSEUDO
- # define PSEUDO(name, syscall_name, args) \
- .text; \
- ENTRY (name); \
- DO_CALL (syscall_name, args);
- # define GETGB \
- grs t0, .Lgetpc; \
- .Lgetpc: \
- lrw gb, .Lgetpc@GOTPC; \
- addu gb, t0;
- # if IS_IN (libc)
- # ifdef __PIC__
- # define PSEUDO_RET \
- btsti a0, 31; \
- bf 1f; \
- subi sp, 8; \
- st.w lr, (sp); \
- st.w gb, (sp, 4); \
- GETGB; \
- lrw a2, SYSCALL_ERROR@PLT; \
- add a2, gb; \
- ld.w a2, (a2); \
- jsr a2; \
- ld.w lr, (sp); \
- ld.w gb, (sp, 4); \
- addi sp, 8; \
- 1: \
- rts
- # else
- # define PSEUDO_RET \
- btsti a0, 31; \
- bf 1f; \
- jmpi SYSCALL_ERROR; \
- 1: \
- rts
- # endif
- # else
- # ifdef __PIC__
- # define PSEUDO_RET \
- btsti a0, 31; \
- bf 1f; \
- subi sp, 8; \
- st.w lr, (sp); \
- st.w gb, (sp, 4); \
- GETGB; \
- bsr SYSCALL_ERROR; \
- ld.w lr, (sp); \
- ld.w gb, (sp, 4); \
- addi sp, 8; \
- 1: \
- rts
- # else
- # define PSEUDO_RET \
- btsti a0, 31; \
- bt SYSCALL_ERROR; \
- rts
- # endif
- # endif
- # undef ret
- # define ret PSEUDO_RET
- # undef PSEUDO_END
- # define PSEUDO_END(name) \
- .align 4; \
- SYSCALL_ERROR_HANDLER; \
- END (name)
- # undef PSEUDO_NOERRNO
- # define PSEUDO_NOERRNO(name, syscall_name, args) \
- .text; \
- ENTRY (name); \
- DO_CALL (syscall_name, args)
- # define PSEUDO_RET_NOERRNO rts
- # undef ret_NOERRNO
- # define ret_NOERRNO PSEUDO_RET_NOERRNO
- # undef PSEUDO_END_NOERRNO
- # define PSEUDO_END_NOERRNO(name) END (name)
- /* The function has to return the error code. */
- # undef PSEUDO_ERRVAL
- # define PSEUDO_ERRVAL(name, syscall_name, args) \
- .text; \
- ENTRY (name) \
- DO_CALL (syscall_name, args); \
- not a0; \
- addi a0, 1
- # undef PSEUDO_END_ERRVAL
- # define PSEUDO_END_ERRVAL(name) END (name)
- # define ret_ERRVAL rts
- # if !IS_IN (libc)
- # define SYSCALL_ERROR __local_syscall_error
- # if RTLD_PRIVATE_ERRNO
- # ifdef __PIC__
- # define SYSCALL_ERROR_HANDLER \
- __local_syscall_error: \
- lrw a1, rtld_errno@PLT; \
- addu a1, gb; \
- ldw a1, (a1); \
- rsubi a0, 0; \
- stw a0, (a1); \
- bmaski a0, 0; \
- rts
- # else /* __PIC__ */
- # define SYSCALL_ERROR_HANDLER \
- __local_syscall_error: \
- lrw a1, rtld_errno; \
- rsubi a0, 0; \
- stw a0, (a1); \
- bmaski a0, 0; \
- rts
- # endif /* __PIC__ */
- # else /* !RTLD_PRIVATE_ERRNO */
- # ifdef __PIC__
- # define SYSCALL_ERROR_HANDLER \
- __local_syscall_error: \
- subi sp, 8; \
- stw a0, (sp, 0); \
- stw r15, (sp, 4); \
- lrw a1, __errno_location@PLT; \
- add a1, gb; \
- ldw a1, (a1); \
- jsr a1; \
- ldw a1, (sp, 0); /* load errno*/ \
- ldw r15, (sp, 4); \
- addi sp, 8; \
- movi a2, 0; \
- rsub a1, a1, a2; \
- stw a1, (a0); \
- bmaski a0, 0; \
- rts
- # else
- # define SYSCALL_ERROR_HANDLER \
- __local_syscall_error: \
- subi sp, 8; \
- stw a0, (sp, 0); \
- stw r15, (sp, 4); \
- lrw a1, __errno_location; \
- jsr a1; \
- ldw a1, (sp, 0); /* load errno */ \
- ldw r15, (sp, 4); \
- addi sp, 8; \
- movi a2, 0; \
- rsub a1, a1, a2; \
- stw a1, (a0); \
- bmaski a0, 0; \
- rts
- # endif /* __PIC__ */
- # endif/* RTLD_PRIVATE_ERROR */
- # else
- # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
- # define SYSCALL_ERROR __syscall_error
- # endif/* IS_IN (libc) */
- /* define DO_CALL */
- # undef DO_CALL
- # define DO_CALL(syscall_name, args) \
- DOARGS_##args; \
- lrw r7, SYS_ify(syscall_name); \
- trap 0; \
- UNDOARGS_##args
- # undef DOARGS_0
- # define DOARGS_0 \
- subi sp, 8; \
- cfi_adjust_cfa_offset (8); \
- stw r7, (sp, 0); \
- cfi_rel_offset (r7, 0);
- # undef DOARGS_1
- # define DOARGS_1 DOARGS_0
- # undef DOARGS_2
- # define DOARGS_2 DOARGS_0
- # undef DOARGS_3
- # define DOARGS_3 DOARGS_0
- # undef DOARGS_4
- # define DOARGS_4 DOARGS_0
- # undef DOARGS_5
- # define DOARGS_5 \
- subi sp, 8; \
- cfi_adjust_cfa_offset (8); \
- stw r7, (sp, 0); \
- cfi_rel_offset (7, 0); \
- stw r4, (sp, 4); \
- cfi_rel_offset (4, 4); \
- ldw r4, (sp, 8)
- # undef DOARGS_6
- # define DOARGS_6 \
- subi sp, 16; \
- cfi_adjust_cfa_offset (16); \
- stw r7, (sp, 0); \
- cfi_rel_offset (7, 0); \
- stw r4, (sp, 4); \
- cfi_rel_offset (4, 4); \
- stw r5, (sp, 8); \
- cfi_rel_offset (5, 8); \
- ldw r4, (sp, 16); \
- ldw r5, (sp, 20)
- # undef UNDOARGS_0
- # define UNDOARGS_0 \
- ldw r7, (sp, 0); \
- cfi_restore (r7); \
- addi sp, 8; \
- cfi_adjust_cfa_offset (-8);
- # undef UNDOARGS_1
- # define UNDOARGS_1 UNDOARGS_0
- # undef UNDOARGS_2
- # define UNDOARGS_2 UNDOARGS_0
- # undef UNDOARGS_3
- # define UNDOARGS_3 UNDOARGS_0
- # undef UNDOARGS_4
- # define UNDOARGS_4 UNDOARGS_0
- # undef UNDOARGS_5
- # define UNDOARGS_5 \
- ldw r7, (sp, 0); \
- cfi_restore (r4); \
- ldw r4, (sp, 4); \
- cfi_restore (r4); \
- addi sp, 8; \
- cfi_adjust_cfa_offset (-8);
- # undef UNDOARGS_6
- # define UNDOARGS_6 \
- ldw r7, (sp, 0); \
- cfi_restore (r7); \
- ldw r4, (sp, 4); \
- cfi_restore (r4); \
- ldw r5, (sp, 8); \
- cfi_restore (r5); \
- addi sp, 16; \
- cfi_adjust_cfa_offset (-16);
- #else /* not __ASSEMBLER__ */
- /* Define a macro which expands into the inline wrapper code for a system
- call. */
- # undef INLINE_SYSCALL
- # define INLINE_SYSCALL(name, nr, args...) \
- ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args); \
- if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result,), 0)) \
- { \
- __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \
- _sys_result = (unsigned int) -1; \
- } \
- (int) _sys_result; })
- # undef INTERNAL_SYSCALL_DECL
- # define INTERNAL_SYSCALL_DECL(err) do { } while (0)
- # undef INTERNAL_SYSCALL_ERROR_P
- # define INTERNAL_SYSCALL_ERROR_P(val, err) \
- ((unsigned int) (val) >= 0xffffff01u)
- # undef INTERNAL_SYSCALL_ERRNO
- # define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
- # undef INTERNAL_SYSCALL_RAW
- # define INTERNAL_SYSCALL_RAW0(name, err, dummy...) \
- ({unsigned int __sys_result; \
- { \
- register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # define INTERNAL_SYSCALL_RAW1(name, err, arg1) \
- ({unsigned int __sys_result; \
- register int _tmp_arg1 = (int)(arg1); \
- { \
- register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
- _a1 = _tmp_arg1; \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr), "r" (_a1) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # define INTERNAL_SYSCALL_RAW2(name, err, arg1, arg2) \
- ({unsigned int __sys_result; \
- register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
- { \
- register int _nr __asm__ ("r7"); \
- register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
- _a1 = _tmp_arg1, _a2 = _tmp_arg2; \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr), "r" (_a1), "r" (_a2) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # define INTERNAL_SYSCALL_RAW3(name, err, arg1, arg2, arg3) \
- ({unsigned int __sys_result; \
- register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
- register int _tmp_arg3 = (int)(arg3); \
- { \
- register int _nr __asm__ ("r7"); \
- register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
- register int _a3 __asm__ ("a2"); \
- _a1 = _tmp_arg1; \
- _a2 = _tmp_arg2; \
- _a3 = _tmp_arg3; \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr), "r" (_a1), "r" (_a2), \
- "r" (_a3) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # define INTERNAL_SYSCALL_RAW4(name, err, arg1, arg2, arg3, arg4) \
- ({unsigned int __sys_result; \
- register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
- register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
- { \
- register int _nr __asm__ ("r7"); \
- register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
- register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
- _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
- _a4 = _tmp_arg4; \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr), "r" (_a1), "r" (_a2), \
- "r" (_a3), "r" (_a4) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # define INTERNAL_SYSCALL_RAW5(name, err, arg1, arg2, arg3, arg4, \
- arg5) \
- ({unsigned int __sys_result; \
- register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
- register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
- register int _tmp_arg5 = (int)(arg5); \
- { \
- register int _nr __asm__ ("r7"); \
- register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
- register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
- register int _a5 __asm__ ("r4"); \
- _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
- _a4 = _tmp_arg4, _a5 = _tmp_arg5; \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr), "r" (_a1), "r" (_a2), \
- "r" (_a3), "r" (_a4), "r" (_a5) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # define INTERNAL_SYSCALL_RAW6(name, err, arg1, arg2, arg3, arg4, \
- arg5, arg6) \
- ({unsigned int __sys_result; \
- register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
- register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
- register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
- { \
- register int _nr __asm__ ("r7"); \
- register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
- register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
- register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
- _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
- _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr), "r" (_a1), "r" (_a2), \
- "r" (_a3), "r" (_a4), "r" (_a5), \
- "r" (_a6) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # define INTERNAL_SYSCALL_RAW7(name, err, arg1, arg2, arg3, arg4, \
- arg5, arg6, arg7) \
- ({unsigned int __sys_result; \
- register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
- register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
- register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
- register int _tmp_arg7 = (int)(arg7); \
- { \
- register int _nr __asm__ ("r7"); \
- register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
- register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
- register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
- register int _a7 __asm__ ("r6"); \
- _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
- _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
- _a7 = _tmp_arg7; \
- _nr = name; \
- __asm__ __volatile__ ("trap 0 \n\t" \
- : "=r" (_a1) \
- : "r" (_nr), "r" (_a1), "r" (_a2), \
- "r" (_a3), "r" (_a4), "r" (_a5), \
- "r" (_a6), "r" (_a7) \
- : "memory"); \
- __sys_result = _a1; \
- } \
- (int) __sys_result; })
- # undef INTERNAL_SYSCALL
- # define INTERNAL_SYSCALL(name, err, nr, args...) \
- INTERNAL_SYSCALL_RAW##nr(SYS_ify(name), err, args)
- # undef INTERNAL_SYSCALL_NCS
- # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
- INTERNAL_SYSCALL_RAW##nr (number, err, args)
- #endif /* __ASSEMBLER__ */
- /* Pointer mangling support. */
- #if (IS_IN (rtld) || \
- (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
- # ifdef __ASSEMBLER__
- # define PTR_MANGLE(dst, src, guard) \
- grs t0, 1f; \
- 1: \
- lrw guard, 1b@GOTPC; \
- addu t0, guard; \
- lrw guard, __pointer_chk_guard_local@GOT; \
- ldr.w guard, (t0, guard << 0); \
- ldw guard, (guard, 0); \
- xor dst, src, guard;
- # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
- # define PTR_MANGLE2(dst, src, guard) \
- xor dst, src, guard
- # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
- # else
- extern uintptr_t __pointer_chk_guard_local;
- # define PTR_MANGLE(var) \
- (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
- # define PTR_DEMANGLE(var) PTR_MANGLE (var)
- # endif
- #else
- # ifdef __ASSEMBLER__
- # define PTR_MANGLE(dst, src, guard) \
- grs t0, 1f; \
- 1: \
- lrw guard, 1b@GOTPC; \
- addu t0, guard; \
- lrw guard, __pointer_chk_guard@GOT; \
- ldr.w guard, (t0, guard << 0); \
- ldw guard, (guard, 0); \
- xor dst, src, guard;
- # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
- # define PTR_MANGLE2(dst, src, guard) \
- xor dst, src, guard
- # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
- # else
- extern uintptr_t __pointer_chk_guard;
- # define PTR_MANGLE(var) \
- (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
- # define PTR_DEMANGLE(var) PTR_MANGLE (var)
- # endif
- #endif
- #endif /* linux/csky/sysdep.h */
|