aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/arc/sysdep.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/arc/sysdep.h')
-rw-r--r--sysdeps/unix/sysv/linux/arc/sysdep.h226
1 files changed, 226 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/arc/sysdep.h b/sysdeps/unix/sysv/linux/arc/sysdep.h
new file mode 100644
index 0000000000..8465a2f623
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/sysdep.h
@@ -0,0 +1,226 @@
+/* Assembler macros for ARC.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LINUX_ARC_SYSDEP_H
+#define _LINUX_ARC_SYSDEP_H 1
+
+#include <sysdeps/arc/sysdep.h>
+#include <sysdeps/unix/sysv/linux/generic/sysdep.h>
+
+/* "workarounds" for generic code needing to handle 64-bit time_t. */
+
+/* Fix sysdeps/unix/sysv/linux/clock_getcpuclockid.c. */
+#define __NR_clock_getres __NR_clock_getres_time64
+/* Fix sysdeps/nptl/lowlevellock-futex.h. */
+#define __NR_futex __NR_futex_time64
+/* Fix sysdeps/unix/sysv/linux/pause.c. */
+#define __NR_ppoll __NR_ppoll_time64
+/* Fix sysdeps/unix/sysv/linux/select.c. */
+#define __NR_pselect6 __NR_pselect6_time64
+/* Fix sysdeps/unix/sysv/linux/recvmmsg.c. */
+#define __NR_recvmmsg __NR_recvmmsg_time64
+/* Fix sysdeps/unix/sysv/linux/sigtimedwait.c. */
+#define __NR_rt_sigtimedwait __NR_rt_sigtimedwait_time64
+/* Fix sysdeps/unix/sysv/linux/semtimedop.c. */
+#define __NR_semtimedop __NR_semtimedop_time64
+/* Hack sysdeps/unix/sysv/linux/generic/utimes.c. */
+#define __NR_utimensat __NR_utimensat_time64
+
+/* For RTLD_PRIVATE_ERRNO. */
+#include <dl-sysdep.h>
+
+#include <tls.h>
+
+#undef SYS_ify
+#define SYS_ify(syscall_name) __NR_##syscall_name
+
+#ifdef __ASSEMBLER__
+
+/* This is a "normal" system call stub: if there is an error,
+ it returns -1 and sets errno. */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ PSEUDO_NOERRNO(name, syscall_name, args) ASM_LINE_SEP \
+ brhi r0, -4096, L (call_syscall_err) ASM_LINE_SEP
+
+# define ret j_s [blink]
+
+# undef PSEUDO_END
+# define PSEUDO_END(name) \
+ SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
+ END (name)
+
+/* --------- Helper for SYSCALL_NOERRNO -----------
+ This kind of system call stub never returns an error.
+ We return the return value register to the caller unexamined. */
+
+# undef PSEUDO_NOERRNO
+# define PSEUDO_NOERRNO(name, syscall_name, args) \
+ .text ASM_LINE_SEP \
+ ENTRY (name) ASM_LINE_SEP \
+ DO_CALL (syscall_name, args) ASM_LINE_SEP \
+
+/* Return the return value register unexamined. Since r0 is both
+ syscall return reg and function return reg, no work needed. */
+# define ret_NOERRNO \
+ j_s [blink] ASM_LINE_SEP
+
+# undef PSEUDO_END_NOERRNO
+# define PSEUDO_END_NOERRNO(name) \
+ END (name)
+
+/* --------- Helper for SYSCALL_ERRVAL -----------
+ This kind of system call stub returns the errno code as its return
+ value, or zero for success. We may massage the kernel's return value
+ to meet that ABI, but we never set errno here. */
+
+# undef PSEUDO_ERRVAL
+# define PSEUDO_ERRVAL(name, syscall_name, args) \
+ PSEUDO_NOERRNO(name, syscall_name, args) ASM_LINE_SEP
+
+/* Don't set errno, return kernel error (in errno form) or zero. */
+# define ret_ERRVAL \
+ rsub r0, r0, 0 ASM_LINE_SEP \
+ ret_NOERRNO
+
+# undef PSEUDO_END_ERRVAL
+# define PSEUDO_END_ERRVAL(name) \
+ END (name)
+
+
+/* To reduce the code footprint, we confine the actual errno access
+ to single place in __syscall_error().
+ This takes raw kernel error value, sets errno and returns -1. */
+# if IS_IN (libc)
+# define CALL_ERRNO_SETTER_C bl PLTJMP(HIDDEN_JUMPTARGET(__syscall_error))
+# else
+# define CALL_ERRNO_SETTER_C bl PLTJMP(__syscall_error)
+# endif
+
+# define SYSCALL_ERROR_HANDLER \
+L (call_syscall_err): ASM_LINE_SEP \
+ push_s blink ASM_LINE_SEP \
+ cfi_adjust_cfa_offset (4) ASM_LINE_SEP \
+ cfi_rel_offset (blink, 0) ASM_LINE_SEP \
+ CALL_ERRNO_SETTER_C ASM_LINE_SEP \
+ pop_s blink ASM_LINE_SEP \
+ cfi_adjust_cfa_offset (-4) ASM_LINE_SEP \
+ cfi_restore (blink) ASM_LINE_SEP \
+ j_s [blink]
+
+# define DO_CALL(syscall_name, args) \
+ mov r8, __NR_##syscall_name ASM_LINE_SEP \
+ ARC_TRAP_INSN ASM_LINE_SEP
+
+# define ARC_TRAP_INSN trap_s 0
+
+#else /* !__ASSEMBLER__ */
+
+# define SINGLE_THREAD_BY_GLOBAL 1
+
+# if IS_IN (libc)
+extern long int __syscall_error (long int);
+hidden_proto (__syscall_error)
+# endif
+
+# define ARC_TRAP_INSN "trap_s 0 \n\t"
+
+# undef INTERNAL_SYSCALL_NCS
+# define INTERNAL_SYSCALL_NCS(number, nr_args, args...) \
+ ({ \
+ /* Per ABI, r0 is 1st arg and return reg. */ \
+ register long int __ret __asm__("r0"); \
+ register long int _sys_num __asm__("r8"); \
+ \
+ LOAD_ARGS_##nr_args (number, args) \
+ \
+ __asm__ volatile ( \
+ ARC_TRAP_INSN \
+ : "+r" (__ret) \
+ : "r"(_sys_num) ASM_ARGS_##nr_args \
+ : "memory"); \
+ \
+ __ret; })
+
+# undef INTERNAL_SYSCALL
+# define INTERNAL_SYSCALL(name, nr, args...) \
+ INTERNAL_SYSCALL_NCS(__NR_##name, nr, args)
+
+/* Macros for setting up inline __asm__ input regs. */
+# define ASM_ARGS_0
+# define ASM_ARGS_1 ASM_ARGS_0, "r" (__ret)
+# define ASM_ARGS_2 ASM_ARGS_1, "r" (_arg2)
+# define ASM_ARGS_3 ASM_ARGS_2, "r" (_arg3)
+# define ASM_ARGS_4 ASM_ARGS_3, "r" (_arg4)
+# define ASM_ARGS_5 ASM_ARGS_4, "r" (_arg5)
+# define ASM_ARGS_6 ASM_ARGS_5, "r" (_arg6)
+# define ASM_ARGS_7 ASM_ARGS_6, "r" (_arg7)
+
+/* Macros for converting sys-call wrapper args into sys call args. */
+# define LOAD_ARGS_0(nm, arg) \
+ _sys_num = (long int) (nm);
+
+# define LOAD_ARGS_1(nm, arg1) \
+ __ret = (long int) (arg1); \
+ LOAD_ARGS_0 (nm, arg1)
+
+/* Note that the use of _tmpX might look superflous, however it is needed
+ to ensure that register variables are not clobbered if arg happens to be
+ a function call itself. e.g. sched_setaffinity() calling getpid() for arg2
+ Also this specific order of recursive calling is important to segregate
+ the tmp args evaluation (function call case described above) and assigment
+ of register variables. */
+
+# define LOAD_ARGS_2(nm, arg1, arg2) \
+ long int _tmp2 = (long int) (arg2); \
+ LOAD_ARGS_1 (nm, arg1) \
+ register long int _arg2 __asm__ ("r1") = _tmp2;
+
+# define LOAD_ARGS_3(nm, arg1, arg2, arg3) \
+ long int _tmp3 = (long int) (arg3); \
+ LOAD_ARGS_2 (nm, arg1, arg2) \
+ register long int _arg3 __asm__ ("r2") = _tmp3;
+
+#define LOAD_ARGS_4(nm, arg1, arg2, arg3, arg4) \
+ long int _tmp4 = (long int) (arg4); \
+ LOAD_ARGS_3 (nm, arg1, arg2, arg3) \
+ register long int _arg4 __asm__ ("r3") = _tmp4;
+
+# define LOAD_ARGS_5(nm, arg1, arg2, arg3, arg4, arg5) \
+ long int _tmp5 = (long int) (arg5); \
+ LOAD_ARGS_4 (nm, arg1, arg2, arg3, arg4) \
+ register long int _arg5 __asm__ ("r4") = _tmp5;
+
+# define LOAD_ARGS_6(nm, arg1, arg2, arg3, arg4, arg5, arg6)\
+ long int _tmp6 = (long int) (arg6); \
+ LOAD_ARGS_5 (nm, arg1, arg2, arg3, arg4, arg5) \
+ register long int _arg6 __asm__ ("r5") = _tmp6;
+
+# define LOAD_ARGS_7(nm, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
+ long int _tmp7 = (int) (arg7); \
+ LOAD_ARGS_6 (nm, arg1, arg2, arg3, arg4, arg5, arg6) \
+ register long int _arg7 __asm__ ("r6") = _tmp7;
+
+/* Pointer mangling not yet supported. */
+# define PTR_MANGLE(var) (void) (var)
+# define PTR_DEMANGLE(var) (void) (var)
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* linux/arc/sysdep.h */