|
|
Message-ID: <20261102165837.24591-10-kaloz@kernel.org>
Date: Mon, 2 Nov 2026 17:58:36 +0100
From: Imre Kaloz <kaloz@...nel.org>
To: musl@...ts.openwall.com
Subject: [PATCH 09/10] add sparc64 port
This uses the clone, rt_sigaction, ipc, suseconds_t, MC_NPC, PLT write
and local symbol hooks. The thread pointer is %g7, fenv_t is the whole
%fsr, and long double is quad precision. Long double arithmetic is done
in software by the _Qp_* helpers.
---
arch/sparc64/atomic_arch.h | 35 ++
arch/sparc64/bits/alltypes.h.in | 18 +
arch/sparc64/bits/errno.h | 134 ++++++
arch/sparc64/bits/fcntl.h | 39 ++
arch/sparc64/bits/fenv.h | 17 +
arch/sparc64/bits/float.h | 20 +
arch/sparc64/bits/ioctl.h | 101 +++++
arch/sparc64/bits/limits.h | 1 +
arch/sparc64/bits/mman.h | 12 +
arch/sparc64/bits/poll.h | 5 +
arch/sparc64/bits/resource.h | 5 +
arch/sparc64/bits/setjmp.h | 1 +
arch/sparc64/bits/shm.h | 24 +
arch/sparc64/bits/signal.h | 98 +++++
arch/sparc64/bits/socket.h | 81 ++++
arch/sparc64/bits/syscall.h.in | 395 +++++++++++++++++
arch/sparc64/bits/termios.h | 151 +++++++
arch/sparc64/bits/user.h | 25 ++
arch/sparc64/crt_arch.h | 19 +
arch/sparc64/ksigaction.h | 10 +
arch/sparc64/kstat.h | 23 +
arch/sparc64/pthread_arch.h | 10 +
arch/sparc64/reloc.h | 69 +++
arch/sparc64/syscall_arch.h | 134 ++++++
configure | 5 +
src/fenv/sparc64/fenv.c | 58 +++
src/ldso/sparc64/dlsym.s | 8 +
src/math/sparc64/qp.c | 231 ++++++++++
src/math/sparc64/quad.h | 580 +++++++++++++++++++++++++
src/setjmp/sparc64/longjmp.s | 18 +
src/setjmp/sparc64/setjmp.s | 22 +
src/signal/sparc64/restore.s | 15 +
src/signal/sparc64/sigsetjmp.s | 25 ++
src/thread/sparc64/__set_thread_area.s | 8 +
src/thread/sparc64/__unmapself.c | 28 ++
src/thread/sparc64/clone.S | 51 +++
src/thread/sparc64/syscall_cp.s | 38 ++
src/unistd/sparc64/pipe.s | 18 +
38 files changed, 2532 insertions(+)
create mode 100644 arch/sparc64/atomic_arch.h
create mode 100644 arch/sparc64/bits/alltypes.h.in
create mode 100644 arch/sparc64/bits/errno.h
create mode 100644 arch/sparc64/bits/fcntl.h
create mode 100644 arch/sparc64/bits/fenv.h
create mode 100644 arch/sparc64/bits/float.h
create mode 100644 arch/sparc64/bits/ioctl.h
create mode 100644 arch/sparc64/bits/limits.h
create mode 100644 arch/sparc64/bits/mman.h
create mode 100644 arch/sparc64/bits/poll.h
create mode 100644 arch/sparc64/bits/resource.h
create mode 100644 arch/sparc64/bits/setjmp.h
create mode 100644 arch/sparc64/bits/shm.h
create mode 100644 arch/sparc64/bits/signal.h
create mode 100644 arch/sparc64/bits/socket.h
create mode 100644 arch/sparc64/bits/syscall.h.in
create mode 100644 arch/sparc64/bits/termios.h
create mode 100644 arch/sparc64/bits/user.h
create mode 100644 arch/sparc64/crt_arch.h
create mode 100644 arch/sparc64/ksigaction.h
create mode 100644 arch/sparc64/kstat.h
create mode 100644 arch/sparc64/pthread_arch.h
create mode 100644 arch/sparc64/reloc.h
create mode 100644 arch/sparc64/syscall_arch.h
create mode 100644 src/fenv/sparc64/fenv.c
create mode 100644 src/ldso/sparc64/dlsym.s
create mode 100644 src/math/sparc64/qp.c
create mode 100644 src/math/sparc64/quad.h
create mode 100644 src/setjmp/sparc64/longjmp.s
create mode 100644 src/setjmp/sparc64/setjmp.s
create mode 100644 src/signal/sparc64/restore.s
create mode 100644 src/signal/sparc64/sigsetjmp.s
create mode 100644 src/thread/sparc64/__set_thread_area.s
create mode 100644 src/thread/sparc64/__unmapself.c
create mode 100644 src/thread/sparc64/clone.S
create mode 100644 src/thread/sparc64/syscall_cp.s
create mode 100644 src/unistd/sparc64/pipe.s
diff --git a/arch/sparc64/atomic_arch.h b/arch/sparc64/atomic_arch.h
new file mode 100644
index 00000000..580a99b7
--- /dev/null
+++ b/arch/sparc64/atomic_arch.h
@@ -0,0 +1,35 @@
+#define a_cas a_cas
+static inline int a_cas(volatile int *p, int t, int s)
+{
+ __asm__ __volatile__ (
+ "cas [%1], %2, %0"
+ : "+r"(s)
+ : "r"(p), "r"(t)
+ : "memory");
+ return s;
+}
+
+#define a_cas_p a_cas_p
+static inline void *a_cas_p(volatile void *p, void *t, void *s)
+{
+ __asm__ __volatile__ (
+ "casx [%1], %2, %0"
+ : "+r"(s)
+ : "r"(p), "r"(t)
+ : "memory");
+ return s;
+}
+
+#define a_barrier a_barrier
+static inline void a_barrier()
+{
+ __asm__ __volatile__ (
+ "membar #LoadLoad|#LoadStore|#StoreStore|#StoreLoad"
+ ::: "memory");
+}
+
+#define a_crash a_crash
+static inline void a_crash()
+{
+ __asm__ __volatile__ ("illtrap 0");
+}
diff --git a/arch/sparc64/bits/alltypes.h.in b/arch/sparc64/bits/alltypes.h.in
new file mode 100644
index 00000000..e13962d1
--- /dev/null
+++ b/arch/sparc64/bits/alltypes.h.in
@@ -0,0 +1,18 @@
+#define _Addr long
+#define _Int64 long
+#define _Reg long
+
+#define __BYTE_ORDER 4321
+#define __LONG_MAX 0x7fffffffffffffffL
+
+#ifndef __cplusplus
+TYPEDEF int wchar_t;
+#endif
+
+TYPEDEF int blksize_t;
+TYPEDEF unsigned int nlink_t;
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
diff --git a/arch/sparc64/bits/errno.h b/arch/sparc64/bits/errno.h
new file mode 100644
index 00000000..98dbdd7c
--- /dev/null
+++ b/arch/sparc64/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 78
+#define ENAMETOOLONG 63
+#define ENOLCK 79
+#define ENOSYS 90
+#define ENOTEMPTY 66
+#define ELOOP 62
+#define EWOULDBLOCK EAGAIN
+#define ENOMSG 75
+#define EIDRM 77
+#define ECHRNG 94
+#define EL2NSYNC 95
+#define EL3HLT 96
+#define EL3RST 97
+#define ELNRNG 98
+#define EUNATCH 99
+#define ENOCSI 100
+#define EL2HLT 101
+#define EBADE 102
+#define EBADR 103
+#define EXFULL 104
+#define ENOANO 105
+#define EBADRQC 106
+#define EBADSLT 107
+#define EDEADLOCK 108
+#define EBFONT 109
+#define ENOSTR 72
+#define ENODATA 111
+#define ETIME 73
+#define ENOSR 74
+#define ENONET 80
+#define ENOPKG 113
+#define EREMOTE 71
+#define ENOLINK 82
+#define EADV 83
+#define ESRMNT 84
+#define ECOMM 85
+#define EPROTO 86
+#define EMULTIHOP 87
+#define EDOTDOT 88
+#define EBADMSG 76
+#define EOVERFLOW 92
+#define ENOTUNIQ 115
+#define EBADFD 93
+#define EREMCHG 89
+#define ELIBACC 114
+#define ELIBBAD 112
+#define ELIBSCN 124
+#define ELIBMAX 123
+#define ELIBEXEC 110
+#define EILSEQ 122
+#define ERESTART 116
+#define ESTRPIPE 91
+#define EUSERS 68
+#define ENOTSOCK 38
+#define EDESTADDRREQ 39
+#define EMSGSIZE 40
+#define EPROTOTYPE 41
+#define ENOPROTOOPT 42
+#define EPROTONOSUPPORT 43
+#define ESOCKTNOSUPPORT 44
+#define EOPNOTSUPP 45
+#define ENOTSUP EOPNOTSUPP
+#define EPFNOSUPPORT 46
+#define EAFNOSUPPORT 47
+#define EADDRINUSE 48
+#define EADDRNOTAVAIL 49
+#define ENETDOWN 50
+#define ENETUNREACH 51
+#define ENETRESET 52
+#define ECONNABORTED 53
+#define ECONNRESET 54
+#define ENOBUFS 55
+#define EISCONN 56
+#define ENOTCONN 57
+#define ESHUTDOWN 58
+#define ETOOMANYREFS 59
+#define ETIMEDOUT 60
+#define ECONNREFUSED 61
+#define EHOSTDOWN 64
+#define EHOSTUNREACH 65
+#define EALREADY 37
+#define EINPROGRESS 36
+#define ESTALE 70
+#define EUCLEAN 117
+#define ENOTNAM 118
+#define ENAVAIL 119
+#define EISNAM 120
+#define EREMOTEIO 121
+#define EDQUOT 69
+#define ENOMEDIUM 125
+#define EMEDIUMTYPE 126
+#define ECANCELED 127
+#define ENOKEY 128
+#define EKEYEXPIRED 129
+#define EKEYREVOKED 130
+#define EKEYREJECTED 131
+#define EOWNERDEAD 132
+#define ENOTRECOVERABLE 133
+#define ERFKILL 134
+#define EHWPOISON 135
diff --git a/arch/sparc64/bits/fcntl.h b/arch/sparc64/bits/fcntl.h
new file mode 100644
index 00000000..9562c78f
--- /dev/null
+++ b/arch/sparc64/bits/fcntl.h
@@ -0,0 +1,39 @@
+#define O_CREAT 01000
+#define O_EXCL 04000
+#define O_NOCTTY 0100000
+#define O_TRUNC 02000
+#define O_APPEND 010
+#define O_NONBLOCK 040000
+#define O_DSYNC 020000
+#define O_SYNC 040020000
+#define O_RSYNC 040020000
+#define O_DIRECTORY 0200000
+#define O_NOFOLLOW 0400000
+#define O_CLOEXEC 020000000
+#define O_ASYNC 0100
+#define O_DIRECT 04000000
+#define O_LARGEFILE 01000000
+#define O_NOATIME 010000000
+#define O_PATH 0100000000
+#define O_TMPFILE 0200200000
+#define F_DUPFD 0
+#define F_GETFD 1
+#define F_SETFD 2
+#define F_GETFL 3
+#define F_SETFL 4
+#define F_SETOWN 6
+#define F_GETOWN 5
+#define F_SETSIG 10
+#define F_GETSIG 11
+#define F_GETLK 7
+#define F_SETLK 8
+#define F_SETLKW 9
+#define F_SETOWN_EX 15
+#define F_GETOWN_EX 16
+#define F_GETOWNER_UIDS 17
+
+#define O_NDELAY O_NONBLOCK
+
+#define F_RDLCK 1
+#define F_WRLCK 2
+#define F_UNLCK 3
diff --git a/arch/sparc64/bits/fenv.h b/arch/sparc64/bits/fenv.h
new file mode 100644
index 00000000..5f411b97
--- /dev/null
+++ b/arch/sparc64/bits/fenv.h
@@ -0,0 +1,17 @@
+#define FE_INEXACT 0x020
+#define FE_DIVBYZERO 0x040
+#define FE_UNDERFLOW 0x080
+#define FE_OVERFLOW 0x100
+#define FE_INVALID 0x200
+
+#define FE_ALL_EXCEPT 0x3e0
+
+#define FE_TONEAREST 0
+#define FE_TOWARDZERO 1
+#define FE_UPWARD 2
+#define FE_DOWNWARD 3
+
+typedef unsigned long fexcept_t;
+typedef unsigned long fenv_t;
+
+#define FE_DFL_ENV ((const fenv_t *)-1)
diff --git a/arch/sparc64/bits/float.h b/arch/sparc64/bits/float.h
new file mode 100644
index 00000000..e188cb61
--- /dev/null
+++ b/arch/sparc64/bits/float.h
@@ -0,0 +1,20 @@
+#ifdef __FLT_EVAL_METHOD__
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#else
+#define FLT_EVAL_METHOD 0
+#endif
+
+#define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L
+#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
+#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
+#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
+
+#define LDBL_MANT_DIG 113
+#define LDBL_MIN_EXP (-16381)
+#define LDBL_MAX_EXP 16384
+
+#define LDBL_DIG 33
+#define LDBL_MIN_10_EXP (-4931)
+#define LDBL_MAX_10_EXP 4932
+
+#define DECIMAL_DIG 36
diff --git a/arch/sparc64/bits/ioctl.h b/arch/sparc64/bits/ioctl.h
new file mode 100644
index 00000000..802f470d
--- /dev/null
+++ b/arch/sparc64/bits/ioctl.h
@@ -0,0 +1,101 @@
+#define _IOC(a,b,c,d) ( ((a)<<29) | ((b)<<8) | (c) | ((d)<<16) )
+#define _IOC_NONE 1U
+#define _IOC_READ 2U
+#define _IOC_WRITE 4U
+
+#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 TCGETS 0x40245408
+#define TCSETS 0x80245409
+#define TCSETSW 0x8024540a
+#define TCSETSF 0x8024540b
+#define TCGETA 0x40125401
+#define TCSETA 0x80125402
+#define TCSETAW 0x80125403
+#define TCSETAF 0x80125404
+#define TCSBRK 0x20005405
+#define TCXONC 0x20005406
+#define TCFLSH 0x20005407
+#define TIOCEXCL 0x2000740d
+#define TIOCNXCL 0x2000740e
+#define TIOCSCTTY 0x20007484
+#define TIOCGPGRP 0x40047483
+#define TIOCSPGRP 0x80047482
+#define TIOCOUTQ 0x40047473
+#define TIOCSTI 0x80017472
+#define TIOCGWINSZ 0x40087468
+#define TIOCSWINSZ 0x80087467
+#define TIOCMGET 0x4004746a
+#define TIOCMBIS 0x8004746c
+#define TIOCMBIC 0x8004746b
+#define TIOCMSET 0x8004746d
+#define TIOCGSOFTCAR 0x40047464
+#define TIOCSSOFTCAR 0x80047465
+#define FIONREAD 0x4004667f
+#define TIOCLINUX 0x541c
+#define TIOCCONS 0x20007424
+#define TIOCGSERIAL 0x541e
+#define TIOCSSERIAL 0x541f
+#define TIOCPKT 0x80047470
+#define FIONBIO 0x8004667e
+#define TIOCNOTTY 0x20007471
+#define TIOCSETD 0x80047401
+#define TIOCGETD 0x40047400
+#define TCSBRKP 0x5425
+#define TIOCSBRK 0x2000747b
+#define TIOCCBRK 0x2000747a
+#define TIOCGSID 0x40047485
+#define TIOCGRS485 0x40205441
+#define TIOCSRS485 0xc0205442
+#define TIOCGPTN 0x40047486
+#define TIOCSPTLCK 0x80047487
+#define TIOCGDEV 0x40045432
+#define TIOCSIG 0x80047488
+#define TIOCVHANGUP 0x20005437
+#define TIOCGPKT 0x40045438
+#define TIOCGPTLCK 0x40045439
+#define TIOCGEXCL 0x40045440
+#define TIOCGPTPEER 0x20007489
+#define TIOCGISO7816 0x40285443
+#define TIOCSISO7816 0xc0285444
+#define FIONCLEX 0x20006602
+#define FIOCLEX 0x20006601
+#define FIOASYNC 0x8004667d
+#define TIOCSERCONFIG 0x5453
+#define TIOCSERGWILD 0x5454
+#define TIOCSERSWILD 0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458
+#define TIOCSERGETLSR 0x5459
+#define TIOCSERGETMULTI 0x545a
+#define TIOCSERSETMULTI 0x545b
+#define TIOCMIWAIT 0x545c
+#define TIOCGICOUNT 0x545d
+#define FIOQSIZE 0x40086680
+#define TIOCM_LE 0x1
+#define TIOCM_DTR 0x2
+#define TIOCM_RTS 0x4
+#define TIOCM_ST 0x8
+#define TIOCM_SR 0x10
+#define TIOCM_CTS 0x20
+#define TIOCM_CAR 0x40
+#define TIOCM_RNG 0x80
+#define TIOCM_DSR 0x100
+#define TIOCM_OUT1 0x2000
+#define TIOCM_OUT2 0x4000
+#define TIOCM_LOOP 0x8000
+#define FIOSETOWN 0x8901
+#define SIOCSPGRP 0x8902
+#define FIOGETOWN 0x8903
+#define SIOCGPGRP 0x8904
+#define SIOCATMARK 0x8905
+/* The kernel returns a {long, int} timeval for the _OLD and _NEW
+ * SIOCGSTAMP alike, and ioctl.c converts it. */
+#define SIOCGSTAMP 0x8906
+#define SIOCGSTAMPNS 0x8907
+#define TIOCINQ FIONREAD
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
diff --git a/arch/sparc64/bits/limits.h b/arch/sparc64/bits/limits.h
new file mode 100644
index 00000000..fac47aad
--- /dev/null
+++ b/arch/sparc64/bits/limits.h
@@ -0,0 +1 @@
+#define PAGESIZE 8192
diff --git a/arch/sparc64/bits/mman.h b/arch/sparc64/bits/mman.h
new file mode 100644
index 00000000..588d041b
--- /dev/null
+++ b/arch/sparc64/bits/mman.h
@@ -0,0 +1,12 @@
+#undef MAP_GROWSDOWN
+#define MAP_GROWSDOWN 0x200
+#undef MAP_LOCKED
+#define MAP_LOCKED 0x100
+#undef MAP_NORESERVE
+#define MAP_NORESERVE 0x40
+#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/sparc64/bits/poll.h b/arch/sparc64/bits/poll.h
new file mode 100644
index 00000000..d9952334
--- /dev/null
+++ b/arch/sparc64/bits/poll.h
@@ -0,0 +1,5 @@
+#define POLLWRNORM 4
+#define POLLWRBAND 256
+
+#define POLLMSG 512
+#define POLLRDHUP 2048
diff --git a/arch/sparc64/bits/resource.h b/arch/sparc64/bits/resource.h
new file mode 100644
index 00000000..6623b5e6
--- /dev/null
+++ b/arch/sparc64/bits/resource.h
@@ -0,0 +1,5 @@
+#define RLIMIT_RSS 5
+#define RLIMIT_NPROC 7
+#define RLIMIT_NOFILE 6
+#define RLIMIT_MEMLOCK 8
+#define RLIMIT_AS 9
diff --git a/arch/sparc64/bits/setjmp.h b/arch/sparc64/bits/setjmp.h
new file mode 100644
index 00000000..dae9bc16
--- /dev/null
+++ b/arch/sparc64/bits/setjmp.h
@@ -0,0 +1 @@
+typedef unsigned long __jmp_buf[3];
diff --git a/arch/sparc64/bits/shm.h b/arch/sparc64/bits/shm.h
new file mode 100644
index 00000000..e5bc71be
--- /dev/null
+++ b/arch/sparc64/bits/shm.h
@@ -0,0 +1,24 @@
+#define SHMLBA 16384
+
+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 __pad1;
+ unsigned long __pad2;
+};
+
+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/sparc64/bits/signal.h b/arch/sparc64/bits/signal.h
new file mode 100644
index 00000000..e4f94197
--- /dev/null
+++ b/arch/sparc64/bits/signal.h
@@ -0,0 +1,98 @@
+#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 4096
+#define SIGSTKSZ 16384
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+typedef struct {
+ unsigned long mc_gregs[16]; /* %g0-%g7, %o0-%o7 */
+ unsigned long mc_tstate;
+ unsigned long mc_pc;
+ unsigned long mc_npc;
+ unsigned int mc_y;
+ unsigned int mc_fprs;
+} mcontext_t;
+#else
+
+typedef struct {
+ unsigned long __regs[19];
+ unsigned int __pad[2];
+} mcontext_t;
+#endif
+
+struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+};
+
+/* uc_flags and uc_link are not filled in by signal delivery. Only the
+ * first 8 bytes of uc_sigmask are in the kernel's signal frame, so a
+ * handler changes it with sigaddset or sigdelset, never by assignment. */
+typedef struct __ucontext {
+ char __siginfo_overlay[128];
+ mcontext_t uc_mcontext;
+ void *__fpu_save;
+ stack_t uc_stack;
+ sigset_t uc_sigmask;
+ unsigned long uc_flags;
+ struct __ucontext *uc_link;
+} ucontext_t;
+
+#define SA_NOCLDSTOP 0x8U
+#define SA_NOCLDWAIT 0x100U
+#define SA_SIGINFO 0x200U
+#define SA_ONSTACK 0x1U
+#define SA_RESTART 0x2U
+#define SA_NODEFER 0x20U
+#define SA_RESETHAND 0x4U
+
+#endif
+
+#undef SIG_BLOCK
+#define SIG_BLOCK 1
+#undef SIG_UNBLOCK
+#define SIG_UNBLOCK 2
+#undef SIG_SETMASK
+#define SIG_SETMASK 4
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGEMT 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGBUS 10
+#define SIGSEGV 11
+#define SIGSYS 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGURG 16
+#define SIGSTOP 17
+#define SIGTSTP 18
+#define SIGCONT 19
+#define SIGCHLD 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGIO 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGLOST 29
+#define SIGUSR1 30
+#define SIGUSR2 31
+#define SIGIOT SIGABRT
+#define SIGPOLL SIGIO
+#define SIGPWR SIGLOST
+
+#define _NSIG 65
diff --git a/arch/sparc64/bits/socket.h b/arch/sparc64/bits/socket.h
new file mode 100644
index 00000000..a1bf916d
--- /dev/null
+++ b/arch/sparc64/bits/socket.h
@@ -0,0 +1,81 @@
+#define SOCK_CLOEXEC 4194304
+#define SOCK_NONBLOCK 16384
+
+#define SO_DEBUG 1
+#define SO_REUSEADDR 4
+#define SO_TYPE 4104
+#define SO_ERROR 4103
+#define SO_DONTROUTE 16
+#define SO_BROADCAST 32
+#define SO_SNDBUF 4097
+#define SO_RCVBUF 4098
+#define SO_KEEPALIVE 8
+#define SO_OOBINLINE 256
+#define SO_NO_CHECK 11
+#define SO_PRIORITY 12
+#define SO_LINGER 128
+#define SO_BSDCOMPAT 1024
+#define SO_REUSEPORT 512
+#define SO_PASSCRED 2
+#define SO_PEERCRED 64
+#define SO_RCVLOWAT 2048
+#define SO_SNDLOWAT 4096
+#define SO_ACCEPTCONN 32768
+#define SO_PEERSEC 30
+#define SO_SNDBUFFORCE 4106
+#define SO_RCVBUFFORCE 4107
+#define SO_PROTOCOL 4136
+#define SO_DOMAIN 4137
+
+/* tv_usec in __kernel_old_timeval is an int here, so these are the _NEW numbers */
+#define SO_RCVTIMEO 68
+#define SO_SNDTIMEO 69
+
+#define SO_TIMESTAMP 70
+#define SO_TIMESTAMPNS 66
+#define SO_TIMESTAMPING 67
+
+#define SO_SECURITY_AUTHENTICATION 20481
+#define SO_SECURITY_ENCRYPTION_TRANSPORT 20482
+#define SO_SECURITY_ENCRYPTION_NETWORK 20484
+#define SO_BINDTODEVICE 13
+#define SO_ATTACH_FILTER 26
+#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
+#define SO_PEERNAME 28
+#define SCM_TIMESTAMP SO_TIMESTAMP
+#define SO_PASSSEC 31
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
+#define SO_MARK 34
+#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_RXQ_OVFL 36
+#define SO_WIFI_STATUS 37
+#define SCM_WIFI_STATUS SO_WIFI_STATUS
+#define SO_PEEK_OFF 38
+#define SO_NOFCS 39
+#define SO_LOCK_FILTER 40
+#define SO_SELECT_ERR_QUEUE 41
+#define SO_BUSY_POLL 48
+#define SO_MAX_PACING_RATE 49
+#define SO_BPF_EXTENSIONS 50
+#define SO_INCOMING_CPU 51
+#define SO_ATTACH_BPF 52
+#define SO_DETACH_BPF SO_DETACH_FILTER
+#define SO_ATTACH_REUSEPORT_CBPF 53
+#define SO_ATTACH_REUSEPORT_EBPF 54
+#define SO_CNX_ADVICE 55
+#define SCM_TIMESTAMPING_OPT_STATS 56
+#define SO_MEMINFO 57
+#define SO_INCOMING_NAPI_ID 58
+#define SO_COOKIE 59
+#define SCM_TIMESTAMPING_PKTINFO 60
+#define SO_PEERGROUPS 61
+#define SO_ZEROCOPY 62
+#define SO_TXTIME 63
+#define SCM_TXTIME SO_TXTIME
+#define SO_BINDTOIFINDEX 65
+#define SO_DETACH_REUSEPORT_BPF 71
+#define SO_PREFER_BUSY_POLL 72
+#define SO_BUSY_POLL_BUDGET 73
+
+#define SOL_SOCKET 65535
diff --git a/arch/sparc64/bits/syscall.h.in b/arch/sparc64/bits/syscall.h.in
new file mode 100644
index 00000000..06d3be3d
--- /dev/null
+++ b/arch/sparc64/bits/syscall.h.in
@@ -0,0 +1,395 @@
+#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_wait4 7
+#define __NR_creat 8
+#define __NR_link 9
+#define __NR_unlink 10
+#define __NR_chdir 12
+#define __NR_chown 13
+#define __NR_mknod 14
+#define __NR_chmod 15
+#define __NR_lchown 16
+#define __NR_brk 17
+#define __NR_perfctr 18
+#define __NR_lseek 19
+#define __NR_getpid 20
+#define __NR_capget 21
+#define __NR_capset 22
+#define __NR_setuid 23
+#define __NR_getuid 24
+#define __NR_vmsplice 25
+#define __NR_ptrace 26
+#define __NR_alarm 27
+#define __NR_sigaltstack 28
+#define __NR_utime 30
+#define __NR_access 33
+#define __NR_nice 34
+#define __NR_sync 36
+#define __NR_kill 37
+#define __NR_stat 38
+#define __NR_sendfile 39
+#define __NR_lstat 40
+#define __NR_dup 41
+#define __NR_pipe 42
+#define __NR_times 43
+#define __NR_umount2 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_memory_ordering 52
+#define __NR_ioctl 54
+#define __NR_reboot 55
+#define __NR_symlink 57
+#define __NR_readlink 58
+#define __NR_execve 59
+#define __NR_umask 60
+#define __NR_chroot 61
+#define __NR_fstat 62
+#define __NR_fstat64 63
+#define __NR_getpagesize 64
+#define __NR_msync 65
+#define __NR_vfork 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_mmap 71
+#define __NR_munmap 73
+#define __NR_mprotect 74
+#define __NR_madvise 75
+#define __NR_vhangup 76
+#define __NR_mincore 78
+#define __NR_getgroups 79
+#define __NR_setgroups 80
+#define __NR_getpgrp 81
+#define __NR_setitimer 83
+#define __NR_swapon 85
+#define __NR_getitimer 86
+#define __NR_sethostname 88
+#define __NR_dup2 90
+#define __NR_fcntl 92
+#define __NR_select 93
+#define __NR_fsync 95
+#define __NR_setpriority 96
+#define __NR_socket 97
+#define __NR_connect 98
+#define __NR_accept 99
+#define __NR_getpriority 100
+#define __NR_rt_sigreturn 101
+#define __NR_rt_sigaction 102
+#define __NR_rt_sigprocmask 103
+#define __NR_rt_sigpending 104
+#define __NR_rt_sigtimedwait 105
+#define __NR_rt_sigqueueinfo 106
+#define __NR_rt_sigsuspend 107
+#define __NR_setresuid 108
+#define __NR_getresuid 109
+#define __NR_setresgid 110
+#define __NR_getresgid 111
+#define __NR_recvmsg 113
+#define __NR_sendmsg 114
+#define __NR_gettimeofday 116
+#define __NR_getrusage 117
+#define __NR_getsockopt 118
+#define __NR_getcwd 119
+#define __NR_readv 120
+#define __NR_writev 121
+#define __NR_settimeofday 122
+#define __NR_fchown 123
+#define __NR_fchmod 124
+#define __NR_recvfrom 125
+#define __NR_setreuid 126
+#define __NR_setregid 127
+#define __NR_rename 128
+#define __NR_truncate 129
+#define __NR_ftruncate 130
+#define __NR_flock 131
+#define __NR_lstat64 132
+#define __NR_sendto 133
+#define __NR_shutdown 134
+#define __NR_socketpair 135
+#define __NR_mkdir 136
+#define __NR_rmdir 137
+#define __NR_utimes 138
+#define __NR_stat64 139
+#define __NR_sendfile64 140
+#define __NR_getpeername 141
+#define __NR_futex 142
+#define __NR_gettid 143
+#define __NR_getrlimit 144
+#define __NR_setrlimit 145
+#define __NR_pivot_root 146
+#define __NR_prctl 147
+#define __NR_pciconfig_read 148
+#define __NR_pciconfig_write 149
+#define __NR_getsockname 150
+#define __NR_inotify_init 151
+#define __NR_inotify_add_watch 152
+#define __NR_poll 153
+#define __NR_getdents64 154
+#define __NR_inotify_rm_watch 156
+#define __NR_statfs 157
+#define __NR_fstatfs 158
+#define __NR_umount 159
+#define __NR_sched_set_affinity 160
+#define __NR_sched_get_affinity 161
+#define __NR_getdomainname 162
+#define __NR_setdomainname 163
+#define __NR_utrap_install 164
+#define __NR_quotactl 165
+#define __NR_set_tid_address 166
+#define __NR_mount 167
+#define __NR_ustat 168
+#define __NR_setxattr 169
+#define __NR_lsetxattr 170
+#define __NR_fsetxattr 171
+#define __NR_getxattr 172
+#define __NR_lgetxattr 173
+#define __NR_getdents 174
+#define __NR_setsid 175
+#define __NR_fchdir 176
+#define __NR_fgetxattr 177
+#define __NR_listxattr 178
+#define __NR_llistxattr 179
+#define __NR_flistxattr 180
+#define __NR_removexattr 181
+#define __NR_lremovexattr 182
+#define __NR_query_module 184
+#define __NR_setpgid 185
+#define __NR_fremovexattr 186
+#define __NR_tkill 187
+#define __NR_exit_group 188
+#define __NR_uname 189
+#define __NR_init_module 190
+#define __NR_personality 191
+#define __NR_remap_file_pages 192
+#define __NR_epoll_create 193
+#define __NR_epoll_ctl 194
+#define __NR_epoll_wait 195
+#define __NR_ioprio_set 196
+#define __NR_getppid 197
+#define __NR_sgetmask 199
+#define __NR_ssetmask 200
+#define __NR_oldlstat 202
+#define __NR_uselib 203
+#define __NR_readahead 205
+#define __NR_socketcall 206
+#define __NR_syslog 207
+#define __NR_lookup_dcookie 208
+#define __NR_fadvise64 209
+#define __NR_fadvise64_64 210
+#define __NR_tgkill 211
+#define __NR_waitpid 212
+#define __NR_swapoff 213
+#define __NR_sysinfo 214
+#define __NR_ipc 215
+#define __NR_clone 217
+#define __NR_ioprio_get 218
+#define __NR_adjtimex 219
+#define __NR_create_module 221
+#define __NR_delete_module 222
+#define __NR_get_kernel_syms 223
+#define __NR_getpgid 224
+#define __NR_bdflush 225
+#define __NR_sysfs 226
+#define __NR_afs_syscall 227
+#define __NR_setfsuid 228
+#define __NR_setfsgid 229
+#define __NR__newselect 230
+#define __NR_splice 232
+#define __NR_stime 233
+#define __NR_statfs64 234
+#define __NR_fstatfs64 235
+#define __NR__llseek 236
+#define __NR_mlock 237
+#define __NR_munlock 238
+#define __NR_mlockall 239
+#define __NR_munlockall 240
+#define __NR_sched_setparam 241
+#define __NR_sched_getparam 242
+#define __NR_sched_setscheduler 243
+#define __NR_sched_getscheduler 244
+#define __NR_sched_yield 245
+#define __NR_sched_get_priority_max 246
+#define __NR_sched_get_priority_min 247
+#define __NR_sched_rr_get_interval 248
+#define __NR_nanosleep 249
+#define __NR_mremap 250
+#define __NR__sysctl 251
+#define __NR_getsid 252
+#define __NR_fdatasync 253
+#define __NR_nfsservctl 254
+#define __NR_sync_file_range 255
+#define __NR_clock_settime 256
+#define __NR_clock_gettime 257
+#define __NR_clock_getres 258
+#define __NR_clock_nanosleep 259
+#define __NR_sched_getaffinity 260
+#define __NR_sched_setaffinity 261
+#define __NR_timer_settime 262
+#define __NR_timer_gettime 263
+#define __NR_timer_getoverrun 264
+#define __NR_timer_delete 265
+#define __NR_timer_create 266
+#define __NR_vserver 267
+#define __NR_io_setup 268
+#define __NR_io_destroy 269
+#define __NR_io_submit 270
+#define __NR_io_cancel 271
+#define __NR_io_getevents 272
+#define __NR_mq_open 273
+#define __NR_mq_unlink 274
+#define __NR_mq_timedsend 275
+#define __NR_mq_timedreceive 276
+#define __NR_mq_notify 277
+#define __NR_mq_getsetattr 278
+#define __NR_waitid 279
+#define __NR_tee 280
+#define __NR_add_key 281
+#define __NR_request_key 282
+#define __NR_keyctl 283
+#define __NR_openat 284
+#define __NR_mkdirat 285
+#define __NR_mknodat 286
+#define __NR_fchownat 287
+#define __NR_futimesat 288
+#define __NR_fstatat64 289
+#define __NR_unlinkat 290
+#define __NR_renameat 291
+#define __NR_linkat 292
+#define __NR_symlinkat 293
+#define __NR_readlinkat 294
+#define __NR_fchmodat 295
+#define __NR_faccessat 296
+#define __NR_pselect6 297
+#define __NR_ppoll 298
+#define __NR_unshare 299
+#define __NR_set_robust_list 300
+#define __NR_get_robust_list 301
+#define __NR_migrate_pages 302
+#define __NR_mbind 303
+#define __NR_get_mempolicy 304
+#define __NR_set_mempolicy 305
+#define __NR_kexec_load 306
+#define __NR_move_pages 307
+#define __NR_getcpu 308
+#define __NR_epoll_pwait 309
+#define __NR_utimensat 310
+#define __NR_signalfd 311
+#define __NR_timerfd_create 312
+#define __NR_eventfd 313
+#define __NR_fallocate 314
+#define __NR_timerfd_settime 315
+#define __NR_timerfd_gettime 316
+#define __NR_signalfd4 317
+#define __NR_eventfd2 318
+#define __NR_epoll_create1 319
+#define __NR_dup3 320
+#define __NR_pipe2 321
+#define __NR_inotify_init1 322
+#define __NR_accept4 323
+#define __NR_preadv 324
+#define __NR_pwritev 325
+#define __NR_rt_tgsigqueueinfo 326
+#define __NR_perf_event_open 327
+#define __NR_recvmmsg 328
+#define __NR_fanotify_init 329
+#define __NR_fanotify_mark 330
+#define __NR_prlimit64 331
+#define __NR_name_to_handle_at 332
+#define __NR_open_by_handle_at 333
+#define __NR_clock_adjtime 334
+#define __NR_syncfs 335
+#define __NR_sendmmsg 336
+#define __NR_setns 337
+#define __NR_process_vm_readv 338
+#define __NR_process_vm_writev 339
+#define __NR_kern_features 340
+#define __NR_kcmp 341
+#define __NR_finit_module 342
+#define __NR_sched_setattr 343
+#define __NR_sched_getattr 344
+#define __NR_renameat2 345
+#define __NR_seccomp 346
+#define __NR_getrandom 347
+#define __NR_memfd_create 348
+#define __NR_bpf 349
+#define __NR_execveat 350
+#define __NR_membarrier 351
+#define __NR_userfaultfd 352
+#define __NR_bind 353
+#define __NR_listen 354
+#define __NR_setsockopt 355
+#define __NR_mlock2 356
+#define __NR_copy_file_range 357
+#define __NR_preadv2 358
+#define __NR_pwritev2 359
+#define __NR_statx 360
+#define __NR_io_pgetevents 361
+#define __NR_pkey_mprotect 362
+#define __NR_pkey_alloc 363
+#define __NR_pkey_free 364
+#define __NR_rseq 365
+#define __NR_semtimedop 392
+#define __NR_semget 393
+#define __NR_semctl 394
+#define __NR_shmget 395
+#define __NR_shmctl 396
+#define __NR_shmat 397
+#define __NR_shmdt 398
+#define __NR_msgget 399
+#define __NR_msgsnd 400
+#define __NR_msgrcv 401
+#define __NR_msgctl 402
+#define __NR_pidfd_send_signal 424
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_openat2 437
+#define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
+#define __NR_process_madvise 440
+#define __NR_epoll_pwait2 441
+#define __NR_mount_setattr 442
+#define __NR_quotactl_fd 443
+#define __NR_landlock_create_ruleset 444
+#define __NR_landlock_add_rule 445
+#define __NR_landlock_restrict_self 446
+#define __NR_process_mrelease 448
+#define __NR_futex_waitv 449
+#define __NR_set_mempolicy_home_node 450
+#define __NR_cachestat 451
+#define __NR_fchmodat2 452
+#define __NR_map_shadow_stack 453
+#define __NR_futex_wake 454
+#define __NR_futex_wait 455
+#define __NR_futex_requeue 456
+#define __NR_statmount 457
+#define __NR_listmount 458
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_set_self_attr 460
+#define __NR_lsm_list_modules 461
+#define __NR_mseal 462
+#define __NR_setxattrat 463
+#define __NR_getxattrat 464
+#define __NR_listxattrat 465
+#define __NR_removexattrat 466
+#define __NR_open_tree_attr 467
+#define __NR_file_getattr 468
+#define __NR_file_setattr 469
+#define __NR_listns 470
diff --git a/arch/sparc64/bits/termios.h b/arch/sparc64/bits/termios.h
new file mode 100644
index 00000000..6bdad4a2
--- /dev/null
+++ b/arch/sparc64/bits/termios.h
@@ -0,0 +1,151 @@
+#undef NCCS
+#define NCCS 17
+struct termios {
+ tcflag_t c_iflag;
+ tcflag_t c_oflag;
+ tcflag_t c_cflag;
+ tcflag_t c_lflag;
+ cc_t c_line;
+ cc_t c_cc[NCCS];
+ speed_t __c_ispeed;
+ speed_t __c_ospeed;
+};
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 4
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VDSUSP 11
+#define VEOL 5
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 6
+#define IGNBRK 1
+#define BRKINT 2
+#define IGNPAR 4
+#define PARMRK 8
+#define INPCK 16
+#define ISTRIP 32
+#define INLCR 64
+#define IGNCR 128
+#define ICRNL 256
+#define IUCLC 512
+#define IXON 1024
+#define IXANY 2048
+#define IXOFF 4096
+#define IMAXBEL 8192
+#define IUTF8 16384
+#define OPOST 1
+#define OLCUC 2
+#define ONLCR 4
+#define OCRNL 8
+#define ONOCR 16
+#define ONLRET 32
+#define OFILL 64
+#define OFDEL 128
+#define NLDLY 256
+#define NL0 0
+#define NL1 256
+#define CRDLY 1536
+#define CR0 0
+#define CR1 512
+#define CR2 1024
+#define CR3 1536
+#define TABDLY 6144
+#define TAB0 0
+#define TAB1 2048
+#define TAB2 4096
+#define TAB3 6144
+#define BSDLY 8192
+#define BS0 0
+#define BS1 8192
+#define FFDLY 32768
+#define FF0 0
+#define FF1 32768
+#define VTDLY 16384
+#define VT0 0
+#define VT1 16384
+#define B0 0
+#define B50 1
+#define B75 2
+#define B110 3
+#define B134 4
+#define B150 5
+#define B200 6
+#define B300 7
+#define B600 8
+#define B1200 9
+#define B1800 10
+#define B2400 11
+#define B4800 12
+#define B9600 13
+#define B19200 14
+#define B38400 15
+#define B57600 4097
+#define B76800 4101
+#define B115200 4098
+#define B153600 4102
+#define B230400 4099
+#define B307200 4103
+#define B460800 4100
+#define B500000 4106
+#define B576000 4107
+#define B614400 4104
+#define B921600 4105
+#define B1000000 4108
+#define B1152000 4109
+#define B1500000 4110
+#define B2000000 4111
+#define CSIZE 48
+#define CS5 0
+#define CS6 16
+#define CS7 32
+#define CS8 48
+#define CSTOPB 64
+#define CREAD 128
+#define PARENB 256
+#define PARODD 512
+#define HUPCL 1024
+#define CLOCAL 2048
+#define ISIG 1
+#define ICANON 2
+#define ECHO 8
+#define ECHOE 16
+#define ECHOK 32
+#define ECHONL 64
+#define NOFLSH 128
+#define TOSTOP 256
+#define IEXTEN 32768
+#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
+#define EXTA 14
+#define EXTB 15
+#define CBAUD 4111
+#define CBAUDEX 4096
+#define CIBAUD 269418496
+#define CMSPAR 1073741824
+#define CRTSCTS 2147483648
+#define XCASE 4
+#define ECHOCTL 512
+#define ECHOPRT 1024
+#define ECHOKE 2048
+#define FLUSHO 8192
+#define PENDIN 16384
+#define EXTPROC 65536
+#define XTABS 6144
diff --git a/arch/sparc64/bits/user.h b/arch/sparc64/bits/user.h
new file mode 100644
index 00000000..c0047c70
--- /dev/null
+++ b/arch/sparc64/bits/user.h
@@ -0,0 +1,25 @@
+struct user {
+ struct {
+ unsigned long u_regs[16];
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned int y;
+ unsigned int magic;
+ } 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 36
+typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+typedef struct {
+ unsigned long pr_regs[32];
+ unsigned long pr_fsr;
+ unsigned long pr_gsr;
+ unsigned long pr_fprs;
+} elf_fpregset_t;
diff --git a/arch/sparc64/crt_arch.h b/arch/sparc64/crt_arch.h
new file mode 100644
index 00000000..023f4d9a
--- /dev/null
+++ b/arch/sparc64/crt_arch.h
@@ -0,0 +1,19 @@
+__asm__(
+".text\n"
+".global " START "\n"
+".type " START ",#function\n"
+START ":\n"
+" mov %g0, %fp\n"
+" call 1f\n"
+" nop\n"
+"1: add %o7, 8, %g1\n"
+" ldsw [%g1 + (2f - 1b)], %o1\n"
+" add %g1, %o1, %o1\n"
+" call " START "_c\n"
+" add %sp, 2175, %o0\n"
+" unimp\n"
+" .align 4\n"
+".weak _DYNAMIC\n"
+".hidden _DYNAMIC\n"
+"2: .word _DYNAMIC - 1b\n"
+);
diff --git a/arch/sparc64/ksigaction.h b/arch/sparc64/ksigaction.h
new file mode 100644
index 00000000..ba21964c
--- /dev/null
+++ b/arch/sparc64/ksigaction.h
@@ -0,0 +1,10 @@
+#include <features.h>
+
+struct k_sigaction {
+ void (*handler)(int);
+ unsigned long flags;
+ void (*restorer)(void);
+ unsigned mask[2];
+};
+
+hidden void __restore(), __restore_rt();
diff --git a/arch/sparc64/kstat.h b/arch/sparc64/kstat.h
new file mode 100644
index 00000000..96fa6284
--- /dev/null
+++ b/arch/sparc64/kstat.h
@@ -0,0 +1,23 @@
+struct kstat {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+
+ unsigned st_mode;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned __pad0;
+
+ unsigned long st_rdev;
+ long st_size;
+ long st_blksize;
+ long st_blocks;
+
+ unsigned long st_atime_sec;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime_sec;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime_sec;
+ unsigned long st_ctime_nsec;
+ long __unused[3];
+};
diff --git a/arch/sparc64/pthread_arch.h b/arch/sparc64/pthread_arch.h
new file mode 100644
index 00000000..5092c077
--- /dev/null
+++ b/arch/sparc64/pthread_arch.h
@@ -0,0 +1,10 @@
+static inline uintptr_t __get_tp()
+{
+ uintptr_t tp;
+ __asm__ __volatile__ ("mov %%g7, %0" : "=r"(tp));
+ return tp;
+}
+
+#define MC_PC mc_pc
+
+#define MC_NPC mc_npc
diff --git a/arch/sparc64/reloc.h b/arch/sparc64/reloc.h
new file mode 100644
index 00000000..527dbb05
--- /dev/null
+++ b/arch/sparc64/reloc.h
@@ -0,0 +1,69 @@
+#include <elf.h>
+
+#define LDSO_ARCH "sparc64"
+
+#define REL_SYMBOLIC R_SPARC_64
+#define REL_USYMBOLIC R_SPARC_UA64
+#define REL_GOT R_SPARC_GLOB_DAT
+#define REL_PLT R_SPARC_JMP_SLOT
+#define REL_RELATIVE R_SPARC_RELATIVE
+#define REL_COPY R_SPARC_COPY
+#define REL_DTPMOD R_SPARC_TLS_DTPMOD64
+#define REL_DTPOFF R_SPARC_TLS_DTPOFF64
+#define REL_TPOFF R_SPARC_TLS_TPOFF64
+
+#define CRTJMP(pc,sp) __asm__ __volatile__( \
+ "sub %1,2175,%%sp ; jmpl %0,%%g0 ; nop" : : "r"(pc), "r"(sp) : "memory" )
+
+#define _SP_SETHI(rd, imm22) (0x01000000u | ((unsigned)(rd) << 25) \
+ | ((unsigned)(imm22) & 0x3fffffu))
+#define _SP_ORI(rs1, imm13, rd) (0x80102000u | ((unsigned)(rd) << 25) \
+ | ((unsigned)(rs1) << 14) \
+ | ((unsigned)(imm13) & 0x1fffu))
+#define _SP_OR(rs1, rs2, rd) (0x80100000u | ((unsigned)(rd) << 25) \
+ | ((unsigned)(rs1) << 14) | (unsigned)(rs2))
+#define _SP_SLLX(rs1, imm6, rd) (0x81283000u | ((unsigned)(rd) << 25) \
+ | ((unsigned)(rs1) << 14) \
+ | ((unsigned)(imm6) & 0x3fu))
+#define _SP_JMPL(rs1, imm13, rd) (0x81c02000u | ((unsigned)(rd) << 25) \
+ | ((unsigned)(rs1) << 14) \
+ | ((unsigned)(imm13) & 0x1fffu))
+#define _SP_NOP 0x01000000u
+
+#define _SP_G0 0
+#define _SP_G1 1
+#define _SP_G5 5
+
+#define ARCH_LOCAL_SYM_IS_BASE 1
+#define ARCH_PLT_WRITE 1
+
+static inline void arch_plt_write(volatile void *p, size_t val,
+ size_t addend, unsigned char *base)
+{
+ volatile unsigned *insn = p;
+
+ /* JMP_SLOTs from the 32768th PLT entry on carry a nonzero addend
+ * and target a data word holding the entry's displacement to the
+ * symbol */
+ if (addend) {
+ *(volatile size_t *)p = val - (size_t)base;
+ return;
+ }
+
+ unsigned hh = (unsigned)(val >> 42);
+ unsigned hm = (unsigned)((val >> 32) & 0x3ff);
+ unsigned lm = (unsigned)((val >> 10) & 0x3fffff);
+ unsigned lo = (unsigned)(val & 0x3ff);
+
+ insn[0] = _SP_SETHI(_SP_G1, hh);
+ insn[1] = _SP_ORI(_SP_G1, hm, _SP_G1);
+ insn[2] = _SP_SLLX(_SP_G1, 32, _SP_G1);
+ insn[3] = _SP_SETHI(_SP_G5, lm);
+ insn[4] = _SP_OR(_SP_G1, _SP_G5, _SP_G1);
+ insn[5] = _SP_JMPL(_SP_G1, lo, _SP_G0);
+ insn[6] = _SP_NOP;
+
+ /* flush acts on the doubleword it addresses */
+ for (int i = 0; i < 32; i += 8)
+ __asm__ __volatile__ ("flush %0" :: "r"((char *)p + i) : "memory");
+}
diff --git a/arch/sparc64/syscall_arch.h b/arch/sparc64/syscall_arch.h
new file mode 100644
index 00000000..c6dcdf67
--- /dev/null
+++ b/arch/sparc64/syscall_arch.h
@@ -0,0 +1,134 @@
+#define __SYSCALL_LL_E(x) (x)
+#define __SYSCALL_LL_O(x) (x)
+
+/* ta 0x6d traps to the kernel; the syscall number goes in %g1, and an
+ * error is the carry flag set with a positive errno in %o0, negated below.
+ * Other registers survive the trap except %o1, a second return value
+ * for fork, vfork, clone and pipe. */
+static __inline long __syscall0(long n)
+{
+ register long g1 __asm__("g1") = n;
+ register long o0 __asm__("o0");
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %1 ; movcs %%xcc, 1, %1"
+ : "=r"(o0), "=&r"(err)
+ : "r"(g1)
+ : "memory", "cc", "o1");
+ return err ? -o0 : o0;
+}
+
+static __inline long __syscall1(long n, long a)
+{
+ register long g1 __asm__("g1") = n;
+ register long o0 __asm__("o0") = a;
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %1 ; movcs %%xcc, 1, %1"
+ : "+r"(o0), "=&r"(err)
+ : "r"(g1)
+ : "memory", "cc", "o1");
+ return err ? -o0 : o0;
+}
+
+static __inline long __syscall2(long n, long a, long b)
+{
+ register long g1 __asm__("g1") = n;
+ register long o0 __asm__("o0") = a;
+ register long o1 __asm__("o1") = b;
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %2 ; movcs %%xcc, 1, %2"
+ : "+r"(o0), "+r"(o1), "=&r"(err)
+ : "r"(g1)
+ : "memory", "cc");
+ return err ? -o0 : o0;
+}
+
+static __inline long __syscall3(long n, long a, long b, long c)
+{
+ register long g1 __asm__("g1") = n;
+ register long o0 __asm__("o0") = a;
+ register long o1 __asm__("o1") = b;
+ register long o2 __asm__("o2") = c;
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %2 ; movcs %%xcc, 1, %2"
+ : "+r"(o0), "+r"(o1), "=&r"(err)
+ : "r"(g1), "r"(o2)
+ : "memory", "cc");
+ return err ? -o0 : o0;
+}
+
+static __inline long __syscall4(long n, long a, long b, long c, long d)
+{
+ register long g1 __asm__("g1") = n;
+ register long o0 __asm__("o0") = a;
+ register long o1 __asm__("o1") = b;
+ register long o2 __asm__("o2") = c;
+ register long o3 __asm__("o3") = d;
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %2 ; movcs %%xcc, 1, %2"
+ : "+r"(o0), "+r"(o1), "=&r"(err)
+ : "r"(g1), "r"(o2), "r"(o3)
+ : "memory", "cc");
+ return err ? -o0 : o0;
+}
+
+static __inline long __syscall5(long n, long a, long b, long c, long d, long e)
+{
+ register long g1 __asm__("g1") = n;
+ register long o0 __asm__("o0") = a;
+ register long o1 __asm__("o1") = b;
+ register long o2 __asm__("o2") = c;
+ register long o3 __asm__("o3") = d;
+ register long o4 __asm__("o4") = e;
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %2 ; movcs %%xcc, 1, %2"
+ : "+r"(o0), "+r"(o1), "=&r"(err)
+ : "r"(g1), "r"(o2), "r"(o3), "r"(o4)
+ : "memory", "cc");
+ return err ? -o0 : o0;
+}
+
+static __inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
+{
+ register long g1 __asm__("g1") = n;
+ register long o0 __asm__("o0") = a;
+ register long o1 __asm__("o1") = b;
+ register long o2 __asm__("o2") = c;
+ register long o3 __asm__("o3") = d;
+ register long o4 __asm__("o4") = e;
+ register long o5 __asm__("o5") = f;
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %2 ; movcs %%xcc, 1, %2"
+ : "+r"(o0), "+r"(o1), "=&r"(err)
+ : "r"(g1), "r"(o2), "r"(o3), "r"(o4), "r"(o5)
+ : "memory", "cc");
+ return err ? -o0 : o0;
+}
+
+#define SYSCALL_CLONE_SUNOS 1
+#define SYSCALL_IPC_SEMUN_DIRECT 1
+#define SYSCALL_IPC_MSGRCV_DIRECT 1
+#define SYSCALL_RT_SIGACTION_RESTORER 1
+
+static __inline long __syscall_clone_sunos(long flags, long stack)
+{
+ register long g1 __asm__("g1") = SYS_clone;
+ register long o0 __asm__("o0") = flags;
+ register long o1 __asm__("o1") = stack;
+ long err;
+ __asm__ __volatile__ ("ta 0x6d ; mov 0, %2 ; movcs %%xcc, 1, %2"
+ : "+r"(o0), "+r"(o1), "=&r"(err)
+ : "r"(g1)
+ : "memory", "cc");
+ /* copy_thread() gives the child %o1 = 1 and the parent's pid in %o0 */
+ if (err) return -o0;
+ if (o1) return 0;
+ return o0;
+}
+
+#define SO_RCVTIMEO_OLD 8192
+#define SO_SNDTIMEO_OLD 16384
+#define SO_TIMESTAMP_OLD 29
+#define SO_TIMESTAMPNS_OLD 33
+#define SO_TIMESTAMPING_OLD 35
+
+#define KERNEL_SUSECONDS_IS_INT 1
diff --git a/configure b/configure
index bc9fbe48..9d7ee892 100755
--- a/configure
+++ b/configure
@@ -340,6 +340,7 @@ riscv64*) ARCH=riscv64 ;;
riscv32*) ARCH=riscv32 ;;
sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
s390x*) ARCH=s390x ;;
+sparc64*) ARCH=sparc64 ;;
unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
*) fail "$0: unknown or unsupported target \"$target\"" ;;
esac
@@ -756,6 +757,10 @@ SUBARCH=${SUBARCH}-fdpic
fi
fi
+if test "$ARCH" = "sparc64" ; then
+trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on $ARCH"
+fi
+
test "$SUBARCH" \
&& printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH"
diff --git a/src/fenv/sparc64/fenv.c b/src/fenv/sparc64/fenv.c
new file mode 100644
index 00000000..84847bf2
--- /dev/null
+++ b/src/fenv/sparc64/fenv.c
@@ -0,0 +1,58 @@
+#include <fenv.h>
+
+#define _FE_RD_SHIFT 30
+#define _FE_RD_MASK (3UL << _FE_RD_SHIFT)
+
+static inline unsigned long get_fsr(void)
+{
+ unsigned long fsr;
+ __asm__ __volatile__ ("stx %%fsr, %0" : "=m"(fsr));
+ return fsr;
+}
+
+static inline void set_fsr(unsigned long fsr)
+{
+ __asm__ __volatile__ ("ldx %0, %%fsr" : : "m"(fsr));
+}
+
+int feclearexcept(int mask)
+{
+ mask &= FE_ALL_EXCEPT;
+ set_fsr(get_fsr() & ~(unsigned long)mask);
+ return 0;
+}
+
+int feraiseexcept(int mask)
+{
+ mask &= FE_ALL_EXCEPT;
+ set_fsr(get_fsr() | (unsigned long)mask);
+ return 0;
+}
+
+int fetestexcept(int mask)
+{
+ return get_fsr() & mask & FE_ALL_EXCEPT;
+}
+
+int fegetround(void)
+{
+ return (get_fsr() >> _FE_RD_SHIFT) & 3;
+}
+
+int __fesetround(int r)
+{
+ set_fsr((get_fsr() & ~_FE_RD_MASK) | ((unsigned long)r << _FE_RD_SHIFT));
+ return 0;
+}
+
+int fegetenv(fenv_t *envp)
+{
+ *envp = get_fsr();
+ return 0;
+}
+
+int fesetenv(const fenv_t *envp)
+{
+ set_fsr(envp == FE_DFL_ENV ? 0 : *envp);
+ return 0;
+}
diff --git a/src/ldso/sparc64/dlsym.s b/src/ldso/sparc64/dlsym.s
new file mode 100644
index 00000000..e6ba5a06
--- /dev/null
+++ b/src/ldso/sparc64/dlsym.s
@@ -0,0 +1,8 @@
+ .text
+ .global dlsym
+ .hidden __dlsym
+ .type dlsym,#function
+dlsym:
+ ba __dlsym
+ mov %o7, %o2
+ .size dlsym, .-dlsym
diff --git a/src/math/sparc64/qp.c b/src/math/sparc64/qp.c
new file mode 100644
index 00000000..704850ab
--- /dev/null
+++ b/src/math/sparc64/qp.c
@@ -0,0 +1,231 @@
+/* gcc lowers sparc64 long double arithmetic and conversions to these
+ * _Qp_* calls; libgcc references them but does not define them. */
+
+static inline unsigned long get_fsr(void)
+{
+ unsigned long x;
+ __asm__ __volatile__ ("stx %%fsr, %0" : "=m"(x));
+ return x;
+}
+
+static inline void set_fsr(unsigned long x)
+{
+ __asm__ __volatile__ ("ldx %0, %%fsr" : : "m"(x));
+}
+
+#include "quad.h"
+#include "../sqrt_data.h"
+
+/* see sqrtl.c */
+static int qsqrt(u128 *r, u128 a, int rd)
+{
+ u128 ml;
+ int e, even;
+
+ if (isnan_q(a))
+ return qnan2(r, a, a);
+ if (iszero_q(a) || (isinf_q(a) && !(a.hi>>63))) {
+ *r = a;
+ return 0;
+ }
+ if (a.hi>>63) {
+ *r = qnan_default;
+ return NV;
+ }
+ e = qnorm(a, &ml);
+
+ /* x = 4^e m; with int e and m in [1, 4) */
+ even = !(e & 1);
+ uint64_t i = (uint64_t)even<<6 | ml.hi>>57 & 63;
+ if (even)
+ ml = rsh(ml, 1);
+ e = (e - !even) / 2;
+
+ /* r ~ 1/sqrt(m) */
+ const uint64_t three = 0xc0000000;
+ uint64_t r0, s, d, u;
+ r0 = (uint32_t)__rsqrt_tab[i] << 16;
+ /* |r sqrt(m) - 1| < 0x1p-8 */
+ s = mul32(ml.hi>>32, r0);
+ d = mul32(s, r0);
+ u = three - d;
+ r0 = mul32(u, r0) << 1;
+ /* |r sqrt(m) - 1| < 0x1.7bp-16, switch to 64bit */
+ r0 = r0<<32;
+ s = mul64(ml.hi, r0);
+ d = mul64(s, r0);
+ u = (three<<32) - d;
+ r0 = mul64(u, r0) << 1;
+ /* |r sqrt(m) - 1| < 0x1.a5p-31 */
+ s = mul64(u, s) << 1;
+ d = mul64(s, r0);
+ u = (three<<32) - d;
+ r0 = mul64(u, r0) << 1;
+ /* |r sqrt(m) - 1| < 0x1.c001p-59, switch to 128bit */
+
+ const u128 threel = {.hi=three<<32, .lo=0};
+ u128 rl, sl, dl, ul;
+ rl.hi = r0;
+ rl.lo = 0;
+ sl = mul128(ml, rl);
+ dl = mul128(sl, rl);
+ ul = sub128(threel, dl);
+ sl = mul128(ul, sl); /* repr: 3.125 */
+ /* -0x1p-116 < s - sqrt(m) < 0x3.8001p-125 */
+ sl = rsh(sub64(sl, 4), 125-112);
+ /* s < sqrt(m) < s + 1 ULP + tiny */
+
+ u128 d2, d1, d0;
+ d0 = sub128(lsh(ml, 2*112-126), mul128_tail(sl,sl));
+ d1 = sub128(sl, d0);
+ d2 = add128(add64(sl, 1), d1);
+ /* d2 = (s+1)^2 - m: round from s+1 if sqrt(m) >= s+1, else from s
+ * with the half ULP bit taken from the sign of d1 = (s+1/2)^2 - m - 1/4 */
+ if (d2.hi>>63 || iszero(d2)) {
+ ml = lsh(add64(sl, 1), 15);
+ ml.lo |= !iszero(d2);
+ } else {
+ ml = lsh(sl, 15);
+ ml.lo |= d1.hi>>63<<14 | 1;
+ }
+ return qround(r, 0, e, ml, 113, 15, rd);
+}
+
+void _Qp_add(long double *c, const long double *a, const long double *b)
+{
+ *c = qf(qop(qadd, a, b));
+}
+
+void _Qp_sub(long double *c, const long double *a, const long double *b)
+{
+ *c = qf(qop(qsub, a, b));
+}
+
+void _Qp_mul(long double *c, const long double *a, const long double *b)
+{
+ *c = qf(qop(qmul, a, b));
+}
+
+void _Qp_div(long double *c, const long double *a, const long double *b)
+{
+ *c = qf(qop(qdiv, a, b));
+}
+
+void _Qp_sqrt(long double *c, const long double *a)
+{
+ unsigned long fsr = get_fsr();
+ u128 r;
+ qexc(fsr, qsqrt(&r, ld(a), fsr>>30 & 3));
+ *c = qf(r);
+}
+
+void _Qp_neg(long double *c, const long double *a)
+{
+ u128 r = ld(a);
+ r.hi ^= 1ULL<<63;
+ *c = qf(r);
+}
+
+int _Qp_feq(const long double *a, const long double *b)
+{
+ return cmp(a, b, 0) == 0;
+}
+
+int _Qp_fne(const long double *a, const long double *b)
+{
+ return cmp(a, b, 0) != 0;
+}
+
+int _Qp_flt(const long double *a, const long double *b)
+{
+ return cmp(a, b, 1) == 1;
+}
+
+int _Qp_fle(const long double *a, const long double *b)
+{
+ return cmp(a, b, 1) < 2;
+}
+
+int _Qp_fgt(const long double *a, const long double *b)
+{
+ return cmp(a, b, 1) == 2;
+}
+
+int _Qp_fge(const long double *a, const long double *b)
+{
+ return (cmp(a, b, 1) & 1) == 0;
+}
+
+int _Qp_cmp(const long double *a, const long double *b)
+{
+ return cmp(a, b, 0);
+}
+
+int _Qp_cmpe(const long double *a, const long double *b)
+{
+ return cmp(a, b, 1);
+}
+
+void _Qp_itoq(long double *c, int a)
+{
+ *c = qf(qfromint(a < 0, a < 0 ? -(uint64_t)a : a));
+}
+
+void _Qp_uitoq(long double *c, unsigned a)
+{
+ *c = qf(qfromint(0, a));
+}
+
+void _Qp_xtoq(long double *c, long a)
+{
+ *c = qf(qfromint(a < 0, a < 0 ? -(uint64_t)a : a));
+}
+
+void _Qp_uxtoq(long double *c, unsigned long a)
+{
+ *c = qf(qfromint(0, a));
+}
+
+void _Qp_stoq(long double *c, float a)
+{
+ union { float f; uint32_t i; } u = {a};
+ *c = qf(fromflt(u.i, 24, 8));
+}
+
+void _Qp_dtoq(long double *c, double a)
+{
+ union { double f; uint64_t i; } u = {a};
+ *c = qf(fromflt(u.i, 53, 11));
+}
+
+int _Qp_qtoi(const long double *a)
+{
+ return toint(a, 32, 1);
+}
+
+unsigned _Qp_qtoui(const long double *a)
+{
+ return toint(a, 32, 0);
+}
+
+long _Qp_qtox(const long double *a)
+{
+ return toint(a, 64, 1);
+}
+
+unsigned long _Qp_qtoux(const long double *a)
+{
+ return toint(a, 64, 0);
+}
+
+float _Qp_qtos(const long double *a)
+{
+ union { uint32_t i; float f; } u = {toflt(a, 24, 8)};
+ return u.f;
+}
+
+double _Qp_qtod(const long double *a)
+{
+ union { uint64_t i; double f; } u = {toflt(a, 53, 11)};
+ return u.f;
+}
diff --git a/src/math/sparc64/quad.h b/src/math/sparc64/quad.h
new file mode 100644
index 00000000..e0dcd0ad
--- /dev/null
+++ b/src/math/sparc64/quad.h
@@ -0,0 +1,580 @@
+/* IEEE binary128 arithmetic for the SPARC quad helpers, with rounding
+ * mode, exceptions and NaN results as the hardware quad FPops define
+ * them. The including file provides get_fsr and set_fsr. */
+
+#include <features.h>
+#include <stdint.h>
+#include "atomic.h"
+
+#define NX 1
+#define DZ 2
+#define UF 4
+#define OF 8
+#define NV 16
+/* tiny before rounding: traps with UFM set even when exact */
+#define TINY 32
+
+typedef struct {
+ uint64_t hi;
+ uint64_t lo;
+} u128;
+
+static const u128 qnan_default = {0x7fffffffffffffff, -1};
+
+/* returns a*b*2^-32 - e, with error 0 <= e < 1. */
+static inline uint32_t mul32(uint32_t a, uint32_t b)
+{
+ return (uint64_t)a*b >> 32;
+}
+
+/* returns a*b*2^-64 - e, with error 0 <= e < 3. */
+static inline uint64_t mul64(uint64_t a, uint64_t b)
+{
+ uint64_t ahi = a>>32;
+ uint64_t alo = a&0xffffffff;
+ uint64_t bhi = b>>32;
+ uint64_t blo = b&0xffffffff;
+ return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32);
+}
+
+static inline u128 add64(u128 a, uint64_t b)
+{
+ u128 r;
+ r.lo = a.lo + b;
+ r.hi = a.hi;
+ if (r.lo < a.lo)
+ r.hi++;
+ return r;
+}
+
+static inline u128 add128(u128 a, u128 b)
+{
+ u128 r;
+ r.lo = a.lo + b.lo;
+ r.hi = a.hi + b.hi;
+ if (r.lo < a.lo)
+ r.hi++;
+ return r;
+}
+
+static inline u128 sub64(u128 a, uint64_t b)
+{
+ u128 r;
+ r.lo = a.lo - b;
+ r.hi = a.hi;
+ if (a.lo < b)
+ r.hi--;
+ return r;
+}
+
+static inline u128 sub128(u128 a, u128 b)
+{
+ u128 r;
+ r.lo = a.lo - b.lo;
+ r.hi = a.hi - b.hi;
+ if (a.lo < b.lo)
+ r.hi--;
+ return r;
+}
+
+/* a<<n, 0 <= n <= 127 */
+static inline u128 lsh(u128 a, int n)
+{
+ if (n == 0)
+ return a;
+ if (n >= 64) {
+ a.hi = a.lo<<(n-64);
+ a.lo = 0;
+ } else {
+ a.hi = (a.hi<<n) | (a.lo>>(64-n));
+ a.lo = a.lo<<n;
+ }
+ return a;
+}
+
+/* a>>n, 0 <= n <= 127 */
+static inline u128 rsh(u128 a, int n)
+{
+ if (n == 0)
+ return a;
+ if (n >= 64) {
+ a.lo = a.hi>>(n-64);
+ a.hi = 0;
+ } else {
+ a.lo = (a.lo>>n) | (a.hi<<(64-n));
+ a.hi = a.hi>>n;
+ }
+ return a;
+}
+
+/* returns a*b exactly. */
+static inline u128 mul64_128(uint64_t a, uint64_t b)
+{
+ u128 r;
+ uint64_t ahi = a>>32;
+ uint64_t alo = a&0xffffffff;
+ uint64_t bhi = b>>32;
+ uint64_t blo = b&0xffffffff;
+ uint64_t lo1 = ((ahi*blo)&0xffffffff) + ((alo*bhi)&0xffffffff) + (alo*blo>>32);
+ uint64_t lo2 = (alo*blo)&0xffffffff;
+ r.hi = ahi*bhi + (ahi*blo>>32) + (alo*bhi>>32) + (lo1>>32);
+ r.lo = (lo1<<32) + lo2;
+ return r;
+}
+
+/* returns a*b*2^-128 - e, with error 0 <= e < 7. */
+static inline u128 mul128(u128 a, u128 b)
+{
+ u128 hi = mul64_128(a.hi, b.hi);
+ uint64_t m1 = mul64(a.hi, b.lo);
+ uint64_t m2 = mul64(a.lo, b.hi);
+ return add64(add64(hi, m1), m2);
+}
+
+/* returns a*b % 2^128. */
+static inline u128 mul128_tail(u128 a, u128 b)
+{
+ u128 lo = mul64_128(a.lo, b.lo);
+ lo.hi += a.hi*b.lo + a.lo*b.hi;
+ return lo;
+}
+
+static inline int lt128(u128 a, u128 b)
+{
+ return a.hi < b.hi || (a.hi == b.hi && a.lo < b.lo);
+}
+
+static inline int iszero(u128 a)
+{
+ return !(a.hi | a.lo);
+}
+
+static inline int clz128(u128 a)
+{
+ return a.hi ? a_clz_64(a.hi) : 64 + a_clz_64(a.lo);
+}
+
+/* a>>n with the bits shifted out ORed into bit 0 */
+static inline u128 srj(u128 a, int n)
+{
+ u128 r = {0, !iszero(a)};
+ if (n == 0)
+ return a;
+ if (n < 128) {
+ r = rsh(a, n);
+ r.lo |= !iszero(lsh(a, 128-n));
+ }
+ return r;
+}
+
+static inline int isinf_q(u128 a)
+{
+ return (a.hi<<1) == 0xfffe000000000000 && !a.lo;
+}
+
+static inline int isnan_q(u128 a)
+{
+ return (a.hi<<1 >> 49) == 0x7fff && (a.hi<<16 | a.lo);
+}
+
+static inline int issnan_q(u128 a)
+{
+ return isnan_q(a) && !(a.hi>>47 & 1);
+}
+
+static inline int iszero_q(u128 a)
+{
+ return !(a.hi<<1 | a.lo);
+}
+
+/* exponent of the leading bit of finite nonzero a; *m gets the
+ * significand with that bit at bit 127 */
+static inline int qnorm(u128 a, u128 *m)
+{
+ int e = a.hi>>48 & 0x7fff, n;
+ a.hi &= 0xffffffffffff;
+ if (e)
+ a.hi |= 1ULL<<48;
+ else
+ e = 1;
+ a = lsh(a, 15);
+ n = clz128(a);
+ *m = lsh(a, n);
+ return e - 16383 - n;
+}
+
+static inline u128 or128(u128 a, u128 b)
+{
+ a.hi |= b.hi;
+ a.lo |= b.lo;
+ return a;
+}
+
+/* the sign bit of a format with p significand and ebits exponent bits */
+static inline u128 qsign(int s, int p, int ebits)
+{
+ return lsh((u128){0, s}, p+ebits-1);
+}
+
+/* a signed infinity, or the largest finite value when inf is 0 */
+static inline u128 qhuge(int s, int p, int ebits, int inf)
+{
+ u128 r = lsh((u128){0, (2ULL<<(ebits-1)) - 1}, p-1);
+ if (!inf)
+ r = sub64(r, 1);
+ return or128(r, qsign(s, p, ebits));
+}
+
+/* round (-1)^s * m * 2^(e-127), m with its top bit set and bit 0 sticky,
+ * to a format with p significand and ebits exponent bits */
+static int qround(u128 *r, int s, int e, u128 m, int p, int ebits, int rd)
+{
+ int emax = (1<<(ebits-1)) - 1, sh = 128 - p, ex = 0, inc, g;
+
+ if (e < 1 - emax) {
+ sh += 1 - emax - e;
+ e = 1 - emax;
+ ex = TINY;
+ }
+ m = srj(m, sh - 2);
+ g = m.lo & 3;
+ m = rsh(m, 2);
+ if (g)
+ ex |= ex ? NX|UF : NX;
+ switch (rd) {
+ case 0: inc = g>>1 && (g&1 || m.lo&1); break;
+ case 1: inc = 0; break;
+ case 2: inc = g && !s; break;
+ default: inc = g && s;
+ }
+ m = add64(m, inc);
+ /* a carry out of the significand increments the exponent */
+ m = add128(m, lsh((u128){0, e + emax - 1}, p-1));
+ if (rsh(m, p-1).lo >= 2*emax+1) {
+ *r = qhuge(s, p, ebits, rd == 0 || rd == 2+s);
+ return OF|NX;
+ }
+ *r = or128(m, qsign(s, p, ebits));
+ return ex;
+}
+
+static int qnan2(u128 *r, u128 a, u128 b)
+{
+ *r = isnan_q(b) && (issnan_q(b) || !issnan_q(a)) ? b : a;
+ r->hi |= 1ULL<<47;
+ return issnan_q(a) || issnan_q(b) ? NV : 0;
+}
+
+static int qadd(u128 *r, u128 a, u128 b, int rd)
+{
+ int sa = a.hi>>63, sb = b.hi>>63, ea, eb, n;
+ u128 ma, mb, t;
+
+ if (isnan_q(a) || isnan_q(b))
+ return qnan2(r, a, b);
+ if (isinf_q(a)) {
+ if (isinf_q(b) && sa != sb) {
+ *r = qnan_default;
+ return NV;
+ }
+ *r = a;
+ return 0;
+ }
+ if (isinf_q(b) || iszero_q(a)) {
+ *r = b;
+ if (iszero_q(b) && sa != sb)
+ r->hi = (uint64_t)(rd == 3)<<63;
+ return 0;
+ }
+ if (iszero_q(b)) {
+ *r = a;
+ return 0;
+ }
+ ma = a, mb = b;
+ ma.hi &= -1ULL>>1;
+ mb.hi &= -1ULL>>1;
+ if (lt128(ma, mb)) {
+ t = a, a = b, b = t;
+ n = sa, sa = sb, sb = n;
+ }
+ ea = qnorm(a, &ma);
+ eb = qnorm(b, &mb);
+ ma = rsh(ma, 1);
+ mb = srj(rsh(mb, 1), ea - eb);
+ if (sa == sb) {
+ ma = add128(ma, mb);
+ } else {
+ ma = sub128(ma, mb);
+ if (iszero(ma)) {
+ *r = (u128){(uint64_t)(rd == 3)<<63, 0};
+ return 0;
+ }
+ }
+ n = clz128(ma);
+ return qround(r, sa, ea + 1 - n, lsh(ma, n), 113, 15, rd);
+}
+
+static int qmul(u128 *r, u128 a, u128 b, int rd)
+{
+ int s = (a.hi ^ b.hi)>>63, e;
+ u128 ma, mb, hh, hl, lh, ll, mid;
+
+ if (isnan_q(a) || isnan_q(b))
+ return qnan2(r, a, b);
+ if (isinf_q(a) || isinf_q(b)) {
+ if (iszero_q(a) || iszero_q(b)) {
+ *r = qnan_default;
+ return NV;
+ }
+ *r = qhuge(s, 113, 15, 1);
+ return 0;
+ }
+ if (iszero_q(a) || iszero_q(b)) {
+ *r = qsign(s, 113, 15);
+ return 0;
+ }
+ e = qnorm(a, &ma) + qnorm(b, &mb) + 1;
+ /* 256-bit product: high half in hh, low half in ll */
+ hh = mul64_128(ma.hi, mb.hi);
+ hl = mul64_128(ma.hi, mb.lo);
+ lh = mul64_128(ma.lo, mb.hi);
+ ll = mul64_128(ma.lo, mb.lo);
+ mid = add128(hl, lh);
+ if (lt128(mid, hl))
+ hh.hi++;
+ ll.hi += mid.lo;
+ hh = add64(add64(hh, mid.hi), ll.hi < mid.lo);
+ if (!(hh.hi>>63)) {
+ hh = lsh(hh, 1);
+ hh.lo |= ll.hi>>63;
+ ll = lsh(ll, 1);
+ e--;
+ }
+ hh.lo |= !iszero(ll);
+ return qround(r, s, e, hh, 113, 15, rd);
+}
+
+static int qdiv(u128 *r, u128 a, u128 b, int rd)
+{
+ int s = (a.hi ^ b.hi)>>63, e, i, n;
+ u128 ma, mb, q = {0, 0};
+
+ if (isnan_q(a) || isnan_q(b))
+ return qnan2(r, a, b);
+ if (isinf_q(a) || iszero_q(b)) {
+ if (isinf_q(b) || iszero_q(a)) {
+ *r = qnan_default;
+ return NV;
+ }
+ *r = qhuge(s, 113, 15, 1);
+ return isinf_q(a) ? 0 : DZ;
+ }
+ if (isinf_q(b) || iszero_q(a)) {
+ *r = qsign(s, 113, 15);
+ return 0;
+ }
+ e = qnorm(a, &ma) - qnorm(b, &mb);
+ ma = rsh(ma, 1);
+ mb = rsh(mb, 1);
+ for (i = 0; i < 116; i++) {
+ q = lsh(q, 1);
+ if (!lt128(ma, mb)) {
+ ma = sub128(ma, mb);
+ q.lo |= 1;
+ }
+ ma = lsh(ma, 1);
+ }
+ q.lo |= !iszero(ma);
+ n = clz128(q);
+ return qround(r, s, e - n + 12, lsh(q, n), 113, 15, rd);
+}
+
+/* *c: 0 equal, 1 less, 2 greater, 3 unordered */
+static int qcmp(int *c, u128 a, u128 b, int sig)
+{
+ int sa = a.hi>>63;
+
+ if (isnan_q(a) || isnan_q(b)) {
+ *c = 3;
+ return sig || issnan_q(a) || issnan_q(b) ? NV : 0;
+ }
+ if (iszero_q(a) && iszero_q(b))
+ *c = 0;
+ else if (sa != b.hi>>63)
+ *c = 2 - sa;
+ else if (a.hi == b.hi && a.lo == b.lo)
+ *c = 0;
+ else
+ *c = lt128(a, b) ^ sa ? 1 : 2;
+ return 0;
+}
+
+static u128 qfromint(int s, uint64_t v)
+{
+ int n;
+ u128 r = {0, 0};
+
+ if (v) {
+ n = a_clz_64(v);
+ r = lsh((u128){0, v}, 49 + n);
+ r.hi &= 0xffffffffffff;
+ r.hi |= (uint64_t)s<<63 | (uint64_t)(16383 + 63 - n)<<48;
+ }
+ return r;
+}
+
+/* truncate to a bits wide integer, signed when sgn */
+static int qtoint(uint64_t *r, u128 a, int bits, int sgn)
+{
+ int s = a.hi>>63, e = (a.hi>>48 & 0x7fff) - 16383, ex = 0;
+ uint64_t v = 0, lim = sgn ? (1ULL<<(bits-1)) - !s : s ? 0 : (2ULL<<(bits-1)) - 1;
+ u128 m = a;
+
+ m.hi = (m.hi & 0xffffffffffff) | 1ULL<<48;
+ if (e < 0) {
+ ex = iszero_q(a) ? 0 : NX;
+ } else if (e < 64) {
+ v = rsh(m, 112 - e).lo;
+ ex = iszero(lsh(m, 16 + e)) ? 0 : NX;
+ }
+ if (e >= 64 || v > lim) {
+ v = sgn || !s ? lim : 0;
+ ex = NV;
+ }
+ *r = sgn && s ? -v : v;
+ return ex;
+}
+
+/* convert a narrower format with p significand and ebits exponent bits */
+static int qwiden(u128 *r, uint64_t x, int p, int ebits)
+{
+ int emax = (1<<(ebits-1)) - 1, ex = 0, n;
+ int e = x>>(p-1) & (2*emax+1);
+ uint64_t f = x & ((1ULL<<(p-1)) - 1);
+
+ if (e == 2*emax+1) {
+ e = 0x7fff;
+ if (f && !(f>>(p-2) & 1))
+ ex = NV;
+ if (f)
+ f |= 1ULL<<(p-2);
+ } else if (e) {
+ e += 16383 - emax;
+ } else if (f) {
+ n = a_clz_64(f) - (64 - p);
+ f = f<<n & ((1ULL<<(p-1)) - 1);
+ e = 16383 - emax + 1 - n;
+ }
+ *r = lsh((u128){0, f}, 113 - p);
+ r->hi |= (uint64_t)(x>>(p+ebits-1) & 1)<<63 | (uint64_t)e<<48;
+ return ex;
+}
+
+/* round to a narrower format with p significand and ebits exponent bits */
+static int qnarrow(uint64_t *r, u128 a, int p, int ebits, int rd)
+{
+ int s = a.hi>>63, ex = 0, e;
+ u128 m;
+
+ if (isnan_q(a)) {
+ m = rsh(a, 113 - p);
+ m.lo &= (1ULL<<(p-1)) - 1;
+ m = or128(m, qhuge(s, p, ebits, 1));
+ m.lo |= 1ULL<<(p-2);
+ ex = issnan_q(a) ? NV : 0;
+ } else if (isinf_q(a)) {
+ m = qhuge(s, p, ebits, 1);
+ } else if (iszero_q(a)) {
+ m = qsign(s, p, ebits);
+ } else {
+ e = qnorm(a, &m);
+ ex = qround(&m, s, e, m, p, ebits, rd);
+ }
+ *r = m.lo;
+ return ex;
+}
+
+/* A trap-enabled exception is raised by a double FPop that causes it,
+ * so SIGFPE carries the same si_code as a hardware quad FPop. Otherwise
+ * the exceptions go to cexc and accumulate in aexc. */
+static void qexc(unsigned long fsr, int ex)
+{
+ volatile double z = 0, one = 1, big = 0x1p1023, tiny = 0x1p-1022, y;
+ int t = (ex | (ex & TINY ? UF : 0)) & fsr>>23 & 31;
+
+ ex &= 31;
+ if (t & NV)
+ y = z / z;
+ else if (t & OF)
+ y = big * big;
+ else if (t & UF)
+ y = tiny * tiny;
+ else if (t & DZ)
+ y = one / z;
+ else if (t & NX)
+ y = one + tiny;
+ else if (fsr != ((fsr & ~0x1fUL) | ex<<5 | ex))
+ set_fsr((fsr & ~0x1fUL) | ex<<5 | ex);
+}
+
+union q {
+ long double f;
+ u128 i;
+};
+
+static inline u128 ld(const long double *p)
+{
+ union q u = {*p};
+ return u.i;
+}
+
+static inline long double qf(u128 x)
+{
+ union q u = {.i = x};
+ return u.f;
+}
+
+static int qsub(u128 *r, u128 a, u128 b, int rd)
+{
+ if (isnan_q(b))
+ return qnan2(r, a, b);
+ b.hi ^= 1ULL<<63;
+ return qadd(r, a, b, rd);
+}
+
+static u128 qop(int (*op)(u128 *, u128, u128, int), const long double *a, const long double *b)
+{
+ unsigned long fsr = get_fsr();
+ u128 r;
+ qexc(fsr, op(&r, ld(a), ld(b), fsr>>30 & 3));
+ return r;
+}
+
+static int cmp(const long double *a, const long double *b, int sig)
+{
+ int c;
+ qexc(get_fsr(), qcmp(&c, ld(a), ld(b), sig));
+ return c;
+}
+
+static uint64_t toint(const long double *a, int bits, int sgn)
+{
+ uint64_t r;
+ qexc(get_fsr(), qtoint(&r, ld(a), bits, sgn));
+ return r;
+}
+
+static u128 fromflt(uint64_t x, int p, int ebits)
+{
+ u128 r;
+ qexc(get_fsr(), qwiden(&r, x, p, ebits));
+ return r;
+}
+
+static uint64_t toflt(const long double *a, int p, int ebits)
+{
+ unsigned long fsr = get_fsr();
+ uint64_t r;
+ qexc(fsr, qnarrow(&r, ld(a), p, ebits, fsr>>30 & 3));
+ return r;
+}
diff --git a/src/setjmp/sparc64/longjmp.s b/src/setjmp/sparc64/longjmp.s
new file mode 100644
index 00000000..ef915fc3
--- /dev/null
+++ b/src/setjmp/sparc64/longjmp.s
@@ -0,0 +1,18 @@
+ .register %g2, #scratch
+
+ .text
+ .global _longjmp
+ .global longjmp
+ .type _longjmp,#function
+ .type longjmp,#function
+_longjmp:
+longjmp:
+ save %sp, -176, %sp
+ flushw
+ ldx [%i0 + 0], %fp
+ ldx [%i0 + 8], %i7
+ mov %i1, %g2
+ movrz %i1, 1, %g2
+ mov %i0, %g1
+ ret
+ restore %g2, 0, %o0
diff --git a/src/setjmp/sparc64/setjmp.s b/src/setjmp/sparc64/setjmp.s
new file mode 100644
index 00000000..d282cfcb
--- /dev/null
+++ b/src/setjmp/sparc64/setjmp.s
@@ -0,0 +1,22 @@
+ .text
+ .global ___setjmp
+ .hidden ___setjmp
+ .global __setjmp
+ .global _setjmp
+ .global setjmp
+ .type ___setjmp,#function
+ .type __setjmp,#function
+ .type _setjmp,#function
+ .type setjmp,#function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+ save %sp, -176, %sp
+ flushw
+ stx %fp, [%i0 + 0]
+ stx %i7, [%i0 + 8]
+
+ mov %i0, %g1
+ ret
+ restore %g0, 0, %o0
diff --git a/src/signal/sparc64/restore.s b/src/signal/sparc64/restore.s
new file mode 100644
index 00000000..699eb648
--- /dev/null
+++ b/src/signal/sparc64/restore.s
@@ -0,0 +1,15 @@
+/* the kernel sets the handler's %o7 to the restorer, so it is entered 8 bytes in */
+ .text
+ .global __restore_rt
+ .hidden __restore_rt
+ .type __restore_rt,#function
+ .global __restore
+ .hidden __restore
+ .type __restore,#function
+__restore_rt:
+__restore:
+ nop
+ nop
+ mov 101, %g1
+ ta 0x6d
+ unimp
diff --git a/src/signal/sparc64/sigsetjmp.s b/src/signal/sparc64/sigsetjmp.s
new file mode 100644
index 00000000..32ebed03
--- /dev/null
+++ b/src/signal/sparc64/sigsetjmp.s
@@ -0,0 +1,25 @@
+ .text
+ .global sigsetjmp
+ .global __sigsetjmp
+ .type sigsetjmp,#function
+ .type __sigsetjmp,#function
+ .hidden ___setjmp
+ .hidden __sigsetjmp_tail
+sigsetjmp:
+__sigsetjmp:
+ tst %o1
+ be ___setjmp
+ nop
+
+ stx %o7, [%o0 + 16]
+ call ___setjmp
+ nop
+
+ /* ___setjmp and longjmp both return with jb in %g1 */
+ mov %o0, %o1
+ mov %g1, %o0
+ ldx [%o0 + 16], %o7
+
+ ba __sigsetjmp_tail
+ nop
+ .size sigsetjmp, .-sigsetjmp
diff --git a/src/thread/sparc64/__set_thread_area.s b/src/thread/sparc64/__set_thread_area.s
new file mode 100644
index 00000000..25390610
--- /dev/null
+++ b/src/thread/sparc64/__set_thread_area.s
@@ -0,0 +1,8 @@
+ .text
+ .global __set_thread_area
+ .hidden __set_thread_area
+ .type __set_thread_area,#function
+__set_thread_area:
+ mov %o0, %g7
+ retl
+ mov 0, %o0
diff --git a/src/thread/sparc64/__unmapself.c b/src/thread/sparc64/__unmapself.c
new file mode 100644
index 00000000..f7c106f5
--- /dev/null
+++ b/src/thread/sparc64/__unmapself.c
@@ -0,0 +1,28 @@
+#include "pthread_impl.h"
+#include "syscall.h"
+
+#define STACK_BIAS 2047
+
+/* Threads exiting at once share scratch: after the windows are flushed
+ * only a kernel window spill writes to it, and nothing reads it back. */
+static char scratch[512] __attribute__((aligned(16)));
+
+void __unmapself(void *base, size_t size)
+{
+ register long a0 __asm__("o0") = (long)base;
+ register long a1 __asm__("o1") = (long)size;
+ __asm__ __volatile__(
+ "flushw\n\t"
+ "mov %2, %%sp\n\t"
+ "mov %3, %%g1\n\t"
+ "ta 0x6d\n\t"
+ "mov 0, %%o0\n\t"
+ "mov %4, %%g1\n\t"
+ "ta 0x6d\n\t"
+ :
+ : "r"(a0), "r"(a1),
+ "r"((unsigned long)scratch + 128 - STACK_BIAS),
+ "i"(SYS_munmap), "i"(SYS_exit)
+ : "g1", "memory");
+ __builtin_unreachable();
+}
diff --git a/src/thread/sparc64/clone.S b/src/thread/sparc64/clone.S
new file mode 100644
index 00000000..d15eee85
--- /dev/null
+++ b/src/thread/sparc64/clone.S
@@ -0,0 +1,51 @@
+#define SYS_clone 217
+#define SYS_exit 1
+
+ .register %g2, #scratch
+ .register %g3, #scratch
+
+ .text
+ .global __clone
+ .hidden __clone
+ .type __clone,#function
+__clone:
+ /* clone_stackframe() copies the frame of whoever holds %sp, so take our own */
+ save %sp, -176, %sp
+ ldx [%fp + 2223], %g1 /* 2223 = STACK_BIAS + 176 */
+
+ mov %i0, %g2
+ mov %i3, %g3
+
+ and %i1, -16, %o1
+ sub %o1, 2223, %o1
+
+ /* sparc_clone() takes tls in arg4 and child_tid in arg5 */
+ mov %i2, %o0
+ mov %i4, %o2
+ mov %i5, %o3
+ mov %g1, %o4
+
+ flushw
+ mov SYS_clone, %g1
+ ta 0x6d
+ bcs,pn %xcc, 2f
+ nop
+
+ brnz,pn %o1, 1f
+ nop
+
+ ret
+ restore %o0, %g0, %o0
+
+1:
+ mov %g3, %o0
+ call %g2
+ nop
+ mov SYS_exit, %g1
+ ta 0x6d
+ unimp
+
+2: sub %g0, %o0, %o0
+ ret
+ restore %o0, %g0, %o0
+ .size __clone, .-__clone
diff --git a/src/thread/sparc64/syscall_cp.s b/src/thread/sparc64/syscall_cp.s
new file mode 100644
index 00000000..47d2b60c
--- /dev/null
+++ b/src/thread/sparc64/syscall_cp.s
@@ -0,0 +1,38 @@
+ .text
+ .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
+ .type __syscall_cp_asm,#function
+__syscall_cp_asm:
+__cp_begin:
+ ld [%o0], %g1
+ brnz,pn %g1, __cp_cancel
+ nop
+
+ mov %o1, %g1
+ mov %o2, %o0
+ mov %o3, %o1
+ mov %o4, %o2
+ mov %o5, %o3
+ ldx [%sp + 2223], %o4
+ ldx [%sp + 2231], %o5
+ ta 0x6d
+__cp_end:
+ /* on error the carry is set and %o0 holds a positive errno */
+ bcs,pn %xcc, 1f
+ nop
+ retl
+ nop
+1: retl
+ sub %g0, %o0, %o0
+
+__cp_cancel:
+ ba __cancel
+ nop
+ .size __syscall_cp_asm, .-__syscall_cp_asm
diff --git a/src/unistd/sparc64/pipe.s b/src/unistd/sparc64/pipe.s
new file mode 100644
index 00000000..9860e4f0
--- /dev/null
+++ b/src/unistd/sparc64/pipe.s
@@ -0,0 +1,18 @@
+ .text
+ .global pipe
+ .type pipe,#function
+ .hidden __syscall_ret
+pipe:
+ mov %o0, %o2
+ mov 42, %g1
+ ta 0x6d
+ /* the kernel returns fd[0] in %o0 and fd[1] in %o1 */
+ bcs,pn %xcc, 1f
+ nop
+ st %o0, [%o2]
+ st %o1, [%o2 + 4]
+ retl
+ clr %o0
+1: ba __syscall_ret
+ neg %o0
+ .size pipe, .-pipe
--
2.47.3
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.