/* Assembler macros with cancellation support, Nios II version.
Copyright (C) 2003-2016 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
. */
#include
#include
#ifndef __ASSEMBLER__
# include
#endif
#if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
.type __##syscall_name##_nocancel, @function; \
.globl __##syscall_name##_nocancel; \
__##syscall_name##_nocancel: \
cfi_startproc; \
DO_CALL (syscall_name, args); \
bne r7, zero, SYSCALL_ERROR_LABEL; \
ret; \
cfi_endproc; \
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
ENTRY (name) \
SINGLE_THREAD_P(r2); \
bne r2, zero, pseudo_cancel; \
DO_CALL (syscall_name, args); \
bne r7, zero, SYSCALL_ERROR_LABEL; \
ret; \
pseudo_cancel: \
SAVESTK_##args; /* save syscall args and adjust stack */ \
SAVEREG(ra, 0); /* save return address */ \
SAVEREG(r22, 4); /* save GOT pointer */ \
nextpc r22; \
1: movhi r2, %hiadj(_gp_got - 1b); \
addi r2, r2, %lo(_gp_got - 1b); \
add r22, r22, r2; \
CENABLE; \
callr r3; \
stw r2, 8(sp); /* save mask */ \
LOADARGS_##args; \
movi r2, SYS_ify(syscall_name); \
trap; \
stw r2, 12(sp); /* save syscall result */ \
stw r7, 16(sp); /* save syscall error flag */ \
ldw r4, 8(sp); /* pass mask as argument 1 */ \
CDISABLE; \
callr r3; \
ldw r7, 16(sp); /* restore syscall error flag */ \
ldw r2, 12(sp); /* restore syscall result */ \
ldw ra, 0(sp); /* restore return address */ \
ldw r22, 4(sp); /* restore GOT pointer */ \
RESTORESTK_##args; \
bne r7, zero, SYSCALL_ERROR_LABEL;
# undef PSEUDO_END
# define PSEUDO_END(sym) \
SYSCALL_ERROR_HANDLER \
END (sym)
#define SAVEREG(REG, LOC) stw REG, LOC(sp); cfi_rel_offset (REG, LOC)
#define SAVESTK(X) subi sp, sp, X; cfi_adjust_cfa_offset(X)
#define SAVESTK_0 SAVESTK(20)
#define SAVEARG_1 SAVEREG(r4, 20)
#define SAVESTK_1 SAVESTK(24); SAVEARG_1
#define SAVEARG_2 SAVEREG(r5, 24); SAVEARG_1
#define SAVESTK_2 SAVESTK(28); SAVEARG_2
#define SAVEARG_3 SAVEREG(r6, 28); SAVEARG_2
#define SAVESTK_3 SAVESTK(32); SAVEARG_3
#define SAVEARG_4 SAVEREG(r7, 32); SAVEARG_3
#define SAVESTK_4 SAVESTK(36); SAVEARG_4
#define SAVESTK_5 SAVESTK_4
#define SAVESTK_6 SAVESTK_5
#define LOADARGS_0
#define LOADARGS_1 ldw r4, 20(sp)
#define LOADARGS_2 LOADARGS_1; ldw r5, 24(sp)
#define LOADARGS_3 LOADARGS_2; ldw r6, 28(sp)
#define LOADARGS_4 LOADARGS_3; ldw r7, 32(sp)
#define LOADARGS_5 LOADARGS_4; ldw r8, 36(sp)
#define LOADARGS_6 LOADARGS_5; ldw r9, 40(sp)
#define RESTORESTK(X) addi sp, sp, X; cfi_adjust_cfa_offset(-X)
#define RESTORESTK_0 RESTORESTK(20)
#define RESTORESTK_1 RESTORESTK(24)
#define RESTORESTK_2 RESTORESTK(28)
#define RESTORESTK_3 RESTORESTK(32)
#define RESTORESTK_4 RESTORESTK(36)
#define RESTORESTK_5 RESTORESTK(36)
#define RESTORESTK_6 RESTORESTK(36)
# if IS_IN (libpthread)
# define CENABLE ldw r3, %call(__pthread_enable_asynccancel)(r22)
# define CDISABLE ldw r3, %call(__pthread_disable_asynccancel)(r22)
# elif IS_IN (librt)
# define CENABLE ldw r3, %call(__librt_enable_asynccancel)(r22)
# define CDISABLE ldw r3, %call(__librt_disable_asynccancel)(r22)
# elif IS_IN (libc)
# define CENABLE ldw r3, %call(__libc_enable_asynccancel)(r22)
# define CDISABLE ldw r3, %call(__libc_disable_asynccancel)(r22)
# else
# error Unsupported library
# endif
# ifndef __ASSEMBLER__
# define SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) \
== 0, 1)
# else
# define SINGLE_THREAD_P(reg) \
ldw reg, MULTIPLE_THREADS_OFFSET(r23)
#endif
#elif !defined __ASSEMBLER__
# define SINGLE_THREAD_P 1
# define NO_CANCELLATION 1
#endif
#ifndef __ASSEMBLER__
# define RTLD_SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
#endif