]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/csky/sysdep.h
92216572a6d98cb5afd822699d5a6850c5d98560
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / csky / sysdep.h
1 /* Assembly macros for C-SKY.
2 Copyright (C) 2018-2020 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 <https://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 # undef INTERNAL_SYSCALL_RAW
297 # define INTERNAL_SYSCALL_RAW0(name, dummy...) \
298 ({unsigned int __sys_result; \
299 { \
300 register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
301 _nr = name; \
302 __asm__ __volatile__ ("trap 0 \n\t" \
303 : "=r" (_a1) \
304 : "r" (_nr) \
305 : "memory"); \
306 __sys_result = _a1; \
307 } \
308 (int) __sys_result; })
309
310 # define INTERNAL_SYSCALL_RAW1(name, arg1) \
311 ({unsigned int __sys_result; \
312 register int _tmp_arg1 = (int)(arg1); \
313 { \
314 register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
315 _a1 = _tmp_arg1; \
316 _nr = name; \
317 __asm__ __volatile__ ("trap 0 \n\t" \
318 : "=r" (_a1) \
319 : "r" (_nr), "r" (_a1) \
320 : "memory"); \
321 __sys_result = _a1; \
322 } \
323 (int) __sys_result; })
324
325 # define INTERNAL_SYSCALL_RAW2(name, arg1, arg2) \
326 ({unsigned int __sys_result; \
327 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
328 { \
329 register int _nr __asm__ ("r7"); \
330 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
331 _a1 = _tmp_arg1, _a2 = _tmp_arg2; \
332 _nr = name; \
333 __asm__ __volatile__ ("trap 0 \n\t" \
334 : "=r" (_a1) \
335 : "r" (_nr), "r" (_a1), "r" (_a2) \
336 : "memory"); \
337 __sys_result = _a1; \
338 } \
339 (int) __sys_result; })
340
341 # define INTERNAL_SYSCALL_RAW3(name, arg1, arg2, arg3) \
342 ({unsigned int __sys_result; \
343 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
344 register int _tmp_arg3 = (int)(arg3); \
345 { \
346 register int _nr __asm__ ("r7"); \
347 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
348 register int _a3 __asm__ ("a2"); \
349 _a1 = _tmp_arg1; \
350 _a2 = _tmp_arg2; \
351 _a3 = _tmp_arg3; \
352 _nr = name; \
353 __asm__ __volatile__ ("trap 0 \n\t" \
354 : "=r" (_a1) \
355 : "r" (_nr), "r" (_a1), "r" (_a2), \
356 "r" (_a3) \
357 : "memory"); \
358 __sys_result = _a1; \
359 } \
360 (int) __sys_result; })
361
362 # define INTERNAL_SYSCALL_RAW4(name, arg1, arg2, arg3, arg4) \
363 ({unsigned int __sys_result; \
364 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
365 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
366 { \
367 register int _nr __asm__ ("r7"); \
368 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
369 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
370 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
371 _a4 = _tmp_arg4; \
372 _nr = name; \
373 __asm__ __volatile__ ("trap 0 \n\t" \
374 : "=r" (_a1) \
375 : "r" (_nr), "r" (_a1), "r" (_a2), \
376 "r" (_a3), "r" (_a4) \
377 : "memory"); \
378 __sys_result = _a1; \
379 } \
380 (int) __sys_result; })
381
382 # define INTERNAL_SYSCALL_RAW5(name, arg1, arg2, arg3, arg4, \
383 arg5) \
384 ({unsigned int __sys_result; \
385 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
386 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
387 register int _tmp_arg5 = (int)(arg5); \
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 register int _a5 __asm__ ("r4"); \
393 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
394 _a4 = _tmp_arg4, _a5 = _tmp_arg5; \
395 _nr = name; \
396 __asm__ __volatile__ ("trap 0 \n\t" \
397 : "=r" (_a1) \
398 : "r" (_nr), "r" (_a1), "r" (_a2), \
399 "r" (_a3), "r" (_a4), "r" (_a5) \
400 : "memory"); \
401 __sys_result = _a1; \
402 } \
403 (int) __sys_result; })
404
405 # define INTERNAL_SYSCALL_RAW6(name, arg1, arg2, arg3, arg4, \
406 arg5, arg6) \
407 ({unsigned int __sys_result; \
408 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
409 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
410 register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
411 { \
412 register int _nr __asm__ ("r7"); \
413 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
414 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
415 register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
416 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
417 _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
418 _nr = name; \
419 __asm__ __volatile__ ("trap 0 \n\t" \
420 : "=r" (_a1) \
421 : "r" (_nr), "r" (_a1), "r" (_a2), \
422 "r" (_a3), "r" (_a4), "r" (_a5), \
423 "r" (_a6) \
424 : "memory"); \
425 __sys_result = _a1; \
426 } \
427 (int) __sys_result; })
428
429 # define INTERNAL_SYSCALL_RAW7(name, arg1, arg2, arg3, arg4, \
430 arg5, arg6, arg7) \
431 ({unsigned int __sys_result; \
432 register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
433 register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
434 register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
435 register int _tmp_arg7 = (int)(arg7); \
436 { \
437 register int _nr __asm__ ("r7"); \
438 register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
439 register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
440 register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
441 register int _a7 __asm__ ("r6"); \
442 _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
443 _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
444 _a7 = _tmp_arg7; \
445 _nr = name; \
446 __asm__ __volatile__ ("trap 0 \n\t" \
447 : "=r" (_a1) \
448 : "r" (_nr), "r" (_a1), "r" (_a2), \
449 "r" (_a3), "r" (_a4), "r" (_a5), \
450 "r" (_a6), "r" (_a7) \
451 : "memory"); \
452 __sys_result = _a1; \
453 } \
454 (int) __sys_result; })
455
456 # undef INTERNAL_SYSCALL
457 # define INTERNAL_SYSCALL(name, nr, args...) \
458 INTERNAL_SYSCALL_RAW##nr(SYS_ify(name), args)
459
460 # undef INTERNAL_SYSCALL_NCS
461 # define INTERNAL_SYSCALL_NCS(number, nr, args...) \
462 INTERNAL_SYSCALL_RAW##nr (number, args)
463
464 #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
465 #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
466
467 #endif /* __ASSEMBLER__ */
468
469 /* Pointer mangling support. */
470 #if (IS_IN (rtld) \
471 || (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
472 # ifdef __ASSEMBLER__
473 # define PTR_MANGLE(dst, src, guard) \
474 grs t0, 1f; \
475 1: \
476 lrw guard, 1b@GOTPC; \
477 addu t0, guard; \
478 lrw guard, __pointer_chk_guard_local@GOT; \
479 ldr.w guard, (t0, guard << 0); \
480 ldw guard, (guard, 0); \
481 xor dst, src, guard;
482 # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
483 # define PTR_MANGLE2(dst, src, guard) \
484 xor dst, src, guard
485 # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
486 # else
487 extern uintptr_t __pointer_chk_guard_local;
488 # define PTR_MANGLE(var) \
489 (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
490 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
491 # endif
492 #else
493 # ifdef __ASSEMBLER__
494 # define PTR_MANGLE(dst, src, guard) \
495 grs t0, 1f; \
496 1: \
497 lrw guard, 1b@GOTPC; \
498 addu t0, guard; \
499 lrw guard, __pointer_chk_guard@GOT; \
500 ldr.w guard, (t0, guard << 0); \
501 ldw guard, (guard, 0); \
502 xor dst, src, guard;
503 # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
504 # define PTR_MANGLE2(dst, src, guard) \
505 xor dst, src, guard
506 # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
507 # else
508 extern uintptr_t __pointer_chk_guard;
509 # define PTR_MANGLE(var) \
510 (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
511 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
512 # endif
513 #endif
514
515 #endif /* linux/csky/sysdep.h */