Signed-off-by: Vineet Gupta <vgu...@synopsys.com>
---
 ChangeLog                                     |  12 ++
 sysdeps/unix/sysv/linux/arc/cacheflush.c      |  29 +++
 sysdeps/unix/sysv/linux/arc/clone.S           | 100 ++++++++++
 sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h  |   6 +
 sysdeps/unix/sysv/linux/arc/kernel-features.h |  28 +++
 sysdeps/unix/sysv/linux/arc/mmap_internal.h   |  26 +++
 sysdeps/unix/sysv/linux/arc/profil-counter.h  |   2 +
 sysdeps/unix/sysv/linux/arc/pt-vfork.S        |   1 +
 sysdeps/unix/sysv/linux/arc/sigaction.c       |  69 +++++++
 sysdeps/unix/sysv/linux/arc/syscall.S         |  38 ++++
 sysdeps/unix/sysv/linux/arc/sysdep.c          |  33 ++++
 sysdeps/unix/sysv/linux/arc/sysdep.h          | 259 ++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/arc/vfork.S           |  42 +++++
 13 files changed, 645 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/arc/cacheflush.c
 create mode 100644 sysdeps/unix/sysv/linux/arc/clone.S
 create mode 100644 sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h
 create mode 100644 sysdeps/unix/sysv/linux/arc/kernel-features.h
 create mode 100644 sysdeps/unix/sysv/linux/arc/mmap_internal.h
 create mode 100644 sysdeps/unix/sysv/linux/arc/profil-counter.h
 create mode 100644 sysdeps/unix/sysv/linux/arc/pt-vfork.S
 create mode 100644 sysdeps/unix/sysv/linux/arc/sigaction.c
 create mode 100644 sysdeps/unix/sysv/linux/arc/syscall.S
 create mode 100644 sysdeps/unix/sysv/linux/arc/sysdep.c
 create mode 100644 sysdeps/unix/sysv/linux/arc/sysdep.h
 create mode 100644 sysdeps/unix/sysv/linux/arc/vfork.S

diff --git a/ChangeLog b/ChangeLog
index b946f57204b6..08a3ac7e8064 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -44,6 +44,18 @@
        * sysdeps/arc/nofpu/math-tests-exception.h: New file.
        * sysdeps/arc/nofpu/math-tests-rounding.h: New file.
        * sysdeps/arc/sfp-machine.h: New file.
+       * sysdeps/unix/sysv/linux/arc/cacheflush.c: New file.
+       * sysdeps/unix/sysv/linux/arc/clone.S: New file.
+       * sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h: New file.
+       * sysdeps/unix/sysv/linux/arc/kernel-features.h: New file.
+       * sysdeps/unix/sysv/linux/arc/mmap_internal.h: New file.
+       * sysdeps/unix/sysv/linux/arc/profil-counter.h: New file.
+       * sysdeps/unix/sysv/linux/arc/pt-vfork.S: New file.
+       * sysdeps/unix/sysv/linux/arc/sigaction.c: New file.
+       * sysdeps/unix/sysv/linux/arc/syscall.S: New file.
+       * sysdeps/unix/sysv/linux/arc/sysdep.c: New file.
+       * sysdeps/unix/sysv/linux/arc/sysdep.h: New file.
+       * sysdeps/unix/sysv/linux/arc/vfork.S: New file.
 
 2018-12-17  Joseph Myers  <jos...@codesourcery.com>
 
