Description: add aarch64 support
Origin: https://github.com/codehelp/klibc-aarch64/commit/244098c5e274b0c2fdf68ffc944cac17647de99f
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=698018
Author: Neil Williams <codehelp@debian.org>
Last-Update: 2013-08-15

Index: klibc/usr/include/arch/aarch64/klibc/archconfig.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/include/arch/aarch64/klibc/archconfig.h	2013-08-15 11:17:20.450140882 -0600
@@ -0,0 +1,15 @@
+/*
+ * include/arch/aarch64/klibc/archconfig.h
+ *
+ * See include/klibc/sysconfig.h for the options that can be set in
+ * this file.
+ *
+ */
+
+#ifndef _KLIBC_ARCHCONFIG_H
+#define _KLIBC_ARCHCONFIG_H
+
+/* Use rt_* signals */
+#define _KLIBC_USE_RT_SIG 1
+
+#endif				/* _KLIBC_ARCHCONFIG_H */
Index: klibc/usr/include/arch/aarch64/klibc/archsetjmp.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/include/arch/aarch64/klibc/archsetjmp.h	2013-08-15 11:17:20.450140882 -0600
@@ -0,0 +1,19 @@
+/*
+ * arch/i386/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+/* 0-7 are temporary, starting at x8, skip x16, go up to x30
+also store the d registers, d8 to d15.
+*/
+
+struct __jmp_buf {
+	uint64_t __gregs[22];
+	uint64_t __fpregs[8];
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif				/* _SETJMP_H */
Index: klibc/usr/include/arch/aarch64/klibc/archsignal.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/include/arch/aarch64/klibc/archsignal.h	2013-08-15 11:17:20.450140882 -0600
@@ -0,0 +1,14 @@
+/*
+ * arch/arm/include/klibc/archsignal.h
+ *
+ * Architecture-specific signal definitions
+ *
+ */
+
+#ifndef _KLIBC_ARCHSIGNAL_H
+#define _KLIBC_ARCHSIGNAL_H
+
+#include <asm/signal.h>
+/* No special stuff for this architecture */
+
+#endif
Index: klibc/usr/include/arch/aarch64/klibc/archstat.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/include/arch/aarch64/klibc/archstat.h	2013-08-15 11:17:20.450140882 -0600
@@ -0,0 +1,26 @@
+#ifndef _KLIBC_ARCHSTAT_H
+#define _KLIBC_ARCHSTAT_H
+
+#include <klibc/stathelp.h>
+
+#define _STATBUF_ST_NSEC
+
+struct stat {
+	__stdev64	(st_dev);
+	unsigned long	st_ino;
+	unsigned long	st_nlink;
+	unsigned int	st_mode;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	unsigned int	__pad1;
+	__stdev64	(st_rdev);
+	unsigned long	st_size;
+	struct timespec	st_atim;
+	struct timespec	st_mtim;
+	struct timespec	st_ctim;
+	unsigned long	st_blksize;
+	long		st_blocks;
+	unsigned long	__unused[3];
+};
+
+#endif
Index: klibc/usr/include/arch/aarch64/klibc/asmmacros.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/include/arch/aarch64/klibc/asmmacros.h	2013-08-15 11:17:20.450140882 -0600
@@ -0,0 +1,11 @@
+/*
+ * usr/include/arch/arm/klibc/asmmacros.h
+ *
+ * Assembly macros used by ARM system call stubs
+ */
+
+#ifndef _KLIBC_ASMMACROS_H
+#define _KLIBC_ASMMACROS_H
+
+
+#endif /* _KLIBC_ASMMACROS_H */
Index: klibc/usr/klibc/README.klibc
===================================================================
--- klibc.orig/usr/klibc/README.klibc	2013-08-15 11:13:53.045634000 -0600
+++ klibc/usr/klibc/README.klibc	2013-08-15 11:17:20.450140882 -0600
@@ -33,6 +33,7 @@
 
    The following is the last known status of various architectures:
 
+   aarch64:  Untested
    alpha:	 Working
    arm-thumb:	 Untested
    arm:		 Working
Index: klibc/usr/klibc/SYSCALLS.def
===================================================================
--- klibc.orig/usr/klibc/SYSCALLS.def	2013-08-15 11:13:53.045634000 -0600
+++ klibc/usr/klibc/SYSCALLS.def	2013-08-15 11:17:20.454140926 -0600
@@ -106,34 +106,34 @@
 /*
  * Inode-related system calls
  */
-int access(const char *, int);
+<!aarch64> int access(const char *, int);
 int faccessat(int, const char *, int, int);
-int link(const char *, const char *);
+<!aarch64> int link(const char *, const char *);
 <?> int linkat(int, const char *, int, const char *);
-int unlink(const char *);
+<!aarch64> int unlink(const char *);
 <?> int unlinkat(int, const char *, int);
 int chdir(const char *);
 int fchdir(int);
-int rename(const char *, const char *);
+<!aarch64> int rename(const char *, const char *);
 <?> int renameat(int, const char *, int, const char *);
-int mknod(const char *, mode_t, dev_t);
+<!aarch64> int mknod(const char *, mode_t, dev_t);
 <?> int mknodat(int, const char *, const char *, mode_t, dev_t);
-int chmod(const char *, mode_t);
+<!aarch64> int chmod(const char *, mode_t);
 int fchmod(int, mode_t);
 <?> int fchmodat(int, const char *, mode_t);
-int mkdir(const char *, mode_t);
+<!aarch64> int mkdir(const char *, mode_t);
 <?> int mkdirat(int, const char *, const char *, mode_t);
-int rmdir(const char *);
-<!alpha,ia64,mips,mips64,sh,sparc,sparc64> int pipe(int *);
+<!aarch64> int rmdir(const char *);
+<!alpha,aarch64,ia64,mips,mips64,sh,sparc,sparc64> int pipe(int *);
 int pipe2(int *, int);
 mode_t umask(mode_t);
 int chroot(const char *);
-int symlink(const char *, const char *);
+<!aarch64> int symlink(const char *, const char *);
 <?> int symlinkat(const char *, int, const char *);
-int readlink(const char *, char *, size_t);
+<!aarch64> int readlink(const char *, char *, size_t);
 <?> int readlinkat(int, const char *, char *, int);
-<!ppc64> int stat64,stat::stat(const char *, struct stat *);
-<!ppc64> int lstat64,lstat::lstat(const char *, struct stat *);
+<!aarch64,ppc64> int stat64,stat::stat(const char *, struct stat *);
+<!aarch64,ppc64> int lstat64,lstat::lstat(const char *, struct stat *);
 <!ppc64> int fstat64,fstat::fstat(int, struct stat *);
 <ppc64> int stat::stat(const char *, struct stat *);
 <ppc64> int lstat::lstat(const char *, struct stat *);
@@ -141,14 +141,15 @@
 /* XXX: Is this right?! */
 <?> int fstatat64,newfstatat,fstatat::fstatat(int, const char *, struct stat *, int);
 int getdents64,getdents::getdents(unsigned int, struct dirent *, unsigned int);
-int chown32,chown::chown(const char *, uid_t, gid_t);
+<!aarch64> int chown32,chown::chown(const char *, uid_t, gid_t);
 int fchown32,fchown::fchown(int, uid_t, gid_t);
 <?> int fchownat(int, const char *, uid_t, gid_t, int);
-int lchown32,lchown::lchown(const char *, uid_t, gid_t);
+<!aarch64> int lchown32,lchown::lchown(const char *, uid_t, gid_t);
 int getcwd::__getcwd(char *, size_t);
 <?> int utime(const char *, const struct utimbuf *);
 <?> int utimes(const char *, const struct timeval *);
 <?> int futimesat(int, const char *, const struct timeval *);
+<aarch64> int utimensat(int, const char *, const struct timespec *, int);
 <?> int inotify_init();
 <?> int inotify_add_watch(int, const char *, __u32);
 <?> int inotify_rm_watch(int, __u32);
@@ -158,7 +159,7 @@
  */
 <!i386,m68k,64> int open::__open(const char *, int, mode_t);
 <?!i386,m68k,64> int openat::__openat(int, const char *, int, mode_t);
-<64> int open(const char *, int, mode_t);
+<?64> int open(const char *, int, mode_t);
 <64> int openat(int, const char *, int, mode_t);
 ssize_t read(int, void *, size_t);
 ssize_t write(int, const void *, size_t);
@@ -166,14 +167,14 @@
 <64> off_t lseek(int, off_t, int);
 <32> int _llseek::__llseek(int, unsigned long, unsigned long, off_t *, int);
 int dup(int);
-int dup2(int, int);
+<!aarch64> int dup2(int, int);
 int dup3(int, int, int);
 <i386> int fcntl64@varadic::fcntl(int, int, unsigned long);
 <ppc64> int fcntl(int, int, unsigned long);
 <!i386,ppc64> int fcntl64,fcntl::fcntl(int, int, unsigned long);
 int ioctl(int, int, void *);
 int flock(int, int);
-int _newselect,select::select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+<!aarch64> int _newselect,select::select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 #if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG
 int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *);
 #elif defined(__NR_pselect7)
