From 42be1f29f1f08ca9a38bbc0fe3b4bf75c3b43eed Mon Sep 17 00:00:00 2001
From: swcompiler <lc@wxiat.com>
Date: Fri, 29 Nov 2024 13:52:33 +0800
Subject: [PATCH 03/23] Sw64: ABI Implementation

---
 sysdeps/sw_64/__longjmp.S                     |  64 +++
 sysdeps/sw_64/_mcount.S                       | 105 ++++
 sysdeps/sw_64/bits/endianness.h               |  11 +
 sysdeps/sw_64/bits/link.h                     |  64 +++
 sysdeps/sw_64/bits/setjmp.h                   |  61 ++
 sysdeps/sw_64/bsd-_setjmp.S                   |   1 +
 sysdeps/sw_64/bsd-setjmp.S                    |   1 +
 sysdeps/sw_64/crti.S                          | 101 ++++
 sysdeps/sw_64/crtn.S                          |  49 ++
 sysdeps/sw_64/dl-dtprocnum.h                  |   3 +
 sysdeps/sw_64/dl-machine.h                    | 463 +++++++++++++++
 sysdeps/sw_64/dl-procinfo.c                   |  63 ++
 sysdeps/sw_64/dl-procinfo.h                   |  58 ++
 sysdeps/sw_64/dl-sysdep.h                     |  23 +
 sysdeps/sw_64/dl-trampoline.S                 | 540 ++++++++++++++++++
 sysdeps/sw_64/ffs.S                           |  91 +++
 sysdeps/sw_64/ffsll.S                         |   1 +
 sysdeps/sw_64/jmpbuf-offsets.h                |  35 ++
 sysdeps/sw_64/jmpbuf-unwind.h                 |  45 ++
 sysdeps/sw_64/ldsodefs.h                      |  40 ++
 sysdeps/sw_64/machine-gmon.h                  |  24 +
 sysdeps/sw_64/nptl/pthread-offsets.h          |   3 +
 sysdeps/sw_64/nptl/pthreaddef.h               |  31 +
 sysdeps/sw_64/setjmp.S                        | 121 ++++
 sysdeps/sw_64/sotruss-lib.c                   |  48 ++
 sysdeps/sw_64/start.S                         | 103 ++++
 sysdeps/sw_64/sw8a/nptl/pthread-offsets.h     |   3 +
 sysdeps/sw_64/sw8a/nptl/pthreaddef.h          |  31 +
 sysdeps/sw_64/sw8a/nptl/tcb-offsets.sym       |  13 +
 sysdeps/sw_64/tls-macros.h                    |  36 ++
 sysdeps/sw_64/tst-audit.h                     |  24 +
 sysdeps/sw_64/tst-file-align.h                |  20 +
 sysdeps/sw_64/unwind-arch.h                   |  28 +
 .../unix/sysv/linux/sw_64/____longjmp_chk.S   | 145 +++++
 34 files changed, 2449 insertions(+)
 create mode 100644 sysdeps/sw_64/__longjmp.S
 create mode 100644 sysdeps/sw_64/_mcount.S
 create mode 100644 sysdeps/sw_64/bits/endianness.h
 create mode 100644 sysdeps/sw_64/bits/link.h
 create mode 100644 sysdeps/sw_64/bits/setjmp.h
 create mode 100644 sysdeps/sw_64/bsd-_setjmp.S
 create mode 100644 sysdeps/sw_64/bsd-setjmp.S
 create mode 100644 sysdeps/sw_64/crti.S
 create mode 100644 sysdeps/sw_64/crtn.S
 create mode 100644 sysdeps/sw_64/dl-dtprocnum.h
 create mode 100644 sysdeps/sw_64/dl-machine.h
 create mode 100644 sysdeps/sw_64/dl-procinfo.c
 create mode 100644 sysdeps/sw_64/dl-procinfo.h
 create mode 100644 sysdeps/sw_64/dl-sysdep.h
 create mode 100644 sysdeps/sw_64/dl-trampoline.S
 create mode 100644 sysdeps/sw_64/ffs.S
 create mode 100644 sysdeps/sw_64/ffsll.S
 create mode 100644 sysdeps/sw_64/jmpbuf-offsets.h
 create mode 100644 sysdeps/sw_64/jmpbuf-unwind.h
 create mode 100644 sysdeps/sw_64/ldsodefs.h
 create mode 100644 sysdeps/sw_64/machine-gmon.h
 create mode 100644 sysdeps/sw_64/nptl/pthread-offsets.h
 create mode 100644 sysdeps/sw_64/nptl/pthreaddef.h
 create mode 100644 sysdeps/sw_64/setjmp.S
 create mode 100644 sysdeps/sw_64/sotruss-lib.c
 create mode 100644 sysdeps/sw_64/start.S
 create mode 100644 sysdeps/sw_64/sw8a/nptl/pthread-offsets.h
 create mode 100644 sysdeps/sw_64/sw8a/nptl/pthreaddef.h
 create mode 100644 sysdeps/sw_64/sw8a/nptl/tcb-offsets.sym
 create mode 100644 sysdeps/sw_64/tls-macros.h
 create mode 100644 sysdeps/sw_64/tst-audit.h
 create mode 100644 sysdeps/sw_64/tst-file-align.h
 create mode 100644 sysdeps/sw_64/unwind-arch.h
 create mode 100644 sysdeps/unix/sysv/linux/sw_64/____longjmp_chk.S