diff --git a/sysdeps/unix/sysv/linux/arc/cacheflush.c 
b/sysdeps/unix/sysv/linux/arc/cacheflush.c
new file mode 100644
index 000000000000..7b14211eccf7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/cacheflush.c
@@ -0,0 +1,29 @@
+/* cacheflush system call for ARC Linux.
+   Copyright (C) 2017-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <stddef.h>
+#include <unistd.h>
+
+/* Flush cache(s).  */
+int
+_flush_cache (char *addr, const int nbytes, const int op)
+{
+  return INLINE_SYSCALL (cacheflush, 3, addr, nbytes, op);
+}
+weak_alias (_flush_cache, cacheflush)
diff --git a/sysdeps/unix/sysv/linux/arc/clone.S 
b/sysdeps/unix/sysv/linux/arc/clone.S
new file mode 100644
index 000000000000..04f2df5ef06d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/clone.S
@@ -0,0 +1,100 @@
+/* clone() implementation for ARC.
+   Copyright (C) 2008-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andrew Jenner <and...@codesourcery.com>, 2008.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+
+#include <sysdep.h>
+#define _ERRNO_H       1
+#include <bits/errno.h>
+#include <tcb-offsets.h>
+
+#define CLONE_SETTLS           0x00080000
+
+; int clone(int (*fn)(void *), void *child_stack,
+;           int flags, void *arg, ...
+;           /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */);
+;
+; NOTE: I'm assuming that the last 3 args are NOT var-args and in case all
+;      3 are not relevant, caller will nevertheless pass those as NULL.
+;       Current (Jul 2012) upstream powerpc/clone.S assumes similarly.
+;      Our LTP (from 2007) doesn't seem to have tests to prove otherwise
+
+; clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS)
+;
+; int sys_clone(unsigned long clone_flags,
+;              unsigned long newsp,
+;              int __user *parent_tidptr,
+;              void *tls,
+;              int __user *child_tidptr)
+
+ENTRY(__clone)
+       cmp     r0, 0           ; @fn can't be NULL
+       cmp.ne  r1, 0           ; @child_stack can't be NULL
+       bz      .L__sys_err
+
+       ; save some of the orig args
+       ; r0 containg @fn will be clobbered AFTER syscall (with ret val)
+       ; rest are clobbered BEFORE syscall due to different arg ordering
+       mov     r10, r0         ; @fn
+       mov     r11, r3         ; @args
+       mov     r12, r2         ; @clone_flags
+       mov     r9,  r5         ; @tls
+
+       ; adjust libc args for syscall
+
+       mov     r0, r2          ; libc @flags is 1st syscall arg
+       mov     r2, r4          ; libc @ptid
+       mov     r3, r5          ; libc @tls
+       mov     r4, r6          ; libc @ctid
+       mov     r8, __NR_clone
+       ARC_TRAP_INSN
+
+       cmp     r0, 0           ; return code : 0 new process, !0 parent
+       blt     .L__sys_err2    ; < 0 (signed) error
+       jnz     [blink]         ; Parent returns
+
+       ; ----- child starts here ---------
+
+       ; Setup TP register (only recent kernels v4.19+ do that)
+       and.f   0, r12, CLONE_SETTLS
+       mov.nz  r25, r9
+
+       ; child jumps off to @fn with @arg as argument, and returns here
+       jl.d    [r10]
+       mov     r0, r11
+
+       ; exit() with result from @fn (already in r0)
+       mov     r8, __NR_exit
+       ARC_TRAP_INSN
+       ; In case it ever came back
+       flag    1
+
+.L__sys_err:
+       mov     r0, -EINVAL
+.L__sys_err2:
+       ; (1) No need to make -ve kernel error code as positive errno
+       ;   __syscall_error expects the -ve error code returned by kernel
+       ; (2) r0 still had orig -ve kernel error code
+       ; (3) Tail call to __syscall_error so we dont have to come back
+       ;     here hence instead of jmp-n-link (reg push/pop) we do jmp
+       ; (4) No need to route __syscall_error via PLT, B is inherently
+       ;     position independent
+       b   __syscall_error
+PSEUDO_END (__clone)
+libc_hidden_def (__clone)
+weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h 
b/sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h
new file mode 100644
index 000000000000..2fec69d21657
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h
@@ -0,0 +1,6 @@
+#define JMP_BUF_SIZE           (32 + 1 + 1024/32) * 4
+#define SIGJMP_BUF_SIZE                (32 + 1 + 1024/32) * 4
+#define JMP_BUF_ALIGN          4
+#define SIGJMP_BUF_ALIGN       4
+#define MASK_WAS_SAVED_OFFSET  32 * 4
+#define SAVED_MASK_OFFSET      33 * 4
diff --git a/sysdeps/unix/sysv/linux/arc/kernel-features.h 
b/sysdeps/unix/sysv/linux/arc/kernel-features.h
new file mode 100644
index 000000000000..d8f667ca4759
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/kernel-features.h
@@ -0,0 +1,28 @@
+/* Set flags signalling availability of kernel features based on given
+   kernel version number.
+
+   Copyright (C) 2009-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+/* The minimum supported kernel version for ARC is 3.9,
+   guaranteeing many kernel features.  */
+
+#include_next <kernel-features.h>
+
+#undef __ASSUME_CLONE_DEFAULT
+#define __ASSUME_CLONE_BACKWARDS 1
diff --git a/sysdeps/unix/sysv/linux/arc/mmap_internal.h 
b/sysdeps/unix/sysv/linux/arc/mmap_internal.h
new file mode 100644
index 000000000000..3c8c55d57d0e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/mmap_internal.h
@@ -0,0 +1,26 @@
+/* mmap - map files or devices into memory.  Linux/ARC version.
+   Copyright (C) 2017-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef MMAP_ARC_INTERNAL_H
+#define MMAP_ARC_INTERNAL_H
+
+#define MMAP2_PAGE_UNIT 8192ULL        /* 8K page is default for ARC */
+
+#include_next <mmap_internal.h>
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/arc/profil-counter.h 
b/sysdeps/unix/sysv/linux/arc/profil-counter.h
new file mode 100644
index 000000000000..8a6a0bcf3d59
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/profil-counter.h
@@ -0,0 +1,2 @@
+/* We can use the ix86 version.  */
+#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>
diff --git a/sysdeps/unix/sysv/linux/arc/pt-vfork.S 
b/sysdeps/unix/sysv/linux/arc/pt-vfork.S
new file mode 100644
index 000000000000..65cc3823ac87
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/pt-vfork.S
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/arc/sigaction.c 
b/sysdeps/unix/sysv/linux/arc/sigaction.c
new file mode 100644
index 000000000000..0a58e78f8834
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/sigaction.c
@@ -0,0 +1,69 @@
+/* ARC specific sigaction and signal restorer
+   Copyright (C) 1997-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/syscall.h>
+
+/*
+ * Default sigretrun stub if user doesn't specify SA_RESTORER
+ */
+static void __default_rt_sa_restorer(void)
+{
+       INTERNAL_SYSCALL_NCS(__NR_rt_sigreturn, , 0);
+}
+
+#define SA_RESTORER    0x04000000
+
+/* If @act is not NULL, change the action for @sig to @act.
+   If @oact is not NULL, put the old action for @sig in @oact.  */
+int
+__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
+{
+       struct sigaction kact;
+       const struct sigaction *arg;
+
+       /*
+        * SA_RESTORER is only relevant for act != NULL case
+        * (!act means caller only wants to know @oact)
+        */
+       if (act && !(act->sa_flags & SA_RESTORER)) {
+               kact.sa_restorer = __default_rt_sa_restorer;
+               kact.sa_flags = act->sa_flags | SA_RESTORER;
+
+               kact.sa_handler = act->sa_handler;
+               kact.sa_mask = act->sa_mask;
+
+               arg = &kact;
+       } else {
+               arg = act;
+       }
+
+       /*
+        * syscall also expects sizeof(sa_mask) and asm-generic kernel syscall
+        * ABI mandates it be 2 words (8 bytes below) although glibc defines
+        * sigset_to be much larger (1024 / 32 == 64 bytes)
+        */
+       return INLINE_SYSCALL(rt_sigaction, 4, sig, arg, oact, _NSIG / 8);
+}
+
+libc_hidden_def (__libc_sigaction)
+
+#include <nptl/sigaction.c>
diff --git a/sysdeps/unix/sysv/linux/arc/syscall.S 
b/sysdeps/unix/sysv/linux/arc/syscall.S
new file mode 100644
index 000000000000..8f76fa43e95f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/syscall.S
@@ -0,0 +1,38 @@
+/* syscall - indirect system call.
+   Copyright (C) 2017-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+ENTRY (syscall)
+       mov_s   r8, r0
+       mov_s   r0, r1
+       mov_s   r1, r2
+       mov_s   r2, r3
+       mov_s   r3, r4
+#ifdef __ARC700__
+       mov     r4, r5
+       mov     r5, r6
+#else
+       mov_s   r4, r5
+       mov_s   r5, r6
+#endif
+
+       ARC_TRAP_INSN
+       brhi    r0, -1024, .Lcall_syscall_err
+       j       [blink]
+PSEUDO_END (syscall)
diff --git a/sysdeps/unix/sysv/linux/arc/sysdep.c 
b/sysdeps/unix/sysv/linux/arc/sysdep.c
new file mode 100644
index 000000000000..d9bcc305b846
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/sysdep.c
@@ -0,0 +1,33 @@
+/* ARC wrapper for setting errno
+   Copyright (C) 1997-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <errno.h>
+
+/* All syscall handler come here to avoid generated code bloat due to
+ * GOT reference  to errno_location or it's equivalent
+ */
+int __syscall_error(int err_no)
+{
+       __set_errno(-err_no);
+       return -1;
+}
+
+#if IS_IN (libc)
+hidden_def (__syscall_error)
+#endif
diff --git a/sysdeps/unix/sysv/linux/arc/sysdep.h 
b/sysdeps/unix/sysv/linux/arc/sysdep.h
new file mode 100644
index 000000000000..39d1f03c3710
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/sysdep.h
@@ -0,0 +1,259 @@
+/* Assembler macros for ARC.
+   Copyright (C) 2000-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LINUX_ARC_SYSDEP_H
+#define _LINUX_ARC_SYSDEP_H 1
+
+#include <asm/unistd.h>
+#include <sysdeps/arc/sysdep.h>
+#include <sysdeps/unix/sysv/linux/generic/sysdep.h>
+
+/* 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, -1024, .Lcall_syscall_err       ASM_LINE_SEP
+
+#define ret    j  [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
+ * r0 is both syscall return reg and function return reg, so no need to do
+ * anything
+ */
+# 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                                 \
+.Lcall_syscall_err:                            ASM_LINE_SEP    \
+    st.a   blink, [sp, -4]                     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    \
+    ld.ab  blink, [sp, 4]                      ASM_LINE_SEP    \
+    cfi_adjust_cfa_offset (-4)                 ASM_LINE_SEP    \
+    cfi_restore (blink)                                ASM_LINE_SEP    \
+    j      [blink]
+
+# define DO_CALL(syscall_name, args)                           \
+    mov    r8, SYS_ify (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
+
+/* In order to get __set_errno() definition in INLINE_SYSCALL.  */
+#include <errno.h>
+
+extern int __syscall_error (int);
+
+#if IS_IN (libc)
+hidden_proto (__syscall_error)
+#define CALL_ERRNO_SETTER   "bl   __syscall_error    \n\t"
+#else
+#define CALL_ERRNO_SETTER   "bl   __syscall_error@plt    \n\t"
+#endif
+
+
+/* Define a macro which expands into the inline wrapper code for a system
+   call.  */
+#undef INLINE_SYSCALL
+#define INLINE_SYSCALL(name, nr_args, args...)                         \
+({                                                                     \
+       register int __res __asm__("r0");                               \
+       __res = INTERNAL_SYSCALL_NCS(__NR_##name, , nr_args, args);     \
+       if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P ((__res), ), 0)) \
+       {                                                               \
+               asm volatile ("st.a blink, [sp, -4] \n\t"               \
+                             CALL_ERRNO_SETTER                         \
+                             "ld.ab blink, [sp, 4] \n\t"               \
+                             :"+r" (__res)                             \
+                             :                                         \
+                             :"r1","r2","r3","r4","r5","r6",           \
+                              "r7","r8","r9","r10","r11","r12");       \
+       }                                                               \
+       __res;                                                          \
+})
+
+#undef INTERNAL_SYSCALL_DECL
+#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
+#undef INTERNAL_SYSCALL_ERRNO
+# define INTERNAL_SYSCALL_ERRNO(val, err)    (-(val))
+
+/* -1 to -1023 are valid errno values */
+#undef INTERNAL_SYSCALL_ERROR_P
+#define INTERNAL_SYSCALL_ERROR_P(val, err)     \
+       ((unsigned int) (val) > -1024U)
+
+#define ARC_TRAP_INSN  "trap_s 0       \n\t"
+
+#undef INTERNAL_SYSCALL_RAW
+#define INTERNAL_SYSCALL_RAW(name, err, nr_args, args...)      \
+({                                                     \
+       /* Per ABI, r0 is 1st arg and return reg */     \
+       register int __ret __asm__("r0");               \
+       register int _sys_num __asm__("r8");            \
+                                                       \
+       LOAD_ARGS_##nr_args (name, args)                \
+                                                       \
+        __asm__ volatile (                             \
+               ARC_TRAP_INSN                           \
+               : "+r" (__ret)                          \
+               : "r"(_sys_num) ASM_ARGS_##nr_args      \
+               : "memory");                            \
+                                                        \
+       __ret;                                          \
+})
+
+/* 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 = (int) (nm);
+
+#define LOAD_ARGS_1(nm, arg1)                                  \
+       __ret = (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)                            \
+       int _tmp2 = (int) (arg2);                               \
+       LOAD_ARGS_1 (nm, arg1)                                  \
+       register int _arg2 __asm__ ("r1") = _tmp2;
+
+#define LOAD_ARGS_3(nm, arg1, arg2, arg3)                      \
+       int _tmp3 = (int) (arg3);                               \
+       LOAD_ARGS_2 (nm, arg1, arg2)                            \
+       register int _arg3 __asm__ ("r2") = _tmp3;
+
+#define LOAD_ARGS_4(nm, arg1, arg2, arg3, arg4)                        \
+       int _tmp4 = (int) (arg4);                               \
+       LOAD_ARGS_3 (nm, arg1, arg2, arg3)                      \
+       register int _arg4 __asm__ ("r3") = _tmp4;
+
+#define LOAD_ARGS_5(nm, arg1, arg2, arg3, arg4, arg5)          \
+       int _tmp5 = (int) (arg5);                               \
+       LOAD_ARGS_4 (nm, arg1, arg2, arg3, arg4)                \
+       register int _arg5 __asm__ ("r4") = _tmp5;
+
+#define LOAD_ARGS_6(nm,  arg1, arg2, arg3, arg4, arg5, arg6)   \
+       int _tmp6 = (int) (arg6);                               \
+       LOAD_ARGS_5 (nm, arg1, arg2, arg3, arg4, arg5)          \
+       register int _arg6 __asm__ ("r5") = _tmp6;
+
+#define LOAD_ARGS_7(nm, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
+       int _tmp7 = (int) (arg7);                               \
+       LOAD_ARGS_6 (nm, arg1, arg2, arg3, arg4, arg5, arg6)    \
+       register int _arg7 __asm__ ("r6") = _tmp7;
+
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, err, nr, args...) \
+       INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
+
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+       INTERNAL_SYSCALL_RAW(number, err, nr, args)
+
+/* Pointer mangling not yet supported  */
+# define PTR_MANGLE(var) (void) (var)
+# define PTR_DEMANGLE(var) (void) (var)
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* linux/arc/sysdep.h */
diff --git a/sysdeps/unix/sysv/linux/arc/vfork.S 
b/sysdeps/unix/sysv/linux/arc/vfork.S
new file mode 100644
index 000000000000..6d7f63c9900b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arc/vfork.S
@@ -0,0 +1,42 @@
+/* vfork for ARC Linux.
+   Copyright (C) 2005-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/syscall.h>
+#include <sysdep.h>
+#include <tcb-offsets.h>
+#define _SIGNAL_H
+#include <bits/signum.h>       /* For SIGCHLD */
+
+#define CLONE_VM               0x00000100
+#define CLONE_VFORK            0x00004000
+#define CLONE_FLAGS_FOR_VFORK  (CLONE_VM|CLONE_VFORK|SIGCHLD)
+
+ENTRY(__vfork)
+       mov     r0, CLONE_FLAGS_FOR_VFORK
+       mov_s   r1, sp
+       mov     r8, __NR_clone
+       ARC_TRAP_INSN
+
+       cmp     r0, 0
+       jge     [blink] ; child continues
+
+       b   __syscall_error
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
-- 
2.7.4


_______________________________________________
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc

Reply via email to