@@ -181,7 +182,7 @@
 #elif defined(__NR_pselect6)
 int pselect6::__pselect6(int, fd_set *, fd_set *, fd_set *, struct timespec *, const struct __pselect6 *);
 #endif
-int poll(struct pollfd *, nfds_t, long);
+<!aarch64> int poll(struct pollfd *, nfds_t, long);
 <?> int ppoll::__ppoll(struct pollfd *, nfds_t, struct timespec *, const sigset_t *, size_t);
 int fsync(int);
 int fdatasync,fsync::fdatasync(int);
Index: klibc/usr/klibc/arch/aarch64/Kbuild
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/Kbuild	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,9 @@
+#
+# klibc files for aarch64
+#
+
+klib-y := setjmp.o dup2.o unlink.o rmdir.o utimes.o fork.o open.o \
+ select.o poll.o stat.o lstat.o mkdir.o access.o mknod.o vfork.o pipe.o \
+ chmod.o link.o symlink.o rename.o readlink.o chown.o lchown.o
+always  := crt0.o
+targets := crt0.o
Index: klibc/usr/klibc/arch/aarch64/MCONFIG
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/MCONFIG	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,24 @@
+# -*- makefile -*-
+#
+# arch/aarch64/MCONFIG
+#
+# Special rules for this architecture.  Note that this is actually
+# included from the main Makefile, and that pathnames should be
+# accordingly.
+#
+
+CPU_ARCH ?= armv8-a
+CPU_TUNE ?= generic
+
+KLIBCOPTFLAGS += -Os -march=$(CPU_ARCH) -mtune=$(CPU_TUNE)
+KLIBCBITSIZE  = 64
+KLIBCREQFLAGS += -fno-exceptions
+#KLIBCSTRIPFLAGS += -R .ARM.exidx
+
+# Extra linkflags when building the shared version of the library
+# This address needs to be reachable using normal inter-module
+# calls, and work on the memory models for this architecture
+#KLIBCSHAREDFLAGS = -Ttext 0x01800200
+#KLIBCREQFLAGS +=
+#KLIBCOPTFLAGS += -mgeneral-regs-only
+
Index: klibc/usr/klibc/arch/aarch64/access.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/access.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int access(const char *pathname, int mode)
+{
+	return faccessat (AT_FDCWD, pathname, mode, 0);
+}
Index: klibc/usr/klibc/arch/aarch64/chmod.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/chmod.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,12 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int chmod(const char *path, mode_t mode)
+{
+	int fd = open (path, O_RDONLY);
+	int ret = fchmod (fd, mode);
+	close (fd);
+	return ret;
+}
Index: klibc/usr/klibc/arch/aarch64/chown.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/chown.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int chown(const char *path, uid_t owner, gid_t group)
+{
+	return fchownat(AT_FDCWD, path, owner, group, 0);
+}
Index: klibc/usr/klibc/arch/aarch64/crt0.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/crt0.S	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,18 @@
+#
+# arch/aarch64/crt0.S
+#
+# void _start(void)
+# {
+#    __libc_init(elf_structure, atexit_ptr);
+# }
+#
+
+	.text
+	.balign 8
+	.type _start,#function
+	.globl _start
+
+_start: mov x0, sp
+	mov	x1, #0
+	bl	__libc_init
+	.size _start,.-_start
Index: klibc/usr/klibc/arch/aarch64/dup2.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/dup2.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,5 @@
+#include <unistd.h>
+
+int dup2 (int fd, int fd2) {
+	return dup3 (fd, fd2, 0);
+}
Index: klibc/usr/klibc/arch/aarch64/fork.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/fork.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,21 @@
+/*
+ * fork.c
+ *
+ * This is normally just a syscall stub, but at least one system
+ * doesn't have sys_fork, only sys_clone...
+ */
+
+#include <sys/syscall.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sched.h>
+#include <klibc/sysconfig.h>
+
+#if !defined(__NR_fork)
+
+pid_t fork(void)
+{
+	return __clone(SIGCHLD, 0);
+}
+
+#endif				/* __NR_fork */
Index: klibc/usr/klibc/arch/aarch64/lchown.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/lchown.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int lchown(const char *path, uid_t owner, gid_t group)
+{
+	return fchownat (AT_FDCWD, path, owner, group, AT_SYMLINK_NOFOLLOW);
+}
Index: klibc/usr/klibc/arch/aarch64/link.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/link.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int link(const char *oldpath, const char *newpath)
+{
+	return linkat (AT_FDCWD, oldpath, AT_FDCWD, newpath);
+}
Index: klibc/usr/klibc/arch/aarch64/lstat.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/lstat.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,14 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// FIXME
+
+int lstat(const char *path, struct stat *buf)
+{
+	int fd = open (path, O_RDONLY);
+	int ret = fstat (fd, buf);
+	close (fd);
+	return ret;
+}
Index: klibc/usr/klibc/arch/aarch64/mkdir.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/mkdir.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+int mkdir(const char *pathname, mode_t mode)
+{
+	return mkdirat (AT_FDCWD, pathname, mode);
+}
Index: klibc/usr/klibc/arch/aarch64/mknod.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/mknod.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,11 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+// FIXME what is the second const char * ?
+
+int mknod(const char *pathname, mode_t mode, dev_t dev)
+{
+	return mknodat(AT_FDCWD, pathname, pathname, mode, dev);
+}
Index: klibc/usr/klibc/arch/aarch64/open.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/open.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,13 @@
+/*
+ * open.c
+ *
+ */
+
+#define _KLIBC_IN_OPEN_C
+#include <unistd.h>
+#include <fcntl.h>
+
+int open(const char *pathname, int flags, mode_t mode)
+{
+	return openat(AT_FDCWD, pathname, flags, mode);
+}
Index: klibc/usr/klibc/arch/aarch64/pipe.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/pipe.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,6 @@
+#include <unistd.h>
+
+int pipe(int pipefd[2])
+{
+	return pipe2 (pipefd, 0);
+}
Index: klibc/usr/klibc/arch/aarch64/poll.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/poll.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,15 @@
+#include <errno.h>
+#include <sys/poll.h>
+#include <sys/syscall.h>
+
+int poll (struct pollfd *fds, nfds_t nfds, long timeout) {
+	struct timespec timeout_ts;
+	struct timespec *timeout_ts_p = NULL;
+
+	if (timeout >= 0) {
+		timeout_ts.tv_sec = timeout / 1000;
+		timeout_ts.tv_nsec = (timeout % 1000) * 1000000;
+		timeout_ts_p = &timeout_ts;
+	}
+	return ppoll (fds, nfds, timeout_ts_p, 0);
+}
Index: klibc/usr/klibc/arch/aarch64/readlink.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/readlink.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int readlink(const char *path, char *buf, size_t bufsiz)
+{
+	return readlinkat(AT_FDCWD, path, buf, bufsiz);
+}
Index: klibc/usr/klibc/arch/aarch64/rename.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/rename.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <stdio.h>
+
+int rename(const char *oldpath, const char *newpath)
+{
+	return renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);
+}
Index: klibc/usr/klibc/arch/aarch64/rmdir.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/rmdir.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int rmdir(const char *pathname) {
+	return unlinkat (AT_FDCWD, pathname, AT_REMOVEDIR);
+}
+
Index: klibc/usr/klibc/arch/aarch64/select.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/select.c	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,21 @@
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <errno.h>
+//#include <sysdep-cancel.h>
+
+int select(int nfds, fd_set *readfds, fd_set *writefds,
+			fd_set *exceptfds, struct timeval *timeout) {
+	int result;
+	struct timespec ts;
+	if (timeout) {
+		ts.tv_sec = timeout->tv_sec;
+		ts.tv_nsec = timeout->tv_usec * 1000;
+	}
+	result = __pselect6 (nfds, readfds, writefds, exceptfds, &ts, NULL);
+	if (timeout) {
+		ts.tv_sec = timeout->tv_sec;
+		ts.tv_nsec = timeout->tv_usec * 1000;
+	}
+	return result;
+}
Index: klibc/usr/klibc/arch/aarch64/setjmp.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/setjmp.S	2013-08-15 11:17:20.454140926 -0600
@@ -0,0 +1,61 @@
+#
+# arch/aarch64/setjmp.S
+#
+# setjmp/longjmp for the AARCH64 architecture
+#
+
+#include <klibc/asmmacros.h>
+
+	.text
+	.balign 8
+	.globl setjmp
+	.type setjmp, #function
+setjmp:
+	// x0-x7 are temporary, possibly skip x16
+	// glibc stores only x19 to x30, this may need to be clarified.
+	// also store the d registers, same as glibc
+	stp	x8, x9,   [x0, #0]
+	stp	x10, x11, [x0, #16]
+	stp	x12, x13, [x0, #32]
+	stp	x14, x15, [x0, #48]
+	stp	x17, x18, [x0, #64]
+	stp	x19, x20, [x0, #80]
+	stp	x21, x22, [x0, #96]
+	stp	x23, x24, [x0, #112]
+	stp	x25, x26, [x0, #128]
+	stp	x27, x28, [x0, #144]
+	stp	x29, x30, [x0, #160]
+	stp	d8, d9,   [x0, #176]
+	stp	d10, d11, [x0, #192]
+	stp	d12, d13, [x0, #208]
+	stp	d14, d15, [x0, #224]
+	mov x0, #0 			// set the return value of setjmp
+	br x30
+	.size setjmp,.-setjmp
+
+	.text
+	.balign 8
+	.globl longjmp
+	.type longjmp, #function
+longjmp:
+	ldp x8, x9,   [x0, #0]
+	ldp x10, x11, [x0, #16]
+	ldp x12, x13, [x0, #32]
+	ldp x14, x15, [x0, #48]
+	ldp x17, x18, [x0, #64]
+	ldp x19, x20, [x0, #80]
+	ldp x21, x22, [x0, #96]
+	ldp x23, x24, [x0, #112]
+	ldp x25, x26, [x0, #128]
+	ldp x27, x28, [x0, #144]
+	ldp x29, x30, [x0, #160]
+	ldp	d8, d9,   [x0, #176]
+	ldp	d10, d11, [x0, #192]
+	ldp	d12, d13, [x0, #208]
+	ldp	d14, d15, [x0, #224]
+	mov x0, x1
+	cbnz x1, 1f // if x1 is not zero, branch to 1:
+	mov x0, #1
+1:
+	br x30
+	.size longjmp,.-longjmp
Index: klibc/usr/klibc/arch/aarch64/stat.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/stat.c	2013-08-15 11:17:20.458140970 -0600
@@ -0,0 +1,12 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int stat(const char *path, struct stat *buf)
+{
+	int fd = open (path, O_RDONLY);
+	int ret = fstat (fd, buf);
+	close (fd);
+	return ret;
+}
Index: klibc/usr/klibc/arch/aarch64/symlink.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/symlink.c	2013-08-15 11:17:20.458140970 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int symlink (const char *oldpath, const char *newpath)
+{
+	return symlinkat (AT_FDCWD, oldpath, newpath);
+}
Index: klibc/usr/klibc/arch/aarch64/sysstub.ph
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/sysstub.ph	2013-08-15 11:17:20.458140970 -0600
@@ -0,0 +1,29 @@
+# -*- perl -*-
+#
+# arch/aarch64/sysstub.ph
+#
+# Script to generate system call stubs
+#
+
+sub make_sysstub($$$$$@) {
+    my($outputdir, $fname, $type, $sname, $stype, @args) = @_;
+
+    open(OUT, '>', "${outputdir}/${fname}.S");
+    print  OUT "#include <asm/unistd.h>\n";
+    print  OUT "#include <klibc/asmmacros.h>\n";
+    print  OUT "	.text\n";
+    print  OUT "	.type	${fname}, #function\n";
+    print  OUT "	.globl	${fname}\n";
+    print  out "	.balign	8\n";
+    print  OUT "${fname}:\n";
+    print  OUT "	mov x0,__NR_${sname}\n";
+    print  OUT "	svc	0\n";
+    print  OUT "	.word	__NR_${sname}\n";
+    print  OUT "	.size	${fname},.-${fname}\n";
+# branch if not set
+#    print  OUT "	b .__syscall_error\n";
+#    print  OUT "	.size .${fname},.-.${fname}\n";
+
+}
+
+1;
Index: klibc/usr/klibc/arch/aarch64/unlink.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/unlink.c	2013-08-15 11:17:20.458140970 -0600
@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int unlink(const char *pathname) {
+	return unlinkat (AT_FDCWD, pathname, 0);
+}
+
Index: klibc/usr/klibc/arch/aarch64/utimes.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/utimes.c	2013-08-15 11:17:20.458140970 -0600
@@ -0,0 +1,13 @@
+#include <fcntl.h>
+#include <sys/time.h>
+
+int utimes (const char *file, const struct timeval tvp[2]) {
+	struct timespec ts[2];
+
+	if (tvp) {
+		ts->tv_sec = tvp->tv_sec;
+		ts->tv_nsec = tvp->tv_usec * 1000;
+	}
+	return utimensat (AT_FDCWD, file, &ts[0], 0);
+}
+
Index: klibc/usr/klibc/arch/aarch64/vfork.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc/usr/klibc/arch/aarch64/vfork.S	2013-08-15 11:17:20.458140970 -0600
@@ -0,0 +1,22 @@
+/*
+ * arch/aarch64/vfork.S
+ *
+ * vfork - nasty system call which must not use the stack.
+ */
+
+#include <klibc/asmmacros.h>
+#include <asm/unistd.h>
+
+// FIXME: no save or restore PID support
+
+	.type	vfork,#function
+	.globl	vfork
+	.balign	8
+vfork:
+	mov	x0, #0x4111	/* CLONE_VM | CLONE_VFORK | SIGCHLD */
+	mov	x1, sp
+	cmn	x0, #4095
+	b.cs    1f
+	RET
+1:
+	.word	errno
