Implement C23 <stdbit.h>
[glibc.git] / sysdeps / unix / sysv / linux / loongarch / sysdep.h
blobeb0ba790daa6e27c3ce9e8ec2d4b476ae382d9df
1 /* Assembly macros for LoongArch.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #ifndef _LINUX_LOONGARCH_SYSDEP_H
20 #define _LINUX_LOONGARCH_SYSDEP_H 1
22 #include <sysdeps/unix/sysv/linux/sysdep.h>
23 #include <sysdeps/unix/sysdep.h>
24 #include <tls.h>
26 #ifdef __ASSEMBLER__
28 #include <sys/asm.h>
29 #define ret jirl zero, ra, 0
30 #define L(label) .L##label
32 /* Performs a system call, handling errors by setting errno. Linux indicates
33 errors by setting a0 to a value between -1 and -4095. */
34 #undef PSEUDO
35 #define PSEUDO(name, syscall_name, args) \
36 ENTRY (name); \
37 li.d a7, SYS_ify (syscall_name); \
38 syscall 0; \
39 li.d a7, -4096; \
40 bltu a7, a0, .Lsyscall_error##name;
42 #undef PSEUDO_END
43 #define PSEUDO_END(sym) \
44 SYSCALL_ERROR_HANDLER (sym); \
45 ret; \
46 END (sym);
48 #if !IS_IN(libc)
49 #if RTLD_PRIVATE_ERRNO
51 #define SYSCALL_ERROR_HANDLER(name) \
52 .Lsyscall_error##name : la t0, rtld_errno; \
53 sub.w a0, zero, a0; \
54 st.w a0, t0, 0; \
55 li.d a0, -1;
57 #else
59 #define SYSCALL_ERROR_HANDLER(name) \
60 .Lsyscall_error##name : la.tls.ie t0, errno; \
61 add.d t0, tp, t0; \
62 sub.w a0, zero, a0; \
63 st.w a0, t0, 0; \
64 li.d a0, -1;
66 #endif
67 #else
69 #define SYSCALL_ERROR_HANDLER(name) .Lsyscall_error##name : b __syscall_error;
71 #endif
73 /* Performs a system call, not setting errno. */
74 #undef PSEUDO_NEORRNO
75 #define PSEUDO_NOERRNO(name, syscall_name, args) \
76 ENTRY (name); \
77 li.d a7, SYS_ify (syscall_name); \
78 syscall 0;
80 #undef PSEUDO_END_NOERRNO
81 #define PSEUDO_END_NOERRNO(name) END (name);
83 #undef ret_NOERRNO
84 #define ret_NOERRNO ret
86 /* Performs a system call, returning the error code. */
87 #undef PSEUDO_ERRVAL
88 #define PSEUDO_ERRVAL(name, syscall_name, args) \
89 PSEUDO_NOERRNO (name, syscall_name, args); \
90 slli.d a0, a0, 32; \
91 srai.d a0, a0, 32; /* sign_ext */ \
92 sub.d a0, zero, a0;
94 #undef PSEUDO_END_ERRVAL
95 #define PSEUDO_END_ERRVAL(name) END (name);
97 #undef ret_ERRVAL
98 #define ret_ERRVAL ret
100 #endif /* __ASSEMBLER__ */
102 /* In order to get __set_errno() definition in INLINE_SYSCALL. */
103 #ifndef __ASSEMBLER__
104 #include <errno.h>
105 #endif
107 #include <sysdeps/unix/sysdep.h>
109 #undef SYS_ify
110 #define SYS_ify(syscall_name) __NR_##syscall_name
112 #ifndef __ASSEMBLER__
114 #define VDSO_NAME "LINUX_5.10"
115 #define VDSO_HASH 182947696
117 /* List of system calls which are supported as vsyscalls. */
118 #define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres"
119 #define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime"
120 #define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday"
121 #define HAVE_GETCPU_VSYSCALL "__vdso_getcpu"
123 #define HAVE_CLONE3_WRAPPER 1
125 #define INTERNAL_SYSCALL(name, nr, args...) \
126 internal_syscall##nr (SYS_ify (name), args)
128 #define INTERNAL_SYSCALL_NCS(number, nr, args...) \
129 internal_syscall##nr (number, args)
131 #define internal_syscall0(number, dummy...) \
132 ({ \
133 long int _sys_result; \
136 register long int __a7 asm ("$a7") = number; \
137 register long int __a0 asm ("$a0"); \
138 __asm__ volatile ("syscall 0\n\t" \
139 : "=r"(__a0) \
140 : "r"(__a7) \
141 : __SYSCALL_CLOBBERS); \
142 _sys_result = __a0; \
144 _sys_result; \
147 #define internal_syscall1(number, arg0) \
148 ({ \
149 long int _sys_result; \
152 long int _arg0 = (long int) (arg0); \
153 register long int __a7 asm ("$a7") = number; \
154 register long int __a0 asm ("$a0") = _arg0; \
155 __asm__ volatile ("syscall 0\n\t" \
156 : "+r"(__a0) \
157 : "r"(__a7) \
158 : __SYSCALL_CLOBBERS); \
159 _sys_result = __a0; \
161 _sys_result; \
164 #define internal_syscall2(number, arg0, arg1) \
165 ({ \
166 long int _sys_result; \
169 long int _arg0 = (long int) (arg0); \
170 long int _arg1 = (long int) (arg1); \
171 register long int __a7 asm ("$a7") = number; \
172 register long int __a0 asm ("$a0") = _arg0; \
173 register long int __a1 asm ("$a1") = _arg1; \
174 __asm__ volatile ("syscall 0\n\t" \
175 : "+r"(__a0) \
176 : "r"(__a7), "r"(__a1) \
177 : __SYSCALL_CLOBBERS); \
178 _sys_result = __a0; \
180 _sys_result; \
183 #define internal_syscall3(number, arg0, arg1, arg2) \
184 ({ \
185 long int _sys_result; \
188 long int _arg0 = (long int) (arg0); \
189 long int _arg1 = (long int) (arg1); \
190 long int _arg2 = (long int) (arg2); \
191 register long int __a7 asm ("$a7") = number; \
192 register long int __a0 asm ("$a0") = _arg0; \
193 register long int __a1 asm ("$a1") = _arg1; \
194 register long int __a2 asm ("$a2") = _arg2; \
195 __asm__ volatile ("syscall 0\n\t" \
196 : "+r"(__a0) \
197 : "r"(__a7), "r"(__a1), "r"(__a2) \
198 : __SYSCALL_CLOBBERS); \
199 _sys_result = __a0; \
201 _sys_result; \
204 #define internal_syscall4(number, arg0, arg1, arg2, arg3) \
205 ({ \
206 long int _sys_result; \
209 long int _arg0 = (long int) (arg0); \
210 long int _arg1 = (long int) (arg1); \
211 long int _arg2 = (long int) (arg2); \
212 long int _arg3 = (long int) (arg3); \
213 register long int __a7 asm ("$a7") = number; \
214 register long int __a0 asm ("$a0") = _arg0; \
215 register long int __a1 asm ("$a1") = _arg1; \
216 register long int __a2 asm ("$a2") = _arg2; \
217 register long int __a3 asm ("$a3") = _arg3; \
218 __asm__ volatile ("syscall 0\n\t" \
219 : "+r"(__a0) \
220 : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3) \
221 : __SYSCALL_CLOBBERS); \
222 _sys_result = __a0; \
224 _sys_result; \
227 #define internal_syscall5(number, arg0, arg1, arg2, arg3, arg4) \
228 ({ \
229 long int _sys_result; \
232 long int _arg0 = (long int) (arg0); \
233 long int _arg1 = (long int) (arg1); \
234 long int _arg2 = (long int) (arg2); \
235 long int _arg3 = (long int) (arg3); \
236 long int _arg4 = (long int) (arg4); \
237 register long int __a7 asm ("$a7") = number; \
238 register long int __a0 asm ("$a0") = _arg0; \
239 register long int __a1 asm ("$a1") = _arg1; \
240 register long int __a2 asm ("$a2") = _arg2; \
241 register long int __a3 asm ("$a3") = _arg3; \
242 register long int __a4 asm ("$a4") = _arg4; \
243 __asm__ volatile ("syscall 0\n\t" \
244 : "+r"(__a0) \
245 : "r"(__a7), "r"(__a1), "r"(__a2), \
246 "r"(__a3), "r"(__a4) \
247 : __SYSCALL_CLOBBERS); \
248 _sys_result = __a0; \
250 _sys_result; \
253 #define internal_syscall6(number, arg0, arg1, arg2, arg3, arg4, arg5) \
254 ({ \
255 long int _sys_result; \
258 long int _arg0 = (long int) (arg0); \
259 long int _arg1 = (long int) (arg1); \
260 long int _arg2 = (long int) (arg2); \
261 long int _arg3 = (long int) (arg3); \
262 long int _arg4 = (long int) (arg4); \
263 long int _arg5 = (long int) (arg5); \
264 register long int __a7 asm ("$a7") = number; \
265 register long int __a0 asm ("$a0") = _arg0; \
266 register long int __a1 asm ("$a1") = _arg1; \
267 register long int __a2 asm ("$a2") = _arg2; \
268 register long int __a3 asm ("$a3") = _arg3; \
269 register long int __a4 asm ("$a4") = _arg4; \
270 register long int __a5 asm ("$a5") = _arg5; \
271 __asm__ volatile ("syscall 0\n\t" \
272 : "+r"(__a0) \
273 : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \
274 "r"(__a4), "r"(__a5) \
275 : __SYSCALL_CLOBBERS); \
276 _sys_result = __a0; \
278 _sys_result; \
281 #define internal_syscall7(number, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \
282 ({ \
283 long int _sys_result; \
286 long int _arg0 = (long int) (arg0); \
287 long int _arg1 = (long int) (arg1); \
288 long int _arg2 = (long int) (arg2); \
289 long int _arg3 = (long int) (arg3); \
290 long int _arg4 = (long int) (arg4); \
291 long int _arg5 = (long int) (arg5); \
292 long int _arg6 = (long int) (arg6); \
293 register long int __a7 asm ("$a7") = number; \
294 register long int __a0 asm ("$a0") = _arg0; \
295 register long int __a1 asm ("$a1") = _arg1; \
296 register long int __a2 asm ("$a2") = _arg2; \
297 register long int __a3 asm ("$a3") = _arg3; \
298 register long int __a4 asm ("$a4") = _arg4; \
299 register long int __a5 asm ("$a5") = _arg5; \
300 register long int __a6 asm ("$a6") = _arg6; \
301 __asm__ volatile ("syscall 0\n\t" \
302 : "+r"(__a0) \
303 : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \
304 "r"(__a4), "r"(__a5), "r"(__a6) \
305 : __SYSCALL_CLOBBERS); \
306 _sys_result = __a0; \
308 _sys_result; \
311 #define __SYSCALL_CLOBBERS \
312 "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
314 extern long int __syscall_error (long int neg_errno);
316 #endif /* ! __ASSEMBLER__ */
318 #endif /* linux/loongarch/sysdep.h */