Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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.