glibc/0003-Sw64-ABI-Implementation.patch
swcompiler 55189b18b5 Sw64: Add Sw64 ISA support
(cherry picked from commit 7c7ae25b26c3c937686ae3f686a768532b14ec36)
2025-01-04 15:06:39 +08:00

2733 lines
83 KiB
Diff

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