Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /* Copyright (C) 2000-2024 Free Software Foundation, Inc. |
---|---|
2 | |
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 License as |
7 | published by the Free Software Foundation; either version 2.1 of the |
8 | 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 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #ifndef _LINUX_MICROBLAZE_SYSDEP_H |
20 | #define _LINUX_MICROBLAZE_SYSDEP_H 1 |
21 | |
22 | #include <sysdeps/unix/sysdep.h> |
23 | #include <sysdeps/unix/sysv/linux/sysdep.h> |
24 | #include <sysdeps/microblaze/sysdep.h> |
25 | |
26 | /* Defines RTLD_PRIVATE_ERRNO. */ |
27 | #include <dl-sysdep.h> |
28 | |
29 | #include <tls.h> |
30 | |
31 | /* In order to get __set_errno() definition in INLINE_SYSCALL. */ |
32 | #ifndef __ASSEMBLER__ |
33 | # include <errno.h> |
34 | #endif |
35 | |
36 | /* For Linux we can use the system call table in the header file |
37 | /usr/include/asm/unistd.h |
38 | of the kernel. But these symbols do not follow the SYS_* syntax |
39 | so we have to redefine the `SYS_ify' macro here. */ |
40 | #undef SYS_ify |
41 | #define SYS_ify(syscall_name) __NR_##syscall_name |
42 | |
43 | #ifdef __ASSEMBLER__ |
44 | |
45 | /* In microblaze ABI function call arguments are passed in registers |
46 | r5...r10. The return value is stored in r3 (or r3:r4 register pair). |
47 | Linux syscall uses the same convention with the addition that the |
48 | syscall number is passed in r12. To enter the kernel "brki r14,8" |
49 | instruction is used. |
50 | None of the abovementioned registers are presumed across function call |
51 | or syscall. |
52 | */ |
53 | /* Linux uses a negative return value to indicate syscall errors, unlike |
54 | most Unices, which use the condition codes' carry flag. |
55 | |
56 | Since version 2.1 the return value of a system call might be negative |
57 | even if the call succeeded. E.g., the `lseek' system call might return |
58 | a large offset. Therefore we must not anymore test for < 0, but test |
59 | for a real error by making sure the value in %d0 is a real error |
60 | number. Linus said he will make sure the no syscall returns a value |
61 | in -1 .. -4095 as a valid result so we can safely test with -4095. */ |
62 | |
63 | /* We don't want the label for the error handler to be visible in the symbol |
64 | table when we define it here. */ |
65 | # undef SYSCALL_ERROR_LABEL |
66 | # ifdef PIC |
67 | # define SYSCALL_ERROR_LABEL 0f |
68 | # else |
69 | # define SYSCALL_ERROR_LABEL __syscall_error |
70 | # endif |
71 | |
72 | # undef PSEUDO |
73 | # define PSEUDO(name, syscall_name, args) \ |
74 | .text; \ |
75 | ENTRY (name) \ |
76 | DO_CALL (syscall_name, args); \ |
77 | addik r12,r0,-4095; \ |
78 | cmpu r12,r12,r3; \ |
79 | bgei r12,SYSCALL_ERROR_LABEL; |
80 | |
81 | # undef PSEUDO_END |
82 | # define PSEUDO_END(name) \ |
83 | SYSCALL_ERROR_HANDLER; \ |
84 | END (name) |
85 | |
86 | # undef PSEUDO_NOERRNO |
87 | # define PSEUDO_NOERRNO(name, syscall_name, args) \ |
88 | .text; \ |
89 | ENTRY (name) \ |
90 | DO_CALL (syscall_name, args); |
91 | |
92 | # undef PSEUDO_END_NOERRNO |
93 | # define PSEUDO_END_NOERRNO(name) \ |
94 | END (name) |
95 | |
96 | /* The function has to return the error code. */ |
97 | # undef PSEUDO_ERRVAL |
98 | # define PSEUDO_ERRVAL(name, syscall_name, args) \ |
99 | .text; \ |
100 | ENTRY (name) \ |
101 | DO_CALL (syscall_name, args); \ |
102 | |
103 | # undef PSEUDO_END_ERRVAL |
104 | # define PSEUDO_END_ERRVAL(name) \ |
105 | END (name) |
106 | |
107 | # define ret_NOERRNO \ |
108 | rtsd r15,8; addk r0,r0,r0; |
109 | |
110 | # define ret_ERRVAL \ |
111 | rtsd r15,8; rsubk r3,r3,r0; |
112 | |
113 | # ifdef PIC |
114 | # define SYSCALL_ERROR_LABEL_DCL 0 |
115 | # if RTLD_PRIVATE_ERRNO |
116 | # define SYSCALL_ERROR_HANDLER \ |
117 | SYSCALL_ERROR_LABEL_DCL: \ |
118 | mfs r12,rpc; \ |
119 | addik r12,r12,_GLOBAL_OFFSET_TABLE_+8; \ |
120 | lwi r12,r12,rtld_errno@GOT; \ |
121 | rsubk r3,r3,r0; \ |
122 | swi r3,r12,0; \ |
123 | rtsd r15,8; \ |
124 | addik r3,r0,-1; |
125 | # else /* !RTLD_PRIVATE_ERRNO. */ |
126 | /* Store (-r3) into errno through the GOT. */ |
127 | # if defined _LIBC_REENTRANT |
128 | # define SYSCALL_ERROR_HANDLER \ |
129 | SYSCALL_ERROR_LABEL_DCL: \ |
130 | addik r1,r1,-16; \ |
131 | swi r15,r1,0; \ |
132 | swi r20,r1,8; \ |
133 | rsubk r3,r3,r0; \ |
134 | swi r3,r1,12; \ |
135 | mfs r20,rpc; \ |
136 | addik r20,r20,_GLOBAL_OFFSET_TABLE_+8; \ |
137 | brlid r15,__errno_location@PLT; \ |
138 | nop; \ |
139 | lwi r4,r1,12; \ |
140 | swi r4,r3,0; \ |
141 | lwi r20,r1,8; \ |
142 | lwi r15,r1,0; \ |
143 | addik r1,r1,16; \ |
144 | rtsd r15,8; \ |
145 | addik r3,r0,-1; |
146 | # else /* !_LIBC_REENTRANT. */ |
147 | # define SYSCALL_ERROR_HANDLER \ |
148 | SYSCALL_ERROR_LABEL_DCL: \ |
149 | mfs r12,rpc; \ |
150 | addik r12,r12,_GLOBAL_OFFSET_TABLE_+8; \ |
151 | lwi r12,r12,errno@GOT; \ |
152 | rsubk r3,r3,r0; \ |
153 | swi r3,r12,0; \ |
154 | rtsd r15,8; \ |
155 | addik r3,r0,-1; |
156 | # endif /* _LIBC_REENTRANT. */ |
157 | # endif /* RTLD_PRIVATE_ERRNO. */ |
158 | # else |
159 | # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ |
160 | # endif /* PIC. */ |
161 | |
162 | # define DO_CALL(syscall_name, args) \ |
163 | addik r12,r0,SYS_ify (syscall_name); \ |
164 | brki r14,8; \ |
165 | addk r0,r0,r0; |
166 | |
167 | #else /* not __ASSEMBLER__ */ |
168 | |
169 | /* Define a macro which expands inline into the wrapper code for a system |
170 | call. This use is for internal calls that do not need to handle errors |
171 | normally. It will never touch errno. This returns just what the kernel |
172 | gave back. */ |
173 | # undef INTERNAL_SYSCALL |
174 | # define INTERNAL_SYSCALL(name, nr, args...) \ |
175 | inline_syscall##nr(SYS_ify(name), args) |
176 | |
177 | # undef INTERNAL_SYSCALL_NCS |
178 | # define INTERNAL_SYSCALL_NCS(name, nr, args...) \ |
179 | inline_syscall##nr(name, args) |
180 | |
181 | # define SYSCALL_CLOBBERS_6 "r11", "r4", "memory" |
182 | # define SYSCALL_CLOBBERS_5 "r10", SYSCALL_CLOBBERS_6 |
183 | # define SYSCALL_CLOBBERS_4 "r9", SYSCALL_CLOBBERS_5 |
184 | # define SYSCALL_CLOBBERS_3 "r8", SYSCALL_CLOBBERS_4 |
185 | # define SYSCALL_CLOBBERS_2 "r7", SYSCALL_CLOBBERS_3 |
186 | # define SYSCALL_CLOBBERS_1 "r6", SYSCALL_CLOBBERS_2 |
187 | # define SYSCALL_CLOBBERS_0 "r5", SYSCALL_CLOBBERS_1 |
188 | |
189 | # define inline_syscall0(name,dummy) \ |
190 | ({ \ |
191 | register long int __ret __asm__("r3"); \ |
192 | register long int __r12 __asm__("r12") = name; \ |
193 | __asm__ __volatile__( "brki r14,8; nop;" \ |
194 | : "=r"(__ret) \ |
195 | : "r"(__r12) \ |
196 | : SYSCALL_CLOBBERS_0 ); __ret; \ |
197 | }) |
198 | |
199 | # define inline_syscall1(name,arg1) \ |
200 | ({ \ |
201 | long int __arg1 = (long int) (arg1); \ |
202 | register long int __ret __asm__("r3"); \ |
203 | register long int __r12 __asm__("r12") = name; \ |
204 | register long int __r5 __asm__("r5") = __arg1; \ |
205 | __asm__ __volatile__( "brki r14,8; nop;" \ |
206 | : "=r"(__ret) \ |
207 | : "r"(__r5), "r"(__r12) \ |
208 | : SYSCALL_CLOBBERS_1 ); __ret; \ |
209 | }) |
210 | |
211 | # define inline_syscall2(name,arg1,arg2) \ |
212 | ({ \ |
213 | long int __arg1 = (long int) (arg1); \ |
214 | long int __arg2 = (long int) (arg2); \ |
215 | register long int __ret __asm__("r3"); \ |
216 | register long int __r12 __asm__("r12") = name; \ |
217 | register long int __r5 __asm__("r5") = __arg1; \ |
218 | register long int __r6 __asm__("r6") = __arg2; \ |
219 | __asm__ __volatile__( "brki r14,8; nop;" \ |
220 | : "=r"(__ret) \ |
221 | : "r"(__r5), "r"(__r6), "r"(__r12) \ |
222 | : SYSCALL_CLOBBERS_2 ); __ret; \ |
223 | }) |
224 | |
225 | |
226 | # define inline_syscall3(name,arg1,arg2,arg3) \ |
227 | ({ \ |
228 | long int __arg1 = (long int) (arg1); \ |
229 | long int __arg2 = (long int) (arg2); \ |
230 | long int __arg3 = (long int) (arg3); \ |
231 | register long int __ret __asm__("r3"); \ |
232 | register long int __r12 __asm__("r12") = name; \ |
233 | register long int __r5 __asm__("r5") = __arg1; \ |
234 | register long int __r6 __asm__("r6") = __arg2; \ |
235 | register long int __r7 __asm__("r7") = __arg3; \ |
236 | __asm__ __volatile__( "brki r14,8; nop;" \ |
237 | : "=r"(__ret) \ |
238 | : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r12) \ |
239 | : SYSCALL_CLOBBERS_3 ); __ret; \ |
240 | }) |
241 | |
242 | |
243 | # define inline_syscall4(name,arg1,arg2,arg3,arg4) \ |
244 | ({ \ |
245 | long int __arg1 = (long int) (arg1); \ |
246 | long int __arg2 = (long int) (arg2); \ |
247 | long int __arg3 = (long int) (arg3); \ |
248 | long int __arg4 = (long int) (arg4); \ |
249 | register long int __ret __asm__("r3"); \ |
250 | register long int __r12 __asm__("r12") = name; \ |
251 | register long int __r5 __asm__("r5") = __arg1; \ |
252 | register long int __r6 __asm__("r6") = __arg2; \ |
253 | register long int __r7 __asm__("r7") = __arg3; \ |
254 | register long int __r8 __asm__("r8") = __arg4; \ |
255 | __asm__ __volatile__( "brki r14,8; nop;" \ |
256 | : "=r"(__ret) \ |
257 | : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r12) \ |
258 | : SYSCALL_CLOBBERS_4 ); __ret; \ |
259 | }) |
260 | |
261 | |
262 | # define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \ |
263 | ({ \ |
264 | long int __arg1 = (long int) (arg1); \ |
265 | long int __arg2 = (long int) (arg2); \ |
266 | long int __arg3 = (long int) (arg3); \ |
267 | long int __arg4 = (long int) (arg4); \ |
268 | long int __arg5 = (long int) (arg5); \ |
269 | register long int __ret __asm__("r3"); \ |
270 | register long int __r12 __asm__("r12") = name; \ |
271 | register long int __r5 __asm__("r5") = __arg1; \ |
272 | register long int __r6 __asm__("r6") = __arg2; \ |
273 | register long int __r7 __asm__("r7") = __arg3; \ |
274 | register long int __r8 __asm__("r8") = __arg4; \ |
275 | register long int __r9 __asm__("r9") = __arg5; \ |
276 | __asm__ __volatile__( "brki r14,8; nop;" \ |
277 | : "=r"(__ret) \ |
278 | : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r12) \ |
279 | : SYSCALL_CLOBBERS_5 ); __ret; \ |
280 | }) |
281 | |
282 | |
283 | # define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \ |
284 | ({ \ |
285 | long int __arg1 = (long int) (arg1); \ |
286 | long int __arg2 = (long int) (arg2); \ |
287 | long int __arg3 = (long int) (arg3); \ |
288 | long int __arg4 = (long int) (arg4); \ |
289 | long int __arg5 = (long int) (arg5); \ |
290 | long int __arg6 = (long int) (arg6); \ |
291 | register long int __ret __asm__("r3"); \ |
292 | register long int __r12 __asm__("r12") = name; \ |
293 | register long int __r5 __asm__("r5") = __arg1; \ |
294 | register long int __r6 __asm__("r6") = __arg2; \ |
295 | register long int __r7 __asm__("r7") = __arg3; \ |
296 | register long int __r8 __asm__("r8") = __arg4; \ |
297 | register long int __r9 __asm__("r9") = __arg5; \ |
298 | register long int __r10 __asm__("r10") = __arg6; \ |
299 | __asm__ __volatile__( "brki r14,8; nop;" \ |
300 | : "=r"(__ret) \ |
301 | : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r10), \ |
302 | "r"(__r12) \ |
303 | : SYSCALL_CLOBBERS_6 ); __ret; \ |
304 | }) |
305 | |
306 | |
307 | #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL |
308 | #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 |
309 | |
310 | #endif /* not __ASSEMBLER__ */ |
311 | |
312 | #endif /* _LINUX_MICROBLAZE_SYSDEP_H */ |
313 |
Warning: That file was not part of the compilation database. It may have many parsing errors.