]>
Commit | Line | Data |
---|---|---|
522e6ee3 | 1 | /* Assembler macros with cancellation support, Nios II version. |
f7a9f785 | 2 | Copyright (C) 2003-2016 Free Software Foundation, Inc. |
522e6ee3 CLT |
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 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <sysdep.h> | |
20 | #include <tls.h> | |
21 | #ifndef __ASSEMBLER__ | |
22 | # include <nptl/pthreadP.h> | |
23 | #endif | |
24 | ||
25 | #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) | |
26 | ||
27 | # undef PSEUDO | |
28 | # define PSEUDO(name, syscall_name, args) \ | |
29 | .type __##syscall_name##_nocancel, @function; \ | |
30 | .globl __##syscall_name##_nocancel; \ | |
31 | __##syscall_name##_nocancel: \ | |
32 | cfi_startproc; \ | |
33 | DO_CALL (syscall_name, args); \ | |
34 | bne r7, zero, SYSCALL_ERROR_LABEL; \ | |
35 | ret; \ | |
36 | cfi_endproc; \ | |
37 | .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ | |
38 | ENTRY (name) \ | |
39 | SINGLE_THREAD_P(r2); \ | |
40 | bne r2, zero, pseudo_cancel; \ | |
41 | DO_CALL (syscall_name, args); \ | |
42 | bne r7, zero, SYSCALL_ERROR_LABEL; \ | |
43 | ret; \ | |
44 | pseudo_cancel: \ | |
45 | SAVESTK_##args; /* save syscall args and adjust stack */ \ | |
46 | SAVEREG(ra, 0); /* save return address */ \ | |
47 | SAVEREG(r22, 4); /* save GOT pointer */ \ | |
48 | nextpc r22; \ | |
49 | 1: movhi r2, %hiadj(_gp_got - 1b); \ | |
50 | addi r2, r2, %lo(_gp_got - 1b); \ | |
51 | add r22, r22, r2; \ | |
52 | CENABLE; \ | |
53 | callr r3; \ | |
54 | stw r2, 8(sp); /* save mask */ \ | |
55 | LOADARGS_##args; \ | |
56 | movi r2, SYS_ify(syscall_name); \ | |
57 | trap; \ | |
58 | stw r2, 12(sp); /* save syscall result */ \ | |
59 | stw r7, 16(sp); /* save syscall error flag */ \ | |
60 | ldw r4, 8(sp); /* pass mask as argument 1 */ \ | |
61 | CDISABLE; \ | |
62 | callr r3; \ | |
63 | ldw r7, 16(sp); /* restore syscall error flag */ \ | |
64 | ldw r2, 12(sp); /* restore syscall result */ \ | |
65 | ldw ra, 0(sp); /* restore return address */ \ | |
66 | ldw r22, 4(sp); /* restore GOT pointer */ \ | |
67 | RESTORESTK_##args; \ | |
68 | bne r7, zero, SYSCALL_ERROR_LABEL; | |
69 | ||
70 | ||
71 | # undef PSEUDO_END | |
72 | # define PSEUDO_END(sym) \ | |
73 | SYSCALL_ERROR_HANDLER \ | |
74 | END (sym) | |
75 | ||
76 | #define SAVEREG(REG, LOC) stw REG, LOC(sp); cfi_rel_offset (REG, LOC) | |
77 | #define SAVESTK(X) subi sp, sp, X; cfi_adjust_cfa_offset(X) | |
78 | #define SAVESTK_0 SAVESTK(20) | |
79 | #define SAVEARG_1 SAVEREG(r4, 20) | |
80 | #define SAVESTK_1 SAVESTK(24); SAVEARG_1 | |
81 | #define SAVEARG_2 SAVEREG(r5, 24); SAVEARG_1 | |
82 | #define SAVESTK_2 SAVESTK(28); SAVEARG_2 | |
83 | #define SAVEARG_3 SAVEREG(r6, 28); SAVEARG_2 | |
84 | #define SAVESTK_3 SAVESTK(32); SAVEARG_3 | |
85 | #define SAVEARG_4 SAVEREG(r7, 32); SAVEARG_3 | |
86 | #define SAVESTK_4 SAVESTK(36); SAVEARG_4 | |
87 | #define SAVESTK_5 SAVESTK_4 | |
88 | #define SAVESTK_6 SAVESTK_5 | |
89 | ||
90 | #define LOADARGS_0 | |
91 | #define LOADARGS_1 ldw r4, 20(sp) | |
92 | #define LOADARGS_2 LOADARGS_1; ldw r5, 24(sp) | |
93 | #define LOADARGS_3 LOADARGS_2; ldw r6, 28(sp) | |
94 | #define LOADARGS_4 LOADARGS_3; ldw r7, 32(sp) | |
95 | #define LOADARGS_5 LOADARGS_4; ldw r8, 36(sp) | |
96 | #define LOADARGS_6 LOADARGS_5; ldw r9, 40(sp) | |
97 | ||
98 | #define RESTORESTK(X) addi sp, sp, X; cfi_adjust_cfa_offset(-X) | |
99 | #define RESTORESTK_0 RESTORESTK(20) | |
100 | #define RESTORESTK_1 RESTORESTK(24) | |
101 | #define RESTORESTK_2 RESTORESTK(28) | |
102 | #define RESTORESTK_3 RESTORESTK(32) | |
103 | #define RESTORESTK_4 RESTORESTK(36) | |
104 | #define RESTORESTK_5 RESTORESTK(36) | |
105 | #define RESTORESTK_6 RESTORESTK(36) | |
106 | ||
107 | # if IS_IN (libpthread) | |
108 | # define CENABLE ldw r3, %call(__pthread_enable_asynccancel)(r22) | |
109 | # define CDISABLE ldw r3, %call(__pthread_disable_asynccancel)(r22) | |
110 | # elif IS_IN (librt) | |
111 | # define CENABLE ldw r3, %call(__librt_enable_asynccancel)(r22) | |
112 | # define CDISABLE ldw r3, %call(__librt_disable_asynccancel)(r22) | |
113 | # elif IS_IN (libc) | |
114 | # define CENABLE ldw r3, %call(__libc_enable_asynccancel)(r22) | |
115 | # define CDISABLE ldw r3, %call(__libc_disable_asynccancel)(r22) | |
116 | # else | |
117 | # error Unsupported library | |
118 | # endif | |
119 | ||
120 | # ifndef __ASSEMBLER__ | |
121 | # define SINGLE_THREAD_P \ | |
122 | __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ | |
123 | header.multiple_threads) \ | |
124 | == 0, 1) | |
125 | # else | |
126 | # define SINGLE_THREAD_P(reg) \ | |
127 | ldw reg, MULTIPLE_THREADS_OFFSET(r23) | |
128 | #endif | |
129 | ||
130 | #elif !defined __ASSEMBLER__ | |
131 | ||
132 | # define SINGLE_THREAD_P 1 | |
133 | # define NO_CANCELLATION 1 | |
134 | ||
135 | #endif | |
136 | ||
137 | #ifndef __ASSEMBLER__ | |
138 | # define RTLD_SINGLE_THREAD_P \ | |
139 | __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ | |
140 | header.multiple_threads) == 0, 1) | |
141 | #endif |