]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/csky/sysdep.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / csky / sysdep.h
1 /* Assembly macros for C-SKY.
2 Copyright (C) 2018-2019 Free Software Foundation, Inc.
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 #ifndef _LINUX_CSKY_SYSDEP_H
20 #define _LINUX_CSKY_SYSDEP_H 1
21
22 /* There is some commonality. */
23 #include <sysdeps/unix/sysv/linux/generic/sysdep.h>
24 #include <sysdeps/unix/sysv/linux/sysdep.h>
25 #include <sysdeps/csky/sysdep.h>
26
27 /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
28 #include <dl-sysdep.h>
29
30 #include <tls.h>
31
32 /* In order to get __set_errno() definition in INLINE_SYSCALL. */
33 #ifndef __ASSEMBLER__
34 # include <errno.h>
35 #endif
36
37 #undef SYS_ify
38 #define SYS_ify(syscall_name) (__NR_##syscall_name)
39
40 #ifdef __ASSEMBLER__
41 /* Linux uses a negative return value to indicate syscall errors,
42 unlike most Unices, which use the condition codes' carry flag.
43
44 Since version 2.1 the return value of a system call might be
45 negative even if the call succeeded. E.g., the `lseek' system call
46 might return a large offset. Therefore we must not anymore test
47 for < 0, but test for a real error by making sure the value in R0
48 is a real error number. Linus said he will make sure the no syscall
49 returns a value in -1 .. -4095 as a valid result so we can safely
50 test with -4095. */
51
52 # undef PSEUDO
53 # define PSEUDO(name, syscall_name, args) \
54 .text; \
55 ENTRY (name); \
56 DO_CALL (syscall_name, args);
57
58 # define GETGB \
59 grs t0, .Lgetpc; \
60 .Lgetpc: \
61 lrw gb, .Lgetpc@GOTPC; \
62 addu gb, t0;
63
64 # if IS_IN (libc)
65 # ifdef __PIC__
66 # define PSEUDO_RET \
67 btsti a0, 31; \
68 bf 1f; \
69 subi sp, 8; \
70 st.w lr, (sp); \
71 st.w gb, (sp, 4); \
72 GETGB; \
73 lrw a2, SYSCALL_ERROR@PLT; \
74 add a2, gb; \
75 ld.w a2, (a2); \
76 jsr a2; \
77 ld.w lr, (sp); \
78 ld.w gb, (sp, 4); \
79 addi sp, 8; \
80 1: \
81 rts
82 # else
83 # define PSEUDO_RET \
84 btsti a0, 31; \
85 bf 1f; \
86 jmpi SYSCALL_ERROR; \
87 1: \
88 rts
89 # endif
90 # else
91 # ifdef __PIC__
92 # define PSEUDO_RET \
93 btsti a0, 31; \
94 bf 1f; \
95 subi sp, 8; \
96 st.w lr, (sp); \
97 st.w gb, (sp, 4); \
98 GETGB; \
99 bsr SYSCALL_ERROR; \
100 ld.w lr, (sp); \
101 ld.w gb, (sp, 4); \
102 addi sp, 8; \
103 1: \
104 rts
105 # else
106 # define PSEUDO_RET \
107 btsti a0, 31; \
108 bt SYSCALL_ERROR; \
109 rts
110 # endif
111 # endif
112
113 # undef ret
114 # define ret PSEUDO_RET
115
116 # undef PSEUDO_END
117 # define PSEUDO_END(name) \
118 .align 4; \
119 SYSCALL_ERROR_HANDLER; \
120 END (name)
121
122 # undef PSEUDO_NOERRNO
123 # define PSEUDO_NOERRNO(name, syscall_name, args) \
124 .text; \
125 ENTRY (name); \
126 DO_CALL (syscall_name, args)
127
128 # define PSEUDO_RET_NOERRNO rts
129
130 # undef ret_NOERRNO
131 # define ret_NOERRNO PSEUDO_RET_NOERRNO
132
133 # undef PSEUDO_END_NOERRNO
134 # define PSEUDO_END_NOERRNO(name) END (name)
135
136 /* The function has to return the error code. */
137 # undef PSEUDO_ERRVAL
138 # define PSEUDO_ERRVAL(name, syscall_name, args) \
139 .text; \
140 ENTRY (name) \
141 DO_CALL (syscall_name, args); \
142 not a0; \
143 addi a0, 1
144
145 # undef PSEUDO_END_ERRVAL
146 # define PSEUDO_END_ERRVAL(name) END (name)
147
148 # define ret_ERRVAL rts
149
150 # if !IS_IN (libc)
151 # define SYSCALL_ERROR __local_syscall_error
152 # if RTLD_PRIVATE_ERRNO
153 # ifdef __PIC__
154 # define SYSCALL_ERROR_HANDLER \
155 __local_syscall_error: \
156 lrw a1, rtld_errno@PLT; \
157 addu a1, gb; \
158 ldw a1, (a1); \
159 rsubi a0, 0; \
160 stw a0, (a1); \
161 bmaski a0, 0; \
162 rts
163 # else /* __PIC__ */
164 # define SYSCALL_ERROR_HANDLER \
165 __local_syscall_error: \
166 lrw a1, rtld_errno; \
167 rsubi a0, 0; \
168 stw a0, (a1); \
169 bmaski a0, 0; \
170 rts
171 # endif /* __PIC__ */
172 # else /* !RTLD_PRIVATE_ERRNO */
173 # ifdef __PIC__
174 # define SYSCALL_ERROR_HANDLER \
175 __local_syscall_error: \
176 subi sp, 8; \
177 stw a0, (sp, 0); \
178 stw r15, (sp, 4); \
179 lrw a1, __errno_location@PLT; \
180 add a1, gb; \
181 ldw a1, (a1); \
182 jsr a1; \
183 ldw a1, (sp, 0); /* load errno*/ \
184 ldw r15, (sp, 4); \
185 addi sp, 8; \
186 movi a2, 0; \
187 rsub a1, a1, a2; \
188 stw a1, (a0); \
189 bmaski a0, 0; \
190 rts
191 # else
192 # define SYSCALL_ERROR_HANDLER \
193 __local_syscall_error: \
194 subi sp, 8; \
195 stw a0, (sp, 0); \
196 stw r15, (sp, 4); \
197 lrw a1, __errno_location; \
198 jsr a1; \
199 ldw a1, (sp, 0); /* load errno */ \
200 ldw r15, (sp, 4); \
201 addi sp, 8; \
202 movi a2, 0; \
203 rsub a1, a1, a2; \
204 stw a1, (a0); \
205 bmaski a0, 0; \
206 rts
207 # endif /* __PIC__ */
208 # endif/* RTLD_PRIVATE_ERROR */
209 # else
210 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
211 # define SYSCALL_ERROR __syscall_error
212 # endif/* IS_IN (libc) */
213
214 /* define DO_CALL */
215 # undef DO_CALL
216 # define DO_CALL(syscall_name, args) \
217 DOARGS_##args; \
218 lrw r7, SYS_ify(syscall_name); \
219 trap 0; \
220 UNDOARGS_##args
221
222 # undef DOARGS_0
223 # define DOARGS_0 \
224 subi sp, 8; \
225 cfi_adjust_cfa_offset (8); \
226 stw r7, (sp, 0); \
227 cfi_rel_offset (r7, 0);
228
229 # undef DOARGS_1
230 # define DOARGS_1 DOARGS_0
231 # undef DOARGS_2
232 # define DOARGS_2 DOARGS_0
233 # undef DOARGS_3
234 # define DOARGS_3 DOARGS_0
235 # undef DOARGS_4
236 # define DOARGS_4 DOARGS_0
237 # undef DOARGS_5
238 # define DOARGS_5 \
239 subi sp, 8; \
240 cfi_adjust_cfa_offset (8); \
241 stw r7, (sp, 0); \
242 cfi_rel_offset (7, 0); \
243 stw r4, (sp, 4); \
244 cfi_rel_offset (4, 4); \
245 ldw r4, (sp, 8)
246 # undef DOARGS_6
247 # define DOARGS_6 \
248 subi sp, 16; \
249 cfi_adjust_cfa_offset (16); \
250 stw r7, (sp, 0); \
251 cfi_rel_offset (7, 0); \
252 stw r4, (sp, 4); \
253 cfi_rel_offset (4, 4); \
254 stw r5, (sp, 8); \
255 cfi_rel_offset (5, 8); \
256 ldw r4, (sp, 16); \
257 ldw r5, (sp, 20)
258
259 # undef UNDOARGS_0
260 # define UNDOARGS_0 \
261 ldw r7, (sp, 0); \
262 cfi_restore (r7); \
263 addi sp, 8; \
264 cfi_adjust_cfa_offset (-8);
265
266 # undef UNDOARGS_1
267 # define UNDOARGS_1 UNDOARGS_0
268 # undef UNDOARGS_2
269 # define UNDOARGS_2 UNDOARGS_0
270 # undef UNDOARGS_3
271 # define UNDOARGS_3 UNDOARGS_0
272 # undef UNDOARGS_4
273 # define UNDOARGS_4 UNDOARGS_0
274 # undef UNDOARGS_5
275 # define UNDOARGS_5 \
276 ldw r7, (sp, 0); \
277 cfi_restore (r4); \
278 ldw r4, (sp, 4); \
279 cfi_restore (r4); \
280 addi sp, 8; \
281 cfi_adjust_cfa_offset (-8);
282
283 # undef UNDOARGS_6
284 # define UNDOARGS_6 \
285 ldw r7, (sp, 0); \
286 cfi_restore (r7); \
287 ldw r4, (sp, 4); \
288 cfi_restore (r4); \
289 ldw r5, (sp, 8); \
290 cfi_restore (r5); \
291 addi sp, 16; \
292 cfi_adjust_cfa_offset (-16);
293
294 #else /* not __ASSEMBLER__ */
295
296 /* Define a macro which expands into the inline wrapper code for a system
297 call. */
298 # undef INLINE_SYSCALL
299 # define INLINE_SYSCALL(name, nr, args...) \
300 ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args); \
301 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result,), 0)) \
302 { \
303 __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \
304 _sys_result = (unsigned int) -1; \
305 } \
306 (int) _sys_result; })
307
308 # undef INTERNAL_SYSCALL_DECL
309 # define INTERNAL_SYSCALL_DECL(err) do { } while (0)
310
311 # undef INTERNAL_SYSCALL_ERROR_P
312 # define INTERNAL_SYSCALL_ERROR_P(val, err) \
313 ((unsigned int) (val) >= 0xffffff01u)
314
315 # undef INTERNAL_SYSCALL_ERRNO
316 # define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
317
318 # undef INTERNAL_SYSCALL_RAW
319 # define INTERNAL_SYSCALL_RAW0(name, err, dummy...) \
320 ({unsigned int __sys_result; \
321 { \
322 register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
323 _nr = name; \
324 __asm__ __volatile__ ("trap 0 \n\t" \
325 : "=r" (_a1) \
326 : "r" (_nr) \
327 : "memory"); \
328 __sys_result = _a1; \
329 } \
330 (int) __sys_result; })
331
332 # define INTERNAL_SYSCALL_RAW1(name, err, arg1) \
333 ({unsigned int __sys_result; \
334 register int _tmp_arg1 = (int)(arg1); \
335 { \
336 register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
337 _a1 = _tmp_arg1; \
338 _nr = name; \
339 __asm__ __volatile__ ("trap 0 \n\t" \
340 : "=r" (_a1) \
341 : "r" (_nr), "r" (_a1) \
342 : "memory"); \
343 __sys_result = _a1; \
344 } \
345 (int) __sys_result; })
346
347 # define INTERNAL_SYSCALL_RAW2(name, err, arg1, arg2) \
348 ({unsigned int __sys_result; \
349 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
350 { \
351 register int _nr __asm__ ("r7"); \
352 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
353 _a1 = _tmp_arg1, _a2 = _tmp_arg2; \
354 _nr = name; \
355 __asm__ __volatile__ ("trap 0 \n\t" \
356 : "=r" (_a1) \
357 : "r" (_nr), "r" (_a1), "r" (_a2) \
358 : "memory"); \
359 __sys_result = _a1; \
360 } \
361 (int) __sys_result; })
362
363 # define INTERNAL_SYSCALL_RAW3(name, err, arg1, arg2, arg3) \
364 ({unsigned int __sys_result; \
365 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
366 register int _tmp_arg3 = (int)(arg3); \
367 { \
368 register int _nr __asm__ ("r7"); \
369 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
370 register int _a3 __asm__ ("a2"); \
371 _a1 = _tmp_arg1; \
372 _a2 = _tmp_arg2; \
373 _a3 = _tmp_arg3; \
374 _nr = name; \
375 __asm__ __volatile__ ("trap 0 \n\t" \
376 : "=r" (_a1) \
377 : "r" (_nr), "r" (_a1), "r" (_a2), \
378 "r" (_a3) \
379 : "memory"); \
380 __sys_result = _a1; \
381 } \
382 (int) __sys_result; })
383
384 # define INTERNAL_SYSCALL_RAW4(name, err, arg1, arg2, arg3, arg4) \
385 ({unsigned int __sys_result; \
386 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
387 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
388 { \
389 register int _nr __asm__ ("r7"); \
390 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
391 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
392 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
393 _a4 = _tmp_arg4; \
394 _nr = name; \
395 __asm__ __volatile__ ("trap 0 \n\t" \
396 : "=r" (_a1) \
397 : "r" (_nr), "r" (_a1), "r" (_a2), \
398 "r" (_a3), "r" (_a4) \
399 : "memory"); \
400 __sys_result = _a1; \
401 } \
402 (int) __sys_result; })
403
404 # define INTERNAL_SYSCALL_RAW5(name, err, arg1, arg2, arg3, arg4, \
405 arg5) \
406 ({unsigned int __sys_result; \
407 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
408 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
409 register int _tmp_arg5 = (int)(arg5); \
410 { \
411 register int _nr __asm__ ("r7"); \
412 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
413 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
414 register int _a5 __asm__ ("r4"); \
415 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
416 _a4 = _tmp_arg4, _a5 = _tmp_arg5; \
417 _nr = name; \
418 __asm__ __volatile__ ("trap 0 \n\t" \
419 : "=r" (_a1) \
420 : "r" (_nr), "r" (_a1), "r" (_a2), \
421 "r" (_a3), "r" (_a4), "r" (_a5) \
422 : "memory"); \
423 __sys_result = _a1; \
424 } \
425 (int) __sys_result; })
426
427 # define INTERNAL_SYSCALL_RAW6(name, err, arg1, arg2, arg3, arg4, \
428 arg5, arg6) \
429 ({unsigned int __sys_result; \
430 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
431 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
432 register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
433 { \
434 register int _nr __asm__ ("r7"); \
435 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
436 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
437 register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
438 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
439 _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
440 _nr = name; \
441 __asm__ __volatile__ ("trap 0 \n\t" \
442 : "=r" (_a1) \
443 : "r" (_nr), "r" (_a1), "r" (_a2), \
444 "r" (_a3), "r" (_a4), "r" (_a5), \
445 "r" (_a6) \
446 : "memory"); \
447 __sys_result = _a1; \
448 } \
449 (int) __sys_result; })
450
451 # define INTERNAL_SYSCALL_RAW7(name, err, arg1, arg2, arg3, arg4, \
452 arg5, arg6, arg7) \
453 ({unsigned int __sys_result; \
454 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
455 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
456 register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
457 register int _tmp_arg7 = (int)(arg7); \
458 { \
459 register int _nr __asm__ ("r7"); \
460 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
461 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
462 register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
463 register int _a7 __asm__ ("r6"); \
464 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
465 _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
466 _a7 = _tmp_arg7; \
467 _nr = name; \
468 __asm__ __volatile__ ("trap 0 \n\t" \
469 : "=r" (_a1) \
470 : "r" (_nr), "r" (_a1), "r" (_a2), \
471 "r" (_a3), "r" (_a4), "r" (_a5), \
472 "r" (_a6), "r" (_a7) \
473 : "memory"); \
474 __sys_result = _a1; \
475 } \
476 (int) __sys_result; })
477
478 # undef INTERNAL_SYSCALL
479 # define INTERNAL_SYSCALL(name, err, nr, args...) \
480 INTERNAL_SYSCALL_RAW##nr(SYS_ify(name), err, args)
481
482 # undef INTERNAL_SYSCALL_NCS
483 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
484 INTERNAL_SYSCALL_RAW##nr (number, err, args)
485
486 #endif /* __ASSEMBLER__ */
487
488 /* Pointer mangling support. */
489 #if (IS_IN (rtld) || \
490 (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
491 # ifdef __ASSEMBLER__
492 # define PTR_MANGLE(dst, src, guard) \
493 grs t0, 1f; \
494 1: \
495 lrw guard, 1b@GOTPC; \
496 addu t0, guard; \
497 lrw guard, __pointer_chk_guard_local@GOT; \
498 ldr.w guard, (t0, guard << 0); \
499 ldw guard, (guard, 0); \
500 xor dst, src, guard;
501 # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
502 # define PTR_MANGLE2(dst, src, guard) \
503 xor dst, src, guard
504 # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
505 # else
506 extern uintptr_t __pointer_chk_guard_local;
507 # define PTR_MANGLE(var) \
508 (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
509 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
510 # endif
511 #else
512 # ifdef __ASSEMBLER__
513 # define PTR_MANGLE(dst, src, guard) \
514 grs t0, 1f; \
515 1: \
516 lrw guard, 1b@GOTPC; \
517 addu t0, guard; \
518 lrw guard, __pointer_chk_guard@GOT; \
519 ldr.w guard, (t0, guard << 0); \
520 ldw guard, (guard, 0); \
521 xor dst, src, guard;
522 # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
523 # define PTR_MANGLE2(dst, src, guard) \
524 xor dst, src, guard
525 # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
526 # else
527 extern uintptr_t __pointer_chk_guard;
528 # define PTR_MANGLE(var) \
529 (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
530 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
531 # endif
532 #endif
533
534 #endif /* linux/csky/sysdep.h */