Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /* Assembler macros for ARC. |
---|---|
2 | Copyright (C) 2020-2024 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_ARC_SYSDEP_H |
20 | #define _LINUX_ARC_SYSDEP_H 1 |
21 | |
22 | #include <sysdeps/arc/sysdep.h> |
23 | #include <bits/wordsize.h> |
24 | #include <sysdeps/unix/sysdep.h> |
25 | #include <sysdeps/unix/sysv/linux/sysdep.h> |
26 | |
27 | /* "workarounds" for generic code needing to handle 64-bit time_t. */ |
28 | |
29 | /* Fix sysdeps/unix/sysv/linux/clock_getcpuclockid.c. */ |
30 | #define __NR_clock_getres __NR_clock_getres_time64 |
31 | /* Fix sysdeps/nptl/lowlevellock-futex.h. */ |
32 | #define __NR_futex __NR_futex_time64 |
33 | /* Fix sysdeps/unix/sysv/linux/pause.c. */ |
34 | #define __NR_ppoll __NR_ppoll_time64 |
35 | /* Fix sysdeps/unix/sysv/linux/select.c. */ |
36 | #define __NR_pselect6 __NR_pselect6_time64 |
37 | /* Fix sysdeps/unix/sysv/linux/recvmmsg.c. */ |
38 | #define __NR_recvmmsg __NR_recvmmsg_time64 |
39 | /* Fix sysdeps/unix/sysv/linux/sigtimedwait.c. */ |
40 | #define __NR_rt_sigtimedwait __NR_rt_sigtimedwait_time64 |
41 | /* Fix sysdeps/unix/sysv/linux/semtimedop.c. */ |
42 | #define __NR_semtimedop __NR_semtimedop_time64 |
43 | /* Hack sysdeps/unix/sysv/linux/generic/utimes.c. */ |
44 | #define __NR_utimensat __NR_utimensat_time64 |
45 | |
46 | /* For RTLD_PRIVATE_ERRNO. */ |
47 | #include <dl-sysdep.h> |
48 | |
49 | #include <tls.h> |
50 | |
51 | #undef SYS_ify |
52 | #define SYS_ify(syscall_name) __NR_##syscall_name |
53 | |
54 | #ifdef __ASSEMBLER__ |
55 | |
56 | /* This is a "normal" system call stub: if there is an error, |
57 | it returns -1 and sets errno. */ |
58 | |
59 | # undef PSEUDO |
60 | # define PSEUDO(name, syscall_name, args) \ |
61 | PSEUDO_NOERRNO(name, syscall_name, args) ASM_LINE_SEP \ |
62 | brhi r0, -4096, L (call_syscall_err) ASM_LINE_SEP |
63 | |
64 | # define ret j_s [blink] |
65 | |
66 | # undef PSEUDO_END |
67 | # define PSEUDO_END(name) \ |
68 | SYSCALL_ERROR_HANDLER ASM_LINE_SEP \ |
69 | END (name) |
70 | |
71 | /* --------- Helper for SYSCALL_NOERRNO ----------- |
72 | This kind of system call stub never returns an error. |
73 | We return the return value register to the caller unexamined. */ |
74 | |
75 | # undef PSEUDO_NOERRNO |
76 | # define PSEUDO_NOERRNO(name, syscall_name, args) \ |
77 | .text ASM_LINE_SEP \ |
78 | ENTRY (name) ASM_LINE_SEP \ |
79 | DO_CALL (syscall_name, args) ASM_LINE_SEP \ |
80 | |
81 | /* Return the return value register unexamined. Since r0 is both |
82 | syscall return reg and function return reg, no work needed. */ |
83 | # define ret_NOERRNO \ |
84 | j_s [blink] ASM_LINE_SEP |
85 | |
86 | # undef PSEUDO_END_NOERRNO |
87 | # define PSEUDO_END_NOERRNO(name) \ |
88 | END (name) |
89 | |
90 | /* --------- Helper for SYSCALL_ERRVAL ----------- |
91 | This kind of system call stub returns the errno code as its return |
92 | value, or zero for success. We may massage the kernel's return value |
93 | to meet that ABI, but we never set errno here. */ |
94 | |
95 | # undef PSEUDO_ERRVAL |
96 | # define PSEUDO_ERRVAL(name, syscall_name, args) \ |
97 | PSEUDO_NOERRNO(name, syscall_name, args) ASM_LINE_SEP |
98 | |
99 | /* Don't set errno, return kernel error (in errno form) or zero. */ |
100 | # define ret_ERRVAL \ |
101 | rsub r0, r0, 0 ASM_LINE_SEP \ |
102 | ret_NOERRNO |
103 | |
104 | # undef PSEUDO_END_ERRVAL |
105 | # define PSEUDO_END_ERRVAL(name) \ |
106 | END (name) |
107 | |
108 | |
109 | /* To reduce the code footprint, we confine the actual errno access |
110 | to single place in __syscall_error(). |
111 | This takes raw kernel error value, sets errno and returns -1. */ |
112 | # if IS_IN (libc) |
113 | # define CALL_ERRNO_SETTER_C bl PLTJMP(HIDDEN_JUMPTARGET(__syscall_error)) |
114 | # else |
115 | # define CALL_ERRNO_SETTER_C bl PLTJMP(__syscall_error) |
116 | # endif |
117 | |
118 | # define SYSCALL_ERROR_HANDLER \ |
119 | L (call_syscall_err): ASM_LINE_SEP \ |
120 | push_s blink ASM_LINE_SEP \ |
121 | cfi_adjust_cfa_offset (4) ASM_LINE_SEP \ |
122 | cfi_rel_offset (blink, 0) ASM_LINE_SEP \ |
123 | CALL_ERRNO_SETTER_C ASM_LINE_SEP \ |
124 | pop_s blink ASM_LINE_SEP \ |
125 | cfi_adjust_cfa_offset (-4) ASM_LINE_SEP \ |
126 | cfi_restore (blink) ASM_LINE_SEP \ |
127 | j_s [blink] |
128 | |
129 | # define DO_CALL(syscall_name, args) \ |
130 | mov r8, __NR_##syscall_name ASM_LINE_SEP \ |
131 | ARC_TRAP_INSN ASM_LINE_SEP |
132 | |
133 | # define ARC_TRAP_INSN trap_s 0 |
134 | |
135 | #else /* !__ASSEMBLER__ */ |
136 | |
137 | # if IS_IN (libc) |
138 | extern long int __syscall_error (long int); |
139 | hidden_proto (__syscall_error) |
140 | # endif |
141 | |
142 | # define ARC_TRAP_INSN "trap_s 0 \n\t" |
143 | |
144 | # define HAVE_CLONE3_WRAPPER 1 |
145 | |
146 | # undef INTERNAL_SYSCALL_NCS |
147 | # define INTERNAL_SYSCALL_NCS(number, nr_args, args...) \ |
148 | ({ \ |
149 | /* Per ABI, r0 is 1st arg and return reg. */ \ |
150 | register long int __ret __asm__("r0"); \ |
151 | register long int _sys_num __asm__("r8"); \ |
152 | \ |
153 | LOAD_ARGS_##nr_args (number, args) \ |
154 | \ |
155 | __asm__ volatile ( \ |
156 | ARC_TRAP_INSN \ |
157 | : "+r" (__ret) \ |
158 | : "r"(_sys_num) ASM_ARGS_##nr_args \ |
159 | : "memory"); \ |
160 | \ |
161 | __ret; }) |
162 | |
163 | # undef INTERNAL_SYSCALL |
164 | # define INTERNAL_SYSCALL(name, nr, args...) \ |
165 | INTERNAL_SYSCALL_NCS(__NR_##name, nr, args) |
166 | |
167 | /* Macros for setting up inline __asm__ input regs. */ |
168 | # define ASM_ARGS_0 |
169 | # define ASM_ARGS_1 ASM_ARGS_0, "r" (__ret) |
170 | # define ASM_ARGS_2 ASM_ARGS_1, "r" (_arg2) |
171 | # define ASM_ARGS_3 ASM_ARGS_2, "r" (_arg3) |
172 | # define ASM_ARGS_4 ASM_ARGS_3, "r" (_arg4) |
173 | # define ASM_ARGS_5 ASM_ARGS_4, "r" (_arg5) |
174 | # define ASM_ARGS_6 ASM_ARGS_5, "r" (_arg6) |
175 | # define ASM_ARGS_7 ASM_ARGS_6, "r" (_arg7) |
176 | |
177 | /* Macros for converting sys-call wrapper args into sys call args. */ |
178 | # define LOAD_ARGS_0(nm, arg) \ |
179 | _sys_num = (long int) (nm); |
180 | |
181 | # define LOAD_ARGS_1(nm, arg1) \ |
182 | __ret = (long int) (arg1); \ |
183 | LOAD_ARGS_0 (nm, arg1) |
184 | |
185 | /* Note that the use of _tmpX might look superfluous, however it is needed |
186 | to ensure that register variables are not clobbered if arg happens to be |
187 | a function call itself. e.g. sched_setaffinity() calling getpid() for arg2 |
188 | Also this specific order of recursive calling is important to segregate |
189 | the tmp args evaluation (function call case described above) and assignment |
190 | of register variables. */ |
191 | |
192 | # define LOAD_ARGS_2(nm, arg1, arg2) \ |
193 | long int _tmp2 = (long int) (arg2); \ |
194 | LOAD_ARGS_1 (nm, arg1) \ |
195 | register long int _arg2 __asm__ ("r1") = _tmp2; |
196 | |
197 | # define LOAD_ARGS_3(nm, arg1, arg2, arg3) \ |
198 | long int _tmp3 = (long int) (arg3); \ |
199 | LOAD_ARGS_2 (nm, arg1, arg2) \ |
200 | register long int _arg3 __asm__ ("r2") = _tmp3; |
201 | |
202 | #define LOAD_ARGS_4(nm, arg1, arg2, arg3, arg4) \ |
203 | long int _tmp4 = (long int) (arg4); \ |
204 | LOAD_ARGS_3 (nm, arg1, arg2, arg3) \ |
205 | register long int _arg4 __asm__ ("r3") = _tmp4; |
206 | |
207 | # define LOAD_ARGS_5(nm, arg1, arg2, arg3, arg4, arg5) \ |
208 | long int _tmp5 = (long int) (arg5); \ |
209 | LOAD_ARGS_4 (nm, arg1, arg2, arg3, arg4) \ |
210 | register long int _arg5 __asm__ ("r4") = _tmp5; |
211 | |
212 | # define LOAD_ARGS_6(nm, arg1, arg2, arg3, arg4, arg5, arg6)\ |
213 | long int _tmp6 = (long int) (arg6); \ |
214 | LOAD_ARGS_5 (nm, arg1, arg2, arg3, arg4, arg5) \ |
215 | register long int _arg6 __asm__ ("r5") = _tmp6; |
216 | |
217 | # define LOAD_ARGS_7(nm, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ |
218 | long int _tmp7 = (int) (arg7); \ |
219 | LOAD_ARGS_6 (nm, arg1, arg2, arg3, arg4, arg5, arg6) \ |
220 | register long int _arg7 __asm__ ("r6") = _tmp7; |
221 | |
222 | # undef HAVE_INTERNAL_BRK_ADDR_SYMBOL |
223 | # define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 |
224 | |
225 | #endif /* !__ASSEMBLER__ */ |
226 | |
227 | #endif /* linux/arc/sysdep.h */ |
228 |
Warning: That file was not part of the compilation database. It may have many parsing errors.