diff --git a/sysdeps/sw_64/__longjmp.S b/sysdeps/sw_64/__longjmp.S
new file mode 100644
index 00000000..1321350e
--- /dev/null
+++ b/sysdeps/sw_64/__longjmp.S
@@ -0,0 +1,64 @@
+/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define __ASSEMBLY__
+
+#include <sysdep.h>
+#include <pointer_guard.h>
+#include <jmpbuf-offsets.h>
+
+
+ENTRY(__longjmp)
+#ifdef PROF
+	ldgp    gp, 0(pv)
+	.set noat
+	ldi     AT, _mcount
+	call     AT, (AT), _mcount
+	.set at
+	.prologue 1
+#else
+	.prologue 0
+#endif
+
+	mov     a1, v0
+	ldl     s0, JB_S0*8(a0)
+	ldl     s1, JB_S1*8(a0)
+	ldl     s2, JB_S2*8(a0)
+	ldl     s3, JB_S3*8(a0)
+	ldl     s4, JB_S4*8(a0)
+	ldl     s5, JB_S5*8(a0)
+	ldl     ra, JB_PC*8(a0)
+	ldl     fp, JB_FP*8(a0)
+	ldl     t0, JB_SP*8(a0)
+	fldd     $f2, JB_F2*8(a0)
+	fldd     $f3, JB_F3*8(a0)
+	fldd     $f4, JB_F4*8(a0)
+	fldd     $f5, JB_F5*8(a0)
+	fldd     $f6, JB_F6*8(a0)
+	fldd     $f7, JB_F7*8(a0)
+	fldd     $f8, JB_F8*8(a0)
+	fldd     $f9, JB_F9*8(a0)
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE(ra, t1)
+	PTR_DEMANGLE2(t0, t1)
+	PTR_DEMANGLE2(fp, t1)
+#endif
+	seleq  v0, 1, v0, v0
+	mov     t0, sp
+	ret
+
+END(__longjmp)
diff --git a/sysdeps/sw_64/_mcount.S b/sysdeps/sw_64/_mcount.S
new file mode 100644
index 00000000..44871413
--- /dev/null
+++ b/sysdeps/sw_64/_mcount.S
@@ -0,0 +1,105 @@
+/* Machine-specific calling sequence for `mcount' profiling function.  sw_64
+   Copyright (C) 1995-2023 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Assembly stub to invoke _mcount().  Compiler generated code calls
+   this stub after executing a function's prologue and without saving any
+   registers.  It is therefore necessary to preserve a0..a5 as they may
+   contain function arguments.  To work correctly with frame- less
+   functions, it is also necessary to preserve ra.  Finally, division
+   routines are invoked with a special calling convention and the
+   compiler treats those calls as if they were instructions.  In
+   particular, it doesn't save any of the temporary registers (caller
+   saved registers).  It is therefore necessary to preserve all
+   caller-saved registers as well.
+
+   Upon entering _mcount, register $at hoflds the return address and ra
+   hoflds the return address of the function's caller (selfpc and frompc,
+   respectively in gmon.c language...). */
+
+#include <sysdep.h>
+
+	.set	noat
+	.set	noreorder
+
+LEAF(_mcount, 0xb0)
+	subl	 sp, 0xb0, sp
+	.prologue 0
+	stl	 a0, 0x00(sp)
+	mov	 ra, a0		# a0 = caller-pc
+	stl	 a1, 0x08(sp)
+	mov	$at, a1		# a1 = self-pc
+	stl	$at, 0x10(sp)
+
+	stl	 a2, 0x18(sp)
+	stl	 a3, 0x20(sp)
+	stl	 a4, 0x28(sp)
+	stl	 a5, 0x30(sp)
+	stl	 ra, 0x38(sp)
+	stl	 gp, 0x40(sp)
+
+	br	gp, 1f
+1:	ldgp	gp, 0(gp)
+
+	stl	 t0, 0x48(sp)
+	stl	 t1, 0x50(sp)
+	stl	 t2, 0x58(sp)
+	stl	 t3, 0x60(sp)
+	stl	 t4, 0x68(sp)
+	stl	 t5, 0x70(sp)
+	stl	 t6, 0x78(sp)
+
+	stl	 t7, 0x80(sp)
+	stl	 t8, 0x88(sp)
+	stl	 t9, 0x90(sp)
+	stl	t10, 0x98(sp)
+	stl	t11, 0xa0(sp)
+	stl	 v0, 0xa8(sp)
+
+	call	ra, __mcount
+
+	ldl	 a0, 0x00(sp)
+	ldl	 a1, 0x08(sp)
+	ldl	$at, 0x10(sp)	# restore self-pc
+	ldl	 a2, 0x18(sp)
+	ldl	 a3, 0x20(sp)
+	ldl	 a4, 0x28(sp)
+	ldl	 a5, 0x30(sp)
+	ldl	 ra, 0x38(sp)
+	ldl	 gp, 0x40(sp)
+	mov	$at, pv		# make pv point to return address
+	ldl	 t0, 0x48(sp)	# this is important under OSF/1 to
+	ldl	 t1, 0x50(sp)	# ensure that the code that we return
+	ldl	 t2, 0x58(sp)	# can correctly compute its gp
+	ldl	 t3, 0x60(sp)
+	ldl	 t4, 0x68(sp)
+	ldl	 t5, 0x70(sp)
+	ldl	 t6, 0x78(sp)
+	ldl	 t7, 0x80(sp)
+	ldl	 t8, 0x88(sp)
+	ldl	 t9, 0x90(sp)
+	ldl	t10, 0x98(sp)
+	ldl	t11, 0xa0(sp)
+	ldl	 v0, 0xa8(sp)
+
+	addl	sp, 0xb0, sp
+	ret	zero,($at),1
+
+	END(_mcount)
+
+weak_alias (_mcount, mcount)
diff --git a/sysdeps/sw_64/bits/endianness.h b/sysdeps/sw_64/bits/endianness.h
new file mode 100644
index 00000000..2c226169
--- /dev/null
+++ b/sysdeps/sw_64/bits/endianness.h
@@ -0,0 +1,11 @@
+#ifndef _BITS_ENDIANNESS_H
+#define _BITS_ENDIANNESS_H 1
+
+#ifndef _BITS_ENDIAN_H
+#  error "Never use <bits/endianness.h> directly; include <endian.h> instead."
+#endif
+
+/* Sw_64 is little-endian.  */
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif /* bits/endianness.h */
diff --git a/sysdeps/sw_64/bits/link.h b/sysdeps/sw_64/bits/link.h
new file mode 100644
index 00000000..312d8550
--- /dev/null
+++ b/sysdeps/sw_64/bits/link.h
@@ -0,0 +1,64 @@
+/* Copyright (C) 2005-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LINK_H
+#  error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+/* Registers for entry into PLT on Sw_64.  */
+typedef struct La_sw_64_regs
+{
+  uint64_t lr_r26;
+  uint64_t lr_sp;
+  uint64_t lr_r16;
+  uint64_t lr_r17;
+  uint64_t lr_r18;
+  uint64_t lr_r19;
+  uint64_t lr_r20;
+  uint64_t lr_r21;
+  double lr_f16;
+  double lr_f17;
+  double lr_f18;
+  double lr_f19;
+  double lr_f20;
+  double lr_f21;
+} La_sw_64_regs;
+
+/* Return values for calls from PLT on Sw_64.  */
+typedef struct La_sw_64_retval
+{
+  uint64_t lrv_r0;
+  uint64_t lrv_r1;
+  double lrv_f0;
+  double lrv_f1;
+} La_sw_64_retval;
+
+__BEGIN_DECLS
+
+extern Elf64_Addr
+la_sw_64_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
+		       uintptr_t *__refcook, uintptr_t *__defcook,
+		       La_sw_64_regs *__regs, unsigned int *__flags,
+		       const char *__symname, long int *__framesizep);
+extern unsigned int la_sw_64_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
+					  uintptr_t *__refcook,
+					  uintptr_t *__defcook,
+					  const La_sw_64_regs *__inregs,
+					  La_sw_64_retval *__outregs,
+					  const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/sw_64/bits/setjmp.h b/sysdeps/sw_64/bits/setjmp.h
new file mode 100644
index 00000000..f8488a2f
--- /dev/null
+++ b/sysdeps/sw_64/bits/setjmp.h
@@ -0,0 +1,61 @@
+/* Define the machine-dependent type `jmp_buf'.  Sw_64 version.
+   Copyright (C) 1992-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_SETJMP_H
+#define _BITS_SETJMP_H 1
+
+#if !defined _SETJMP_H && !defined _PTHREAD_H
+#  error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
+#endif
+
+/* The previous bits/setjmp.h had __jmp_buf defined as a structure.
+   We use an array of 'long int' instead, to make writing the
+   assembler easier.  Naturally, user code should not depend on
+   either representation.  */
+
+/*
+ * Integer registers:
+ *    $0 is the return value (va);
+ *    $1-$8, $22-$25, $28 are call-used (t0-t7, t8-t11, at);
+ *    $9-$14 we save here (s0-s5);
+ *    $15 is the FP and we save it here (fp or s6);
+ *    $16-$21 are input arguments (call-used) (a0-a5);
+ *    $26 is the return PC and we save it here (ra);
+ *    $27 is the procedure value (i.e., the address of __setjmp) (pv or t12);
+ *    $29 is the global pointer, which the caller will reconstruct
+ *	from the return address restored in $26 (gp);
+ *    $30 is the stack pointer and we save it here (sp);
+ *    $31 is always zero (zero).
+ *
+ * Floating-point registers:
+ *    $f0 is the floating return value;
+ *    $f1, $f10-$f15, $f22-$f30 are call-used;
+ *    $f2-$f9 we save here;
+ *    $f16-$21 are input args (call-used);
+ *    $f31 is always zero.
+ *
+ * Note that even on Sw_64 hardware that does not have an FPU (there
+ * isn't such a thing currently) it is required to implement the FP
+ * registers.
+ */
+
+#ifndef __ASSEMBLY__
+typedef long int __jmp_buf[17];
+#endif
+
+#endif /* bits/setjmp.h */
diff --git a/sysdeps/sw_64/bsd-_setjmp.S b/sysdeps/sw_64/bsd-_setjmp.S
new file mode 100644
index 00000000..4e6a2da5
--- /dev/null
+++ b/sysdeps/sw_64/bsd-_setjmp.S
@@ -0,0 +1 @@
+/* _setjmp is in setjmp.S  */
diff --git a/sysdeps/sw_64/bsd-setjmp.S b/sysdeps/sw_64/bsd-setjmp.S
new file mode 100644
index 00000000..1da848d2
--- /dev/null
+++ b/sysdeps/sw_64/bsd-setjmp.S
@@ -0,0 +1 @@
+/* setjmp is in setjmp.S  */
diff --git a/sysdeps/sw_64/crti.S b/sysdeps/sw_64/crti.S
new file mode 100644
index 00000000..29cf51ec
--- /dev/null
+++ b/sysdeps/sw_64/crti.S
@@ -0,0 +1,101 @@
+/* Special .init and .fini section support for Sw_64.
+   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so.  The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* crti.S puts a function prologue at the beginning of the .init and
+   .fini sections and defines global symbols for those addresses, so
+   they can be called as functions.  The symbols _init and _fini are
+   magic and cause the linker to emit DT_INIT and DT_FINI.
+
+   This differs from what would be generated for ordinary code in that
+   we save and restore the GP within the function.  In order for linker
+   relaxation to work, the value in the GP register on exit from a function
+   must be valid for the function entry point.  Normally, a function is
+   contained within one object file and this is not an issue, provided
+   that the function reloads the gp after making any function calls.
+   However, _init and _fini are constructed from pieces of many object
+   files, all of which may have different GP values.  So we must reload
+   the GP value from crti.o in crtn.o.  */
+
+#include <libc-symbols.h>
+#include <sysdep.h>
+
+#ifndef PREINIT_FUNCTION
+# define PREINIT_FUNCTION __gmon_start__
+#endif
+
+#ifndef PREINIT_FUNCTION_WEAK
+# define PREINIT_FUNCTION_WEAK 1
+#endif
+
+#if PREINIT_FUNCTION_WEAK
+	weak_extern (PREINIT_FUNCTION)
+#else
+	.hidden PREINIT_FUNCTION
+#endif
+
+	.section .init, "ax", @progbits
+	.globl	_init
+	.hidden	_init
+	.type	_init, @function
+	.usepv	_init, std
+_init:
+	ldgp	$29, 0($27)
+	subl	$30, 16, $30
+#if PREINIT_FUNCTION_WEAK
+	ldi	$27, PREINIT_FUNCTION
+#endif
+	stl	$26, 0($30)
+	stl	$29, 8($30)
+#if PREINIT_FUNCTION_WEAK
+	beq	$27, 1f
+	call	$26, ($27), PREINIT_FUNCTION
+	ldl	$29, 8($30)
+1:
+#else
+	bsr	$26, PREINIT_FUNCTION !samegp
+#endif
+	.p2align 3
+
+	.section .fini, "ax", @progbits
+	.globl	_fini
+	.hidden	_fini
+	.type	_fini,@function
+	.usepv	_fini,std
+_fini:
+	ldgp	$29, 0($27)
+	subl	$30, 16, $30
+	stl	$26, 0($30)
+	stl	$29, 8($30)
+	.p2align 3
diff --git a/sysdeps/sw_64/crtn.S b/sysdeps/sw_64/crtn.S
new file mode 100644
index 00000000..4de241a9
--- /dev/null
+++ b/sysdeps/sw_64/crtn.S
@@ -0,0 +1,49 @@
+/* Special .init and .fini section support for Sw_64.
+   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so.  The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+   corresponding to the prologues in crti.S.  */
+
+	.section .init, "ax", @progbits
+	ldl	$26, 0($30)
+	ldl	$29, 8($30)
+	addl	$30, 16, $30
+	ret
+
+	.section .fini, "ax", @progbits
+	ldl	$26, 0($30)
+	ldl	$29, 8($30)
+	addl	$30, 16, $30
+	ret
diff --git a/sysdeps/sw_64/dl-dtprocnum.h b/sysdeps/sw_64/dl-dtprocnum.h
new file mode 100644
index 00000000..05777c06
--- /dev/null
+++ b/sysdeps/sw_64/dl-dtprocnum.h
@@ -0,0 +1,3 @@
+/* Number of extra dynamic section entries for this architecture.  By
+   default there are none.  */
+#define DT_THISPROCNUM DT_SW_64_NUM
diff --git a/sysdeps/sw_64/dl-machine.h b/sysdeps/sw_64/dl-machine.h
new file mode 100644
index 00000000..54822f12
--- /dev/null
+++ b/sysdeps/sw_64/dl-machine.h
@@ -0,0 +1,463 @@
+/* Machine-dependent ELF dynamic relocation inline functions.  Sw_64 version.
+   Copyright (C) 1996-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This was written in the absence of an ABI -- don't expect
+   it to remain unchanged.  */
+
+#ifndef dl_machine_h
+#define dl_machine_h 1
+
+#define ELF_MACHINE_NAME "sw_64"
+
+#include <string.h>
+#include <dl-static-tls.h>
+#include <dl-machine-rel.h>
+
+/* Mask identifying addresses reserved for the user program,
+   where the dynamic linker should not map anything.  */
+#define ELF_MACHINE_USER_ADDRESS_MASK 0x120000000UL
+
+/* Translate a processor specific dynamic tag to the index in l_info array.  */
+#define DT_SW_64(x) (DT_SW_64_##x - DT_LOPROC + DT_NUM)
+
+/* Return nonzero iff ELF header is compatible with the running host.  */
+static inline int
+elf_machine_matches_host (const Elf64_Ehdr *ehdr)
+{
+  return ehdr->e_machine == EM_SW_64;
+}
+
+/* Return the link-time address of _DYNAMIC.  The multiple-got-capable
+   linker no longer allocates the first .got entry for this.  But not to
+   worry, no special tricks are needed.  */
+static inline Elf64_Addr
+elf_machine_dynamic (void)
+{
+#ifndef NO_AXP_MULTI_GOT_LD
+  return (Elf64_Addr) &_DYNAMIC;
+#else
+  register Elf64_Addr *gp __asm__ ("$29");
+  return gp[-4096];
+#endif
+}
+
+/* Return the run-time load address of the shared object.  */
+
+static inline Elf64_Addr
+elf_machine_load_address (void)
+{
+  /* This relies on the compiler using gp-relative addresses for static
+   * symbols.  */
+  static void *dot = &dot;
+  return (void *) &dot - dot;
+}
+
+/* Set up the loaded object described by L so its unrelocated PLT
+   entries will jump to the on-demand fixup code in dl-runtime.c.  */
+
+static inline int
+elf_machine_runtime_setup (struct link_map *map, struct r_scope_elem *scope[],
+			   int lazy, int profile)
+{
+  extern char _dl_runtime_resolve_new[] attribute_hidden;
+  extern char _dl_runtime_profile_new[] attribute_hidden;
+  extern char _dl_runtime_resolve_old[] attribute_hidden;
+  extern char _dl_runtime_profile_old[] attribute_hidden;
+
+  struct pltgot
+  {
+    char *resolve;
+    struct link_map *link;
+  };
+
+  struct pltgot *pg;
+  long secureplt;
+  char *resolve;
+
+  if (map->l_info[DT_JMPREL] == 0 || !lazy)
+    return lazy;
+
+  /* Check to see if we're using the read-only plt form.  */
+  secureplt = map->l_info[DT_SW_64 (PLTRO)] != 0;
+
+  /* If the binary uses the read-only secure plt format, PG points to
+     the .got.plt section, which is the right place for ld.so to place
+     its hooks.  Otherwise, PG is currently pointing at the start of
+     the plt; the hooks go at offset 16.  */
+  pg = (struct pltgot *) D_PTR (map, l_info[DT_PLTGOT]);
+  pg += !secureplt;
+
+  /* This function will be called to perform the relocation.  They're
+     not declared as functions to convince the compiler to use gp
+     relative relocations for them.  */
+  if (secureplt)
+    resolve = _dl_runtime_resolve_new;
+  else
+    resolve = _dl_runtime_resolve_old;
+
+  if (__builtin_expect (profile, 0))
+    {
+      if (secureplt)
+	resolve = _dl_runtime_profile_new;
+      else
+	resolve = _dl_runtime_profile_old;
+
+      if (GLRO (dl_profile) && _dl_name_match_p (GLRO (dl_profile), map))
+	{
+	  /* This is the object we are looking for.  Say that we really
+	     want profiling and the timers are started.  */
+	  GL (dl_profile_map) = map;
+	}
+    }
+
+  pg->resolve = resolve;
+  pg->link = map;
+
+  return lazy;
+}
+
+/* Initial entry point code for the dynamic linker.
+   The C function `_dl_start' is the real entry point;
+   its return value is the user program's entry point.  */
+
+#define RTLD_START							    \
+  asm("\
+	.section .text						\n\
+	.set at							\n\
+	.globl _start						\n\
+	.ent _start						\n\
+_start:								\n\
+	.frame $31,0,$31,0					\n\
+	br	$gp, 0f						\n\
+0:	ldgp	$gp, 0($gp)					\n\
+	.prologue 0						\n\
+	/* Pass pointer to argument block to _dl_start.  */	\n\
+	mov	$sp, $16					\n\
+	bsr	$26, _dl_start		!samegp			\n\
+	.end _start						\n\
+	/* FALLTHRU */						\n\
+	.globl _dl_start_user					\n\
+	.ent _dl_start_user					\n\
+_dl_start_user:							\n\
+	.frame $31,0,$31,0					\n\
+	.prologue 0						\n\
+	/* Save the user entry point address in s0.  */		\n\
+	mov	$0, $9						\n\
+	/* The special initializer gets called with the stack	\n\
+	   just as the application's entry point will see it;	\n\
+	   it can switch stacks if it moves these contents	\n\
+	   over.  */						\n\
+" RTLD_START_SPECIAL_INIT "					\n\
+	/* Call _dl_init(_dl_loaded, argc, argv, envp) to run	\n\
+	   initializers.  */					\n\
+	ldih	$16, _rtld_local($gp)	!gprelhigh		\n\
+	ldl	$16, _rtld_local($16)	!gprellow		\n\
+	ldl	$17, 0($sp)					\n\
+	ldi	$18, 8($sp)					\n\
+	s8addl	$17, 8, $19					\n\
+	addl	$19, $18, $19					\n\
+	bsr	$26, _dl_init		!samegp			\n\
+	/* Pass our finalizer function to the user in $0.  */	\n\
+	ldih	$0, _dl_fini($gp)	!gprelhigh		\n\
+	ldi	$0, _dl_fini($0)	!gprellow		\n\
+	/* Jump to the user's entry point.  */			\n\
+	mov	$9, $27						\n\
+	jmp	($9)						\n\
+	.end _dl_start_user					\n\
+	.set noat						\n\
+.previous");
+
+#ifndef RTLD_START_SPECIAL_INIT
+#  define RTLD_START_SPECIAL_INIT /* nothing */
+#endif
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry
+   or TLS variables, so undefined references should not be allowed
+   to define the value.
+
+   ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve
+   to one of the main executable's symbols, as for a COPY reloc.
+   This is unused on Sw_64.  */
+
+#define elf_machine_type_class(type)					  \
+  (((type) == R_SW_64_JMP_SLOT || (type) == R_SW_64_DTPMOD64		  \
+    || (type) == R_SW_64_DTPREL64 || (type) == R_SW_64_TPREL64)	       \
+   * ELF_RTYPE_CLASS_PLT)
+
+/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
+#define ELF_MACHINE_JMP_SLOT R_SW_64_JMP_SLOT
+
+/* The sw_64 never uses Elf64_Rel relocations.  */
+/*#define ELF_MACHINE_NO_REL 1
+#define ELF_MACHINE_NO_RELA 0
+*/
+/* We define an initialization functions.  This is called very early in
+ *    _dl_sysdep_start.  */
+#define DL_PLATFORM_INIT dl_platform_init ()
+
+static inline void __attribute__ ((unused)) dl_platform_init (void)
+{
+  if (GLRO (dl_platform) != NULL && *GLRO (dl_platform) == '\0')
+    /* Avoid an empty string which would disturb us.  */
+    GLRO (dl_platform) = NULL;
+}
+
+/* Fix up the instructions of a PLT entry to invoke the function
+   rather than the dynamic linker.  */
+static inline Elf64_Addr
+elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+		       const ElfW (Sym) * refsym, const ElfW (Sym) * sym,
+		       const Elf64_Rela *reloc, Elf64_Addr *got_addr,
+		       Elf64_Addr value)
+{
+  const Elf64_Rela *rela_plt;
+  Elf64_Word *plte;
+  long int edisp;
+
+  /* Store the value we are going to load.  */
+  *got_addr = value;
+
+  /* If this binary uses the read-only secure plt format, we're done.  */
+  if (map->l_info[DT_SW_64 (PLTRO)])
+    return value;
+
+  /* Otherwise we have to modify the plt entry in place to do the branch.  */
+
+  /* Recover the PLT entry address by calculating reloc's index into the
+     .rela.plt, and finding that entry in the .plt.  */
+  rela_plt = (const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]);
+  plte = (Elf64_Word *) (D_PTR (map, l_info[DT_PLTGOT]) + 32);
+  plte += 3 * (reloc - rela_plt);
+
+  /* Find the displacement from the plt entry to the function.  */
+  edisp = (long int) (value - (Elf64_Addr) &plte[3]) / 4;
+
+  if (edisp >= -0x100000 && edisp < 0x100000)
+    {
+      /* If we are in range, use br to perfect branch prediction and
+	 elide the dependency on the address load.  This case happens,
+	 e.g., when a shared library call is resolved to the same library.  */
+
+      int hi, lo;
+      hi = value - (Elf64_Addr) &plte[0];
+      lo = (short int) hi;
+      hi = (hi - lo) >> 16;
+
+      /* Emit "lda $27,lo($27)" */
+      plte[1] = 0xfb7b0000 | (lo & 0xffff);
+
+      /* Emit "br $31,function" */
+      plte[2] = 0x13e00000 | (edisp & 0x1fffff);
+
+      /* Think about thread-safety -- the previous instructions must be
+	 committed to memory before the first is overwritten.  */
+      __asm__ __volatile__("memb" : : : "memory");
+
+      /* Emit "ldah $27,hi($27)" */
+      plte[0] = 0xff7b0000 | (hi & 0xffff);
+    }
+  else
+    {
+      /* Don't bother with the hint since we already know the hint is
+	 wrong.  Eliding it prevents the wrong page from getting pulled
+	 into the cache.  */
+
+      int hi, lo;
+      hi = (Elf64_Addr) got_addr - (Elf64_Addr) &plte[0];
+      lo = (short) hi;
+      hi = (hi - lo) >> 16;
+
+      /* Emit "ldq $27,lo($27)" */
+      plte[1] = 0x8f7b0000 | (lo & 0xffff);
+
+      /* Emit "jmp $31,($27)" */
+      plte[2] = 0x0ffb0000;
+      /* Think about thread-safety -- the previous instructions must be
+	 committed to memory before the first is overwritten.  */
+      __asm__ __volatile__("memb" : : : "memory");
+
+      /* Emit "ldah $27,hi($27)" */
+      plte[0] = 0xff7b0000 | (hi & 0xffff);
+    }
+
+  /* At this point, if we've been doing runtime resolution, Icache is dirty.
+     This will be taken care of in _dl_runtime_resolve.  If instead we are
+     doing this as part of non-lazy startup relocation, that bit of code
+     hasn't made it into Icache yet, so there's nothing to clean up.  */
+
+  return value;
+}
+
+/* Return the final value of a plt relocation.  */
+static inline Elf64_Addr
+elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
+		       Elf64_Addr value)
+{
+  return value + reloc->r_addend;
+}
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER sw_64_gnu_pltenter
+#define ARCH_LA_PLTEXIT sw_64_gnu_pltexit
+
+#endif /* !dl_machine_h */
+
+#ifdef RESOLVE_MAP
+
+/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+   MAP is the object containing the reloc.  */
+static inline void __attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
+		  const Elf64_Rela *reloc, const Elf64_Sym *sym,
+		  const struct r_found_version *version,
+		  void *const reloc_addr_arg, int skip_ifunc)
+{
+  Elf64_Addr *const reloc_addr = reloc_addr_arg;
+  unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
+
+  /* We cannot use a switch here because we cannot locate the switch
+     jump table until we've self-relocated.  */
+
+#if !defined RTLD_BOOTSTRAP
+  if (__builtin_expect (r_type == R_SW_64_RELATIVE, 0))
+    {
+      //# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+      //      /* Already done in dynamic linker.  */
+      Elf64_Addr reloc_addr_val;
+      //      if (map != &GL(dl_rtld_map))
+      //# endif
+      //	{
+      /* XXX Make some timings.  Maybe it's preferable to test for
+	 unaligned access and only do it the complex way if necessary.  */
+
+      /* Load value without causing unaligned trap.  */
+      memcpy (&reloc_addr_val, reloc_addr_arg, 8);
+      reloc_addr_val += map->l_addr;
+
+      /* Store value without causing unaligned trap.  */
+      memcpy (reloc_addr_arg, &reloc_addr_val, 8);
+      //	}
+    }
+  else
+#endif
+      if (__builtin_expect (r_type == R_SW_64_NONE, 0))
+    return;
+  else
+    {
+      struct link_map *sym_map
+	  = RESOLVE_MAP (map, scope, &sym, version, r_type);
+      Elf64_Addr sym_value;
+      Elf64_Addr sym_raw_value;
+
+      sym_raw_value = sym_value = reloc->r_addend;
+      if (sym_map)
+	{
+	  sym_raw_value += sym->st_value;
+	  sym_value += SYMBOL_ADDRESS (sym_map, sym, true);
+	}
+
+      if (r_type == R_SW_64_GLOB_DAT)
+	*reloc_addr = sym_value;
+      else if (r_type == R_SW_64_JMP_SLOT)
+	elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr, sym_value);
+#ifndef RTLD_BOOTSTRAP
+      else if (r_type == R_SW_64_REFQUAD)
+	{
+	  /* Store value without causing unaligned trap.  */
+	  memcpy (reloc_addr_arg, &sym_value, 8);
+	}
+#endif
+      else if (r_type == R_SW_64_DTPMOD64)
+	{
+#ifdef RTLD_BOOTSTRAP
+	  /* During startup the dynamic linker is always index 1.  */
+	  *reloc_addr = 1;
+#else
+	  /* Get the information from the link map returned by the
+	     resolv function.  */
+	  if (sym_map != NULL)
+	    *reloc_addr = sym_map->l_tls_modid;
+#endif
+	}
+      else if (r_type == R_SW_64_DTPREL64)
+	{
+#ifndef RTLD_BOOTSTRAP
+	  /* During relocation all TLS symbols are defined and used.
+	     Therefore the offset is already correct.  */
+	  *reloc_addr = sym_raw_value;
+#endif
+	}
+      else if (r_type == R_SW_64_TPREL64)
+	{
+#ifdef RTLD_BOOTSTRAP
+	  *reloc_addr = sym_raw_value + map->l_tls_offset;
+#else
+	  if (sym_map)
+	    {
+	      CHECK_STATIC_TLS (map, sym_map);
+	      *reloc_addr = sym_raw_value + sym_map->l_tls_offset;
+	    }
+#endif
+	}
+      else
+	_dl_reloc_bad_type (map, r_type, 0);
+    }
+}
+
+/* Let do-rel.h know that on Sw_64 if l_addr is 0, all RELATIVE relocs
+   can be skipped.  */
+#define ELF_MACHINE_REL_RELATIVE 1
+
+static inline void __attribute__ ((always_inline))
+elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
+			   void *const reloc_addr_arg)
+{
+  /* XXX Make some timings.  Maybe it's preferable to test for
+     unaligned access and only do it the complex way if necessary.  */
+  Elf64_Addr reloc_addr_val;
+
+  /* Load value without causing unaligned trap.  */
+  memcpy (&reloc_addr_val, reloc_addr_arg, 8);
+  reloc_addr_val += l_addr;
+
+  /* Store value without causing unaligned trap.  */
+  memcpy (reloc_addr_arg, &reloc_addr_val, 8);
+}
+
+static inline void __attribute__ ((always_inline))
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
+		      Elf64_Addr l_addr, const Elf64_Rela *reloc,
+		      int skip_ifunc)
+{
+  Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+  unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
+
+  if (r_type == R_SW_64_JMP_SLOT)
+    {
+      /* Perform a RELATIVE reloc on the .got entry that transfers
+	 to the .plt.  */
+      *reloc_addr += l_addr;
+    }
+  else if (r_type == R_SW_64_NONE)
+    return;
+  else
+    _dl_reloc_bad_type (map, r_type, 1);
+}
+
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/sw_64/dl-procinfo.c b/sysdeps/sw_64/dl-procinfo.c
new file mode 100644
index 00000000..253f3aba
--- /dev/null
+++ b/sysdeps/sw_64/dl-procinfo.c
@@ -0,0 +1,63 @@
+/* Data for Sw_64 version of processor capability information.
+   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aurelien Jarno <aurelien@aurel32.net>, 2008.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This information must be kept in sync with the _DL_PLATFORM_COUNT
+   definitions in procinfo.h.
+
+   If anything should be added here check whether the size of each string
+   is still ok with the given array size.
+
+   All the #ifdefs in the definitions are quite irritating but
+   necessary if we want to avoid duplicating the information.  There
+   are three different modes:
+
+   - PROCINFO_DECL is defined.  This means we are only interested in
+     declarations.
+
+   - PROCINFO_DECL is not defined:
+
+     + if SHARED is defined the file is included in an array
+       initializer.  The .element = { ... } syntax is needed.
+
+     + if SHARED is not defined a normal array initialization is
+       needed.
+  */
+
+#ifndef PROCINFO_CLASS
+#  define PROCINFO_CLASS
+#endif
+
+#if !defined PROCINFO_DECL && defined SHARED
+._dl_sw_64_platforms
+#else
+PROCINFO_CLASS const char _dl_sw_64_platforms[5][5]
+#endif
+#ifndef PROCINFO_DECL
+= {
+    "sw8a", "ev5", "sw6a", "sw6b", "sw6c"
+  }
+#endif
+#if !defined SHARED || defined PROCINFO_DECL
+;
+#else
+    ,
+#endif
+
+#undef PROCINFO_DECL
+#undef PROCINFO_CLASS
diff --git a/sysdeps/sw_64/dl-procinfo.h b/sysdeps/sw_64/dl-procinfo.h
new file mode 100644
index 00000000..ea9df900
--- /dev/null
+++ b/sysdeps/sw_64/dl-procinfo.h
@@ -0,0 +1,58 @@
+/* Sw_64 version of processor capability information handling macros.
+   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Aurelien Jarno <aurelien@aurel32.net>, 2008.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_PROCINFO_H
+#define _DL_PROCINFO_H 1
+
+#include <ldsodefs.h>
+
+/* Mask to filter out platforms.  */
+#define _DL_HWCAP_PLATFORM (-1ULL)
+
+#define _DL_PLATFORMS_COUNT 5
+
+static inline int __attribute__ ((unused, always_inline))
+_dl_string_platform (const char *str)
+{
+  int i;
+
+  if (str != NULL)
+    for (i = 0; i < _DL_PLATFORMS_COUNT; ++i)
+      {
+	if (strcmp (str, GLRO (dl_sw_64_platforms)[i]) == 0)
+	  return i;
+      }
+  return -1;
+};
+
+/* We cannot provide a general printing function.  */
+#define _dl_procinfo(type, word) -1
+
+/* There are no hardware capabilities defined.  */
+#define _dl_hwcap_string(idx) ""
+
+/* By default there is no important hardware capability.  */
+#define HWCAP_IMPORTANT (0)
+
+/* We don't have any hardware capabilities.  */
+#define _DL_HWCAP_COUNT 0
+
+#define _dl_string_hwcap(str) (-1)
+
+#endif /* dl-procinfo.h */
diff --git a/sysdeps/sw_64/dl-sysdep.h b/sysdeps/sw_64/dl-sysdep.h
new file mode 100644
index 00000000..b3823567
--- /dev/null
+++ b/sysdeps/sw_64/dl-sysdep.h
@@ -0,0 +1,23 @@
+/* System-specific settings for dynamic linker code.  Sw_64 version.
+   Copyright (C) 2002-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include_next <dl-sysdep.h>
+
+/* _dl_argv cannot be attribute_relro, because _dl_start_user
+   might write into it after _dl_start returns.  */
+#define DL_ARGV_NOT_RELRO 1
diff --git a/sysdeps/sw_64/dl-trampoline.S b/sysdeps/sw_64/dl-trampoline.S
new file mode 100644
index 00000000..72178557
--- /dev/null
+++ b/sysdeps/sw_64/dl-trampoline.S
@@ -0,0 +1,540 @@
+/* PLT trampolines.  Sw_64 version.
+   Copyright (C) 2005-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+	.set noat
+
+.macro savei regno, offset
+	stl	$\regno, \offset($30)
+	cfi_rel_offset(\regno, \offset)
+.endm
+
+.macro savef regno, offset
+	fstd	$f\regno, \offset($30)
+	cfi_rel_offset(\regno+32, \offset)
+.endm
+
+	.align	4
+	.globl	_dl_runtime_resolve_new
+	.ent	_dl_runtime_resolve_new
+
+#undef FRAMESIZE
+#define FRAMESIZE	14*8
+
+_dl_runtime_resolve_new:
+	.frame	$30, FRAMESIZE, $26, 0
+	.mask	0x4000000, 0
+
+	ldih	$29, 0($27)		!gpdisp!1
+	ldi	$30, -FRAMESIZE($30)
+	stl	$26, 0*8($30)
+	stl	$16, 2*8($30)
+
+	stl	$17, 3*8($30)
+	ldi	$29, 0($29)		!gpdisp!1
+	stl	$18, 4*8($30)
+	mov	$28, $16		/* link_map from .got.plt */
+
+	stl	$19, 5*8($30)
+	mov	$25, $17		/* offset of reloc entry */
+	stl	$20, 6*8($30)
+	mov	$26, $18		/* return address */
+
+	stl	$21, 7*8($30)
+	fstd	$f16, 8*8($30)
+	fstd	$f17, 9*8($30)
+	fstd	$f18, 10*8($30)
+
+	fstd	$f19, 11*8($30)
+	fstd	$f20, 12*8($30)
+	fstd	$f21, 13*8($30)
+	.prologue 2
+
+	bsr	$26, _dl_fixup		!samegp
+	mov	$0, $27
+
+	ldl	$26, 0*8($30)
+	ldl	$16, 2*8($30)
+	ldl	$17, 3*8($30)
+	ldl	$18, 4*8($30)
+	ldl	$19, 5*8($30)
+	ldl	$20, 6*8($30)
+	ldl	$21, 7*8($30)
+	fldd	$f16, 8*8($30)
+	fldd	$f17, 9*8($30)
+	fldd	$f18, 10*8($30)
+	fldd	$f19, 11*8($30)
+	fldd	$f20, 12*8($30)
+	fldd	$f21, 13*8($30)
+	ldi	$30, FRAMESIZE($30)
+	jmp	$31, ($27), 0
+	.end	_dl_runtime_resolve_new
+
+	.globl	_dl_runtime_profile_new
+	.type	_dl_runtime_profile_new, @function
+
+#undef FRAMESIZE
+#define FRAMESIZE	20*8
+
+	/* We save the registers in a different order than desired by
+	   .mask/.fmask, so we have to use explicit cfi directives.  */
+	cfi_startproc
+
+_dl_runtime_profile_new:
+	ldih	$29, 0($27)		!gpdisp!2
+	ldi	$30, -FRAMESIZE($30)
+	savei	26, 0*8
+	stl	$16, 2*8($30)
+
+	stl	$17, 3*8($30)
+	ldi	$29, 0($29)		!gpdisp!2
+	stl	$18, 4*8($30)
+	ldi	$1, FRAMESIZE($30)	/* incoming sp value */
+
+	stl	$1, 1*8($30)
+	stl	$19, 5*8($30)
+	stl	$20, 6*8($30)
+	mov	$28, $16		/* link_map from .got.plt */
+
+	stl	$21, 7*8($30)
+	mov	$25, $17		/* offset of reloc entry */
+	fstd	$f16, 8*8($30)
+	mov	$26, $18		/* return address */
+
+	fstd	$f17, 9*8($30)
+	mov	$30, $19		/* La_sw_64_regs address */
+	fstd	$f18, 10*8($30)
+	ldi	$20, 14*8($30)		/* framesize address */
+
+	fstd	$f19, 11*8($30)
+	fstd	$f20, 12*8($30)
+	fstd	$f21, 13*8($30)
+	stl	$28, 16*8($30)
+	stl	$25, 17*8($30)
+
+	bsr	$26, _dl_profile_fixup	!samegp
+	mov	$0, $27
+
+	/* Discover if we're wrapping this call.  */
+	ldl	$18, 14*8($30)
+	bge	$18, 1f
+
+	ldl	$26, 0*8($30)
+	ldl	$16, 2*8($30)
+	ldl	$17, 3*8($30)
+	ldl	$18, 4*8($30)
+	ldl	$19, 5*8($30)
+	ldl	$20, 6*8($30)
+	ldl	$21, 7*8($30)
+	fldd	$f16, 8*8($30)
+	fldd	$f17, 9*8($30)
+	fldd	$f18, 10*8($30)
+	fldd	$f19, 11*8($30)
+	fldd	$f20, 12*8($30)
+	fldd	$f21, 13*8($30)
+	ldi	$30, FRAMESIZE($30)
+	jmp	$31, ($27), 0
+
+1:
+	/* Create a frame pointer and allocate a new argument frame.  */
+	savei	15, 15*8
+	mov	$30, $15
+	cfi_def_cfa_register (15)
+	addl	$18, 15, $18
+	bic	$18, 15, $18
+	subl	$30, $18, $30
+
+	/* Save the call destination around memcpy.  */
+	stl	$0, 14*8($30)
+
+	/* Copy the stack arguments into place.  */
+	ldi	$16, 0($30)
+	ldi	$17, FRAMESIZE($15)
+	call	$26, memcpy
+	ldgp	$29, 0($26)
+
+	/* Reload the argument registers.  */
+	ldl	$27, 14*8($30)
+	ldl	$16, 2*8($15)
+	ldl	$17, 3*8($15)
+	ldl	$18, 4*8($15)
+	ldl	$19, 5*8($15)
+	ldl	$20, 6*8($15)
+	ldl	$21, 7*8($15)
+	fldd	$f16, 8*8($15)
+	fldd	$f17, 9*8($15)
+	fldd	$f18, 10*8($15)
+	fldd	$f19, 11*8($15)
+	fldd	$f20, 12*8($15)
+	fldd	$f21, 13*8($15)
+
+	call	$26, ($27), 0
+	ldgp	$29, 0($26)
+
+	/* Set up for call to _dl_audit_pltexit.  */
+	ldl	$16, 16*8($15)
+	ldl	$17, 17*8($15)
+	stl	$0, 16*8($15)
+	ldi	$18, 0($15)
+	stl	$1, 17*8($15)
+	ldi	$19, 16*8($15)
+	fstd	$f0, 18*8($15)
+	fstd	$f1, 19*8($15)
+	bsr	$26, _dl_audit_pltexit	!samegp
+
+	mov	$15, $30
+	cfi_def_cfa_register (30)
+	ldl	$26, 0($30)
+	ldl	$15, 15*8($30)
+	ldi	$30, FRAMESIZE($30)
+	ret
+
+	cfi_endproc
+	.size	_dl_runtime_profile_new, .-_dl_runtime_profile_new
+
+	.align	4
+	.globl	_dl_runtime_resolve_old
+	.ent	_dl_runtime_resolve_old
+
+#undef FRAMESIZE
+#define FRAMESIZE	44*8
+
+_dl_runtime_resolve_old:
+	ldi	$30, -FRAMESIZE($30)
+	.frame	$30, FRAMESIZE, $26
+	/* Preserve all registers that C normally doesn't.  */
+	stl	$26, 0*8($30)
+	stl	$0, 1*8($30)
+	stl	$1, 2*8($30)
+	stl	$2, 3*8($30)
+	stl	$3, 4*8($30)
+	stl	$4, 5*8($30)
+	stl	$5, 6*8($30)
+	stl	$6, 7*8($30)
+	stl	$7, 8*8($30)
+	stl	$8, 9*8($30)
+	stl	$16, 10*8($30)
+	stl	$17, 11*8($30)
+	stl	$18, 12*8($30)
+	stl	$19, 13*8($30)
+	stl	$20, 14*8($30)
+	stl	$21, 15*8($30)
+	stl	$22, 16*8($30)
+	stl	$23, 17*8($30)
+	stl	$24, 18*8($30)
+	stl	$25, 19*8($30)
+	stl	$29, 20*8($30)
+	fstd	$f0, 21*8($30)
+	fstd	$f1, 22*8($30)
+	fstd	$f10, 23*8($30)
+	fstd	$f11, 24*8($30)
+	fstd	$f12, 25*8($30)
+	fstd	$f13, 26*8($30)
+	fstd	$f14, 27*8($30)
+	fstd	$f15, 28*8($30)
+	fstd	$f16, 29*8($30)
+	fstd	$f17, 30*8($30)
+	fstd	$f18, 31*8($30)
+	fstd	$f19, 32*8($30)
+	fstd	$f20, 33*8($30)
+	fstd	$f21, 34*8($30)
+	fstd	$f22, 35*8($30)
+	fstd	$f23, 36*8($30)
+	fstd	$f24, 37*8($30)
+	fstd	$f25, 38*8($30)
+	fstd	$f26, 39*8($30)
+	fstd	$f27, 40*8($30)
+	fstd	$f28, 41*8($30)
+	fstd	$f29, 42*8($30)
+	fstd	$f30, 43*8($30)
+	.mask	0x27ff01ff, -FRAMESIZE
+	.fmask	0xfffffc03, -FRAMESIZE+21*8
+	/* Set up our GP.  */
+	br	$29, .+4
+	ldgp	$29, 0($29)
+	.prologue 0
+	/* Set up the arguments for _dl_fixup:
+	   $16 = link_map out of plt0
+	   $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24
+	   $18 = return address
+	*/
+	subl	$28, $27, $17
+	ldl	$16, 8($27)
+	subl	$17, 20, $17
+	mov	$26, $18
+	addl	$17, $17, $17
+	bsr	$26, _dl_fixup	!samegp
+
+	/* Move the destination address into position.  */
+	mov	$0, $27
+	/* Restore program registers.  */
+	ldl	$26, 0*8($30)
+	ldl	$0, 1*8($30)
+	ldl	$1, 2*8($30)
+	ldl	$2, 3*8($30)
+	ldl	$3, 4*8($30)
+	ldl	$4, 5*8($30)
+	ldl	$5, 6*8($30)
+	ldl	$6, 7*8($30)
+	ldl	$7, 8*8($30)
+	ldl	$8, 9*8($30)
+	ldl	$16, 10*8($30)
+	ldl	$17, 11*8($30)
+	ldl	$18, 12*8($30)
+	ldl	$19, 13*8($30)
+	ldl	$20, 14*8($30)
+	ldl	$21, 15*8($30)
+	ldl	$22, 16*8($30)
+	ldl	$23, 17*8($30)
+	ldl	$24, 18*8($30)
+	ldl	$25, 19*8($30)
+	ldl	$29, 20*8($30)
+	fldd	$f0, 21*8($30)
+	fldd	$f1, 22*8($30)
+	fldd	$f10, 23*8($30)
+	fldd	$f11, 24*8($30)
+	fldd	$f12, 25*8($30)
+	fldd	$f13, 26*8($30)
+	fldd	$f14, 27*8($30)
+	fldd	$f15, 28*8($30)
+	fldd	$f16, 29*8($30)
+	fldd	$f17, 30*8($30)
+	fldd	$f18, 31*8($30)
+	fldd	$f19, 32*8($30)
+	fldd	$f20, 33*8($30)
+	fldd	$f21, 34*8($30)
+	fldd	$f22, 35*8($30)
+	fldd	$f23, 36*8($30)
+	fldd	$f24, 37*8($30)
+	fldd	$f25, 38*8($30)
+	fldd	$f26, 39*8($30)
+	fldd	$f27, 40*8($30)
+	fldd	$f28, 41*8($30)
+	fldd	$f29, 42*8($30)
+	fldd	$f30, 43*8($30)
+	/* Flush the Icache after having modified the .plt code.  */
+	imb
+	/* Clean up and turn control to the destination */
+	ldi	$30, FRAMESIZE($30)
+	jmp	$31, ($27)
+
+	.end	_dl_runtime_resolve_old
+
+	.globl	_dl_runtime_profile_old
+	.usepv	_dl_runtime_profile_old, no
+	.type	_dl_runtime_profile_old, @function
+
+	/* We save the registers in a different order than desired by
+	   .mask/.fmask, so we have to use explicit cfi directives.  */
+	cfi_startproc
+
+#undef FRAMESIZE
+#define FRAMESIZE	50*8
+
+	.align	4
+_dl_runtime_profile_old:
+	ldi	$30, -FRAMESIZE($30)
+	cfi_adjust_cfa_offset (FRAMESIZE)
+
+	/* Preserve all argument registers.  This also constructs the
+	   La_sw_64_regs structure.  */
+	savei	26, 0*8
+	savei	16, 2*8
+	savei	17, 3*8
+	savei	18, 4*8
+	savei	19, 5*8
+	savei	20, 6*8
+	savei	21, 7*8
+	ldi	$16, FRAMESIZE($30)
+	savef	16, 8*8
+	savef	17, 9*8
+	savef	18, 10*8
+	savef	19, 11*8
+	savef	20, 12*8
+	savef	21, 13*8
+	stl	$16, 1*8($30)
+
+	/* Preserve all registers that C normally doesn't.  */
+	savei	0, 14*8
+	savei	1, 15*8
+	savei	2, 16*8
+	savei	3, 17*8
+	savei	4, 18*8
+	savei	5, 19*8
+	savei	6, 20*8
+	savei	7, 21*8
+	savei	8, 22*8
+	savei	22, 23*8
+	savei	23, 24*8
+	savei	24, 25*8
+	savei	25, 26*8
+	savei	29, 27*8
+	savef	0, 28*8
+	savef	1, 29*8
+	savef	10, 30*8
+	savef	11, 31*8
+	savef	12, 32*8
+	savef	13, 33*8
+	savef	14, 34*8
+	savef	15, 35*8
+	savef	22, 36*8
+	savef	23, 37*8
+	savef	24, 38*8
+	savef	25, 39*8
+	savef	26, 40*8
+	savef	27, 41*8
+	savef	28, 42*8
+	savef	29, 43*8
+	savef	30, 44*8
+
+	/* Set up our GP.  */
+	br	$29, .+4
+	ldgp	$29, 0($29)
+
+	/* Set up the arguments for _dl_profile_fixup:
+	   $16 = link_map out of plt0
+	   $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24
+	   $18 = return address
+	   $19 = La_sw_64_regs address
+	   $20 = framesize address
+	*/
+	subl	$28, $27, $17
+	ldl	$16, 8($27)
+	subl	$17, 20, $17
+	mov	$26, $18
+	addl	$17, $17, $17
+	ldi	$19, 0($30)
+	ldi	$20, 45*8($30)
+	stl	$16, 48*8($30)
+	stl	$17, 49*8($30)
+
+	bsr	$26, _dl_profile_fixup	!samegp
+
+	/* Discover if we're wrapping this call.  */
+	ldl	$18, 45*8($30)
+	bge	$18, 1f
+
+	/* Move the destination address into position.  */
+	mov	$0, $27
+	/* Restore program registers.  */
+	ldl	$26, 0*8($30)
+	ldl	$16, 2*8($30)
+	ldl	$17, 3*8($30)
+	ldl	$18, 4*8($30)
+	ldl	$19, 5*8($30)
+	ldl	$20, 6*8($30)
+	ldl	$21, 7*8($30)
+	fldd	$f16, 8*8($30)
+	fldd	$f17, 9*8($30)
+	fldd	$f18, 10*8($30)
+	fldd	$f19, 11*8($30)
+	fldd	$f20, 12*8($30)
+	fldd	$f21, 13*8($30)
+	ldl	$0, 14*8($30)
+	ldl	$1, 15*8($30)
+	ldl	$2, 16*8($30)
+	ldl	$3, 17*8($30)
+	ldl	$4, 18*8($30)
+	ldl	$5, 19*8($30)
+	ldl	$6, 20*8($30)
+	ldl	$7, 21*8($30)
+	ldl	$8, 22*8($30)
+	ldl	$22, 23*8($30)
+	ldl	$23, 24*8($30)
+	ldl	$24, 25*8($30)
+	ldl	$25, 26*8($30)
+	ldl	$29, 27*8($30)
+	fldd	$f0, 28*8($30)
+	fldd	$f1, 29*8($30)
+	fldd	$f10, 30*8($30)
+	fldd	$f11, 31*8($30)
+	fldd	$f12, 32*8($30)
+	fldd	$f13, 33*8($30)
+	fldd	$f14, 34*8($30)
+	fldd	$f15, 35*8($30)
+	fldd	$f22, 36*8($30)
+	fldd	$f23, 37*8($30)
+	fldd	$f24, 38*8($30)
+	fldd	$f25, 39*8($30)
+	fldd	$f26, 40*8($30)
+	fldd	$f27, 41*8($30)
+	fldd	$f28, 42*8($30)
+	fldd	$f29, 43*8($30)
+	fldd	$f30, 44*8($30)
+
+	/* Clean up and turn control to the destination.  */
+	ldi	$30, FRAMESIZE($30)
+	jmp	$31, ($27)
+
+1:
+	/* Create a frame pointer and allocate a new argument frame.  */
+	savei	15, 45*8
+	mov	$30, $15
+	cfi_def_cfa_register (15)
+	addl	$18, 15, $18
+	bic	$18, 15, $18
+	subl	$30, $18, $30
+
+	/* Save the call destination around memcpy.  */
+	stl	$0, 46*8($30)
+
+	/* Copy the stack arguments into place.  */
+	ldi	$16, 0($30)
+	ldi	$17, FRAMESIZE($15)
+	call	$26, memcpy
+	ldgp	$29, 0($26)
+
+	/* Reload the argument registers.  */
+	ldl	$27, 46*8($30)
+	ldl	$16, 2*8($15)
+	ldl	$17, 3*8($15)
+	ldl	$18, 4*8($15)
+	ldl	$19, 5*8($15)
+	ldl	$20, 6*8($15)
+	ldl	$21, 7*8($15)
+	fldd	$f16, 8*8($15)
+	fldd	$f17, 9*8($15)
+	fldd	$f18, 10*8($15)
+	fldd	$f19, 11*8($15)
+	fldd	$f20, 12*8($15)
+	fldd	$f21, 13*8($15)
+
+	call	$26, ($27), 0
+	ldgp	$29, 0($26)
+
+	/* Set up for call to _dl_audit_pltexit.  */
+	ldl	$16, 48*8($15)
+	ldl	$17, 49*8($15)
+	stl	$0, 46*8($15)
+	ldi	$18, 0($15)
+	stl	$1, 47*8($15)
+	ldi	$19, 46*8($15)
+	fstd	$f0, 48*8($15)
+	fstd	$f1, 49*8($15)
+	bsr	$26, _dl_audit_pltexit	!samegp
+
+	mov	$15, $30
+	cfi_def_cfa_register (30)
+	ldl	$26, 0($30)
+	ldl	$15, 45*8($30)
+	ldi	$30, FRAMESIZE($30)
+	ret
+
+	cfi_endproc
+	.size	_dl_runtime_profile_old, .-_dl_runtime_profile_old
diff --git a/sysdeps/sw_64/ffs.S b/sysdeps/sw_64/ffs.S
new file mode 100644
index 00000000..f03bf357
--- /dev/null
+++ b/sysdeps/sw_64/ffs.S
@@ -0,0 +1,91 @@
+/* Copyright (C) 1996-2023 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Finds the first bit set in an integer.  Optimized for the Sw_64
+   architecture.  */
+
+#include <sysdep.h>
+
+	.set noreorder
+	.set noat
+
+
+ENTRY(__ffs)
+#ifdef PROF
+	ldgp	gp, 0(pv)
+	ldi	AT, _mcount
+	call	AT, (AT), _mcount
+	.prologue 1
+	zap	$16, 0xF0, $16
+	br	$ffsl..ng
+#else
+	.prologue 0
+	zap	$16, 0xF0, $16
+	# FALLTHRU
+#endif
+END(__ffs)
+
+	.align 4
+ENTRY(ffsl)
+#ifdef PROF
+	ldgp	gp, 0(pv)
+	ldi	AT, _mcount
+	call	AT, (AT), _mcount
+	.prologue 1
+$ffsl..ng:
+#else
+	.prologue 0
+#endif
+	not	$16, $1		# e0    :
+	ldi	$2, -1		# .. e1 :
+	cmpgeb	$1, $2, $3	# e0    : bit N == 1 for byte N == 0
+	clr	$0		# .. e1 :
+	addl	$3, 1, $4	# e0    :
+	bic	$4, $3, $3	# e1    : bit N == 1 for first byte N != 0
+	and	$3, 0xF0, $4	# e0    :
+	and	$3, 0xCC, $5	# .. e1 :
+	and	$3, 0xAA, $6	# e0    :
+	selne	$4, 4, $0, $0	# .. e1 :
+	selne	$5, 2, $5, $5	# e0    :
+	selne   $6, 1, $6, $6	# .. e1 :
+	addw	$0, $5, $0	# e0    :
+	addw	$0, $6, $0	# e1    : $0 == N
+	ext0b	$16, $0, $1	# e0    : $1 == byte N
+	ldi	$2, 1		# .. e1 :
+	negl	$1, $3		# e0    :
+	and	$3, $1, $3	# e1    : bit N == least bit set of byte N
+	and	$3, 0xF0, $4	# e0    :
+	and	$3, 0xCC, $5	# .. e1 :
+	and	$3, 0xAA, $6	# e0    :
+	selne	$4, 5, $2, $2	# .. e1 :
+	selne	$5, 2, $5, $5	# e0    :
+	selne	$6, 1, $6, $6	# .. e1 :
+	s8addw	$0, $2, $0	# e0    : fmuld byte ofs by 8 and sum
+	addw	$5, $6, $5	# .. e1 :
+	addw	$0, $5, $0	# e0    :
+	nop			# .. e1 :
+	seleq	$16, 0, $0, $0	# e0    : trap input == 0 case.
+	ret			# .. e1 : 18
+
+END(ffsl)
+
+weak_alias (__ffs, ffs)
+libc_hidden_def (__ffs)
+libc_hidden_builtin_def (ffs)
+weak_extern (ffsl)
+weak_alias (ffsl, ffsll)
diff --git a/sysdeps/sw_64/ffsll.S b/sysdeps/sw_64/ffsll.S
new file mode 100644
index 00000000..b2f46d89
--- /dev/null
+++ b/sysdeps/sw_64/ffsll.S
@@ -0,0 +1 @@
+/* This function is defined in ffs.S.  */
diff --git a/sysdeps/sw_64/jmpbuf-offsets.h b/sysdeps/sw_64/jmpbuf-offsets.h
new file mode 100644
index 00000000..394ec163
--- /dev/null
+++ b/sysdeps/sw_64/jmpbuf-offsets.h
@@ -0,0 +1,35 @@
+/* Private macros for accessing __jmp_buf contents.  Sw_64 version.
+   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define JB_S0 0
+#define JB_S1 1
+#define JB_S2 2
+#define JB_S3 3
+#define JB_S4 4
+#define JB_S5 5
+#define JB_PC 6
+#define JB_FP 7
+#define JB_SP 8
+#define JB_F2 9
+#define JB_F3 10
+#define JB_F4 11
+#define JB_F5 12
+#define JB_F6 13
+#define JB_F7 14
+#define JB_F8 15
+#define JB_F9 16
diff --git a/sysdeps/sw_64/jmpbuf-unwind.h b/sysdeps/sw_64/jmpbuf-unwind.h
new file mode 100644
index 00000000..9c3bdff9
--- /dev/null
+++ b/sysdeps/sw_64/jmpbuf-unwind.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2003-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <setjmp.h>
+#include <jmpbuf-offsets.h>
+#include <stdint.h>
+#include <unwind.h>
+#include <sysdep.h>
+#include <pointer_guard.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame containing a local
+   variable at ADDRESS.  */
+#define _JMPBUF_UNWINDS(_jmpbuf, _address, _demangle)			 \
+  ((void *) (_address) < (void *) _demangle ((_jmpbuf)[JB_SP]))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj)		      \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+static inline uintptr_t __attribute__ ((unused)) _jmpbuf_sp (__jmp_buf regs)
+{
+  uintptr_t sp = regs[JB_SP];
+  PTR_DEMANGLE (sp);
+  return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj)			  \
+  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+/* We use the normal longjmp for unwinding.  */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/sysdeps/sw_64/ldsodefs.h b/sysdeps/sw_64/ldsodefs.h
new file mode 100644
index 00000000..e46085a0
--- /dev/null
+++ b/sysdeps/sw_64/ldsodefs.h
@@ -0,0 +1,40 @@
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __LDSODEFS_H
+
+#  include <elf.h>
+
+struct La_sw_64_regs;
+struct La_sw_64_retval;
+
+#  define ARCH_PLTENTER_MEMBERS					       \
+    Elf64_Addr (*sw_64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *, \
+				      uintptr_t *, struct La_sw_64_regs *,    \
+				      unsigned int *, const char *name,       \
+				      long int *framesizep);
+
+#  define ARCH_PLTEXIT_MEMBERS						\
+    unsigned int (*sw_64_gnu_pltexit) (				       \
+	Elf64_Sym *, unsigned int, uintptr_t *, uintptr_t *,		  \
+	const struct La_sw_64_regs *, struct La_sw_64_retval *,	       \
+	const char *);
+
+#  include_next <ldsodefs.h>
+
+#endif
diff --git a/sysdeps/sw_64/machine-gmon.h b/sysdeps/sw_64/machine-gmon.h
new file mode 100644
index 00000000..3a558bc6
--- /dev/null
+++ b/sysdeps/sw_64/machine-gmon.h
@@ -0,0 +1,24 @@
+/* Machine-specific calling sequence for `mcount' profiling function.  sw_64
+   Copyright (C) 1995-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define _MCOUNT_DECL(from, self) void __mcount (u_long from, u_long self)
+
+/* Call __mcount with our the return PC for our caller, and the return
+   PC our caller will return to.  Empty since we use an assembly stub
+   instead.  */
+#define MCOUNT
diff --git a/sysdeps/sw_64/nptl/pthread-offsets.h b/sysdeps/sw_64/nptl/pthread-offsets.h
new file mode 100644
index 00000000..370e18ac
--- /dev/null
+++ b/sysdeps/sw_64/nptl/pthread-offsets.h
@@ -0,0 +1,3 @@
+#define __PTHREAD_MUTEX_KIND_OFFSET 16
+
+#define __PTHREAD_RWLOCK_FLAGS_OFFSET 48
diff --git a/sysdeps/sw_64/nptl/pthreaddef.h b/sysdeps/sw_64/nptl/pthreaddef.h
new file mode 100644
index 00000000..e1fb46a9
--- /dev/null
+++ b/sysdeps/sw_64/nptl/pthreaddef.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2003-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Default stack size.  */
+#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024)
+
+/* Minimum guard size.  */
+#define ARCH_MIN_GUARD_SIZE 0
+
+/* Required stack pointer alignment at beginning.  The ABI requires 16.  */
+#define STACK_ALIGN 16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK 4096
+
+/* Location of current stack frame.  */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/sw_64/setjmp.S b/sysdeps/sw_64/setjmp.S
new file mode 100644
index 00000000..9b0867eb
--- /dev/null
+++ b/sysdeps/sw_64/setjmp.S
@@ -0,0 +1,121 @@
+/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define __ASSEMBLY__
+
+#include <sysdep.h>
+#include <pointer_guard.h>
+#include <jmpbuf-offsets.h>
+
+	.ent __sigsetjmp
+	.global __sigsetjmp
+__sigsetjmp:
+	ldgp    gp, 0(pv)
+
+$sigsetjmp_local:
+#ifndef PIC
+#define FRAME	16
+	subl    sp, FRAME, sp
+	.frame  sp, FRAME, ra, 0
+	stl     ra, 0(sp)
+	.mask   0x04000000, -FRAME
+#else
+#define FRAME	0
+	.frame	sp, FRAME, ra, 0
+#endif
+#ifdef PROF
+	.set noat
+	ldi	AT, _mcount
+	call	AT, (AT), _mcount
+	.set at
+#endif
+	.prologue 1
+
+	stl	s0, JB_S0*8(a0)
+	stl	s1, JB_S1*8(a0)
+	stl	s2, JB_S2*8(a0)
+	stl	s3, JB_S3*8(a0)
+	stl	s4, JB_S4*8(a0)
+	stl	s5, JB_S5*8(a0)
+#ifdef PTR_MANGLE
+	PTR_MANGLE(t1, ra, t0)
+	stl	t1, JB_PC*8(a0)
+#else
+	stl	ra, JB_PC*8(a0)
+#endif
+#if defined(PTR_MANGLE) && FRAME == 0
+	PTR_MANGLE2(t1, sp, t0)
+#else
+	addl	sp, FRAME, t1
+# ifdef PTR_MANGLE
+	PTR_MANGLE2(t1, t1, t0)
+# endif
+#endif
+	stl	t1, JB_SP*8(a0)
+#ifdef PTR_MANGLE
+	PTR_MANGLE2(t1, fp, t0)
+	stl	t1, JB_FP*8(a0)
+#else
+	stl	fp, JB_FP*8(a0)
+#endif
+	fstd	$f2, JB_F2*8(a0)
+	fstd	$f3, JB_F3*8(a0)
+	fstd	$f4, JB_F4*8(a0)
+	fstd	$f5, JB_F5*8(a0)
+	fstd	$f6, JB_F6*8(a0)
+	fstd	$f7, JB_F7*8(a0)
+	fstd	$f8, JB_F8*8(a0)
+	fstd	$f9, JB_F9*8(a0)
+
+#ifndef PIC
+	/* Call to C to (potentially) save our signal mask.  */
+	call	ra, __sigjmp_save
+	ldl	ra, 0(sp)
+	addl	sp, 16, sp
+	ret
+#elif IS_IN (rtld)
+	/* In ld.so we never save the signal mask.  */
+	mov	0, v0
+	ret
+#else
+	/* Tailcall to save the signal mask.  */
+	br	$31, __sigjmp_save	!samegp
+#endif
+
+END(__sigsetjmp)
+hidden_def (__sigsetjmp)
+
+/* Put these traditional entry points in the same file so that we can
+   elide much of the nonsense in trying to jmp to the real function.  */
+
+ENTRY(_setjmp)
+	ldgp	gp, 0(pv)
+	.prologue 1
+	mov	0, a1
+	br	$sigsetjmp_local
+END(_setjmp)
+libc_hidden_def (_setjmp)
+
+ENTRY(setjmp)
+	ldgp	gp, 0(pv)
+	.prologue 1
+	mov	1, a1
+	br	$sigsetjmp_local
+END(setjmp)
+
+weak_extern(_setjmp)
+weak_extern(setjmp)
diff --git a/sysdeps/sw_64/sotruss-lib.c b/sysdeps/sw_64/sotruss-lib.c
new file mode 100644
index 00000000..0cf35da9
--- /dev/null
+++ b/sysdeps/sw_64/sotruss-lib.c
@@ -0,0 +1,48 @@
+/* Override generic sotruss-lib.c to define actual functions for Sw_64.
+   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define HAVE_ARCH_PLTENTER
+#define HAVE_ARCH_PLTEXIT
+
+#include <elf/sotruss-lib.c>
+
+ElfW (Addr) la_sw_64_gnu_pltenter (ElfW (Sym) * sym __attribute__ ((unused)),
+				   unsigned int ndx __attribute__ ((unused)),
+				   uintptr_t *refcook, uintptr_t *defcook,
+				   La_sw_64_regs *regs, unsigned int *flags,
+				   const char *symname, long int *framesizep)
+{
+  print_enter (refcook, defcook, symname, regs->lr_r16, regs->lr_r17,
+	       regs->lr_r18, *flags);
+
+  /* No need to copy anything, we will not need the parameters in any case.  */
+  *framesizep = 0;
+
+  return sym->st_value;
+}
+
+unsigned int
+la_sw_64_gnu_pltexit (ElfW (Sym) * sym, unsigned int ndx, uintptr_t *refcook,
+		      uintptr_t *defcook, const struct La_sw_64_regs *inregs,
+		      struct La_sw_64_retval *outregs, const char *symname)
+{
+  print_exit (refcook, defcook, symname, outregs->lrv_r0);
+
+  return 0;
+}
diff --git a/sysdeps/sw_64/start.S b/sysdeps/sw_64/start.S
new file mode 100644
index 00000000..a0edc6ce
--- /dev/null
+++ b/sysdeps/sw_64/start.S
@@ -0,0 +1,103 @@
+/* Startup code for Sw_64/ELF.
+   Copyright (C) 1993-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so.  The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+	.text
+	.align 3
+	.globl _start
+	.ent _start, 0
+	.type _start,@function
+_start:
+	.frame	$15, 0, $15
+	br	gp, 1f
+1:	ldgp	gp, 0(gp)
+	subl	sp, 16, sp
+	mov	0, $15
+	.prologue 0
+
+	rfpcr $f0
+	fimovd $f0,a1
+	ldi a2,1($31)
+	sll a2,45,a2
+	bis a1,a2,a1
+	ifmovd a1,$f0
+	wfpcr $f0
+
+  /* Load address of the user's main function.  */
+	setfpec1
+	ldi	a0, main
+
+	ldw	a1, 16(sp)	/* get argc */
+	ldi	a2, 24(sp)	/* get argv */
+
+  /* Load address of our own entry points to .fini and .init.  */
+	mov	$r31, a3
+	mov	$r31, a4
+
+  /* Store address of the shared library termination function.  */
+	mov	v0, a5
+
+  /* Provide the highest stack address to the user code.  */
+	stl	sp, 0(sp)
+
+/* For 256 simd, we should change the value of $SP to 32 bytes align */
+       and     sp, 0x1f, s0
+       beq     s0, 2f
+       subl    sp, 0x10, sp
+2:
+  /* Call the user's main function, and exit with its value.
+     But let the libc call main.  */
+	call	ra, __libc_start_main
+
+/* Reload sp */
+	beq     s0, 3f
+	addl    sp, 0x10, sp
+3:
+  /* Die very horribly if exit returns.  Call_pal hlt is callable from
+     kernel mode only; this will result in an illegal instruction trap.  */
+	sys_call 0
+	.end _start
+
+/* For ECOFF backwards compatibility.  */
+weak_alias (_start, __start)
+
+/* Define a symbol for the first piece of initialized data.  */
+	.data
+	.globl __data_start
+__data_start:
+	.weak data_start
+	data_start = __data_start
diff --git a/sysdeps/sw_64/sw8a/nptl/pthread-offsets.h b/sysdeps/sw_64/sw8a/nptl/pthread-offsets.h
new file mode 100644
index 00000000..370e18ac
--- /dev/null
+++ b/sysdeps/sw_64/sw8a/nptl/pthread-offsets.h
@@ -0,0 +1,3 @@
+#define __PTHREAD_MUTEX_KIND_OFFSET 16
+
+#define __PTHREAD_RWLOCK_FLAGS_OFFSET 48
diff --git a/sysdeps/sw_64/sw8a/nptl/pthreaddef.h b/sysdeps/sw_64/sw8a/nptl/pthreaddef.h
new file mode 100644
index 00000000..e1fb46a9
--- /dev/null
+++ b/sysdeps/sw_64/sw8a/nptl/pthreaddef.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2003-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Default stack size.  */
+#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024)
+
+/* Minimum guard size.  */
+#define ARCH_MIN_GUARD_SIZE 0
+
+/* Required stack pointer alignment at beginning.  The ABI requires 16.  */
+#define STACK_ALIGN 16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK 4096
+
+/* Location of current stack frame.  */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/sw_64/sw8a/nptl/tcb-offsets.sym b/sysdeps/sw_64/sw8a/nptl/tcb-offsets.sym
new file mode 100644
index 00000000..1005621b
--- /dev/null
+++ b/sysdeps/sw_64/sw8a/nptl/tcb-offsets.sym
@@ -0,0 +1,13 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+-- # define __builtin_thread_pointer()  ((void *) 0)
+-- # define thread_offsetof(mem)     ((void *) &THREAD_SELF->mem - (void *) 0)
+-- Ho hum, this doesn't work in gcc4, so Know Things about THREAD_SELF
+#define thread_offsetof(mem)	(long)(offsetof(struct pthread, mem) - sizeof(struct pthread))
+
+MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads)
+TID_OFFSET			thread_offsetof (tid)
diff --git a/sysdeps/sw_64/tls-macros.h b/sysdeps/sw_64/tls-macros.h
new file mode 100644
index 00000000..0e9c7e26
--- /dev/null
+++ b/sysdeps/sw_64/tls-macros.h
@@ -0,0 +1,36 @@
+/* Macros to support TLS testing in times of missing compiler support.  */
+
+extern void *__tls_get_addr (void *);
+
+#define TLS_GD(x)							     \
+  ({									  \
+    register void *__gp asm("$29");					   \
+    void *__result;							   \
+    asm ("ldi %0, " #x "($gp) !tlsgd" : "=r"(__result) : "r"(__gp));	   \
+    __tls_get_addr (__result);						\
+  })
+
+#define TLS_LD(x)							     \
+  ({									  \
+    register void *__gp asm("$29");					   \
+    void *__result;							   \
+    asm ("ldi %0, " #x "($gp) !tlsldm" : "=r"(__result) : "r"(__gp));	  \
+    __result = __tls_get_addr (__result);				     \
+    asm ("ldi %0, " #x "(%0) !dtprel" : "+r"(__result));		       \
+    __result;								 \
+  })
+
+#define TLS_IE(x)							     \
+  ({									  \
+    register void *__gp asm("$29");					   \
+    long ofs;								 \
+    asm ("ldl %0, " #x "($gp) !gottprel" : "=r"(ofs) : "r"(__gp));	     \
+    __builtin_thread_pointer () + ofs;					\
+  })
+
+#define TLS_LE(x)							     \
+  ({									  \
+    void *__result = __builtin_thread_pointer ();			     \
+    asm ("ldi %0, " #x "(%0) !tprel" : "+r"(__result));			\
+    __result;								 \
+  })
diff --git a/sysdeps/sw_64/tst-audit.h b/sysdeps/sw_64/tst-audit.h
new file mode 100644
index 00000000..6f9633fd
--- /dev/null
+++ b/sysdeps/sw_64/tst-audit.h
@@ -0,0 +1,24 @@
+/* Definitions for testing PLT entry/exit auditing.  Sw_64 version.
+   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define pltenter la_sw_64_gnu_pltenter
+#define pltexit la_sw_64_gnu_pltexit
+#define La_regs La_sw_64_regs
+#define La_retval La_sw_64_retval
+#define int_retval lrv_r0
diff --git a/sysdeps/sw_64/tst-file-align.h b/sysdeps/sw_64/tst-file-align.h
new file mode 100644
index 00000000..2c4847f5
--- /dev/null
+++ b/sysdeps/sw_64/tst-file-align.h
@@ -0,0 +1,20 @@
+/* Check file alignment.  Sw_64 version.
+   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* This should cover all possible alignments we currently support.  */
+#define ALIGN 0x10000
diff --git a/sysdeps/sw_64/unwind-arch.h b/sysdeps/sw_64/unwind-arch.h
new file mode 100644
index 00000000..a64260bd
--- /dev/null
+++ b/sysdeps/sw_64/unwind-arch.h
@@ -0,0 +1,28 @@
+/* Dynamic loading of the libgcc unwinder.  sw_64 customization.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _ARCH_UNWIND_LINK_H
+#define _ARCH_UNWIND_LINK_H
+
+#define UNWIND_LINK_GETIP 1
+#define UNWIND_LINK_FRAME_STATE_FOR 1
+#define UNWIND_LINK_FRAME_ADJUSTMENT 0
+#define UNWIND_LINK_EXTRA_FIELDS
+#define UNWIND_LINK_EXTRA_INIT
+
+#endif /* _ARCH_UNWIND_LINK_H */
diff --git a/sysdeps/unix/sysv/linux/sw_64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/sw_64/____longjmp_chk.S
new file mode 100644
index 00000000..b2c2b539
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sw_64/____longjmp_chk.S
@@ -0,0 +1,145 @@
+/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <pointer_guard.h>
+#include <jmpbuf-offsets.h>
+
+
+	.section .rodata.str1.1,"aMS",@progbits,1
+	.type   longjmp_msg,@object
+longjmp_msg:
+	.string "longjmp causes uninitialized stack frame"
+	.size   longjmp_msg, .-longjmp_msg
+
+
+/* Jump to the position specified by ENV, causing the
+   setjmp call there to return VAL, or 1 if VAL is 0.
+   void __longjmp (__jmp_buf env, int val).  */
+	.text
+	.align	4
+	.globl	____longjmp_chk
+	.type	____longjmp_chk, @function
+	.usepv	____longjmp_chk, std
+
+	cfi_startproc
+____longjmp_chk:
+	ldgp    gp, 0(pv)
+#ifdef PROF
+	.set noat
+	ldi     AT, _mcount
+	call     AT, (AT), _mcount
+	.set at
+#endif
+
+	ldl     s2, JB_PC*8(a0)
+	mov	a0, s0
+	ldl     fp, JB_FP*8(a0)
+	mov     a1, s1
+	ldl     s3, JB_SP*8(a0)
+	seleq   s1, 1, s1, s1
+
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE (s2, t1)
+	PTR_DEMANGLE2 (s3, t1)
+	PTR_DEMANGLE2 (fp, t1)
+#endif
+	/* ??? While this is a proper test for detecting a longjmp to an
+	   invalid frame within any given stack, the main thread stack is
+	   located *below* almost everything in the address space.  Which
+	   means that the test at Lfail vs the signal stack will almost
+	   certainly never pass.  We ought bounds check top and bottom of
+	   the current thread's stack.  */
+	cmpule	s3, sp, t1
+	bne	t1, $Lfail
+
+	.align	4
+$Lok:
+	mov	s0, a0
+	mov	s1, v0
+	mov	s3, t0
+	mov	s2, ra
+	cfi_remember_state
+	cfi_def_cfa (a0, 0)
+	cfi_register (sp, t0)
+	cfi_offset (s0, JB_S0*8)
+	cfi_offset (s1, JB_S1*8)
+	cfi_offset (s2, JB_S2*8)
+	cfi_offset (s3, JB_S3*8)
+	cfi_offset (s4, JB_S4*8)
+	cfi_offset (s5, JB_S5*8)
+	cfi_offset (s3, JB_S3*8)
+	cfi_offset ($f2, JB_F2*8)
+	cfi_offset ($f3, JB_F3*8)
+	cfi_offset ($f4, JB_F4*8)
+	cfi_offset ($f5, JB_F5*8)
+	cfi_offset ($f6, JB_F6*8)
+	cfi_offset ($f7, JB_F7*8)
+	cfi_offset ($f8, JB_F8*8)
+	cfi_offset ($f9, JB_F9*8)
+	ldl	s0, JB_S0*8(a0)
+	ldl	s1, JB_S1*8(a0)
+	ldl	s2, JB_S2*8(a0)
+	ldl	s3, JB_S3*8(a0)
+	ldl	s4, JB_S4*8(a0)
+	ldl	s5, JB_S5*8(a0)
+	fldd     $f2, JB_F2*8(a0)
+	fldd     $f3, JB_F3*8(a0)
+	fldd     $f4, JB_F4*8(a0)
+	fldd     $f5, JB_F5*8(a0)
+	fldd     $f6, JB_F6*8(a0)
+	fldd     $f7, JB_F7*8(a0)
+	fldd     $f8, JB_F8*8(a0)
+	fldd     $f9, JB_F9*8(a0)
+	mov     t0, sp
+	ret
+
+	.align	4
+$Lfail:
+	cfi_restore_state
+	ldi	v0, __NR_sigaltstack
+	ldi	a0, 0
+	ldi	a1, -32(sp)
+	ldi	sp, -32(sp)
+	cfi_adjust_cfa_offset (32)
+	sys_call 0x83
+	ldl	t0, 0(sp)	/* ss_sp */
+	ldw	t1, 8(sp)	/* ss_flags */
+	ldl	t2, 16(sp)	/* ss_size */
+	ldi	sp, 32(sp)
+	cfi_adjust_cfa_offset (-32)
+
+	/* Without working sigaltstack we cannot perform the test.  */
+	bne	a3, $Lok
+
+	addl	t0, t2, t0	/* t0 = ss_sp + ss_size */
+	subl	t0, s3, t0	/* t0 = (ss_sp + ss_size) - new_sp */
+	cmpule	t2, t0, t0	/* t0 = (t0 >= ss_size) */
+	and	t0, t1, t0	/* t0 = (t0 >= ss_size) & (ss_flags & SS_ONSTACK) */
+	bne	t0, $Lok
+
+	ldih	a0, longjmp_msg(gp)	!gprelhigh
+	ldi	a0, longjmp_msg(a0)	!gprellow
+#ifdef PIC
+	call	ra, HIDDEN_JUMPTARGET (__fortify_fail)
+#else
+	bsr	ra, HIDDEN_JUMPTARGET (__fortify_fail)	!samegp
+#endif
+	sys_call 0x81
+
+	cfi_endproc
+	.size	____longjmp_chk, .-____longjmp_chk
-- 
2.25.1

