* [RFC] powerpc64 port
@ 2016-03-27 21:20 Bobby Bingham
2016-03-27 21:20 ` [PATCH 1/2] add 64bit atomics on top of 64bit ll/sc primitives Bobby Bingham
2016-03-27 21:20 ` [PATCH 2/2] add powerpc64 port Bobby Bingham
0 siblings, 2 replies; 18+ messages in thread
From: Bobby Bingham @ 2016-03-27 21:20 UTC (permalink / raw)
To: musl
Here is the ppc64 (ELFv2 ABI) port that I've been working on. I'd like
to start getting it reviewed.
Only 64bit long double is supported as ieee quad is not yet well-
supported by either clang or gcc on ppc64. The ppc64 ELFv2 ABI
supports both little and big endian, though only little endian is in
common use. I've made an effort to support both in this port, but I've
only tested little endian so far.
The first patch in the series adds support to the generic atomic code
for implementing the non-pointer 64bit atomics on top of 64bit ll/sc
primitives when available. The second patch is the ppc64 port itself.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/2] add 64bit atomics on top of 64bit ll/sc primitives
2016-03-27 21:20 [RFC] powerpc64 port Bobby Bingham
@ 2016-03-27 21:20 ` Bobby Bingham
2016-03-27 22:27 ` Rich Felker
2016-03-27 21:20 ` [PATCH 2/2] add powerpc64 port Bobby Bingham
1 sibling, 1 reply; 18+ messages in thread
From: Bobby Bingham @ 2016-03-27 21:20 UTC (permalink / raw)
To: musl
---
src/internal/atomic.h | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/src/internal/atomic.h b/src/internal/atomic.h
index 6f37d25..43a8a00 100644
--- a/src/internal/atomic.h
+++ b/src/internal/atomic.h
@@ -99,6 +99,34 @@ static inline void *a_cas_p(volatile void *p, void *t, void *s)
#endif
+#ifdef a_ll_64
+
+#ifndef a_and_64
+#define a_and_64 a_and_64
+static inline void a_and_64(volatile uint64_t *p, uint64_t v)
+{
+ uint64_t old;
+ a_pre_llsc();
+ do old = a_ll_64(p);
+ while (!a_sc_64(p, old & v));
+ a_post_llsc();
+}
+#endif
+
+#ifndef a_or_64
+#define a_or_64 a_or_64
+static inline void a_or_64(volatile uint64_t *p, uint64_t v)
+{
+ uint64_t old;
+ a_pre_llsc();
+ do old = a_ll_64(p);
+ while (!a_sc_64(p, old | v));
+ a_post_llsc();
+}
+#endif
+
+#endif
+
#ifndef a_cas
#error missing definition of a_cas
#endif
--
2.7.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/2] add powerpc64 port
2016-03-27 21:20 [RFC] powerpc64 port Bobby Bingham
2016-03-27 21:20 ` [PATCH 1/2] add 64bit atomics on top of 64bit ll/sc primitives Bobby Bingham
@ 2016-03-27 21:20 ` Bobby Bingham
2016-03-27 23:37 ` Rich Felker
1 sibling, 1 reply; 18+ messages in thread
From: Bobby Bingham @ 2016-03-27 21:20 UTC (permalink / raw)
To: musl
---
arch/powerpc64/atomic_arch.h | 81 ++++
arch/powerpc64/bits/alltypes.h.in | 26 ++
arch/powerpc64/bits/endian.h | 5 +
arch/powerpc64/bits/errno.h | 134 ++++++
arch/powerpc64/bits/fcntl.h | 40 ++
arch/powerpc64/bits/fenv.h | 31 ++
arch/powerpc64/bits/float.h | 16 +
arch/powerpc64/bits/ioctl.h | 229 ++++++++++
arch/powerpc64/bits/ipc.h | 16 +
arch/powerpc64/bits/limits.h | 7 +
arch/powerpc64/bits/mman.h | 8 +
arch/powerpc64/bits/msg.h | 13 +
arch/powerpc64/bits/posix.h | 2 +
arch/powerpc64/bits/reg.h | 3 +
arch/powerpc64/bits/sem.h | 7 +
arch/powerpc64/bits/setjmp.h | 1 +
arch/powerpc64/bits/shm.h | 25 ++
arch/powerpc64/bits/signal.h | 108 +++++
arch/powerpc64/bits/socket.h | 60 +++
arch/powerpc64/bits/stat.h | 17 +
arch/powerpc64/bits/stdint.h | 20 +
arch/powerpc64/bits/syscall.h | 718 +++++++++++++++++++++++++++++++
arch/powerpc64/bits/termios.h | 170 ++++++++
arch/powerpc64/bits/user.h | 25 ++
arch/powerpc64/crt_arch.h | 21 +
arch/powerpc64/pthread_arch.h | 17 +
arch/powerpc64/reloc.h | 32 ++
arch/powerpc64/syscall_arch.h | 5 +
configure | 9 +-
crt/powerpc64/crti.s | 21 +
crt/powerpc64/crtn.s | 13 +
src/fenv/powerpc64/fenv.c | 68 +++
src/internal/powerpc64/syscall.s | 17 +
src/ldso/powerpc64/dlsym.s | 12 +
src/setjmp/powerpc64/longjmp.S | 93 ++++
src/setjmp/powerpc64/setjmp.S | 97 +++++
src/signal/powerpc64/restore.s | 11 +
src/signal/powerpc64/sigsetjmp.s | 30 ++
src/thread/powerpc64/__set_thread_area.s | 8 +
src/thread/powerpc64/__unmapself.s | 9 +
src/thread/powerpc64/clone.s | 53 +++
src/thread/powerpc64/syscall_cp.s | 37 ++
42 files changed, 2314 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc64/atomic_arch.h
create mode 100644 arch/powerpc64/bits/alltypes.h.in
create mode 100644 arch/powerpc64/bits/endian.h
create mode 100644 arch/powerpc64/bits/errno.h
create mode 100644 arch/powerpc64/bits/fcntl.h
create mode 100644 arch/powerpc64/bits/fenv.h
create mode 100644 arch/powerpc64/bits/float.h
create mode 100644 arch/powerpc64/bits/ioctl.h
create mode 100644 arch/powerpc64/bits/ipc.h
create mode 100644 arch/powerpc64/bits/limits.h
create mode 100644 arch/powerpc64/bits/mman.h
create mode 100644 arch/powerpc64/bits/msg.h
create mode 100644 arch/powerpc64/bits/posix.h
create mode 100644 arch/powerpc64/bits/reg.h
create mode 100644 arch/powerpc64/bits/sem.h
create mode 100644 arch/powerpc64/bits/setjmp.h
create mode 100644 arch/powerpc64/bits/shm.h
create mode 100644 arch/powerpc64/bits/signal.h
create mode 100644 arch/powerpc64/bits/socket.h
create mode 100644 arch/powerpc64/bits/stat.h
create mode 100644 arch/powerpc64/bits/stdint.h
create mode 100644 arch/powerpc64/bits/syscall.h
create mode 100644 arch/powerpc64/bits/termios.h
create mode 100644 arch/powerpc64/bits/user.h
create mode 100644 arch/powerpc64/crt_arch.h
create mode 100644 arch/powerpc64/pthread_arch.h
create mode 100644 arch/powerpc64/reloc.h
create mode 100644 arch/powerpc64/syscall_arch.h
create mode 100644 crt/powerpc64/crti.s
create mode 100644 crt/powerpc64/crtn.s
create mode 100644 src/fenv/powerpc64/fenv.c
create mode 100644 src/internal/powerpc64/syscall.s
create mode 100644 src/ldso/powerpc64/dlsym.s
create mode 100644 src/setjmp/powerpc64/longjmp.S
create mode 100644 src/setjmp/powerpc64/setjmp.S
create mode 100644 src/signal/powerpc64/restore.s
create mode 100644 src/signal/powerpc64/sigsetjmp.s
create mode 100644 src/thread/powerpc64/__set_thread_area.s
create mode 100644 src/thread/powerpc64/__unmapself.s
create mode 100644 src/thread/powerpc64/clone.s
create mode 100644 src/thread/powerpc64/syscall_cp.s
diff --git a/arch/powerpc64/atomic_arch.h b/arch/powerpc64/atomic_arch.h
new file mode 100644
index 0000000..885f111
--- /dev/null
+++ b/arch/powerpc64/atomic_arch.h
@@ -0,0 +1,81 @@
+#define a_ll a_ll
+static inline int a_ll(volatile int *p)
+{
+ int v;
+ __asm__ __volatile__ ("lwarx %0, 0, %2" : "=r"(v) : "m"(*p), "r"(p));
+ return v;
+}
+
+#define a_sc a_sc
+static inline int a_sc(volatile int *p, int v)
+{
+ int r;
+ __asm__ __volatile__ (
+ "stwcx. %2, 0, %3 ; mfcr %0"
+ : "=r"(r), "=m"(*p) : "r"(v), "r"(p) : "memory", "cc");
+ return r & 0x20000000; /* "bit 2" of "cr0" (backwards bit order) */
+}
+
+#define a_ll_64 a_ll_64
+static inline uint64_t a_ll_64(volatile uint64_t *p)
+{
+ uint64_t v;
+ __asm__ __volatile__ ("ldarx %0, 0, %2" : "=r"(v) : "m"(*p), "r"(p));
+ return v;
+}
+
+#define a_sc_64 a_sc_64
+static inline int a_sc_64(volatile uint64_t *p, uint64_t v)
+{
+ int r;
+ __asm__ __volatile__ (
+ "stdcx. %2, 0, %3 ; mfcr %0"
+ : "=r"(r), "=m"(*p) : "r"(v), "r"(p) : "memory", "cc");
+ return r & 0x20000000; /* "bit 2" of "cr0" (backwards bit order) */
+}
+
+#define a_ll_p a_ll_p
+static inline void *a_ll_p(volatile void *p)
+{
+ void *v;
+ __asm__ __volatile__ ("ldarx %0, 0, %2" : "=r"(v) : "m"(*(void *volatile *)p), "r"(p));
+ return v;
+}
+
+#define a_sc_p a_sc_p
+static inline int a_sc_p(volatile void *p, void *v)
+{
+ int r;
+ __asm__ __volatile__ (
+ "stdcx. %2, 0, %3 ; mfcr %0"
+ : "=r"(r), "=m"(*(void *volatile *)p) : "r"(v), "r"(p) : "memory", "cc");
+ return r & 0x20000000; /* "bit 2" of "cr0" (backwards bit order) */
+}
+
+#define a_barrier a_barrier
+static inline void a_barrier()
+{
+ __asm__ __volatile__ ("sync" : : : "memory");
+}
+
+#define a_pre_llsc a_barrier
+
+#define a_post_llsc a_post_llsc
+static inline void a_post_llsc()
+{
+ __asm__ __volatile__ ("isync" : : : "memory");
+}
+
+#define a_store a_store
+static inline void a_store(volatile int *p, int v)
+{
+ a_pre_llsc();
+ *p = v;
+ a_post_llsc();
+}
+
+#define a_crash a_crash
+static inline void a_crash()
+{
+ __asm__ __volatile__ (".long 0");
+}
diff --git a/arch/powerpc64/bits/alltypes.h.in b/arch/powerpc64/bits/alltypes.h.in
new file mode 100644
index 0000000..5b20585
--- /dev/null
+++ b/arch/powerpc64/bits/alltypes.h.in
@@ -0,0 +1,26 @@
+#define _Addr long
+#define _Int64 long
+#define _Reg long
+
+TYPEDEF __builtin_va_list va_list;
+TYPEDEF __builtin_va_list __isoc_va_list;
+
+#ifndef __cplusplus
+TYPEDEF int wchar_t;
+#endif
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
+
+TYPEDEF long time_t;
+TYPEDEF long suseconds_t;
+
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
+TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/arch/powerpc64/bits/endian.h b/arch/powerpc64/bits/endian.h
new file mode 100644
index 0000000..2016cb2
--- /dev/null
+++ b/arch/powerpc64/bits/endian.h
@@ -0,0 +1,5 @@
+#if __BIG_ENDIAN__
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
diff --git a/arch/powerpc64/bits/errno.h b/arch/powerpc64/bits/errno.h
new file mode 100644
index 0000000..36ad2f9
--- /dev/null
+++ b/arch/powerpc64/bits/errno.h
@@ -0,0 +1,134 @@
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define ENOTBLK 15
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define ETXTBSY 26
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define ERANGE 34
+#define EDEADLK 35
+#define ENAMETOOLONG 36
+#define ENOLCK 37
+#define ENOSYS 38
+#define ENOTEMPTY 39
+#define ELOOP 40
+#define EWOULDBLOCK EAGAIN
+#define ENOMSG 42
+#define EIDRM 43
+#define ECHRNG 44
+#define EL2NSYNC 45
+#define EL3HLT 46
+#define EL3RST 47
+#define ELNRNG 48
+#define EUNATCH 49
+#define ENOCSI 50
+#define EL2HLT 51
+#define EBADE 52
+#define EBADR 53
+#define EXFULL 54
+#define ENOANO 55
+#define EBADRQC 56
+#define EBADSLT 57
+#define EDEADLOCK 58
+#define EBFONT 59
+#define ENOSTR 60
+#define ENODATA 61
+#define ETIME 62
+#define ENOSR 63
+#define ENONET 64
+#define ENOPKG 65
+#define EREMOTE 66
+#define ENOLINK 67
+#define EADV 68
+#define ESRMNT 69
+#define ECOMM 70
+#define EPROTO 71
+#define EMULTIHOP 72
+#define EDOTDOT 73
+#define EBADMSG 74
+#define EOVERFLOW 75
+#define ENOTUNIQ 76
+#define EBADFD 77
+#define EREMCHG 78
+#define ELIBACC 79
+#define ELIBBAD 80
+#define ELIBSCN 81
+#define ELIBMAX 82
+#define ELIBEXEC 83
+#define EILSEQ 84
+#define ERESTART 85
+#define ESTRPIPE 86
+#define EUSERS 87
+#define ENOTSOCK 88
+#define EDESTADDRREQ 89
+#define EMSGSIZE 90
+#define EPROTOTYPE 91
+#define ENOPROTOOPT 92
+#define EPROTONOSUPPORT 93
+#define ESOCKTNOSUPPORT 94
+#define EOPNOTSUPP 95
+#define ENOTSUP EOPNOTSUPP
+#define EPFNOSUPPORT 96
+#define EAFNOSUPPORT 97
+#define EADDRINUSE 98
+#define EADDRNOTAVAIL 99
+#define ENETDOWN 100
+#define ENETUNREACH 101
+#define ENETRESET 102
+#define ECONNABORTED 103
+#define ECONNRESET 104
+#define ENOBUFS 105
+#define EISCONN 106
+#define ENOTCONN 107
+#define ESHUTDOWN 108
+#define ETOOMANYREFS 109
+#define ETIMEDOUT 110
+#define ECONNREFUSED 111
+#define EHOSTDOWN 112
+#define EHOSTUNREACH 113
+#define EALREADY 114
+#define EINPROGRESS 115
+#define ESTALE 116
+#define EUCLEAN 117
+#define ENOTNAM 118
+#define ENAVAIL 119
+#define EISNAM 120
+#define EREMOTEIO 121
+#define EDQUOT 122
+#define ENOMEDIUM 123
+#define EMEDIUMTYPE 124
+#define ECANCELED 125
+#define ENOKEY 126
+#define EKEYEXPIRED 127
+#define EKEYREVOKED 128
+#define EKEYREJECTED 129
+#define EOWNERDEAD 130
+#define ENOTRECOVERABLE 131
+#define ERFKILL 132
+#define EHWPOISON 133
diff --git a/arch/powerpc64/bits/fcntl.h b/arch/powerpc64/bits/fcntl.h
new file mode 100644
index 0000000..6f20bac
--- /dev/null
+++ b/arch/powerpc64/bits/fcntl.h
@@ -0,0 +1,40 @@
+#define O_CREAT 0100
+#define O_EXCL 0200
+#define O_NOCTTY 0400
+#define O_TRUNC 01000
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_DSYNC 010000
+#define O_SYNC 04010000
+#define O_RSYNC 04010000
+#define O_DIRECTORY 040000
+#define O_NOFOLLOW 0100000
+#define O_CLOEXEC 02000000
+
+#define O_ASYNC 020000
+#define O_DIRECT 0400000
+#define O_LARGEFILE 0200000
+#define O_NOATIME 01000000
+#define O_PATH 010000000
+#define O_TMPFILE 020040000
+#define O_NDELAY O_NONBLOCK
+
+#define F_DUPFD 0
+#define F_GETFD 1
+#define F_SETFD 2
+#define F_GETFL 3
+#define F_SETFL 4
+
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+
+#define F_SETOWN 8
+#define F_GETOWN 9
+#define F_SETSIG 10
+#define F_GETSIG 11
+
+#define F_SETOWN_EX 15
+#define F_GETOWN_EX 16
+
+#define F_GETOWNER_UIDS 17
diff --git a/arch/powerpc64/bits/fenv.h b/arch/powerpc64/bits/fenv.h
new file mode 100644
index 0000000..4db4638
--- /dev/null
+++ b/arch/powerpc64/bits/fenv.h
@@ -0,0 +1,31 @@
+#define FE_TONEAREST 0
+#define FE_TOWARDZERO 1
+#define FE_UPWARD 2
+#define FE_DOWNWARD 3
+
+#define FE_INEXACT 0x02000000
+#define FE_DIVBYZERO 0x04000000
+#define FE_UNDERFLOW 0x08000000
+#define FE_OVERFLOW 0x10000000
+#define FE_INVALID 0x20000000
+
+#define FE_ALL_EXCEPT 0x3e000000
+
+#ifdef _GNU_SOURCE
+#define FE_INVALID_SNAN 0x01000000
+#define FE_INVALID_ISI 0x00800000
+#define FE_INVALID_IDI 0x00400000
+#define FE_INVALID_ZDZ 0x00200000
+#define FE_INVALID_IMZ 0x00100000
+#define FE_INVALID_COMPARE 0x00080000
+#define FE_INVALID_SOFTWARE 0x00000400
+#define FE_INVALID_SQRT 0x00000200
+#define FE_INVALID_INTEGER_CONVERSION 0x00000100
+
+#define FE_ALL_INVALID 0x01f80700
+#endif
+
+typedef unsigned long fexcept_t;
+typedef double fenv_t;
+
+#define FE_DFL_ENV ((const fenv_t *)-1)
diff --git a/arch/powerpc64/bits/float.h b/arch/powerpc64/bits/float.h
new file mode 100644
index 0000000..c4a655e
--- /dev/null
+++ b/arch/powerpc64/bits/float.h
@@ -0,0 +1,16 @@
+#define FLT_EVAL_METHOD 0
+
+#define LDBL_TRUE_MIN 4.94065645841246544177e-324L
+#define LDBL_MIN 2.22507385850720138309e-308L
+#define LDBL_MAX 1.79769313486231570815e+308L
+#define LDBL_EPSILON 2.22044604925031308085e-16L
+
+#define LDBL_MANT_DIG 53
+#define LDBL_MIN_EXP (-1021)
+#define LDBL_MAX_EXP 1024
+
+#define LDBL_DIG 15
+#define LDBL_MIN_10_EXP (-307)
+#define LDBL_MAX_10_EXP 308
+
+#define DECIMAL_DIG 17
diff --git a/arch/powerpc64/bits/ioctl.h b/arch/powerpc64/bits/ioctl.h
new file mode 100644
index 0000000..44a6cb6
--- /dev/null
+++ b/arch/powerpc64/bits/ioctl.h
@@ -0,0 +1,229 @@
+#define _IOC(a,b,c,d) ( ((a)<<29) | ((b)<<8) | (c) | ((d)<<16) )
+#define _IOC_NONE 1U
+#define _IOC_WRITE 4U
+#define _IOC_READ 2U
+
+#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0)
+#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c))
+#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c))
+#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c))
+
+#define FIONCLEX _IO('f', 2)
+#define FIOCLEX _IO('f', 1)
+#define FIOASYNC _IOW('f', 125, int)
+#define FIONBIO _IOW('f', 126, int)
+#define FIONREAD _IOR('f', 127, int)
+#define TIOCINQ FIONREAD
+#define FIOQSIZE _IOR('f', 128, char[8])
+#define TIOCGETP _IOR('t', 8, char[6])
+#define TIOCSETP _IOW('t', 9, char[6])
+#define TIOCSETN _IOW('t', 10, char[6])
+
+#define TIOCSETC _IOW('t', 17, char[6])
+#define TIOCGETC _IOR('t', 18, char[6])
+#define TCGETS _IOR('t', 19, char[44])
+#define TCSETS _IOW('t', 20, char[44])
+#define TCSETSW _IOW('t', 21, char[44])
+#define TCSETSF _IOW('t', 22, char[44])
+
+#define TCGETA _IOR('t', 23, char[20])
+#define TCSETA _IOW('t', 24, char[20])
+#define TCSETAW _IOW('t', 25, char[20])
+#define TCSETAF _IOW('t', 28, char[20])
+
+#define TCSBRK _IO('t', 29)
+#define TCXONC _IO('t', 30)
+#define TCFLSH _IO('t', 31)
+
+#define TIOCSWINSZ _IOW('t', 103, char[8])
+#define TIOCGWINSZ _IOR('t', 104, char[8])
+#define TIOCSTART _IO('t', 110)
+#define TIOCSTOP _IO('t', 111)
+
+#define TIOCOUTQ _IOR('t', 115, int)
+
+#define TIOCGLTC _IOR('t', 116, char[6])
+#define TIOCSLTC _IOW('t', 117, char[6])
+#define TIOCSPGRP _IOW('t', 118, int)
+#define TIOCGPGRP _IOR('t', 119, int)
+
+#define TIOCEXCL 0x540C
+#define TIOCNXCL 0x540D
+#define TIOCSCTTY 0x540E
+
+#define TIOCSTI 0x5412
+#define TIOCMGET 0x5415
+#define TIOCMBIS 0x5416
+#define TIOCMBIC 0x5417
+#define TIOCMSET 0x5418
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_OUT1 0x2000
+#define TIOCM_OUT2 0x4000
+#define TIOCM_LOOP 0x8000
+
+#define TIOCGSOFTCAR 0x5419
+#define TIOCSSOFTCAR 0x541A
+#define TIOCLINUX 0x541C
+#define TIOCCONS 0x541D
+#define TIOCGSERIAL 0x541E
+#define TIOCSSERIAL 0x541F
+#define TIOCPKT 0x5420
+#define TIOCPKT_DATA 0
+#define TIOCPKT_FLUSHREAD 1
+#define TIOCPKT_FLUSHWRITE 2
+#define TIOCPKT_STOP 4
+#define TIOCPKT_START 8
+#define TIOCPKT_NOSTOP 16
+#define TIOCPKT_DOSTOP 32
+#define TIOCPKT_IOCTL 64
+
+#define TIOCNOTTY 0x5422
+#define TIOCSETD 0x5423
+#define TIOCGETD 0x5424
+#define TCSBRKP 0x5425
+#define TIOCSBRK 0x5427
+#define TIOCCBRK 0x5428
+#define TIOCGSID 0x5429
+#define TIOCGRS485 0x542e
+#define TIOCSRS485 0x542f
+#define TIOCGPTN _IOR('T',0x30, unsigned int)
+#define TIOCSPTLCK _IOW('T',0x31, int)
+#define TIOCGDEV _IOR('T',0x32, unsigned int)
+#define TIOCSIG _IOW('T',0x36, int)
+#define TIOCVHANGUP 0x5437
+#define TIOCGPKT _IOR('T',0x38, int)
+#define TIOCGPTLCK _IOR('T',0x39, int)
+#define TIOCGEXCL _IOR('T',0x40, int)
+
+#define TIOCSERCONFIG 0x5453
+#define TIOCSERGWILD 0x5454
+#define TIOCSERSWILD 0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458
+#define TIOCSERGETLSR 0x5459
+#define TIOCSER_TEMT 0x01
+#define TIOCSERGETMULTI 0x545A
+#define TIOCSERSETMULTI 0x545B
+
+#define TIOCMIWAIT 0x545C
+#define TIOCGICOUNT 0x545D
+
+
+/* end kernel header ioctls.h */
+
+
+#define TIOCTTYGSTRUCT 0x5426
+
+#define TCGETX 0x5432
+#define TCSETX 0x5433
+#define TCSETXF 0x5434
+#define TCSETXW 0x5435
+
+#define TIOCGHAYESESP 0x545E
+#define TIOCSHAYESESP 0x545F
+
+struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define TIOCM_MODEM_BITS TIOCM_OUT2
+
+#define N_TTY 0
+#define N_SLIP 1
+#define N_MOUSE 2
+#define N_PPP 3
+#define N_STRIP 4
+#define N_AX25 5
+#define N_X25 6
+#define N_6PACK 7
+#define N_MASC 8
+#define N_R3964 9
+#define N_PROFIBUS_FDL 10
+#define N_IRDA 11
+#define N_SMSBLOCK 12
+#define N_HDLC 13
+#define N_SYNC_PPP 14
+#define N_HCI 15
+
+#define FIOSETOWN 0x8901
+#define SIOCSPGRP 0x8902
+#define FIOGETOWN 0x8903
+#define SIOCGPGRP 0x8904
+#define SIOCATMARK 0x8905
+#define SIOCGSTAMP 0x8906
+
+#define SIOCADDRT 0x890B
+#define SIOCDELRT 0x890C
+#define SIOCRTMSG 0x890D
+
+#define SIOCGIFNAME 0x8910
+#define SIOCSIFLINK 0x8911
+#define SIOCGIFCONF 0x8912
+#define SIOCGIFFLAGS 0x8913
+#define SIOCSIFFLAGS 0x8914
+#define SIOCGIFADDR 0x8915
+#define SIOCSIFADDR 0x8916
+#define SIOCGIFDSTADDR 0x8917
+#define SIOCSIFDSTADDR 0x8918
+#define SIOCGIFBRDADDR 0x8919
+#define SIOCSIFBRDADDR 0x891a
+#define SIOCGIFNETMASK 0x891b
+#define SIOCSIFNETMASK 0x891c
+#define SIOCGIFMETRIC 0x891d
+#define SIOCSIFMETRIC 0x891e
+#define SIOCGIFMEM 0x891f
+#define SIOCSIFMEM 0x8920
+#define SIOCGIFMTU 0x8921
+#define SIOCSIFMTU 0x8922
+#define SIOCSIFHWADDR 0x8924
+#define SIOCGIFENCAP 0x8925
+#define SIOCSIFENCAP 0x8926
+#define SIOCGIFHWADDR 0x8927
+#define SIOCGIFSLAVE 0x8929
+#define SIOCSIFSLAVE 0x8930
+#define SIOCADDMULTI 0x8931
+#define SIOCDELMULTI 0x8932
+#define SIOCGIFINDEX 0x8933
+#define SIOGIFINDEX SIOCGIFINDEX
+#define SIOCSIFPFLAGS 0x8934
+#define SIOCGIFPFLAGS 0x8935
+#define SIOCDIFADDR 0x8936
+#define SIOCSIFHWBROADCAST 0x8937
+#define SIOCGIFCOUNT 0x8938
+
+#define SIOCGIFBR 0x8940
+#define SIOCSIFBR 0x8941
+
+#define SIOCGIFTXQLEN 0x8942
+#define SIOCSIFTXQLEN 0x8943
+
+#define SIOCDARP 0x8953
+#define SIOCGARP 0x8954
+#define SIOCSARP 0x8955
+
+#define SIOCDRARP 0x8960
+#define SIOCGRARP 0x8961
+#define SIOCSRARP 0x8962
+
+#define SIOCGIFMAP 0x8970
+#define SIOCSIFMAP 0x8971
+
+#define SIOCADDDLCI 0x8980
+#define SIOCDELDLCI 0x8981
+
+#define SIOCDEVPRIVATE 0x89F0
+#define SIOCPROTOPRIVATE 0x89E0
diff --git a/arch/powerpc64/bits/ipc.h b/arch/powerpc64/bits/ipc.h
new file mode 100644
index 0000000..e1bfe2f
--- /dev/null
+++ b/arch/powerpc64/bits/ipc.h
@@ -0,0 +1,16 @@
+struct ipc_perm
+{
+ key_t __ipc_perm_key;
+ uid_t uid;
+ gid_t gid;
+ uid_t cuid;
+ gid_t cgid;
+ mode_t mode;
+ int __ipc_perm_seq;
+ int __pad1;
+ long long __pad2;
+ long long __pad3;
+};
+
+#define IPC_64 0x100
+
diff --git a/arch/powerpc64/bits/limits.h b/arch/powerpc64/bits/limits.h
new file mode 100644
index 0000000..0226588
--- /dev/null
+++ b/arch/powerpc64/bits/limits.h
@@ -0,0 +1,7 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define LONG_BIT 64
+#endif
+
+#define LONG_MAX 0x7fffffffffffffffL
+#define LLONG_MAX 0x7fffffffffffffffLL
diff --git a/arch/powerpc64/bits/mman.h b/arch/powerpc64/bits/mman.h
new file mode 100644
index 0000000..f5974f8
--- /dev/null
+++ b/arch/powerpc64/bits/mman.h
@@ -0,0 +1,8 @@
+#define PROT_SAO 0x10
+
+#undef MCL_CURRENT
+#define MCL_CURRENT 0x2000
+#undef MCL_FUTURE
+#define MCL_FUTURE 0x4000
+#undef MCL_ONFAULT
+#define MCL_ONFAULT 0x8000
diff --git a/arch/powerpc64/bits/msg.h b/arch/powerpc64/bits/msg.h
new file mode 100644
index 0000000..badcf16
--- /dev/null
+++ b/arch/powerpc64/bits/msg.h
@@ -0,0 +1,13 @@
+struct msqid_ds
+{
+ struct ipc_perm msg_perm;
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
+ unsigned long msg_cbytes;
+ msgqnum_t msg_qnum;
+ msglen_t msg_qbytes;
+ pid_t msg_lspid;
+ pid_t msg_lrpid;
+ unsigned long __unused[2];
+};
diff --git a/arch/powerpc64/bits/posix.h b/arch/powerpc64/bits/posix.h
new file mode 100644
index 0000000..c37b94c
--- /dev/null
+++ b/arch/powerpc64/bits/posix.h
@@ -0,0 +1,2 @@
+#define _POSIX_V6_LP64_OFF64 1
+#define _POSIX_V7_LP64_OFF64 1
diff --git a/arch/powerpc64/bits/reg.h b/arch/powerpc64/bits/reg.h
new file mode 100644
index 0000000..49382c8
--- /dev/null
+++ b/arch/powerpc64/bits/reg.h
@@ -0,0 +1,3 @@
+#undef __WORDSIZE
+#define __WORDSIZE 64
+/* FIXME */
diff --git a/arch/powerpc64/bits/sem.h b/arch/powerpc64/bits/sem.h
new file mode 100644
index 0000000..5f04979
--- /dev/null
+++ b/arch/powerpc64/bits/sem.h
@@ -0,0 +1,7 @@
+struct semid_ds {
+ struct ipc_perm sem_perm;
+ time_t sem_otime;
+ time_t sem_ctime;
+ unsigned long sem_nsems;
+ unsigned long __unused[2];
+};
diff --git a/arch/powerpc64/bits/setjmp.h b/arch/powerpc64/bits/setjmp.h
new file mode 100644
index 0000000..589b675
--- /dev/null
+++ b/arch/powerpc64/bits/setjmp.h
@@ -0,0 +1 @@
+typedef unsigned long long __jmp_buf[66];
diff --git a/arch/powerpc64/bits/shm.h b/arch/powerpc64/bits/shm.h
new file mode 100644
index 0000000..9126851
--- /dev/null
+++ b/arch/powerpc64/bits/shm.h
@@ -0,0 +1,25 @@
+#define SHMLBA 4096
+
+struct shmid_ds
+{
+ struct ipc_perm shm_perm;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+ size_t shm_segsz;
+ pid_t shm_cpid;
+ pid_t shm_lpid;
+ unsigned long shm_nattch;
+ unsigned long __unused[2];
+};
+
+struct shminfo {
+ unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
+};
+
+struct shm_info {
+ int __used_ids;
+ unsigned long shm_tot, shm_rss, shm_swp;
+ unsigned long __swap_attempts, __swap_successes;
+};
+
diff --git a/arch/powerpc64/bits/signal.h b/arch/powerpc64/bits/signal.h
new file mode 100644
index 0000000..2a48508
--- /dev/null
+++ b/arch/powerpc64/bits/signal.h
@@ -0,0 +1,108 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+typedef unsigned long greg_t, gregset_t[48];
+
+typedef struct {
+ double fpregs[32];
+ double fpscr;
+} fpregset_t;
+
+typedef struct {
+ unsigned long vrregs[32][2];
+ unsigned _pad[3];
+ unsigned vrsave;
+ unsigned vscr;
+ unsigned _pad2[3];
+} vrregset_t;
+
+typedef struct sigcontext
+{
+ unsigned long _unused[4];
+ int signal;
+ int _pad0;
+ unsigned long handler;
+ unsigned long oldmask;
+ void *regs;
+ gregset_t gp_regs;
+ fpregset_t fp_regs;
+ vrregset_t *v_regs;
+ long vmx_reserve[34+34+32+1];
+} mcontext_t;
+
+#else
+
+typedef struct {
+ long __regs[4+4+48+33+1+34+34+32+1];
+} mcontext_t;
+
+#endif
+
+struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+};
+
+typedef struct __ucontext {
+ unsigned long uc_flags;
+ struct __ucontext *uc_link;
+ stack_t uc_stack;
+ sigset_t uc_sigmask;
+ mcontext_t uc_mcontext;
+} ucontext_t;
+
+#define SA_NOCLDSTOP 1U
+#define SA_NOCLDWAIT 2U
+#define SA_SIGINFO 4U
+#define SA_ONSTACK 0x08000000U
+#define SA_RESTART 0x10000000U
+#define SA_NODEFER 0x40000000U
+#define SA_RESETHAND 0x80000000U
+#define SA_RESTORER 0x04000000U
+
+#endif
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT SIGABRT
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED SIGSYS
+
+#define _NSIG 65
diff --git a/arch/powerpc64/bits/socket.h b/arch/powerpc64/bits/socket.h
new file mode 100644
index 0000000..d388dfe
--- /dev/null
+++ b/arch/powerpc64/bits/socket.h
@@ -0,0 +1,60 @@
+struct msghdr
+{
+ void *msg_name;
+ socklen_t msg_namelen;
+ struct iovec *msg_iov;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ int __pad1, msg_iovlen;
+#else
+ int msg_iovlen, __pad1;
+#endif
+ void *msg_control;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ int __pad2;
+ socklen_t msg_controllen;
+#else
+ socklen_t msg_controllen;
+ int __pad2;
+#endif
+ int msg_flags;
+};
+
+struct cmsghdr
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ int __pad1;
+ socklen_t cmsg_len;
+#else
+ socklen_t cmsg_len;
+ int __pad1;
+#endif
+ int cmsg_level;
+ int cmsg_type;
+};
+
+#define SO_DEBUG 1
+#define SO_REUSEADDR 2
+#define SO_TYPE 3
+#define SO_ERROR 4
+#define SO_DONTROUTE 5
+#define SO_BROADCAST 6
+#define SO_SNDBUF 7
+#define SO_RCVBUF 8
+#define SO_KEEPALIVE 9
+#define SO_OOBINLINE 10
+#define SO_NO_CHECK 11
+#define SO_PRIORITY 12
+#define SO_LINGER 13
+#define SO_BSDCOMPAT 14
+#define SO_REUSEPORT 15
+#define SO_RCVLOWAT 16
+#define SO_SNDLOWAT 17
+#define SO_RCVTIMEO 18
+#define SO_SNDTIMEO 19
+#define SO_PASSCRED 20
+#define SO_PEERCRED 21
+#define SO_ACCEPTCONN 30
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
diff --git a/arch/powerpc64/bits/stat.h b/arch/powerpc64/bits/stat.h
new file mode 100644
index 0000000..8172cff
--- /dev/null
+++ b/arch/powerpc64/bits/stat.h
@@ -0,0 +1,17 @@
+struct stat
+{
+ dev_t st_dev;
+ ino_t st_ino;
+ nlink_t st_nlink;
+ mode_t st_mode;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ blksize_t st_blksize;
+ blkcnt_t st_blocks;
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+ unsigned long __unused[3];
+};
diff --git a/arch/powerpc64/bits/stdint.h b/arch/powerpc64/bits/stdint.h
new file mode 100644
index 0000000..1bb147f
--- /dev/null
+++ b/arch/powerpc64/bits/stdint.h
@@ -0,0 +1,20 @@
+typedef int32_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST32_MIN INT32_MIN
+
+#define INT_FAST16_MAX INT32_MAX
+#define INT_FAST32_MAX INT32_MAX
+
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN INT64_MIN
+#define INTPTR_MAX INT64_MAX
+#define UINTPTR_MAX UINT64_MAX
+#define PTRDIFF_MIN INT64_MIN
+#define PTRDIFF_MAX INT64_MAX
+#define SIZE_MAX UINT64_MAX
diff --git a/arch/powerpc64/bits/syscall.h b/arch/powerpc64/bits/syscall.h
new file mode 100644
index 0000000..bf0161d
--- /dev/null
+++ b/arch/powerpc64/bits/syscall.h
@@ -0,0 +1,718 @@
+#define __NR_restart_syscall 0
+#define __NR_exit 1
+#define __NR_fork 2
+#define __NR_read 3
+#define __NR_write 4
+#define __NR_open 5
+#define __NR_close 6
+#define __NR_waitpid 7
+#define __NR_creat 8
+#define __NR_link 9
+#define __NR_unlink 10
+#define __NR_execve 11
+#define __NR_chdir 12
+#define __NR_time 13
+#define __NR_mknod 14
+#define __NR_chmod 15
+#define __NR_lchown 16
+#define __NR_break 17
+#define __NR_oldstat 18
+#define __NR_lseek 19
+#define __NR_getpid 20
+#define __NR_mount 21
+#define __NR_umount 22
+#define __NR_setuid 23
+#define __NR_getuid 24
+#define __NR_stime 25
+#define __NR_ptrace 26
+#define __NR_alarm 27
+#define __NR_oldfstat 28
+#define __NR_pause 29
+#define __NR_utime 30
+#define __NR_stty 31
+#define __NR_gtty 32
+#define __NR_access 33
+#define __NR_nice 34
+#define __NR_ftime 35
+#define __NR_sync 36
+#define __NR_kill 37
+#define __NR_rename 38
+#define __NR_mkdir 39
+#define __NR_rmdir 40
+#define __NR_dup 41
+#define __NR_pipe 42
+#define __NR_times 43
+#define __NR_prof 44
+#define __NR_brk 45
+#define __NR_setgid 46
+#define __NR_getgid 47
+#define __NR_signal 48
+#define __NR_geteuid 49
+#define __NR_getegid 50
+#define __NR_acct 51
+#define __NR_umount2 52
+#define __NR_lock 53
+#define __NR_ioctl 54
+#define __NR_fcntl 55
+#define __NR_mpx 56
+#define __NR_setpgid 57
+#define __NR_ulimit 58
+#define __NR_oldolduname 59
+#define __NR_umask 60
+#define __NR_chroot 61
+#define __NR_ustat 62
+#define __NR_dup2 63
+#define __NR_getppid 64
+#define __NR_getpgrp 65
+#define __NR_setsid 66
+#define __NR_sigaction 67
+#define __NR_sgetmask 68
+#define __NR_ssetmask 69
+#define __NR_setreuid 70
+#define __NR_setregid 71
+#define __NR_sigsuspend 72
+#define __NR_sigpending 73
+#define __NR_sethostname 74
+#define __NR_setrlimit 75
+#define __NR_getrlimit 76
+#define __NR_getrusage 77
+#define __NR_gettimeofday 78
+#define __NR_settimeofday 79
+#define __NR_getgroups 80
+#define __NR_setgroups 81
+#define __NR_select 82
+#define __NR_symlink 83
+#define __NR_oldlstat 84
+#define __NR_readlink 85
+#define __NR_uselib 86
+#define __NR_swapon 87
+#define __NR_reboot 88
+#define __NR_readdir 89
+#define __NR_mmap 90
+#define __NR_munmap 91
+#define __NR_truncate 92
+#define __NR_ftruncate 93
+#define __NR_fchmod 94
+#define __NR_fchown 95
+#define __NR_getpriority 96
+#define __NR_setpriority 97
+#define __NR_profil 98
+#define __NR_statfs 99
+#define __NR_fstatfs 100
+#define __NR_ioperm 101
+#define __NR_socketcall 102
+#define __NR_syslog 103
+#define __NR_setitimer 104
+#define __NR_getitimer 105
+#define __NR_stat 106
+#define __NR_lstat 107
+#define __NR_fstat 108
+#define __NR_olduname 109
+#define __NR_iopl 110
+#define __NR_vhangup 111
+#define __NR_idle 112
+#define __NR_vm86 113
+#define __NR_wait4 114
+#define __NR_swapoff 115
+#define __NR_sysinfo 116
+#define __NR_ipc 117
+#define __NR_fsync 118
+#define __NR_sigreturn 119
+#define __NR_clone 120
+#define __NR_setdomainname 121
+#define __NR_uname 122
+#define __NR_modify_ldt 123
+#define __NR_adjtimex 124
+#define __NR_mprotect 125
+#define __NR_sigprocmask 126
+#define __NR_create_module 127
+#define __NR_init_module 128
+#define __NR_delete_module 129
+#define __NR_get_kernel_syms 130
+#define __NR_quotactl 131
+#define __NR_getpgid 132
+#define __NR_fchdir 133
+#define __NR_bdflush 134
+#define __NR_sysfs 135
+#define __NR_personality 136
+#define __NR_afs_syscall 137
+#define __NR_setfsuid 138
+#define __NR_setfsgid 139
+#define __NR__llseek 140
+#define __NR_getdents 141
+#define __NR__newselect 142
+#define __NR_flock 143
+#define __NR_msync 144
+#define __NR_readv 145
+#define __NR_writev 146
+#define __NR_getsid 147
+#define __NR_fdatasync 148
+#define __NR__sysctl 149
+#define __NR_mlock 150
+#define __NR_munlock 151
+#define __NR_mlockall 152
+#define __NR_munlockall 153
+#define __NR_sched_setparam 154
+#define __NR_sched_getparam 155
+#define __NR_sched_setscheduler 156
+#define __NR_sched_getscheduler 157
+#define __NR_sched_yield 158
+#define __NR_sched_get_priority_max 159
+#define __NR_sched_get_priority_min 160
+#define __NR_sched_rr_get_interval 161
+#define __NR_nanosleep 162
+#define __NR_mremap 163
+#define __NR_setresuid 164
+#define __NR_getresuid 165
+#define __NR_query_module 166
+#define __NR_poll 167
+#define __NR_nfsservctl 168
+#define __NR_setresgid 169
+#define __NR_getresgid 170
+#define __NR_prctl 171
+#define __NR_rt_sigreturn 172
+#define __NR_rt_sigaction 173
+#define __NR_rt_sigprocmask 174
+#define __NR_rt_sigpending 175
+#define __NR_rt_sigtimedwait 176
+#define __NR_rt_sigqueueinfo 177
+#define __NR_rt_sigsuspend 178
+#define __NR_pread64 179
+#define __NR_pwrite64 180
+#define __NR_chown 181
+#define __NR_getcwd 182
+#define __NR_capget 183
+#define __NR_capset 184
+#define __NR_sigaltstack 185
+#define __NR_sendfile 186
+#define __NR_getpmsg 187
+#define __NR_putpmsg 188
+#define __NR_vfork 189
+#define __NR_ugetrlimit 190
+#define __NR_readahead 191
+#define __NR_pciconfig_read 198
+#define __NR_pciconfig_write 199
+#define __NR_pciconfig_iobase 200
+#define __NR_multiplexer 201
+#define __NR_getdents64 202
+#define __NR_pivot_root 203
+#define __NR_madvise 205
+#define __NR_mincore 206
+#define __NR_gettid 207
+#define __NR_tkill 208
+#define __NR_setxattr 209
+#define __NR_lsetxattr 210
+#define __NR_fsetxattr 211
+#define __NR_getxattr 212
+#define __NR_lgetxattr 213
+#define __NR_fgetxattr 214
+#define __NR_listxattr 215
+#define __NR_llistxattr 216
+#define __NR_flistxattr 217
+#define __NR_removexattr 218
+#define __NR_lremovexattr 219
+#define __NR_fremovexattr 220
+#define __NR_futex 221
+#define __NR_sched_setaffinity 222
+#define __NR_sched_getaffinity 223
+#define __NR_tuxcall 225
+#define __NR_io_setup 227
+#define __NR_io_destroy 228
+#define __NR_io_getevents 229
+#define __NR_io_submit 230
+#define __NR_io_cancel 231
+#define __NR_set_tid_address 232
+#define __NR_fadvise64 233
+#define __NR_exit_group 234
+#define __NR_lookup_dcookie 235
+#define __NR_epoll_create 236
+#define __NR_epoll_ctl 237
+#define __NR_epoll_wait 238
+#define __NR_remap_file_pages 239
+#define __NR_timer_create 240
+#define __NR_timer_settime 241
+#define __NR_timer_gettime 242
+#define __NR_timer_getoverrun 243
+#define __NR_timer_delete 244
+#define __NR_clock_settime 245
+#define __NR_clock_gettime 246
+#define __NR_clock_getres 247
+#define __NR_clock_nanosleep 248
+#define __NR_swapcontext 249
+#define __NR_tgkill 250
+#define __NR_utimes 251
+#define __NR_statfs64 252
+#define __NR_fstatfs64 253
+#define __NR_rtas 255
+#define __NR_sys_debug_setcontext 256
+#define __NR_migrate_pages 258
+#define __NR_mbind 259
+#define __NR_get_mempolicy 260
+#define __NR_set_mempolicy 261
+#define __NR_mq_open 262
+#define __NR_mq_unlink 263
+#define __NR_mq_timedsend 264
+#define __NR_mq_timedreceive 265
+#define __NR_mq_notify 266
+#define __NR_mq_getsetattr 267
+#define __NR_kexec_load 268
+#define __NR_add_key 269
+#define __NR_request_key 270
+#define __NR_keyctl 271
+#define __NR_waitid 272
+#define __NR_ioprio_set 273
+#define __NR_ioprio_get 274
+#define __NR_inotify_init 275
+#define __NR_inotify_add_watch 276
+#define __NR_inotify_rm_watch 277
+#define __NR_spu_run 278
+#define __NR_spu_create 279
+#define __NR_pselect6 280
+#define __NR_ppoll 281
+#define __NR_unshare 282
+#define __NR_splice 283
+#define __NR_tee 284
+#define __NR_vmsplice 285
+#define __NR_openat 286
+#define __NR_mkdirat 287
+#define __NR_mknodat 288
+#define __NR_fchownat 289
+#define __NR_futimesat 290
+#define __NR_newfstatat 291
+#define __NR_unlinkat 292
+#define __NR_renameat 293
+#define __NR_linkat 294
+#define __NR_symlinkat 295
+#define __NR_readlinkat 296
+#define __NR_fchmodat 297
+#define __NR_faccessat 298
+#define __NR_get_robust_list 299
+#define __NR_set_robust_list 300
+#define __NR_move_pages 301
+#define __NR_getcpu 302
+#define __NR_epoll_pwait 303
+#define __NR_utimensat 304
+#define __NR_signalfd 305
+#define __NR_timerfd_create 306
+#define __NR_eventfd 307
+#define __NR_sync_file_range2 308
+#define __NR_fallocate 309
+#define __NR_subpage_prot 310
+#define __NR_timerfd_settime 311
+#define __NR_timerfd_gettime 312
+#define __NR_signalfd4 313
+#define __NR_eventfd2 314
+#define __NR_epoll_create1 315
+#define __NR_dup3 316
+#define __NR_pipe2 317
+#define __NR_inotify_init1 318
+#define __NR_perf_event_open 319
+#define __NR_preadv 320
+#define __NR_pwritev 321
+#define __NR_rt_tgsigqueueinfo 322
+#define __NR_fanotify_init 323
+#define __NR_fanotify_mark 324
+#define __NR_prlimit64 325
+#define __NR_socket 326
+#define __NR_bind 327
+#define __NR_connect 328
+#define __NR_listen 329
+#define __NR_accept 330
+#define __NR_getsockname 331
+#define __NR_getpeername 332
+#define __NR_socketpair 333
+#define __NR_send 334
+#define __NR_sendto 335
+#define __NR_recv 336
+#define __NR_recvfrom 337
+#define __NR_shutdown 338
+#define __NR_setsockopt 339
+#define __NR_getsockopt 340
+#define __NR_sendmsg 341
+#define __NR_recvmsg 342
+#define __NR_recvmmsg 343
+#define __NR_accept4 344
+#define __NR_name_to_handle_at 345
+#define __NR_open_by_handle_at 346
+#define __NR_clock_adjtime 347
+#define __NR_syncfs 348
+#define __NR_sendmmsg 349
+#define __NR_setns 350
+#define __NR_process_vm_readv 351
+#define __NR_process_vm_writev 352
+#define __NR_finit_module 353
+#define __NR_kcmp 354
+#define __NR_sched_setattr 355
+#define __NR_sched_getattr 356
+#define __NR_renameat2 357
+#define __NR_seccomp 358
+#define __NR_getrandom 359
+#define __NR_memfd_create 360
+#define __NR_bpf 361
+#define __NR_execveat 362
+#define __NR_switch_endian 363
+#define __NR_userfaultfd 364
+#define __NR_membarrier 365
+#define __NR_mlock2 378
+#define __NR_copy_file_range 379
+
+/*
+ * repeated with SYS prefix
+ */
+#define SYS_restart_syscall __NR_restart_syscall
+#define SYS_exit __NR_exit
+#define SYS_fork __NR_fork
+#define SYS_read __NR_read
+#define SYS_write __NR_write
+#define SYS_open __NR_open
+#define SYS_close __NR_close
+#define SYS_waitpid __NR_waitpid
+#define SYS_creat __NR_creat
+#define SYS_link __NR_link
+#define SYS_unlink __NR_unlink
+#define SYS_execve __NR_execve
+#define SYS_chdir __NR_chdir
+#define SYS_time __NR_time
+#define SYS_mknod __NR_mknod
+#define SYS_chmod __NR_chmod
+#define SYS_lchown __NR_lchown
+#define SYS_break __NR_break
+#define SYS_oldstat __NR_oldstat
+#define SYS_lseek __NR_lseek
+#define SYS_getpid __NR_getpid
+#define SYS_mount __NR_mount
+#define SYS_umount __NR_umount
+#define SYS_setuid __NR_setuid
+#define SYS_getuid __NR_getuid
+#define SYS_stime __NR_stime
+#define SYS_ptrace __NR_ptrace
+#define SYS_alarm __NR_alarm
+#define SYS_oldfstat __NR_oldfstat
+#define SYS_pause __NR_pause
+#define SYS_utime __NR_utime
+#define SYS_stty __NR_stty
+#define SYS_gtty __NR_gtty
+#define SYS_access __NR_access
+#define SYS_nice __NR_nice
+#define SYS_ftime __NR_ftime
+#define SYS_sync __NR_sync
+#define SYS_kill __NR_kill
+#define SYS_rename __NR_rename
+#define SYS_mkdir __NR_mkdir
+#define SYS_rmdir __NR_rmdir
+#define SYS_dup __NR_dup
+#define SYS_pipe __NR_pipe
+#define SYS_times __NR_times
+#define SYS_prof __NR_prof
+#define SYS_brk __NR_brk
+#define SYS_setgid __NR_setgid
+#define SYS_getgid __NR_getgid
+#define SYS_signal __NR_signal
+#define SYS_geteuid __NR_geteuid
+#define SYS_getegid __NR_getegid
+#define SYS_acct __NR_acct
+#define SYS_umount2 __NR_umount2
+#define SYS_lock __NR_lock
+#define SYS_ioctl __NR_ioctl
+#define SYS_fcntl __NR_fcntl
+#define SYS_mpx __NR_mpx
+#define SYS_setpgid __NR_setpgid
+#define SYS_ulimit __NR_ulimit
+#define SYS_oldolduname __NR_oldolduname
+#define SYS_umask __NR_umask
+#define SYS_chroot __NR_chroot
+#define SYS_ustat __NR_ustat
+#define SYS_dup2 __NR_dup2
+#define SYS_getppid __NR_getppid
+#define SYS_getpgrp __NR_getpgrp
+#define SYS_setsid __NR_setsid
+#define SYS_sigaction __NR_sigaction
+#define SYS_sgetmask __NR_sgetmask
+#define SYS_ssetmask __NR_ssetmask
+#define SYS_setreuid __NR_setreuid
+#define SYS_setregid __NR_setregid
+#define SYS_sigsuspend __NR_sigsuspend
+#define SYS_sigpending __NR_sigpending
+#define SYS_sethostname __NR_sethostname
+#define SYS_setrlimit __NR_setrlimit
+#define SYS_getrlimit __NR_getrlimit
+#define SYS_getrusage __NR_getrusage
+#define SYS_gettimeofday __NR_gettimeofday
+#define SYS_settimeofday __NR_settimeofday
+#define SYS_getgroups __NR_getgroups
+#define SYS_setgroups __NR_setgroups
+#define SYS_select __NR_select
+#define SYS_symlink __NR_symlink
+#define SYS_oldlstat __NR_oldlstat
+#define SYS_readlink __NR_readlink
+#define SYS_uselib __NR_uselib
+#define SYS_swapon __NR_swapon
+#define SYS_reboot __NR_reboot
+#define SYS_readdir __NR_readdir
+#define SYS_mmap __NR_mmap
+#define SYS_munmap __NR_munmap
+#define SYS_truncate __NR_truncate
+#define SYS_ftruncate __NR_ftruncate
+#define SYS_fchmod __NR_fchmod
+#define SYS_fchown __NR_fchown
+#define SYS_getpriority __NR_getpriority
+#define SYS_setpriority __NR_setpriority
+#define SYS_profil __NR_profil
+#define SYS_statfs __NR_statfs
+#define SYS_fstatfs __NR_fstatfs
+#define SYS_ioperm __NR_ioperm
+#define SYS_socketcall __NR_socketcall
+#define SYS_syslog __NR_syslog
+#define SYS_setitimer __NR_setitimer
+#define SYS_getitimer __NR_getitimer
+#define SYS_stat __NR_stat
+#define SYS_lstat __NR_lstat
+#define SYS_fstat __NR_fstat
+#define SYS_olduname __NR_olduname
+#define SYS_iopl __NR_iopl
+#define SYS_vhangup __NR_vhangup
+#define SYS_idle __NR_idle
+#define SYS_vm86 __NR_vm86
+#define SYS_wait4 __NR_wait4
+#define SYS_swapoff __NR_swapoff
+#define SYS_sysinfo __NR_sysinfo
+#define SYS_ipc __NR_ipc
+#define SYS_fsync __NR_fsync
+#define SYS_sigreturn __NR_sigreturn
+#define SYS_clone __NR_clone
+#define SYS_setdomainname __NR_setdomainname
+#define SYS_uname __NR_uname
+#define SYS_modify_ldt __NR_modify_ldt
+#define SYS_adjtimex __NR_adjtimex
+#define SYS_mprotect __NR_mprotect
+#define SYS_sigprocmask __NR_sigprocmask
+#define SYS_create_module __NR_create_module
+#define SYS_init_module __NR_init_module
+#define SYS_delete_module __NR_delete_module
+#define SYS_get_kernel_syms __NR_get_kernel_syms
+#define SYS_quotactl __NR_quotactl
+#define SYS_getpgid __NR_getpgid
+#define SYS_fchdir __NR_fchdir
+#define SYS_bdflush __NR_bdflush
+#define SYS_sysfs __NR_sysfs
+#define SYS_personality __NR_personality
+#define SYS_afs_syscall __NR_afs_syscall
+#define SYS_setfsuid __NR_setfsuid
+#define SYS_setfsgid __NR_setfsgid
+#define SYS__llseek __NR__llseek
+#define SYS_getdents __NR_getdents
+#define SYS__newselect __NR__newselect
+#define SYS_flock __NR_flock
+#define SYS_msync __NR_msync
+#define SYS_readv __NR_readv
+#define SYS_writev __NR_writev
+#define SYS_getsid __NR_getsid
+#define SYS_fdatasync __NR_fdatasync
+#define SYS__sysctl __NR__sysctl
+#define SYS_mlock __NR_mlock
+#define SYS_munlock __NR_munlock
+#define SYS_mlockall __NR_mlockall
+#define SYS_munlockall __NR_munlockall
+#define SYS_sched_setparam __NR_sched_setparam
+#define SYS_sched_getparam __NR_sched_getparam
+#define SYS_sched_setscheduler __NR_sched_setscheduler
+#define SYS_sched_getscheduler __NR_sched_getscheduler
+#define SYS_sched_yield __NR_sched_yield
+#define SYS_sched_get_priority_max __NR_sched_get_priority_max
+#define SYS_sched_get_priority_min __NR_sched_get_priority_min
+#define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
+#define SYS_nanosleep __NR_nanosleep
+#define SYS_mremap __NR_mremap
+#define SYS_setresuid __NR_setresuid
+#define SYS_getresuid __NR_getresuid
+#define SYS_query_module __NR_query_module
+#define SYS_poll __NR_poll
+#define SYS_nfsservctl __NR_nfsservctl
+#define SYS_setresgid __NR_setresgid
+#define SYS_getresgid __NR_getresgid
+#define SYS_prctl __NR_prctl
+#define SYS_rt_sigreturn __NR_rt_sigreturn
+#define SYS_rt_sigaction __NR_rt_sigaction
+#define SYS_rt_sigprocmask __NR_rt_sigprocmask
+#define SYS_rt_sigpending __NR_rt_sigpending
+#define SYS_rt_sigtimedwait __NR_rt_sigtimedwait
+#define SYS_rt_sigqueueinfo __NR_rt_sigqueueinfo
+#define SYS_rt_sigsuspend __NR_rt_sigsuspend
+#define SYS_pread64 __NR_pread64
+#define SYS_pwrite64 __NR_pwrite64
+#define SYS_chown __NR_chown
+#define SYS_getcwd __NR_getcwd
+#define SYS_capget __NR_capget
+#define SYS_capset __NR_capset
+#define SYS_sigaltstack __NR_sigaltstack
+#define SYS_sendfile __NR_sendfile
+#define SYS_getpmsg __NR_getpmsg
+#define SYS_putpmsg __NR_putpmsg
+#define SYS_vfork __NR_vfork
+#define SYS_ugetrlimit __NR_ugetrlimit
+#define SYS_readahead __NR_readahead
+#define SYS_pciconfig_read __NR_pciconfig_read
+#define SYS_pciconfig_write __NR_pciconfig_write
+#define SYS_pciconfig_iobase __NR_pciconfig_iobase
+#define SYS_multiplexer __NR_multiplexer
+#define SYS_getdents64 __NR_getdents64
+#define SYS_pivot_root __NR_pivot_root
+#define SYS_madvise __NR_madvise
+#define SYS_mincore __NR_mincore
+#define SYS_gettid __NR_gettid
+#define SYS_tkill __NR_tkill
+#define SYS_setxattr __NR_setxattr
+#define SYS_lsetxattr __NR_lsetxattr
+#define SYS_fsetxattr __NR_fsetxattr
+#define SYS_getxattr __NR_getxattr
+#define SYS_lgetxattr __NR_lgetxattr
+#define SYS_fgetxattr __NR_fgetxattr
+#define SYS_listxattr __NR_listxattr
+#define SYS_llistxattr __NR_llistxattr
+#define SYS_flistxattr __NR_flistxattr
+#define SYS_removexattr __NR_removexattr
+#define SYS_lremovexattr __NR_lremovexattr
+#define SYS_fremovexattr __NR_fremovexattr
+#define SYS_futex __NR_futex
+#define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_tuxcall __NR_tuxcall
+#define SYS_io_setup __NR_io_setup
+#define SYS_io_destroy __NR_io_destroy
+#define SYS_io_getevents __NR_io_getevents
+#define SYS_io_submit __NR_io_submit
+#define SYS_io_cancel __NR_io_cancel
+#define SYS_set_tid_address __NR_set_tid_address
+#define SYS_fadvise64 __NR_fadvise64
+#define SYS_exit_group __NR_exit_group
+#define SYS_lookup_dcookie __NR_lookup_dcookie
+#define SYS_epoll_create __NR_epoll_create
+#define SYS_epoll_ctl __NR_epoll_ctl
+#define SYS_epoll_wait __NR_epoll_wait
+#define SYS_remap_file_pages __NR_remap_file_pages
+#define SYS_timer_create __NR_timer_create
+#define SYS_timer_settime __NR_timer_settime
+#define SYS_timer_gettime __NR_timer_gettime
+#define SYS_timer_getoverrun __NR_timer_getoverrun
+#define SYS_timer_delete __NR_timer_delete
+#define SYS_clock_settime __NR_clock_settime
+#define SYS_clock_gettime __NR_clock_gettime
+#define SYS_clock_getres __NR_clock_getres
+#define SYS_clock_nanosleep __NR_clock_nanosleep
+#define SYS_swapcontext __NR_swapcontext
+#define SYS_tgkill __NR_tgkill
+#define SYS_utimes __NR_utimes
+#define SYS_statfs64 __NR_statfs64
+#define SYS_fstatfs64 __NR_fstatfs64
+#define SYS_rtas __NR_rtas
+#define SYS_sys_debug_setcontext __NR_sys_debug_setcontext
+#define SYS_migrate_pages __NR_migrate_pages
+#define SYS_mbind __NR_mbind
+#define SYS_get_mempolicy __NR_get_mempolicy
+#define SYS_set_mempolicy __NR_set_mempolicy
+#define SYS_mq_open __NR_mq_open
+#define SYS_mq_unlink __NR_mq_unlink
+#define SYS_mq_timedsend __NR_mq_timedsend
+#define SYS_mq_timedreceive __NR_mq_timedreceive
+#define SYS_mq_notify __NR_mq_notify
+#define SYS_mq_getsetattr __NR_mq_getsetattr
+#define SYS_kexec_load __NR_kexec_load
+#define SYS_add_key __NR_add_key
+#define SYS_request_key __NR_request_key
+#define SYS_keyctl __NR_keyctl
+#define SYS_waitid __NR_waitid
+#define SYS_ioprio_set __NR_ioprio_set
+#define SYS_ioprio_get __NR_ioprio_get
+#define SYS_inotify_init __NR_inotify_init
+#define SYS_inotify_add_watch __NR_inotify_add_watch
+#define SYS_inotify_rm_watch __NR_inotify_rm_watch
+#define SYS_spu_run __NR_spu_run
+#define SYS_spu_create __NR_spu_create
+#define SYS_pselect6 __NR_pselect6
+#define SYS_ppoll __NR_ppoll
+#define SYS_unshare __NR_unshare
+#define SYS_splice __NR_splice
+#define SYS_tee __NR_tee
+#define SYS_vmsplice __NR_vmsplice
+#define SYS_openat __NR_openat
+#define SYS_mkdirat __NR_mkdirat
+#define SYS_mknodat __NR_mknodat
+#define SYS_fchownat __NR_fchownat
+#define SYS_futimesat __NR_futimesat
+#define SYS_newfstatat __NR_newfstatat
+#define SYS_unlinkat __NR_unlinkat
+#define SYS_renameat __NR_renameat
+#define SYS_linkat __NR_linkat
+#define SYS_symlinkat __NR_symlinkat
+#define SYS_readlinkat __NR_readlinkat
+#define SYS_fchmodat __NR_fchmodat
+#define SYS_faccessat __NR_faccessat
+#define SYS_get_robust_list __NR_get_robust_list
+#define SYS_set_robust_list __NR_set_robust_list
+#define SYS_move_pages __NR_move_pages
+#define SYS_getcpu __NR_getcpu
+#define SYS_epoll_pwait __NR_epoll_pwait
+#define SYS_utimensat __NR_utimensat
+#define SYS_signalfd __NR_signalfd
+#define SYS_timerfd_create __NR_timerfd_create
+#define SYS_eventfd __NR_eventfd
+#define SYS_sync_file_range2 __NR_sync_file_range2
+#define SYS_fallocate __NR_fallocate
+#define SYS_subpage_prot __NR_subpage_prot
+#define SYS_timerfd_settime __NR_timerfd_settime
+#define SYS_timerfd_gettime __NR_timerfd_gettime
+#define SYS_signalfd4 __NR_signalfd4
+#define SYS_eventfd2 __NR_eventfd2
+#define SYS_epoll_create1 __NR_epoll_create1
+#define SYS_dup3 __NR_dup3
+#define SYS_pipe2 __NR_pipe2
+#define SYS_inotify_init1 __NR_inotify_init1
+#define SYS_perf_event_open __NR_perf_event_open
+#define SYS_preadv __NR_preadv
+#define SYS_pwritev __NR_pwritev
+#define SYS_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
+#define SYS_fanotify_init __NR_fanotify_init
+#define SYS_fanotify_mark __NR_fanotify_mark
+#define SYS_prlimit64 __NR_prlimit64
+#define SYS_socket __NR_socket
+#define SYS_bind __NR_bind
+#define SYS_connect __NR_connect
+#define SYS_listen __NR_listen
+#define SYS_accept __NR_accept
+#define SYS_getsockname __NR_getsockname
+#define SYS_getpeername __NR_getpeername
+#define SYS_socketpair __NR_socketpair
+#define SYS_send __NR_send
+#define SYS_sendto __NR_sendto
+#define SYS_recv __NR_recv
+#define SYS_recvfrom __NR_recvfrom
+#define SYS_shutdown __NR_shutdown
+#define SYS_setsockopt __NR_setsockopt
+#define SYS_getsockopt __NR_getsockopt
+#define SYS_sendmsg __NR_sendmsg
+#define SYS_recvmsg __NR_recvmsg
+#define SYS_recvmmsg __NR_recvmmsg
+#define SYS_accept4 __NR_accept4
+#define SYS_name_to_handle_at __NR_name_to_handle_at
+#define SYS_open_by_handle_at __NR_open_by_handle_at
+#define SYS_clock_adjtime __NR_clock_adjtime
+#define SYS_syncfs __NR_syncfs
+#define SYS_sendmmsg __NR_sendmmsg
+#define SYS_setns __NR_setns
+#define SYS_process_vm_readv __NR_process_vm_readv
+#define SYS_process_vm_writev __NR_process_vm_writev
+#define SYS_finit_module __NR_finit_module
+#define SYS_kcmp __NR_kcmp
+#define SYS_sched_setattr __NR_sched_setattr
+#define SYS_sched_getattr __NR_sched_getattr
+#define SYS_renameat2 __NR_renameat2
+#define SYS_seccomp __NR_seccomp
+#define SYS_getrandom __NR_getrandom
+#define SYS_memfd_create __NR_memfd_create
+#define SYS_bpf __NR_bpf
+#define SYS_execveat __NR_execveat
+#define SYS_switch_endian __NR_switch_endian
+#define SYS_userfaultfd __NR_userfaultfd
+#define SYS_membarrier __NR_membarrier
+#define SYS_mlock2 __NR_mlock2
+#define SYS_copy_file_range __NR_copy_file_range
diff --git a/arch/powerpc64/bits/termios.h b/arch/powerpc64/bits/termios.h
new file mode 100644
index 0000000..7feaf49
--- /dev/null
+++ b/arch/powerpc64/bits/termios.h
@@ -0,0 +1,170 @@
+#undef NCCS
+#define NCCS 19
+struct termios
+{
+ tcflag_t c_iflag;
+ tcflag_t c_oflag;
+ tcflag_t c_cflag;
+ tcflag_t c_lflag;
+ cc_t c_cc[NCCS];
+ cc_t c_line;
+ speed_t __c_ispeed;
+ speed_t __c_ospeed;
+};
+
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VMIN 5
+#define VEOL 6
+#define VTIME 7
+#define VEOL2 8
+#define VSWTC 9
+#define VWERASE 10
+#define VREPRINT 11
+#define VSUSP 12
+#define VSTART 13
+#define VSTOP 14
+#define VLNEXT 15
+#define VDISCARD 16
+
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK 0000020
+#define ISTRIP 0000040
+#define INLCR 0000100
+#define IGNCR 0000200
+#define ICRNL 0000400
+#define IXON 0001000
+#define IXOFF 0002000
+#define IXANY 0004000
+#define IUCLC 0010000
+#define IMAXBEL 0020000
+#define IUTF8 0040000
+
+#define OPOST 0000001
+#define ONLCR 0000002
+#define OLCUC 0000004
+#define OCRNL 0000010
+#define ONOCR 0000020
+#define ONLRET 0000040
+#define OFILL 0000100
+#define OFDEL 0000200
+#define NLDLY 0001400
+#define NL0 0000000
+#define NL1 0000400
+#define NL2 0001000
+#define NL3 0001400
+#define TABDLY 0006000
+#define TAB0 0000000
+#define TAB1 0002000
+#define TAB2 0004000
+#define TAB3 0006000
+#define CRDLY 0030000
+#define CR0 0000000
+#define CR1 0010000
+#define CR2 0020000
+#define CR3 0030000
+#define FFDLY 0040000
+#define FF0 0000000
+#define FF1 0040000
+#define BSDLY 0100000
+#define BS0 0000000
+#define BS1 0100000
+
+#define VTDLY 0200000
+#define VT0 0000000
+#define VT1 0200000
+
+#define B0 0000000
+#define B50 0000001
+#define B75 0000002
+#define B110 0000003
+#define B134 0000004
+#define B150 0000005
+#define B200 0000006
+#define B300 0000007
+#define B600 0000010
+#define B1200 0000011
+#define B1800 0000012
+#define B2400 0000013
+#define B4800 0000014
+#define B9600 0000015
+#define B19200 0000016
+#define B38400 0000017
+#define EXTA 0000016
+#define EXTB 0000017
+
+#define B57600 00020
+#define B115200 00021
+#define B230400 00022
+#define B460800 00023
+#define B500000 00024
+#define B576000 00025
+#define B921600 00026
+#define B1000000 00027
+#define B1152000 00030
+#define B1500000 00031
+#define B2000000 00032
+#define B2500000 00033
+#define B3000000 00034
+#define B3500000 00035
+#define B4000000 00036
+#define BOTHER 00037
+
+#define CBAUD 00377
+
+#define CSIZE 00001400
+#define CS5 00000000
+#define CS6 00000400
+#define CS7 00001000
+#define CS8 00001400
+#define CSTOPB 00002000
+#define CREAD 00004000
+#define PARENB 00010000
+#define PARODD 00020000
+#define HUPCL 00040000
+#define CLOCAL 00100000
+
+#define ECHOKE 0x00000001
+#define ECHOE 0x00000002
+#define ECHOK 0x00000004
+#define ECHO 0x00000008
+#define ECHONL 0x00000010
+#define ECHOPRT 0x00000020
+#define ECHOCTL 0x00000040
+#define ISIG 0x00000080
+#define ICANON 0x00000100
+#define IEXTEN 0x00000400
+#define XCASE 0x00004000
+#define TOSTOP 0x00400000
+#define FLUSHO 0x00800000
+#define PENDIN 0x20000000
+#define NOFLSH 0x80000000
+
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define CBAUDEX 0000000
+#define CIBAUD 077600000
+#define IBSHIFT 16
+#define CMSPAR 010000000000
+#define CRTSCTS 020000000000
+#define EXTPROC 0x10000000
+#define XTABS 00006000
+#endif
diff --git a/arch/powerpc64/bits/user.h b/arch/powerpc64/bits/user.h
new file mode 100644
index 0000000..7ca459b
--- /dev/null
+++ b/arch/powerpc64/bits/user.h
@@ -0,0 +1,25 @@
+struct pt_regs {
+ unsigned long gpr[32], nip, msr, orig_gpr3, ctr, link, xer, ccr, softe;
+ unsigned long trap, dar, dsisr, result;
+};
+
+struct user {
+ struct pt_regs regs;
+ unsigned long u_tsize, u_dsize, u_ssize;
+ unsigned long start_code, start_data, start_stack;
+ long signal;
+ void *u_ar0;
+ unsigned long magic;
+ char u_comm[32];
+};
+
+#define ELF_NGREG 48
+#define ELF_NFPREG 33
+#define ELF_NVRREG 34
+typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+typedef double elf_fpreg_t, elf_fpregset_t[ELF_NFPREG];
+typedef struct { unsigned u[4]; }
+#ifdef __GNUC__
+__attribute__((__aligned__(16)))
+#endif
+ elf_vrreg_t, elf_vrregset_t[ELF_NVRREG];
diff --git a/arch/powerpc64/crt_arch.h b/arch/powerpc64/crt_arch.h
new file mode 100644
index 0000000..0605511
--- /dev/null
+++ b/arch/powerpc64/crt_arch.h
@@ -0,0 +1,21 @@
+__asm__(
+".text \n"
+".global " START " \n"
+".type " START ", %function \n"
+START ": \n"
+" addis 2, 12, .TOC.-" START "@ha \n"
+" addi 2, 2, .TOC.-" START "@l \n"
+" bl 1f \n"
+".weak _DYNAMIC \n"
+".hidden _DYNAMIC \n"
+" .long _DYNAMIC-. \n"
+"1: mflr 4 \n"
+" lwz 3, 0(4) \n"
+" add 4, 3, 4 \n"
+" mr 3, 1 \n"
+" clrrdi 1, 1, 4 \n"
+" li 0, 0 \n"
+" stdu 0, -32(1) \n"
+" mtlr 0 \n"
+" bl " START "_c \n"
+);
diff --git a/arch/powerpc64/pthread_arch.h b/arch/powerpc64/pthread_arch.h
new file mode 100644
index 0000000..2f976fe
--- /dev/null
+++ b/arch/powerpc64/pthread_arch.h
@@ -0,0 +1,17 @@
+static inline struct pthread *__pthread_self()
+{
+ register char *tp __asm__("r13");
+ __asm__ __volatile__ ("" : "=r" (tp) );
+ return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
+}
+
+#define TLS_ABOVE_TP
+#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
+
+#define DTP_OFFSET 0x8000
+
+// the kernel calls the ip "nip", it's the first saved value after the 32
+// GPRs.
+#define MC_PC gp_regs[32]
+
+#define CANARY canary_at_end
diff --git a/arch/powerpc64/reloc.h b/arch/powerpc64/reloc.h
new file mode 100644
index 0000000..8e60b31
--- /dev/null
+++ b/arch/powerpc64/reloc.h
@@ -0,0 +1,32 @@
+#include <endian.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ENDIAN_SUFFIX "le"
+#else
+#define ENDIAN_SUFFIX ""
+#endif
+
+#define LDSO_ARCH "powerpc64" ENDIAN_SUFFIX
+
+#define TPOFF_K (-0x7000)
+
+#define REL_SYMBOLIC R_PPC64_ADDR64
+#define REL_GOT R_PPC64_GLOB_DAT
+#define REL_PLT R_PPC64_JMP_SLOT
+#define REL_RELATIVE R_PPC64_RELATIVE
+#define REL_COPY R_PPC64_COPY
+#define REL_DTPMOD R_PPC64_DTPMOD64
+#define REL_DTPOFF R_PPC64_DTPREL64
+#define REL_TPOFF R_PPC64_TPREL64
+
+#define CRTJMP(pc,sp) __asm__ __volatile__( \
+ "mr 1,%1 ; mtlr %0 ; blr" : : "r"(pc), "r"(sp) : "memory" )
+
+#define GETFUNCSYM(fp, sym, got) __asm__ ( \
+ ".hidden " #sym " \n" \
+ " bl 1f \n" \
+ " .long " #sym "-. \n" \
+ "1: mflr %1 \n" \
+ " lwz %0, 0(%1) \n" \
+ " add %0, %0, %1 \n" \
+ : "=r"(*(fp)), "=r"((long){0}) : : "memory", "lr" )
diff --git a/arch/powerpc64/syscall_arch.h b/arch/powerpc64/syscall_arch.h
new file mode 100644
index 0000000..aee11eb
--- /dev/null
+++ b/arch/powerpc64/syscall_arch.h
@@ -0,0 +1,5 @@
+#define __SYSCALL_LL_E(x) (x)
+#define __SYSCALL_LL_O(x) (x)
+
+#undef SYSCALL_NO_INLINE
+#define SYSCALL_NO_INLINE
diff --git a/configure b/configure
index 213a825..2eab571 100755
--- a/configure
+++ b/configure
@@ -299,7 +299,6 @@ printf "%s\n" "$target"
#
case "$target" in
# Catch these early to simplify matching for 32-bit archs
-powerpc64*) fail "$0: unsupported target \"$target\"" ;;
arm*) ARCH=arm ;;
aarch64*) ARCH=aarch64 ;;
i?86-nt32*) ARCH=nt32 ;;
@@ -311,6 +310,7 @@ mips64*) ARCH=mips64 ;;
mips*) ARCH=mips ;;
microblaze*) ARCH=microblaze ;;
or1k*) ARCH=or1k ;;
+powerpc64*) ARCH=powerpc64 ;;
powerpc*) ARCH=powerpc ;;
sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
@@ -630,6 +630,13 @@ fi
test "$ARCH" = "microblaze" && trycppif __MICROBLAZEEL__ "$t" \
&& SUBARCH=${SUBARCH}el
+if test "$ARCH" = "powerpc64" ; then
+if ! trycppif "_CALL_ELF == 2" "$t" ; then
+fail "$0: error: unsupported powerpc64 ABI"
+fi
+trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
+fi
+
if test "$ARCH" = "sh" ; then
tryflag CFLAGS_AUTO -Wa,--isa=any
trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
diff --git a/crt/powerpc64/crti.s b/crt/powerpc64/crti.s
new file mode 100644
index 0000000..9f712f0
--- /dev/null
+++ b/crt/powerpc64/crti.s
@@ -0,0 +1,21 @@
+.section .init
+.align 2
+.global _init
+_init:
+ addis 2, 12, .TOC.-_init@ha
+ addi 2, 2, .TOC.-_init@l
+ .localentry _init,.-_init
+ mflr 0
+ std 0, 16(1)
+ stdu 1,-32(1)
+
+.section .fini
+.align 2
+.global _fini
+_fini:
+ addis 2, 12, .TOC.-_fini@ha
+ addi 2, 2, .TOC.-_fini@l
+ .localentry _fini,.-_fini
+ mflr 0
+ std 0, 16(1)
+ stdu 1,-32(1)
diff --git a/crt/powerpc64/crtn.s b/crt/powerpc64/crtn.s
new file mode 100644
index 0000000..a7a9f4a
--- /dev/null
+++ b/crt/powerpc64/crtn.s
@@ -0,0 +1,13 @@
+.section .init
+.align 2
+ addi 1, 1, 32
+ ld 0, 16(1)
+ mtlr 0
+ blr
+
+.section .fini
+.align 2
+ addi 1, 1, 32
+ ld 0, 16(1)
+ mtlr 0
+ blr
diff --git a/src/fenv/powerpc64/fenv.c b/src/fenv/powerpc64/fenv.c
new file mode 100644
index 0000000..739420b
--- /dev/null
+++ b/src/fenv/powerpc64/fenv.c
@@ -0,0 +1,68 @@
+#define _GNU_SOURCE
+#include <fenv.h>
+
+static inline double get_fpscr_f(void)
+{
+ double d;
+ __asm__ __volatile__("mffs %0" : "=d"(d));
+ return d;
+}
+
+static inline long get_fpscr(void)
+{
+ return (union {double f; long i;}) {get_fpscr_f()}.i;
+}
+
+static inline void set_fpscr_f(double fpscr)
+{
+ __asm__ __volatile__("mtfsf 255, %0" : : "d"(fpscr));
+}
+
+static void set_fpscr(long fpscr)
+{
+ set_fpscr_f((union {long i; double f;}) {fpscr}.f);
+}
+
+int feclearexcept(int mask)
+{
+ mask &= FE_ALL_EXCEPT;
+ if (mask & FE_INVALID) mask |= FE_ALL_INVALID;
+ set_fpscr(get_fpscr() & ~mask);
+ return 0;
+}
+
+int feraiseexcept(int mask)
+{
+ mask &= FE_ALL_EXCEPT;
+ if (mask & FE_INVALID) mask |= FE_INVALID_SOFTWARE;
+ set_fpscr(get_fpscr() | mask);
+ return 0;
+}
+
+int fetestexcept(int mask)
+{
+ return get_fpscr() & mask & FE_ALL_EXCEPT;
+}
+
+int fegetround(void)
+{
+ return get_fpscr() & 3;
+}
+
+int __fesetround(int r)
+{
+ set_fpscr(get_fpscr() & ~3L | r);
+ return 0;
+}
+
+int fegetenv(fenv_t *envp)
+{
+ *envp = get_fpscr_f();
+ return 0;
+}
+
+int fesetenv(const fenv_t *envp)
+{
+ set_fpscr_f(envp != FE_DFL_ENV ? *envp : 0);
+ return 0;
+}
diff --git a/src/internal/powerpc64/syscall.s b/src/internal/powerpc64/syscall.s
new file mode 100644
index 0000000..fe21f9e
--- /dev/null
+++ b/src/internal/powerpc64/syscall.s
@@ -0,0 +1,17 @@
+ .global __syscall
+ .hidden __syscall
+ .type __syscall,@function
+__syscall:
+ mr 0, 3 # Save the system call number
+ mr 3, 4 # Shift the arguments: arg1
+ mr 4, 5 # arg2
+ mr 5, 6 # arg3
+ mr 6, 7 # arg4
+ mr 7, 8 # arg5
+ mr 8, 9 # arg6
+ sc
+ bnslr+ # return if not summary overflow
+ neg 3, 3 # otherwise error: return negated value.
+ blr
+ .end __syscall
+ .size __syscall, .-__syscall
diff --git a/src/ldso/powerpc64/dlsym.s b/src/ldso/powerpc64/dlsym.s
new file mode 100644
index 0000000..7eb691d
--- /dev/null
+++ b/src/ldso/powerpc64/dlsym.s
@@ -0,0 +1,12 @@
+ .text
+ .global dlsym
+ .hidden __dlsym
+ .type dlsym,@function
+dlsym:
+ addis 2, 12, .TOC.-dlsym@ha
+ addi 2, 2, .TOC.-dlsym@l
+ .localentry dlsym,.-dlsym
+ mflr 5 # The return address is arg3.
+ b __dlsym
+ .end dlsym
+ .size dlsym, .-dlsym
diff --git a/src/setjmp/powerpc64/longjmp.S b/src/setjmp/powerpc64/longjmp.S
new file mode 100644
index 0000000..e82e2a7
--- /dev/null
+++ b/src/setjmp/powerpc64/longjmp.S
@@ -0,0 +1,93 @@
+ .global _longjmp
+ .global longjmp
+ .type _longjmp,@function
+ .type longjmp,@function
+_longjmp:
+longjmp:
+ # 0) move old return address into the link register
+ ld 0, 0*8(3)
+ mtlr 0
+ # 1) restore cr
+ ld 0, 1*8(3)
+ mtcr 0
+ # 2) restore r1-r2 (SP and TOC)
+ ld 1, 2*8(3)
+ ld 2, 3*8(3)
+ # 3) restore r14-r31
+ ld 14, 4*8(3)
+ ld 15, 5*8(3)
+ ld 16, 6*8(3)
+ ld 17, 7*8(3)
+ ld 18, 8*8(3)
+ ld 19, 9*8(3)
+ ld 20, 10*8(3)
+ ld 21, 11*8(3)
+ ld 22, 12*8(3)
+ ld 23, 13*8(3)
+ ld 24, 14*8(3)
+ ld 25, 15*8(3)
+ ld 26, 16*8(3)
+ ld 27, 17*8(3)
+ ld 28, 18*8(3)
+ ld 29, 19*8(3)
+ ld 30, 20*8(3)
+ ld 31, 21*8(3)
+ # 4) restore floating point registers f14-f31
+ lfd 14, 22*8(3)
+ lfd 15, 23*8(3)
+ lfd 16, 24*8(3)
+ lfd 17, 25*8(3)
+ lfd 18, 26*8(3)
+ lfd 19, 27*8(3)
+ lfd 20, 28*8(3)
+ lfd 21, 29*8(3)
+ lfd 22, 30*8(3)
+ lfd 23, 31*8(3)
+ lfd 24, 32*8(3)
+ lfd 25, 33*8(3)
+ lfd 26, 34*8(3)
+ lfd 27, 35*8(3)
+ lfd 28, 36*8(3)
+ lfd 29, 37*8(3)
+ lfd 30, 38*8(3)
+ lfd 31, 39*8(3)
+
+ # 5) restore vector registers v20-v31
+ addi 3, 3, 40*8
+ lvx 2, 0, 3
+
+#if __BIG_ENDIAN__
+ lvsl 0, 0, 3
+#define load_vr(cur,tmp1,tmp2) \
+ addi 3, 3, 16; \
+ lvx tmp2, 0, 3; \
+ vperm cur, tmp1, tmp2, 0
+#else
+ lvsr 0, 0, 3
+#define load_vr(cur,tmp1,tmp2) \
+ addi 3, 3, 16; \
+ lvx tmp2, 0, 3; \
+ vperm cur, tmp2, tmp1, 0
+#endif
+
+ load_vr(20, 2, 3)
+ load_vr(21, 3, 2)
+ load_vr(22, 2, 3)
+ load_vr(23, 3, 2)
+ load_vr(24, 2, 3)
+ load_vr(25, 3, 2)
+ load_vr(26, 2, 3)
+ load_vr(27, 3, 2)
+ load_vr(28, 2, 3)
+ load_vr(29, 3, 2)
+ load_vr(20, 2, 3)
+ load_vr(31, 3, 2)
+
+ # 6) return r4 ? r4 : 1
+ mr 3, 4
+ cmpwi cr7, 4, 0
+ bne cr7, 1f
+ li 3, 1
+1:
+ blr
+
diff --git a/src/setjmp/powerpc64/setjmp.S b/src/setjmp/powerpc64/setjmp.S
new file mode 100644
index 0000000..ab7fafa
--- /dev/null
+++ b/src/setjmp/powerpc64/setjmp.S
@@ -0,0 +1,97 @@
+ .global ___setjmp
+ .hidden ___setjmp
+ .global __setjmp
+ .global _setjmp
+ .global setjmp
+ .type __setjmp,@function
+ .type _setjmp,@function
+ .type setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+ # 0) store IP into 0, then into the jmpbuf pointed to by r3 (first arg)
+ mflr 0
+ std 0, 0*8(3)
+ # 1) store cr
+ mfcr 0
+ std 0, 1*8(3)
+ # 2) store r1-r2 (SP and TOC)
+ std 1, 2*8(3)
+ std 2, 3*8(3)
+ # 3) store r14-31
+ std 14, 4*8(3)
+ std 15, 5*8(3)
+ std 16, 6*8(3)
+ std 17, 7*8(3)
+ std 18, 8*8(3)
+ std 19, 9*8(3)
+ std 20, 10*8(3)
+ std 21, 11*8(3)
+ std 22, 12*8(3)
+ std 23, 13*8(3)
+ std 24, 14*8(3)
+ std 25, 15*8(3)
+ std 26, 16*8(3)
+ std 27, 17*8(3)
+ std 28, 18*8(3)
+ std 29, 19*8(3)
+ std 30, 20*8(3)
+ std 31, 21*8(3)
+ # 4) store floating point registers f14-f31
+ stfd 14, 22*8(3)
+ stfd 15, 23*8(3)
+ stfd 16, 24*8(3)
+ stfd 17, 25*8(3)
+ stfd 18, 26*8(3)
+ stfd 19, 27*8(3)
+ stfd 20, 28*8(3)
+ stfd 21, 29*8(3)
+ stfd 22, 30*8(3)
+ stfd 23, 31*8(3)
+ stfd 24, 32*8(3)
+ stfd 25, 33*8(3)
+ stfd 26, 34*8(3)
+ stfd 27, 35*8(3)
+ stfd 28, 36*8(3)
+ stfd 29, 37*8(3)
+ stfd 30, 38*8(3)
+ stfd 31, 39*8(3)
+
+ # 5) store vector registers v20-v31
+ addi 3, 3, 40*8
+ lvx 1, 0, 3
+
+#if __BIG_ENDIAN__
+ lvsr 0, 0, 3
+ vperm 1, 1, 1, 0
+#define save_vr(prev,cur) \
+ vperm 2, prev, cur, 0; \
+ stvx 2, 0, 3; \
+ addi 3, 3, 16
+#else
+ lvsl 0, 0, 3
+ vperm 1, 1, 1, 0
+#define save_vr(prev,cur) \
+ vperm 2, cur, prev, 0; \
+ stvx 2, 0, 3; \
+ addi 3, 3, 16
+#endif
+
+ save_vr( 1, 20)
+ save_vr(20, 21)
+ save_vr(21, 22)
+ save_vr(22, 23)
+ save_vr(23, 24)
+ save_vr(24, 25)
+ save_vr(25, 26)
+ save_vr(26, 27)
+ save_vr(27, 28)
+ save_vr(28, 29)
+ save_vr(29, 30)
+ save_vr(30, 31)
+ save_vr(31, 31)
+
+ # 6) return 0
+ li 3, 0
+ blr
diff --git a/src/signal/powerpc64/restore.s b/src/signal/powerpc64/restore.s
new file mode 100644
index 0000000..4d41c27
--- /dev/null
+++ b/src/signal/powerpc64/restore.s
@@ -0,0 +1,11 @@
+ .global __restore
+ .type __restore,%function
+__restore:
+ li 0, 119 #__NR_sigreturn
+ sc
+
+ .global __restore_rt
+ .type __restore_rt,%function
+__restore_rt:
+ li 0, 172 # __NR_rt_sigreturn
+ sc
diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
new file mode 100644
index 0000000..ce59b60
--- /dev/null
+++ b/src/signal/powerpc64/sigsetjmp.s
@@ -0,0 +1,30 @@
+ .global sigsetjmp
+ .global __sigsetjmp
+ .type sigsetjmp,%function
+ .type __sigsetjmp,%function
+ .hidden ___setjmp
+sigsetjmp:
+__sigsetjmp:
+ addis 2, 12, .TOC.-__sigsetjmp@ha
+ addi 2, 2, .TOC.-__sigsetjmp@l
+ .localentry sigsetjmp,.-sigsetjmp
+ .localentry __sigsetjmp,.-__sigsetjmp
+
+ cmpwi cr7, 4, 0
+ beq- cr7, ___setjmp
+
+ mflr 5
+ std 5, 528(3)
+ std 16, 528+8+8(3)
+ mr 16, 3
+
+ bl ___setjmp
+
+ mr 4, 3
+ mr 3, 16
+ ld 5, 528(3)
+ mtlr 5
+ ld 16, 528+8+8(3)
+
+.hidden __sigsetjmp_tail
+ b __sigsetjmp_tail
diff --git a/src/thread/powerpc64/__set_thread_area.s b/src/thread/powerpc64/__set_thread_area.s
new file mode 100644
index 0000000..9622826
--- /dev/null
+++ b/src/thread/powerpc64/__set_thread_area.s
@@ -0,0 +1,8 @@
+.text
+.global __set_thread_area
+.type __set_thread_area, %function
+__set_thread_area:
+ mr 13, 3
+ li 3, 0
+ blr
+
diff --git a/src/thread/powerpc64/__unmapself.s b/src/thread/powerpc64/__unmapself.s
new file mode 100644
index 0000000..c9360b4
--- /dev/null
+++ b/src/thread/powerpc64/__unmapself.s
@@ -0,0 +1,9 @@
+ .text
+ .global __unmapself
+ .type __unmapself,%function
+__unmapself:
+ li 0, 91 # __NR_munmap
+ sc
+ li 0, 1 #__NR_exit
+ sc
+ blr
diff --git a/src/thread/powerpc64/clone.s b/src/thread/powerpc64/clone.s
new file mode 100644
index 0000000..a3cd5ce
--- /dev/null
+++ b/src/thread/powerpc64/clone.s
@@ -0,0 +1,53 @@
+.text
+.global __clone
+.type __clone, %function
+__clone:
+ # int clone(fn, stack, flags, arg, ptid, tls, ctid)
+ # a b c d e f g
+ # 3 4 5 6 7 8 9
+ # pseudo C code:
+ # tid = syscall(SYS_clone,c,b,e,f,g);
+ # if (!tid) syscall(SYS_exit, a(d));
+ # return tid;
+
+ # save r30/r31 on stack so we can put fn/arg in them
+ stdu 30, -32(1)
+ std 31, 8(1)
+
+ # save r3 (func) into r30, and r6(arg) into r31
+ mr 30, 3
+ mr 31, 6
+
+ # shuffle args into correct registers and call SYS_clone
+ mr 3, 5
+ #mr 4, 4
+ mr 5, 7
+ mr 6, 8
+ mr 7, 9
+ li 0, 120 # SYS_clone = 120
+ sc
+
+ # if error, negate return (errno)
+ bns+ 1f
+ neg 3, 3
+
+1: # if we're the parent, goto cleanup
+ cmpwi cr7, 3, 0
+ bne cr7, 2f
+
+ # we're the child. call fn(arg)
+ mr 3, 31
+ mr 12, 30
+ mtctr 12
+ bctrl
+
+ # call SYS_exit. exit code is already in r3 from fn return value
+ li 0, 1 # SYS_exit = 1
+ sc
+
+2: # cleanup: restore r30/r31 from stack and return
+ ld 30, 0(1)
+ ld 31, 8(1)
+ addi 1, 1, 32
+ blr
+
diff --git a/src/thread/powerpc64/syscall_cp.s b/src/thread/powerpc64/syscall_cp.s
new file mode 100644
index 0000000..d420dbd
--- /dev/null
+++ b/src/thread/powerpc64/syscall_cp.s
@@ -0,0 +1,37 @@
+ .global __cp_begin
+ .hidden __cp_begin
+ .global __cp_end
+ .hidden __cp_end
+ .global __cp_cancel
+ .hidden __cp_cancel
+ .hidden __cancel
+ .global __syscall_cp_asm
+ .hidden __syscall_cp_asm
+ .text
+ .type __syscall_cp_asm,%function
+__syscall_cp_asm:
+ # at enter: r3 = pointer to self->cancel, r4: syscall no, r5: first arg, r6: 2nd, r7: 3rd, r8: 4th, r9: 5th, r10: 6th
+__cp_begin:
+ # if (self->cancel) goto __cp_cancel
+ lwz 0, 0(3)
+ cmpwi cr7, 0, 0
+ bne- cr7, __cp_cancel
+
+ # make syscall
+ mr 0, 4
+ mr 3, 5
+ mr 4, 6
+ mr 5, 7
+ mr 6, 8
+ mr 7, 9
+ mr 8, 10
+ sc
+
+__cp_end:
+ # return error ? -r3 : r3
+ bnslr+
+ neg 3, 3
+ blr
+
+__cp_cancel:
+ b __cancel
--
2.7.4
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] add 64bit atomics on top of 64bit ll/sc primitives
2016-03-27 21:20 ` [PATCH 1/2] add 64bit atomics on top of 64bit ll/sc primitives Bobby Bingham
@ 2016-03-27 22:27 ` Rich Felker
0 siblings, 0 replies; 18+ messages in thread
From: Rich Felker @ 2016-03-27 22:27 UTC (permalink / raw)
To: musl
On Sun, Mar 27, 2016 at 04:20:18PM -0500, Bobby Bingham wrote:
> ---
> src/internal/atomic.h | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/src/internal/atomic.h b/src/internal/atomic.h
> index 6f37d25..43a8a00 100644
> --- a/src/internal/atomic.h
> +++ b/src/internal/atomic.h
> @@ -99,6 +99,34 @@ static inline void *a_cas_p(volatile void *p, void *t, void *s)
>
> #endif
>
> +#ifdef a_ll_64
> +
> +#ifndef a_and_64
> +#define a_and_64 a_and_64
> +static inline void a_and_64(volatile uint64_t *p, uint64_t v)
> +{
> + uint64_t old;
> + a_pre_llsc();
> + do old = a_ll_64(p);
> + while (!a_sc_64(p, old & v));
> + a_post_llsc();
> +}
> +#endif
> +
> +#ifndef a_or_64
> +#define a_or_64 a_or_64
> +static inline void a_or_64(volatile uint64_t *p, uint64_t v)
> +{
> + uint64_t old;
> + a_pre_llsc();
> + do old = a_ll_64(p);
> + while (!a_sc_64(p, old | v));
> + a_post_llsc();
> +}
> +#endif
I think we can do without these. a_and_64 and a_or_64 are simply
misnamed (they're only usable as atomic bitset/bitclear, not
necessarily atomic on the whole 64-bit unit since they only operate on
one bit at a time) and I don't think there's any measurable gain to be
had by doing them with 64-bit hardware atomics. They'll probably be
dropped at some point in the future anyway; malloc is essentially the
only user.
Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-27 21:20 ` [PATCH 2/2] add powerpc64 port Bobby Bingham
@ 2016-03-27 23:37 ` Rich Felker
2016-03-28 0:32 ` Bobby Bingham
2016-03-28 22:00 ` Patrick Oppenlander
0 siblings, 2 replies; 18+ messages in thread
From: Rich Felker @ 2016-03-27 23:37 UTC (permalink / raw)
To: musl
On Sun, Mar 27, 2016 at 04:20:19PM -0500, Bobby Bingham wrote:
> diff --git a/arch/powerpc64/bits/endian.h b/arch/powerpc64/bits/endian.h
> new file mode 100644
> index 0000000..2016cb2
> --- /dev/null
> +++ b/arch/powerpc64/bits/endian.h
> @@ -0,0 +1,5 @@
> +#if __BIG_ENDIAN__
> +#define __BYTE_ORDER __BIG_ENDIAN
> +#else
> +#define __BYTE_ORDER __LITTLE_ENDIAN
> +#endif
This should probably use whatever the official psABI macro for PPC BE
is rather than __BIG_ENDIAN__ (which I think is a confusingly-named
GCC thing; it's not clear whether it means "is big endian" or "value
that indicates big endian").
> diff --git a/arch/powerpc64/bits/sem.h b/arch/powerpc64/bits/sem.h
> new file mode 100644
> index 0000000..5f04979
> --- /dev/null
> +++ b/arch/powerpc64/bits/sem.h
> @@ -0,0 +1,7 @@
> +struct semid_ds {
> + struct ipc_perm sem_perm;
> + time_t sem_otime;
> + time_t sem_ctime;
> + unsigned long sem_nsems;
> + unsigned long __unused[2];
> +};
sem_nsems is required to have type unsigned short; this is a POSIX
requirement that Linux botched. The canonical solution is to put
endian-dependent padding around it; see other archs for examples.
> diff --git a/arch/powerpc64/bits/signal.h b/arch/powerpc64/bits/signal.h
> [...]
> +typedef struct sigcontext
> +{
> + unsigned long _unused[4];
> + int signal;
> + int _pad0;
> + unsigned long handler;
> + unsigned long oldmask;
> + void *regs;
> + gregset_t gp_regs;
> + fpregset_t fp_regs;
> + vrregset_t *v_regs;
> + long vmx_reserve[34+34+32+1];
> +} mcontext_t;
> +
> +#else
> +
> +typedef struct {
> + long __regs[4+4+48+33+1+34+34+32+1];
> +} mcontext_t;
> +
> +#endif
Did you check that the layout of the namespace-safe and full mcontex_t
match?
> +#define SA_NOCLDSTOP 1U
> +#define SA_NOCLDWAIT 2U
> +#define SA_SIGINFO 4U
> +#define SA_ONSTACK 0x08000000U
> +#define SA_RESTART 0x10000000U
> +#define SA_NODEFER 0x40000000U
> +#define SA_RESETHAND 0x80000000U
> +#define SA_RESTORER 0x04000000U
Is there a reason for making these unsigned? It's different from other
archs at least, I think.
> diff --git a/arch/powerpc64/crt_arch.h b/arch/powerpc64/crt_arch.h
> new file mode 100644
> index 0000000..0605511
> --- /dev/null
> +++ b/arch/powerpc64/crt_arch.h
> @@ -0,0 +1,21 @@
> +__asm__(
> +".text \n"
> +".global " START " \n"
> +".type " START ", %function \n"
> +START ": \n"
> +" addis 2, 12, .TOC.-" START "@ha \n"
> +" addi 2, 2, .TOC.-" START "@l \n"
What does this do? It looks like canonical function prologue of some
sort, but _start is not a C function and unless r12 is part of the ELFv2
entry point ABI that I'm not aware of, I don't think it's meaningful.
AFAICT r2 is not subsequently used.
> diff --git a/arch/powerpc64/pthread_arch.h b/arch/powerpc64/pthread_arch.h
> new file mode 100644
> index 0000000..2f976fe
> --- /dev/null
> +++ b/arch/powerpc64/pthread_arch.h
> @@ -0,0 +1,17 @@
> +static inline struct pthread *__pthread_self()
> +{
> + register char *tp __asm__("r13");
> + __asm__ __volatile__ ("" : "=r" (tp) );
> + return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
> +}
It's possible this asm should have a "memory" clobber to avoid
reordering across the initial thread pointer setup, but it's
consistent with ppc32 right now, so we should probably review this as
a separate issue to consider for both ports rather than something
blocking the new port.
> diff --git a/arch/powerpc64/reloc.h b/arch/powerpc64/reloc.h
> new file mode 100644
> index 0000000..8e60b31
> --- /dev/null
> +++ b/arch/powerpc64/reloc.h
> @@ -0,0 +1,32 @@
> +#include <endian.h>
> +
> +#if __BYTE_ORDER == __LITTLE_ENDIAN
> +#define ENDIAN_SUFFIX "le"
> +#else
> +#define ENDIAN_SUFFIX ""
> +#endif
> +
> +#define LDSO_ARCH "powerpc64" ENDIAN_SUFFIX
Is it intentional that the "default" subarch variant be suffixed with
"le" and a non-default/unused one be the bare "powerpc64"? I don't
object to that but it's contrary to usual conventions that the bare
arch be the canonical ABI, and it might be contrary to what GCC is
doing now (haven't checked) for the dynamic linker name.
> diff --git a/arch/powerpc64/syscall_arch.h b/arch/powerpc64/syscall_arch.h
> new file mode 100644
> index 0000000..aee11eb
> --- /dev/null
> +++ b/arch/powerpc64/syscall_arch.h
> @@ -0,0 +1,5 @@
> +#define __SYSCALL_LL_E(x) (x)
> +#define __SYSCALL_LL_O(x) (x)
> +
> +#undef SYSCALL_NO_INLINE
> +#define SYSCALL_NO_INLINE
Is this just unfinished or is there a reason inline syscalls don't
work well?
> diff --git a/configure b/configure
> [...]
> +if test "$ARCH" = "powerpc64" ; then
> +if ! trycppif "_CALL_ELF == 2" "$t" ; then
> +fail "$0: error: unsupported powerpc64 ABI"
> +fi
I usually use &&/|| for this kind of thing:
trycppif "_CALL_ELF == 2" "$t" || fail ...
> diff --git a/src/setjmp/powerpc64/longjmp.S b/src/setjmp/powerpc64/longjmp.S
> new file mode 100644
> index 0000000..e82e2a7
> --- /dev/null
> +++ b/src/setjmp/powerpc64/longjmp.S
> @@ -0,0 +1,93 @@
> + .global _longjmp
> + .global longjmp
> + .type _longjmp,@function
> + .type longjmp,@function
> +_longjmp:
> +longjmp:
> + # 0) move old return address into the link register
> + ld 0, 0*8(3)
> + mtlr 0
> + # 1) restore cr
> + ld 0, 1*8(3)
> + mtcr 0
> + # 2) restore r1-r2 (SP and TOC)
> + ld 1, 2*8(3)
> + ld 2, 3*8(3)
> + # 3) restore r14-r31
> + ld 14, 4*8(3)
> + ld 15, 5*8(3)
> + ld 16, 6*8(3)
> + ld 17, 7*8(3)
> + ld 18, 8*8(3)
> + ld 19, 9*8(3)
> + ld 20, 10*8(3)
> + ld 21, 11*8(3)
> + ld 22, 12*8(3)
> + ld 23, 13*8(3)
> + ld 24, 14*8(3)
> + ld 25, 15*8(3)
> + ld 26, 16*8(3)
> + ld 27, 17*8(3)
> + ld 28, 18*8(3)
> + ld 29, 19*8(3)
> + ld 30, 20*8(3)
> + ld 31, 21*8(3)
> + # 4) restore floating point registers f14-f31
> + lfd 14, 22*8(3)
> + lfd 15, 23*8(3)
> + lfd 16, 24*8(3)
> + lfd 17, 25*8(3)
> + lfd 18, 26*8(3)
> + lfd 19, 27*8(3)
> + lfd 20, 28*8(3)
> + lfd 21, 29*8(3)
> + lfd 22, 30*8(3)
> + lfd 23, 31*8(3)
> + lfd 24, 32*8(3)
> + lfd 25, 33*8(3)
> + lfd 26, 34*8(3)
> + lfd 27, 35*8(3)
> + lfd 28, 36*8(3)
> + lfd 29, 37*8(3)
> + lfd 30, 38*8(3)
> + lfd 31, 39*8(3)
> +
> + # 5) restore vector registers v20-v31
> + addi 3, 3, 40*8
> + lvx 2, 0, 3
> +
> +#if __BIG_ENDIAN__
> + lvsl 0, 0, 3
> +#define load_vr(cur,tmp1,tmp2) \
> + addi 3, 3, 16; \
> + lvx tmp2, 0, 3; \
> + vperm cur, tmp1, tmp2, 0
> +#else
> + lvsr 0, 0, 3
> +#define load_vr(cur,tmp1,tmp2) \
> + addi 3, 3, 16; \
> + lvx tmp2, 0, 3; \
> + vperm cur, tmp2, tmp1, 0
> +#endif
> +
> + load_vr(20, 2, 3)
> [...]
This is kind of the reason why I was hesitant to add .S support for so
long. :-)
I don't want to reject it outright, but the idea of adding .S support
was just to allow conditional compilation, not to do condensed
assembly sources that require macro expansion. I can see where the
code might be unwieldy without this though. Anyone else have opinions?
> diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
> new file mode 100644
> index 0000000..ce59b60
> --- /dev/null
> +++ b/src/signal/powerpc64/sigsetjmp.s
> @@ -0,0 +1,30 @@
> + .global sigsetjmp
> + .global __sigsetjmp
> + .type sigsetjmp,%function
> + .type __sigsetjmp,%function
> + .hidden ___setjmp
> +sigsetjmp:
> +__sigsetjmp:
> + addis 2, 12, .TOC.-__sigsetjmp@ha
> + addi 2, 2, .TOC.-__sigsetjmp@l
> + .localentry sigsetjmp,.-sigsetjmp
> + .localentry __sigsetjmp,.-__sigsetjmp
Again I don't see what the purpose of these insns is; if the resulting
value is needed, are you aware of how that interacts with ___setjmp
returning twice?
It looks to me like the assumption is that r12 contains the address of
the callee at the time of a function call, but I don't see how that's
satisfied in the calls I've seen.
Other than that, things looked good! Obviously I haven't tested it
yet, and I also haven't read some of the actual code in detail yet, so
I don't know if there are other bugs; my review so far mostly covers
design/style/conformance/policy matters.
Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-27 23:37 ` Rich Felker
@ 2016-03-28 0:32 ` Bobby Bingham
2016-03-28 2:18 ` Rich Felker
2016-03-28 22:00 ` Patrick Oppenlander
1 sibling, 1 reply; 18+ messages in thread
From: Bobby Bingham @ 2016-03-28 0:32 UTC (permalink / raw)
To: musl
On Sun, Mar 27, 2016 at 07:37:09PM -0400, Rich Felker wrote:
> On Sun, Mar 27, 2016 at 04:20:19PM -0500, Bobby Bingham wrote:
> > diff --git a/arch/powerpc64/bits/endian.h b/arch/powerpc64/bits/endian.h
> > new file mode 100644
> > index 0000000..2016cb2
> > --- /dev/null
> > +++ b/arch/powerpc64/bits/endian.h
> > @@ -0,0 +1,5 @@
> > +#if __BIG_ENDIAN__
> > +#define __BYTE_ORDER __BIG_ENDIAN
> > +#else
> > +#define __BYTE_ORDER __LITTLE_ENDIAN
> > +#endif
>
> This should probably use whatever the official psABI macro for PPC BE
> is rather than __BIG_ENDIAN__ (which I think is a confusingly-named
> GCC thing; it's not clear whether it means "is big endian" or "value
> that indicates big endian").
The ABI spec is at https://members.openpowerfoundation.org/document/dl/576.
Section 5.1.4 documents __BIG_ENDIAN__ and __LITTLE_ENDIAN__ for this
purpose.
>
> > diff --git a/arch/powerpc64/bits/sem.h b/arch/powerpc64/bits/sem.h
> > new file mode 100644
> > index 0000000..5f04979
> > --- /dev/null
> > +++ b/arch/powerpc64/bits/sem.h
> > @@ -0,0 +1,7 @@
> > +struct semid_ds {
> > + struct ipc_perm sem_perm;
> > + time_t sem_otime;
> > + time_t sem_ctime;
> > + unsigned long sem_nsems;
> > + unsigned long __unused[2];
> > +};
>
> sem_nsems is required to have type unsigned short; this is a POSIX
> requirement that Linux botched. The canonical solution is to put
> endian-dependent padding around it; see other archs for examples.
Ok.
>
> > diff --git a/arch/powerpc64/bits/signal.h b/arch/powerpc64/bits/signal.h
> > [...]
> > +typedef struct sigcontext
> > +{
> > + unsigned long _unused[4];
= 4 longs
> > + int signal;
> > + int _pad0;
> > + unsigned long handler;
> > + unsigned long oldmask;
> > + void *regs;
= 4 longs
> > + gregset_t gp_regs;
= 48 longs
> > + fpregset_t fp_regs;
= 33 longs
> > + vrregset_t *v_regs;
= 1 long
> > + long vmx_reserve[34+34+32+1];
= 34+34+32+1 longs
> > +} mcontext_t;
> > +
> > +#else
> > +
> > +typedef struct {
> > + long __regs[4+4+48+33+1+34+34+32+1];
> > +} mcontext_t;
> > +
> > +#endif
>
> Did you check that the layout of the namespace-safe and full mcontex_t
> match?
Yes, see the breakdown above.
>
> > +#define SA_NOCLDSTOP 1U
> > +#define SA_NOCLDWAIT 2U
> > +#define SA_SIGINFO 4U
> > +#define SA_ONSTACK 0x08000000U
> > +#define SA_RESTART 0x10000000U
> > +#define SA_NODEFER 0x40000000U
> > +#define SA_RESETHAND 0x80000000U
> > +#define SA_RESTORER 0x04000000U
>
> Is there a reason for making these unsigned? It's different from other
> archs at least, I think.
It's the same as the ppc32 port.
>
> > diff --git a/arch/powerpc64/crt_arch.h b/arch/powerpc64/crt_arch.h
> > new file mode 100644
> > index 0000000..0605511
> > --- /dev/null
> > +++ b/arch/powerpc64/crt_arch.h
> > @@ -0,0 +1,21 @@
> > +__asm__(
> > +".text \n"
> > +".global " START " \n"
> > +".type " START ", %function \n"
> > +START ": \n"
> > +" addis 2, 12, .TOC.-" START "@ha \n"
> > +" addi 2, 2, .TOC.-" START "@l \n"
>
> What does this do? It looks like canonical function prologue of some
> sort, but _start is not a C function and unless r12 is part of the ELFv2
> entry point ABI that I'm not aware of, I don't think it's meaningful.
> AFAICT r2 is not subsequently used.
In the ABI, C functions have two entry points, the "global" entry point,
and the "local" entry point. The local entry point expects the "table of
contents" pointer in r2. The global entry point expects the address of
global entry point itself in r12, uses the prologue I used here to
calculate the TOC pointer from it, and falls through to the local entry
point. See section 2.3.2.1 of the ABI spec linked above.
Calls within the same module are resolved to the local entry point, so
we need to ensure r2 is set up with the TOC pointer here to call any C
code.
The ABI spec does specify that r12 contains the address of _start,
specifically so this prologue can work (section 4.1.2.1).
>
> > diff --git a/arch/powerpc64/pthread_arch.h b/arch/powerpc64/pthread_arch.h
> > new file mode 100644
> > index 0000000..2f976fe
> > --- /dev/null
> > +++ b/arch/powerpc64/pthread_arch.h
> > @@ -0,0 +1,17 @@
> > +static inline struct pthread *__pthread_self()
> > +{
> > + register char *tp __asm__("r13");
> > + __asm__ __volatile__ ("" : "=r" (tp) );
> > + return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
> > +}
>
> It's possible this asm should have a "memory" clobber to avoid
> reordering across the initial thread pointer setup, but it's
> consistent with ppc32 right now, so we should probably review this as
> a separate issue to consider for both ports rather than something
> blocking the new port.
>
> > diff --git a/arch/powerpc64/reloc.h b/arch/powerpc64/reloc.h
> > new file mode 100644
> > index 0000000..8e60b31
> > --- /dev/null
> > +++ b/arch/powerpc64/reloc.h
> > @@ -0,0 +1,32 @@
> > +#include <endian.h>
> > +
> > +#if __BYTE_ORDER == __LITTLE_ENDIAN
> > +#define ENDIAN_SUFFIX "le"
> > +#else
> > +#define ENDIAN_SUFFIX ""
> > +#endif
> > +
> > +#define LDSO_ARCH "powerpc64" ENDIAN_SUFFIX
>
> Is it intentional that the "default" subarch variant be suffixed with
> "le" and a non-default/unused one be the bare "powerpc64"? I don't
> object to that but it's contrary to usual conventions that the bare
> arch be the canonical ABI, and it might be contrary to what GCC is
> doing now (haven't checked) for the dynamic linker name.
I'll double check, but I skimmed the gcc code here, and it looked like
it uses an "le" suffix. Admittedly, I didn't read it closely enough to
be absolutely sure yet.
>
> > diff --git a/arch/powerpc64/syscall_arch.h b/arch/powerpc64/syscall_arch.h
> > new file mode 100644
> > index 0000000..aee11eb
> > --- /dev/null
> > +++ b/arch/powerpc64/syscall_arch.h
> > @@ -0,0 +1,5 @@
> > +#define __SYSCALL_LL_E(x) (x)
> > +#define __SYSCALL_LL_O(x) (x)
> > +
> > +#undef SYSCALL_NO_INLINE
> > +#define SYSCALL_NO_INLINE
>
> Is this just unfinished or is there a reason inline syscalls don't
> work well?
Just unfinished. ppc32 is the same here. I can add these.
>
> > diff --git a/configure b/configure
> > [...]
> > +if test "$ARCH" = "powerpc64" ; then
> > +if ! trycppif "_CALL_ELF == 2" "$t" ; then
> > +fail "$0: error: unsupported powerpc64 ABI"
> > +fi
>
> I usually use &&/|| for this kind of thing:
>
> trycppif "_CALL_ELF == 2" "$t" || fail ...
Ok.
>
> > diff --git a/src/setjmp/powerpc64/longjmp.S b/src/setjmp/powerpc64/longjmp.S
> > new file mode 100644
> > index 0000000..e82e2a7
> > --- /dev/null
> > +++ b/src/setjmp/powerpc64/longjmp.S
> > @@ -0,0 +1,93 @@
> > + .global _longjmp
> > + .global longjmp
> > + .type _longjmp,@function
> > + .type longjmp,@function
> > +_longjmp:
> > +longjmp:
> > + # 0) move old return address into the link register
> > + ld 0, 0*8(3)
> > + mtlr 0
> > + # 1) restore cr
> > + ld 0, 1*8(3)
> > + mtcr 0
> > + # 2) restore r1-r2 (SP and TOC)
> > + ld 1, 2*8(3)
> > + ld 2, 3*8(3)
> > + # 3) restore r14-r31
> > + ld 14, 4*8(3)
> > + ld 15, 5*8(3)
> > + ld 16, 6*8(3)
> > + ld 17, 7*8(3)
> > + ld 18, 8*8(3)
> > + ld 19, 9*8(3)
> > + ld 20, 10*8(3)
> > + ld 21, 11*8(3)
> > + ld 22, 12*8(3)
> > + ld 23, 13*8(3)
> > + ld 24, 14*8(3)
> > + ld 25, 15*8(3)
> > + ld 26, 16*8(3)
> > + ld 27, 17*8(3)
> > + ld 28, 18*8(3)
> > + ld 29, 19*8(3)
> > + ld 30, 20*8(3)
> > + ld 31, 21*8(3)
> > + # 4) restore floating point registers f14-f31
> > + lfd 14, 22*8(3)
> > + lfd 15, 23*8(3)
> > + lfd 16, 24*8(3)
> > + lfd 17, 25*8(3)
> > + lfd 18, 26*8(3)
> > + lfd 19, 27*8(3)
> > + lfd 20, 28*8(3)
> > + lfd 21, 29*8(3)
> > + lfd 22, 30*8(3)
> > + lfd 23, 31*8(3)
> > + lfd 24, 32*8(3)
> > + lfd 25, 33*8(3)
> > + lfd 26, 34*8(3)
> > + lfd 27, 35*8(3)
> > + lfd 28, 36*8(3)
> > + lfd 29, 37*8(3)
> > + lfd 30, 38*8(3)
> > + lfd 31, 39*8(3)
> > +
> > + # 5) restore vector registers v20-v31
> > + addi 3, 3, 40*8
> > + lvx 2, 0, 3
> > +
> > +#if __BIG_ENDIAN__
> > + lvsl 0, 0, 3
> > +#define load_vr(cur,tmp1,tmp2) \
> > + addi 3, 3, 16; \
> > + lvx tmp2, 0, 3; \
> > + vperm cur, tmp1, tmp2, 0
> > +#else
> > + lvsr 0, 0, 3
> > +#define load_vr(cur,tmp1,tmp2) \
> > + addi 3, 3, 16; \
> > + lvx tmp2, 0, 3; \
> > + vperm cur, tmp2, tmp1, 0
> > +#endif
> > +
> > + load_vr(20, 2, 3)
> > [...]
>
> This is kind of the reason why I was hesitant to add .S support for so
> long. :-)
>
> I don't want to reject it outright, but the idea of adding .S support
> was just to allow conditional compilation, not to do condensed
> assembly sources that require macro expansion. I can see where the
> code might be unwieldy without this though. Anyone else have opinions?
>
> > diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
> > new file mode 100644
> > index 0000000..ce59b60
> > --- /dev/null
> > +++ b/src/signal/powerpc64/sigsetjmp.s
> > @@ -0,0 +1,30 @@
> > + .global sigsetjmp
> > + .global __sigsetjmp
> > + .type sigsetjmp,%function
> > + .type __sigsetjmp,%function
> > + .hidden ___setjmp
> > +sigsetjmp:
> > +__sigsetjmp:
> > + addis 2, 12, .TOC.-__sigsetjmp@ha
> > + addi 2, 2, .TOC.-__sigsetjmp@l
> > + .localentry sigsetjmp,.-sigsetjmp
> > + .localentry __sigsetjmp,.-__sigsetjmp
>
> Again I don't see what the purpose of these insns is; if the resulting
> value is needed, are you aware of how that interacts with ___setjmp
> returning twice?
This sets up r2 with the TOC pointer, as is required by the ABI in order
to call setjmp's local entry point. Since setjmp is also written in asm,
we could do away with this here.
I don't think the fact that setjmp returns twice matters for this.
>
> It looks to me like the assumption is that r12 contains the address of
> the callee at the time of a function call, but I don't see how that's
> satisfied in the calls I've seen.
The instructions before the .localentry directive are the global entry
point. The ABI requires that r12 be the address of the callee whenever
the global entry point of a function is called.
>
> Other than that, things looked good! Obviously I haven't tested it
> yet, and I also haven't read some of the actual code in detail yet, so
> I don't know if there are other bugs; my review so far mostly covers
> design/style/conformance/policy matters.
>
> Rich
Bobby
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-28 0:32 ` Bobby Bingham
@ 2016-03-28 2:18 ` Rich Felker
2016-03-28 3:27 ` Szabolcs Nagy
` (2 more replies)
0 siblings, 3 replies; 18+ messages in thread
From: Rich Felker @ 2016-03-28 2:18 UTC (permalink / raw)
To: musl
On Sun, Mar 27, 2016 at 07:32:20PM -0500, Bobby Bingham wrote:
> On Sun, Mar 27, 2016 at 07:37:09PM -0400, Rich Felker wrote:
> > On Sun, Mar 27, 2016 at 04:20:19PM -0500, Bobby Bingham wrote:
> > > diff --git a/arch/powerpc64/bits/endian.h b/arch/powerpc64/bits/endian.h
> > > new file mode 100644
> > > index 0000000..2016cb2
> > > --- /dev/null
> > > +++ b/arch/powerpc64/bits/endian.h
> > > @@ -0,0 +1,5 @@
> > > +#if __BIG_ENDIAN__
> > > +#define __BYTE_ORDER __BIG_ENDIAN
> > > +#else
> > > +#define __BYTE_ORDER __LITTLE_ENDIAN
> > > +#endif
> >
> > This should probably use whatever the official psABI macro for PPC BE
> > is rather than __BIG_ENDIAN__ (which I think is a confusingly-named
> > GCC thing; it's not clear whether it means "is big endian" or "value
> > that indicates big endian").
>
> The ABI spec is at https://members.openpowerfoundation.org/document/dl/576.
> Section 5.1.4 documents __BIG_ENDIAN__ and __LITTLE_ENDIAN__ for this
> purpose.
OK, __BIG_ENDIAN__ it is then.
> > > +} mcontext_t;
> > > +
> > > +#else
> > > +
> > > +typedef struct {
> > > + long __regs[4+4+48+33+1+34+34+32+1];
> > > +} mcontext_t;
> > > +
> > > +#endif
> >
> > Did you check that the layout of the namespace-safe and full mcontex_t
> > match?
>
> Yes, see the breakdown above.
OK, looks good. I might mildly prefer using int and void * for the
actual slots of those types, but from a practical standpoint it
doesn't matter.
> > > +#define SA_NOCLDSTOP 1U
> > > +#define SA_NOCLDWAIT 2U
> > > +#define SA_SIGINFO 4U
> > > +#define SA_ONSTACK 0x08000000U
> > > +#define SA_RESTART 0x10000000U
> > > +#define SA_NODEFER 0x40000000U
> > > +#define SA_RESETHAND 0x80000000U
> > > +#define SA_RESTORER 0x04000000U
> >
> > Is there a reason for making these unsigned? It's different from other
> > archs at least, I think.
>
> It's the same as the ppc32 port.
OK. Maybe it should be changed but that's a separate issue.
> > > diff --git a/arch/powerpc64/crt_arch.h b/arch/powerpc64/crt_arch.h
> > > new file mode 100644
> > > index 0000000..0605511
> > > --- /dev/null
> > > +++ b/arch/powerpc64/crt_arch.h
> > > @@ -0,0 +1,21 @@
> > > +__asm__(
> > > +".text \n"
> > > +".global " START " \n"
> > > +".type " START ", %function \n"
> > > +START ": \n"
> > > +" addis 2, 12, .TOC.-" START "@ha \n"
> > > +" addi 2, 2, .TOC.-" START "@l \n"
> >
> > What does this do? It looks like canonical function prologue of some
> > sort, but _start is not a C function and unless r12 is part of the ELFv2
> > entry point ABI that I'm not aware of, I don't think it's meaningful.
> > AFAICT r2 is not subsequently used.
>
> In the ABI, C functions have two entry points, the "global" entry point,
> and the "local" entry point. The local entry point expects the "table of
> contents" pointer in r2. The global entry point expects the address of
> global entry point itself in r12, uses the prologue I used here to
> calculate the TOC pointer from it, and falls through to the local entry
> point. See section 2.3.2.1 of the ABI spec linked above.
>
> Calls within the same module are resolved to the local entry point, so
> we need to ensure r2 is set up with the TOC pointer here to call any C
> code.
>
> The ABI spec does specify that r12 contains the address of _start,
> specifically so this prologue can work (section 4.1.2.1).
OK. In that case the subsequent code to compute the address of
_DYNAMIC via PC-relative addressing using the return address is
unnecessary, though; you already have the initial PC and can just
compute _DYNAMIC relative to it.
Also, for dynamic-linked programs, the main program's entry point is
reached via CRTJMP() from the dynamic linker, and your definition is
not setting up r12. In order to meet this part of the ELF ABI it needs
to set r12.
One thing that's not clear to me is whether the jumps/calls from asm,
as you've written them, go to the local entry point or the global
entry point of the callee. Since you're not loading r12 I assume the
intent is to go to the local entry point, but that only works if the
callee is hidden. Or does the PLT take care of converting that for you
(as long as r2 is set)?
One place that looks wrong to me is sigsetjmp. I would expect r2 to be
lost/clobbered when setjmp is called, but maybe not since it looks
like setjmp saves it in the jmp_buf, despite it not being a call-saved
register. Is that your expectation?
> > > diff --git a/arch/powerpc64/reloc.h b/arch/powerpc64/reloc.h
> > > new file mode 100644
> > > index 0000000..8e60b31
> > > --- /dev/null
> > > +++ b/arch/powerpc64/reloc.h
> > > @@ -0,0 +1,32 @@
> > > +#include <endian.h>
> > > +
> > > +#if __BYTE_ORDER == __LITTLE_ENDIAN
> > > +#define ENDIAN_SUFFIX "le"
> > > +#else
> > > +#define ENDIAN_SUFFIX ""
> > > +#endif
> > > +
> > > +#define LDSO_ARCH "powerpc64" ENDIAN_SUFFIX
> >
> > Is it intentional that the "default" subarch variant be suffixed with
> > "le" and a non-default/unused one be the bare "powerpc64"? I don't
> > object to that but it's contrary to usual conventions that the bare
> > arch be the canonical ABI, and it might be contrary to what GCC is
> > doing now (haven't checked) for the dynamic linker name.
>
> I'll double check, but I skimmed the gcc code here, and it looked like
> it uses an "le" suffix. Admittedly, I didn't read it closely enough to
> be absolutely sure yet.
OK, sounds good. Also note that CRTJMP here needs fixing.
> > > diff --git a/arch/powerpc64/syscall_arch.h b/arch/powerpc64/syscall_arch.h
> > > new file mode 100644
> > > index 0000000..aee11eb
> > > --- /dev/null
> > > +++ b/arch/powerpc64/syscall_arch.h
> > > @@ -0,0 +1,5 @@
> > > +#define __SYSCALL_LL_E(x) (x)
> > > +#define __SYSCALL_LL_O(x) (x)
> > > +
> > > +#undef SYSCALL_NO_INLINE
> > > +#define SYSCALL_NO_INLINE
> >
> > Is this just unfinished or is there a reason inline syscalls don't
> > work well?
>
> Just unfinished. ppc32 is the same here. I can add these.
OK.
> > > diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
> > > new file mode 100644
> > > index 0000000..ce59b60
> > > --- /dev/null
> > > +++ b/src/signal/powerpc64/sigsetjmp.s
> > > @@ -0,0 +1,30 @@
> > > + .global sigsetjmp
> > > + .global __sigsetjmp
> > > + .type sigsetjmp,%function
> > > + .type __sigsetjmp,%function
> > > + .hidden ___setjmp
> > > +sigsetjmp:
> > > +__sigsetjmp:
> > > + addis 2, 12, .TOC.-__sigsetjmp@ha
> > > + addi 2, 2, .TOC.-__sigsetjmp@l
> > > + .localentry sigsetjmp,.-sigsetjmp
> > > + .localentry __sigsetjmp,.-__sigsetjmp
> >
> > Again I don't see what the purpose of these insns is; if the resulting
> > value is needed, are you aware of how that interacts with ___setjmp
> > returning twice?
>
> This sets up r2 with the TOC pointer, as is required by the ABI in order
> to call setjmp's local entry point. Since setjmp is also written in asm,
> we could do away with this here.
>
> I don't think the fact that setjmp returns twice matters for this.
When setjmp returns the second time, all registers it did not save
have been clobbered (by arbitrary code that ran after the first return
from setjmp). However despite not being a call-saved register
(AFAICT), r2 is saved by setjmp, so it's probably okay.
> > It looks to me like the assumption is that r12 contains the address of
> > the callee at the time of a function call, but I don't see how that's
> > satisfied in the calls I've seen.
>
> The instructions before the .localentry directive are the global entry
> point. The ABI requires that r12 be the address of the callee whenever
> the global entry point of a function is called.
*nod*
Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-28 2:18 ` Rich Felker
@ 2016-03-28 3:27 ` Szabolcs Nagy
2016-04-02 17:02 ` Bobby Bingham
2016-04-04 4:03 ` Bobby Bingham
2 siblings, 0 replies; 18+ messages in thread
From: Szabolcs Nagy @ 2016-03-28 3:27 UTC (permalink / raw)
To: musl
* Rich Felker <dalias@libc.org> [2016-03-27 22:18:56 -0400]:
> On Sun, Mar 27, 2016 at 07:32:20PM -0500, Bobby Bingham wrote:
> > On Sun, Mar 27, 2016 at 07:37:09PM -0400, Rich Felker wrote:
> > > On Sun, Mar 27, 2016 at 04:20:19PM -0500, Bobby Bingham wrote:
> > > > +#define SA_NOCLDSTOP 1U
> > > > +#define SA_NOCLDWAIT 2U
> > > > +#define SA_SIGINFO 4U
> > > > +#define SA_ONSTACK 0x08000000U
> > > > +#define SA_RESTART 0x10000000U
> > > > +#define SA_NODEFER 0x40000000U
> > > > +#define SA_RESETHAND 0x80000000U
i guess at least this one has to be unsigned
and then others should follow
i think there are other cases where a 1U<<31 flag
forces all others to be unsigned otherwise there
are possible signed int overflow issues
(even though the linux uapi may use signed int)
e.g.
EPOLL* in sys/epoll.h
MS_NOUSER in sys/mount.h ?
> > > > +#define SA_RESTORER 0x04000000U
> > >
> > > Is there a reason for making these unsigned? It's different from other
> > > archs at least, I think.
> >
> > It's the same as the ppc32 port.
>
> OK. Maybe it should be changed but that's a separate issue.
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-27 23:37 ` Rich Felker
2016-03-28 0:32 ` Bobby Bingham
@ 2016-03-28 22:00 ` Patrick Oppenlander
2016-03-28 22:10 ` Rich Felker
1 sibling, 1 reply; 18+ messages in thread
From: Patrick Oppenlander @ 2016-03-28 22:00 UTC (permalink / raw)
To: musl
On 28/03/16 10:37, Rich Felker wrote:
> This is kind of the reason why I was hesitant to add .S support for so
> long. :-)
>
> I don't want to reject it outright, but the idea of adding .S support
> was just to allow conditional compilation, not to do condensed
> assembly sources that require macro expansion. I can see where the
> code might be unwieldy without this though. Anyone else have opinions?
IMHO .S support is worthwhile just to be able to use constant
definitions in assembly.
For example,
__unmapself:
mov r7,#SYS_munmap
svc 0
mov r7,#SYS_exit
svc 0
Is a clearer than:
__unmapself:
mov r7,#91
svc 0
mov r7,#1
svc 0
Especially when approaching the source for the first time.
Patrick
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-28 22:00 ` Patrick Oppenlander
@ 2016-03-28 22:10 ` Rich Felker
2016-03-28 23:04 ` Patrick Oppenlander
0 siblings, 1 reply; 18+ messages in thread
From: Rich Felker @ 2016-03-28 22:10 UTC (permalink / raw)
To: musl
On Tue, Mar 29, 2016 at 09:00:19AM +1100, Patrick Oppenlander wrote:
> On 28/03/16 10:37, Rich Felker wrote:
> >This is kind of the reason why I was hesitant to add .S support for so
> >long. :-)
> >
> >I don't want to reject it outright, but the idea of adding .S support
> >was just to allow conditional compilation, not to do condensed
> >assembly sources that require macro expansion. I can see where the
> >code might be unwieldy without this though. Anyone else have opinions?
>
> IMHO .S support is worthwhile just to be able to use constant
> definitions in assembly.
>
> For example,
>
> __unmapself:
> mov r7,#SYS_munmap
> svc 0
> mov r7,#SYS_exit
> svc 0
>
> Is a clearer than:
>
> __unmapself:
> mov r7,#91
> svc 0
> mov r7,#1
> svc 0
>
> Especially when approaching the source for the first time.
Are there any asm source files making syscalls where it's not obvious
from the public contract for the function(s) being implemented which
syscall they're making? I think it's just as easy to add a comment
with the syscall name if it's unclear, and then the actual number is
present too which is nice because it matches the dissembly.
The time when it would actually improve things to have symbolic
constants in asm files is for places where the constant can actually
vary, e.g. due to being derived from an offset in an implementation
internal structure or such (like struct __pthread). But preprocessor
macros cannot represent that in asm source files anyway. :(
Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-28 22:10 ` Rich Felker
@ 2016-03-28 23:04 ` Patrick Oppenlander
0 siblings, 0 replies; 18+ messages in thread
From: Patrick Oppenlander @ 2016-03-28 23:04 UTC (permalink / raw)
To: musl
On 29/03/16 09:10, Rich Felker wrote:
> On Tue, Mar 29, 2016 at 09:00:19AM +1100, Patrick Oppenlander wrote:
>> On 28/03/16 10:37, Rich Felker wrote:
>>> This is kind of the reason why I was hesitant to add .S support for so
>>> long. :-)
>>>
>>> I don't want to reject it outright, but the idea of adding .S support
>>> was just to allow conditional compilation, not to do condensed
>>> assembly sources that require macro expansion. I can see where the
>>> code might be unwieldy without this though. Anyone else have opinions?
>> IMHO .S support is worthwhile just to be able to use constant
>> definitions in assembly.
>>
>> For example,
>>
>> __unmapself:
>> mov r7,#SYS_munmap
>> svc 0
>> mov r7,#SYS_exit
>> svc 0
>>
>> Is a clearer than:
>>
>> __unmapself:
>> mov r7,#91
>> svc 0
>> mov r7,#1
>> svc 0
>>
>> Especially when approaching the source for the first time.
> Are there any asm source files making syscalls where it's not obvious
> from the public contract for the function(s) being implemented which
> syscall they're making? I think it's just as easy to add a comment
> with the syscall name if it's unclear, and then the actual number is
> present too which is nice because it matches the dissembly.
I guess the reason I chose that particular example because it was one of
my recent pain points porting musl to a small embedded RTOS.
A comment would probably have been sufficient -- at least then 'grep'
would have found it.
> The time when it would actually improve things to have symbolic
> constants in asm files is for places where the constant can actually
> vary, e.g. due to being derived from an offset in an implementation
> internal structure or such (like struct __pthread). But preprocessor
> macros cannot represent that in asm source files anyway. :(
I have seen a solution to this problem. Can't exactly remember where but
the gist of it was to hack some gcc inline assembly together to generate
the required offset constants:
test.c:
struct test {
int a;
int b;
};
#define offset(def, struct, member) \
__asm__("\n#define " def " %0" :: "i" (__builtin_offsetof(struct,
member)))
void offsets(void)
{
offset("A_OFFSET", struct test, a);
offset("B_OFFSET", struct test, b);
}
compile with gcc -S test.c to generate test.s:
.file "test.c"
.text
.globl offsets
.type offsets, @function
offsets:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
#APP
# 11 "test.c" 1
#define A_OFFSET $0
# 0 "" 2
# 12 "test.c" 1
#define B_OFFSET $4
# 0 "" 2
#NO_APP
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size offsets, .-offsets
.ident "GCC: (GNU) 5.3.0"
.section .note.GNU-stack,"",@progbits
pull out the #defines with sed -ne '/^#define/ s/\$// p' test.s
#define A_OFFSET 0
#define B_OFFSET 4
Somewhat grotesque, but it works.
Patrick
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-28 2:18 ` Rich Felker
2016-03-28 3:27 ` Szabolcs Nagy
@ 2016-04-02 17:02 ` Bobby Bingham
2016-04-03 2:09 ` Rich Felker
2016-04-04 4:03 ` Bobby Bingham
2 siblings, 1 reply; 18+ messages in thread
From: Bobby Bingham @ 2016-04-02 17:02 UTC (permalink / raw)
To: musl
On Sun, Mar 27, 2016 at 10:18:56PM -0400, Rich Felker wrote:
> > In the ABI, C functions have two entry points, the "global" entry point,
> > and the "local" entry point. The local entry point expects the "table of
> > contents" pointer in r2. The global entry point expects the address of
> > global entry point itself in r12, uses the prologue I used here to
> > calculate the TOC pointer from it, and falls through to the local entry
> > point. See section 2.3.2.1 of the ABI spec linked above.
> >
> > Calls within the same module are resolved to the local entry point, so
> > we need to ensure r2 is set up with the TOC pointer here to call any C
> > code.
> >
> > The ABI spec does specify that r12 contains the address of _start,
> > specifically so this prologue can work (section 4.1.2.1).
>
> OK. In that case the subsequent code to compute the address of
> _DYNAMIC via PC-relative addressing using the return address is
> unnecessary, though; you already have the initial PC and can just
> compute _DYNAMIC relative to it.
Ok.
>
> Also, for dynamic-linked programs, the main program's entry point is
> reached via CRTJMP() from the dynamic linker, and your definition is
> not setting up r12. In order to meet this part of the ELF ABI it needs
> to set r12.
Good catch.
>
> One thing that's not clear to me is whether the jumps/calls from asm,
> as you've written them, go to the local entry point or the global
> entry point of the callee. Since you're not loading r12 I assume the
> intent is to go to the local entry point, but that only works if the
> callee is hidden. Or does the PLT take care of converting that for you
> (as long as r2 is set)?
Calls that go through the PLT go to the global entry point. Otherwise,
they go to the local entry point.
The PLT stub saves r2 to a slot in the stack from required by the ABI to
be reserved for it, loads the global entry point address to r12, and
calls it. Calls that might go through the PLT are required to be made
with a "bl; nop" sequence, so that the linker can replace the nop with
an instruction to reload r2 from the stack where the PLT stub saved it.
>
> One place that looks wrong to me is sigsetjmp. I would expect r2 to be
> lost/clobbered when setjmp is called, but maybe not since it looks
> like setjmp saves it in the jmp_buf, despite it not being a call-saved
> register. Is that your expectation?
r2 is call-saved when using the local entry point. When using the global
entry point it's technically call-clobbered, but the PLT stub and linker
conspire together to save/restore it.
> > > > diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
> > > > new file mode 100644
> > > > index 0000000..ce59b60
> > > > --- /dev/null
> > > > +++ b/src/signal/powerpc64/sigsetjmp.s
> > > > @@ -0,0 +1,30 @@
> > > > + .global sigsetjmp
> > > > + .global __sigsetjmp
> > > > + .type sigsetjmp,%function
> > > > + .type __sigsetjmp,%function
> > > > + .hidden ___setjmp
> > > > +sigsetjmp:
> > > > +__sigsetjmp:
> > > > + addis 2, 12, .TOC.-__sigsetjmp@ha
> > > > + addi 2, 2, .TOC.-__sigsetjmp@l
> > > > + .localentry sigsetjmp,.-sigsetjmp
> > > > + .localentry __sigsetjmp,.-__sigsetjmp
> > >
> > > Again I don't see what the purpose of these insns is; if the resulting
> > > value is needed, are you aware of how that interacts with ___setjmp
> > > returning twice?
> >
> > This sets up r2 with the TOC pointer, as is required by the ABI in order
> > to call setjmp's local entry point. Since setjmp is also written in asm,
> > we could do away with this here.
> >
> > I don't think the fact that setjmp returns twice matters for this.
>
> When setjmp returns the second time, all registers it did not save
> have been clobbered (by arbitrary code that ran after the first return
> from setjmp). However despite not being a call-saved register
> (AFAICT), r2 is saved by setjmp, so it's probably okay.
r2 is call-saved when calling to the local entry point, so setjmp needs
to save it.
--
Bobby
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-04-02 17:02 ` Bobby Bingham
@ 2016-04-03 2:09 ` Rich Felker
2016-04-03 17:10 ` Bobby Bingham
0 siblings, 1 reply; 18+ messages in thread
From: Rich Felker @ 2016-04-03 2:09 UTC (permalink / raw)
To: musl
On Sat, Apr 02, 2016 at 12:02:28PM -0500, Bobby Bingham wrote:
> > One thing that's not clear to me is whether the jumps/calls from asm,
> > as you've written them, go to the local entry point or the global
> > entry point of the callee. Since you're not loading r12 I assume the
> > intent is to go to the local entry point, but that only works if the
> > callee is hidden. Or does the PLT take care of converting that for you
> > (as long as r2 is set)?
>
> Calls that go through the PLT go to the global entry point. Otherwise,
> they go to the local entry point.
>
> The PLT stub saves r2 to a slot in the stack from required by the ABI to
> be reserved for it, loads the global entry point address to r12, and
> calls it. Calls that might go through the PLT are required to be made
> with a "bl; nop" sequence, so that the linker can replace the nop with
> an instruction to reload r2 from the stack where the PLT stub saved it.
Wow. That's clever but hideous. Thanks for explaining it, though.
> > One place that looks wrong to me is sigsetjmp. I would expect r2 to be
> > lost/clobbered when setjmp is called, but maybe not since it looks
> > like setjmp saves it in the jmp_buf, despite it not being a call-saved
> > register. Is that your expectation?
>
> r2 is call-saved when using the local entry point. When using the global
> entry point it's technically call-clobbered, but the PLT stub and linker
> conspire together to save/restore it.
OK, I see now.
> > > > > diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
> > > > > new file mode 100644
> > > > > index 0000000..ce59b60
> > > > > --- /dev/null
> > > > > +++ b/src/signal/powerpc64/sigsetjmp.s
> > > > > @@ -0,0 +1,30 @@
> > > > > + .global sigsetjmp
> > > > > + .global __sigsetjmp
> > > > > + .type sigsetjmp,%function
> > > > > + .type __sigsetjmp,%function
> > > > > + .hidden ___setjmp
> > > > > +sigsetjmp:
> > > > > +__sigsetjmp:
> > > > > + addis 2, 12, .TOC.-__sigsetjmp@ha
> > > > > + addi 2, 2, .TOC.-__sigsetjmp@l
> > > > > + .localentry sigsetjmp,.-sigsetjmp
> > > > > + .localentry __sigsetjmp,.-__sigsetjmp
> > > >
> > > > Again I don't see what the purpose of these insns is; if the resulting
> > > > value is needed, are you aware of how that interacts with ___setjmp
> > > > returning twice?
> > >
> > > This sets up r2 with the TOC pointer, as is required by the ABI in order
> > > to call setjmp's local entry point. Since setjmp is also written in asm,
> > > we could do away with this here.
> > >
> > > I don't think the fact that setjmp returns twice matters for this.
> >
> > When setjmp returns the second time, all registers it did not save
> > have been clobbered (by arbitrary code that ran after the first return
> > from setjmp). However despite not being a call-saved register
> > (AFAICT), r2 is saved by setjmp, so it's probably okay.
>
> r2 is call-saved when calling to the local entry point, so setjmp needs
> to save it.
OK, I see how this works for local calls to setjmp. But how does the
linker PLT magic work for setjmp?
After the first return, the caller's stack slot where r2 was saved
belongs to the caller, and the compiler can clobber it. Upon the
second return, it would load junk into r2. Does longjmp have to do
something special (its own store to this stack slot, matching what a
PLT thunk would do) so that the caller loads the correct value?
Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-04-03 2:09 ` Rich Felker
@ 2016-04-03 17:10 ` Bobby Bingham
2016-04-03 17:26 ` Rich Felker
0 siblings, 1 reply; 18+ messages in thread
From: Bobby Bingham @ 2016-04-03 17:10 UTC (permalink / raw)
To: musl
On Sat, Apr 02, 2016 at 10:09:47PM -0400, Rich Felker wrote:
> > > > > > diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
> > > > > > new file mode 100644
> > > > > > index 0000000..ce59b60
> > > > > > --- /dev/null
> > > > > > +++ b/src/signal/powerpc64/sigsetjmp.s
> > > > > > @@ -0,0 +1,30 @@
> > > > > > + .global sigsetjmp
> > > > > > + .global __sigsetjmp
> > > > > > + .type sigsetjmp,%function
> > > > > > + .type __sigsetjmp,%function
> > > > > > + .hidden ___setjmp
> > > > > > +sigsetjmp:
> > > > > > +__sigsetjmp:
> > > > > > + addis 2, 12, .TOC.-__sigsetjmp@ha
> > > > > > + addi 2, 2, .TOC.-__sigsetjmp@l
> > > > > > + .localentry sigsetjmp,.-sigsetjmp
> > > > > > + .localentry __sigsetjmp,.-__sigsetjmp
> > > > >
> > > > > Again I don't see what the purpose of these insns is; if the resulting
> > > > > value is needed, are you aware of how that interacts with ___setjmp
> > > > > returning twice?
> > > >
> > > > This sets up r2 with the TOC pointer, as is required by the ABI in order
> > > > to call setjmp's local entry point. Since setjmp is also written in asm,
> > > > we could do away with this here.
> > > >
> > > > I don't think the fact that setjmp returns twice matters for this.
> > >
> > > When setjmp returns the second time, all registers it did not save
> > > have been clobbered (by arbitrary code that ran after the first return
> > > from setjmp). However despite not being a call-saved register
> > > (AFAICT), r2 is saved by setjmp, so it's probably okay.
> >
> > r2 is call-saved when calling to the local entry point, so setjmp needs
> > to save it.
>
> OK, I see how this works for local calls to setjmp. But how does the
> linker PLT magic work for setjmp?
>
> After the first return, the caller's stack slot where r2 was saved
> belongs to the caller, and the compiler can clobber it. Upon the
The ABI is very prescriptive about the layout of a stack frame. Each
stack frame has several slots where callees are allowed to use part of
their caller's frame. For example, the link register is saved to the
caller's frame, not the callee's.
For several of these slots, the ABI explicitly documents that they may
be used as temporary storage which should be considered call-clobbered.
For the slot used for saving the toc pointer (r2), the ABI makes no
mention of it being available for temporary storage. It would be nice
if it were more explicit here, but I believe the intent is that the
compiler may not use this slot for any other purpose.
> second return, it would load junk into r2. Does longjmp have to do
> something special (its own store to this stack slot, matching what a
> PLT thunk would do) so that the caller loads the correct value?
>
> Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-04-03 17:10 ` Bobby Bingham
@ 2016-04-03 17:26 ` Rich Felker
2016-04-03 17:50 ` Bobby Bingham
0 siblings, 1 reply; 18+ messages in thread
From: Rich Felker @ 2016-04-03 17:26 UTC (permalink / raw)
To: musl
On Sun, Apr 03, 2016 at 12:10:44PM -0500, Bobby Bingham wrote:
> > > r2 is call-saved when calling to the local entry point, so setjmp needs
> > > to save it.
> >
> > OK, I see how this works for local calls to setjmp. But how does the
> > linker PLT magic work for setjmp?
> >
> > After the first return, the caller's stack slot where r2 was saved
> > belongs to the caller, and the compiler can clobber it. Upon the
>
> The ABI is very prescriptive about the layout of a stack frame. Each
> stack frame has several slots where callees are allowed to use part of
> their caller's frame. For example, the link register is saved to the
> caller's frame, not the callee's.
>
> For several of these slots, the ABI explicitly documents that they may
> be used as temporary storage which should be considered call-clobbered.
> For the slot used for saving the toc pointer (r2), the ABI makes no
> mention of it being available for temporary storage. It would be nice
> if it were more explicit here, but I believe the intent is that the
> compiler may not use this slot for any other purpose.
My concern was not that the function itself could clobber it (although
I think it would be entitled to if it's no longer live, i.e. if no
code paths remain that reference its value) but that future function
calls might clobber it. However I think they all necessarily either
don't write to this slot at all, or write the same value that was
already there, so it's probably safe without longjmp having to restore
it.
Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-04-03 17:26 ` Rich Felker
@ 2016-04-03 17:50 ` Bobby Bingham
0 siblings, 0 replies; 18+ messages in thread
From: Bobby Bingham @ 2016-04-03 17:50 UTC (permalink / raw)
To: musl
On Sun, Apr 03, 2016 at 01:26:31PM -0400, Rich Felker wrote:
> On Sun, Apr 03, 2016 at 12:10:44PM -0500, Bobby Bingham wrote:
> > > > r2 is call-saved when calling to the local entry point, so setjmp needs
> > > > to save it.
> > >
> > > OK, I see how this works for local calls to setjmp. But how does the
> > > linker PLT magic work for setjmp?
> > >
> > > After the first return, the caller's stack slot where r2 was saved
> > > belongs to the caller, and the compiler can clobber it. Upon the
> >
> > The ABI is very prescriptive about the layout of a stack frame. Each
> > stack frame has several slots where callees are allowed to use part of
> > their caller's frame. For example, the link register is saved to the
> > caller's frame, not the callee's.
> >
> > For several of these slots, the ABI explicitly documents that they may
> > be used as temporary storage which should be considered call-clobbered.
> > For the slot used for saving the toc pointer (r2), the ABI makes no
> > mention of it being available for temporary storage. It would be nice
> > if it were more explicit here, but I believe the intent is that the
> > compiler may not use this slot for any other purpose.
>
> My concern was not that the function itself could clobber it (although
> I think it would be entitled to if it's no longer live, i.e. if no
> code paths remain that reference its value) but that future function
> calls might clobber it. However I think they all necessarily either
> don't write to this slot at all, or write the same value that was
> already there, so it's probably safe without longjmp having to restore
> it.
Yes, that's right. All function calls from a single caller will either
not clobber that stack slot, or will write the same value to it.
>
> Rich
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-03-28 2:18 ` Rich Felker
2016-03-28 3:27 ` Szabolcs Nagy
2016-04-02 17:02 ` Bobby Bingham
@ 2016-04-04 4:03 ` Bobby Bingham
2016-04-04 10:41 ` Szabolcs Nagy
2 siblings, 1 reply; 18+ messages in thread
From: Bobby Bingham @ 2016-04-04 4:03 UTC (permalink / raw)
To: musl
On Sun, Mar 27, 2016 at 10:18:56PM -0400, Rich Felker wrote:
> > > > diff --git a/arch/powerpc64/reloc.h b/arch/powerpc64/reloc.h
> > > > new file mode 100644
> > > > index 0000000..8e60b31
> > > > --- /dev/null
> > > > +++ b/arch/powerpc64/reloc.h
> > > > @@ -0,0 +1,32 @@
> > > > +#include <endian.h>
> > > > +
> > > > +#if __BYTE_ORDER == __LITTLE_ENDIAN
> > > > +#define ENDIAN_SUFFIX "le"
> > > > +#else
> > > > +#define ENDIAN_SUFFIX ""
> > > > +#endif
> > > > +
> > > > +#define LDSO_ARCH "powerpc64" ENDIAN_SUFFIX
> > >
> > > Is it intentional that the "default" subarch variant be suffixed with
> > > "le" and a non-default/unused one be the bare "powerpc64"? I don't
> > > object to that but it's contrary to usual conventions that the bare
> > > arch be the canonical ABI, and it might be contrary to what GCC is
> > > doing now (haven't checked) for the dynamic linker name.
> >
> > I'll double check, but I skimmed the gcc code here, and it looked like
> > it uses an "le" suffix. Admittedly, I didn't read it closely enough to
> > be absolutely sure yet.
>
> OK, sounds good. Also note that CRTJMP here needs fixing.
I checked again, and gcc does indeed use the "le" suffix.
gcc/config/rs6000/linux64.h has:
#define MUSL_DYNAMIC_LINKER64 \
"/lib/ld-musl-powerpc64" MUSL_DYNAMIC_LINKER_E "%{msoft-float:-sf}.so.1"
The two places that define MUSL_DYNAMIC_LINKER_E define it like so:
gcc/config/rs6000/sysv4.h:
#define MUSL_DYNAMIC_LINKER_E ENDIAN_SELECT("", "le", "")
gcc/config/rs6000/sysv4le.h:
#define MUSL_DYNAMIC_LINKER_E ENDIAN_SELECT("", "le", "le")
--
Bobby
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] add powerpc64 port
2016-04-04 4:03 ` Bobby Bingham
@ 2016-04-04 10:41 ` Szabolcs Nagy
0 siblings, 0 replies; 18+ messages in thread
From: Szabolcs Nagy @ 2016-04-04 10:41 UTC (permalink / raw)
To: musl
* Bobby Bingham <koorogi@koorogi.info> [2016-04-03 23:03:54 -0500]:
> On Sun, Mar 27, 2016 at 10:18:56PM -0400, Rich Felker wrote:
> > > > > diff --git a/arch/powerpc64/reloc.h b/arch/powerpc64/reloc.h
> > > > > new file mode 100644
> > > > > index 0000000..8e60b31
> > > > > --- /dev/null
> > > > > +++ b/arch/powerpc64/reloc.h
> > > > > @@ -0,0 +1,32 @@
> > > > > +#include <endian.h>
> > > > > +
> > > > > +#if __BYTE_ORDER == __LITTLE_ENDIAN
> > > > > +#define ENDIAN_SUFFIX "le"
> > > > > +#else
> > > > > +#define ENDIAN_SUFFIX ""
> > > > > +#endif
> > > > > +
> > > > > +#define LDSO_ARCH "powerpc64" ENDIAN_SUFFIX
> > > >
> > > > Is it intentional that the "default" subarch variant be suffixed with
> > > > "le" and a non-default/unused one be the bare "powerpc64"? I don't
> > > > object to that but it's contrary to usual conventions that the bare
> > > > arch be the canonical ABI, and it might be contrary to what GCC is
> > > > doing now (haven't checked) for the dynamic linker name.
> > >
> > > I'll double check, but I skimmed the gcc code here, and it looked like
> > > it uses an "le" suffix. Admittedly, I didn't read it closely enough to
> > > be absolutely sure yet.
> >
> > OK, sounds good. Also note that CRTJMP here needs fixing.
>
> I checked again, and gcc does indeed use the "le" suffix.
>
> gcc/config/rs6000/linux64.h has:
>
> #define MUSL_DYNAMIC_LINKER64 \
> "/lib/ld-musl-powerpc64" MUSL_DYNAMIC_LINKER_E "%{msoft-float:-sf}.so.1"
>
>
> The two places that define MUSL_DYNAMIC_LINKER_E define it like so:
>
> gcc/config/rs6000/sysv4.h:
>
> #define MUSL_DYNAMIC_LINKER_E ENDIAN_SELECT("", "le", "")
>
> gcc/config/rs6000/sysv4le.h:
>
> #define MUSL_DYNAMIC_LINKER_E ENDIAN_SELECT("", "le", "le")
>
i think i just followed the 32bit logic
because 32bit and 64bit use a lot of
common code in gcc
i dont know what's the convention.
i hope this works.
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2016-04-04 10:41 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-27 21:20 [RFC] powerpc64 port Bobby Bingham
2016-03-27 21:20 ` [PATCH 1/2] add 64bit atomics on top of 64bit ll/sc primitives Bobby Bingham
2016-03-27 22:27 ` Rich Felker
2016-03-27 21:20 ` [PATCH 2/2] add powerpc64 port Bobby Bingham
2016-03-27 23:37 ` Rich Felker
2016-03-28 0:32 ` Bobby Bingham
2016-03-28 2:18 ` Rich Felker
2016-03-28 3:27 ` Szabolcs Nagy
2016-04-02 17:02 ` Bobby Bingham
2016-04-03 2:09 ` Rich Felker
2016-04-03 17:10 ` Bobby Bingham
2016-04-03 17:26 ` Rich Felker
2016-04-03 17:50 ` Bobby Bingham
2016-04-04 4:03 ` Bobby Bingham
2016-04-04 10:41 ` Szabolcs Nagy
2016-03-28 22:00 ` Patrick Oppenlander
2016-03-28 22:10 ` Rich Felker
2016-03-28 23:04 ` Patrick Oppenlander
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).