diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2015-09-16 01:49:49 +0300 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2015-10-08 20:31:24 +0200 |
commit | e78a0f58f23347c822c182d1c01f6eb9b9866d60 (patch) | |
tree | 723cfbcd2411d889fb4956adb7f2d11a6d766050 /libpthread/nptl/sysdeps/unix/sysv/linux | |
parent | 9fae2ad9937279c9f7f40975ac14cb7b57f4a36d (diff) |
xtensa: support call0 ABI
Most changes are mechanical replacement of 'retw' instruction with
'abi_ret' macro, defined to 'retw' or 'ret' according to ABI.
Assembly code that makes calls is duplicated for call0 ABI with changed
register numbers for parameters/return value and call instruction.
'entry' instructions are replaced with 'abi_entry' macro.
More interesting changes:
- non-leaf assembly functions (e.g. _dl_tlsdesc_dynamic,
_dl_linux_resolve, SYSCALL_ERROR_HANDLER, PSEUDO) now need to preserve
registers around intermediate calls they make, use temporary stack
frame for that;
- setjmp/longjmp only need to save and restore return address, stack
pointer and callee-saved registers in the jmpbuf;
- __clone and syscall functions had hardcoded offsets to parameter
passed on stack, on call0 ABI they don't need stack frame, so the
offset is different. Replace these offsets with FRAMESIZE macro.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux')
-rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h index f82957d15..02fe27869 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h @@ -25,6 +25,7 @@ #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +#if defined(__XTENSA_WINDOWED_ABI__) /* CENABLE/CDISABLE in PSEUDO below use call8, stack frame size must be * at least 32. */ @@ -58,6 +59,64 @@ j SYSCALL_ERROR_LABEL; \ .Lpseudo_end: +# define CENABLE movi a8, CENABLE_FUNC; \ + callx8 a8 +# define CDISABLE movi a8, CDISABLE_FUNC; \ + callx8 a8 +#elif defined(__XTENSA_CALL0_ABI__) + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P(a10); \ + bnez a10, .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + bgez a2, .Lpseudo_done; \ + movi a4, -4095; \ + blt a2, a4, .Lpseudo_done; \ + j SYSCALL_ERROR_LABEL; \ + .Lpseudo_done: \ + ret; \ + .Lpseudo_cancel: \ + addi a1, a1, -32; \ + /* The syscall args are in a2...a7; save them */ \ + s32i a0, a1, 0; \ + s32i a2, a1, 4; \ + s32i a3, a1, 8; \ + s32i a4, a1, 12; \ + s32i a5, a1, 16; \ + s32i a6, a1, 20; \ + s32i a7, a1, 24; \ + CENABLE; \ + /* Move return value to a10 preserved across the syscall */ \ + mov a10, a2; \ + l32i a2, a1, 4; \ + l32i a3, a1, 8; \ + l32i a4, a1, 12; \ + l32i a5, a1, 16; \ + l32i a6, a1, 20; \ + l32i a7, a1, 24; \ + DO_CALL (syscall_name, args); \ + s32i a2, a1, 4; \ + mov a2, a10; \ + CDISABLE; \ + l32i a2, a1, 4; \ + l32i a0, a1, 0; \ + addi a1, a1, 32; \ + bgez a2, .Lpseudo_end; \ + movi a4, -4095; \ + blt a2, a4, .Lpseudo_end; \ + j SYSCALL_ERROR_LABEL; \ + .Lpseudo_end: + +# define CENABLE movi a0, CENABLE_FUNC; \ + callx0 a0 +# define CDISABLE movi a0, CDISABLE_FUNC; \ + callx0 a0 +#else +#error Unsupported Xtensa ABI +#endif # ifdef IS_IN_libpthread # define CENABLE_FUNC __pthread_enable_asynccancel @@ -74,11 +133,6 @@ # error Unsupported library # endif -# define CENABLE movi a8, CENABLE_FUNC; \ - callx8 a8 -# define CDISABLE movi a8, CDISABLE_FUNC; \ - callx8 a8 - # if defined IS_IN_libpthread || !defined NOT_IN_libc # ifndef __ASSEMBLER__ extern int __local_multiple_threads attribute_hidden; |