From a48f11d0af793110f1a5289967bcb45a188058c3 Mon Sep 17 00:00:00 2001
From: swcompiler <lc@wxiat.com>
Date: Fri, 29 Nov 2024 14:04:40 +0800
Subject: [PATCH 07/23] Sw64: Linux Syscall Interface

---
 sysdeps/unix/sw_64/Makefile                  |   4 +
 sysdeps/unix/sw_64/pipe.S                    |  31 ++
 sysdeps/unix/sw_64/rt-sysdep.S               |   1 +
 sysdeps/unix/sw_64/sysdep.S                  |  65 ++++
 sysdeps/unix/sysv/linux/sw_64/arch-syscall.h | 376 +++++++++++++++++++
 sysdeps/unix/sysv/linux/sw_64/clone.S        | 117 ++++++
 sysdeps/unix/sysv/linux/sw_64/syscall.S      |  70 ++++
 sysdeps/unix/sysv/linux/sw_64/sysdep.h       | 355 +++++++++++++++++
 sysdeps/unix/sysv/linux/sw_64/vfork.S        |  41 ++
 9 files changed, 1060 insertions(+)
 create mode 100644 sysdeps/unix/sw_64/Makefile
 create mode 100644 sysdeps/unix/sw_64/pipe.S
 create mode 100644 sysdeps/unix/sw_64/rt-sysdep.S
 create mode 100644 sysdeps/unix/sw_64/sysdep.S
 create mode 100644 sysdeps/unix/sysv/linux/sw_64/arch-syscall.h
 create mode 100644 sysdeps/unix/sysv/linux/sw_64/clone.S
 create mode 100644 sysdeps/unix/sysv/linux/sw_64/syscall.S
 create mode 100644 sysdeps/unix/sysv/linux/sw_64/sysdep.h
 create mode 100644 sysdeps/unix/sysv/linux/sw_64/vfork.S

diff --git a/sysdeps/unix/sw_64/Makefile b/sysdeps/unix/sw_64/Makefile
new file mode 100644
index 00000000..0660847f
--- /dev/null
+++ b/sysdeps/unix/sw_64/Makefile
@@ -0,0 +1,4 @@
+ifeq ($(subdir),rt)
+librt-sysdep_routines += rt-sysdep
+librt-shared-only-routines += rt-sysdep
+endif
diff --git a/sysdeps/unix/sw_64/pipe.S b/sysdeps/unix/sw_64/pipe.S
new file mode 100644
index 00000000..d851fe17
--- /dev/null
+++ b/sysdeps/unix/sw_64/pipe.S
@@ -0,0 +1,31 @@
+/* Copyright (C) 1993-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by David Mosberger (davidm@cs.arizona.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
+   <https://www.gnu.org/licenses/>.  */
+
+/* __pipe is a special syscall since it returns two values.  */
+
+#include <sysdep.h>
+
+PSEUDO (__pipe, pipe, 0)
+	stw	r0, 0(a0)
+	stw	r1, 4(a0)
+	mov	zero, v0
+	ret
+PSEUDO_END(__pipe)
+
+libc_hidden_def (__pipe)
+weak_alias (__pipe, pipe)
diff --git a/sysdeps/unix/sw_64/rt-sysdep.S b/sysdeps/unix/sw_64/rt-sysdep.S
new file mode 100644
index 00000000..f966bf1e
--- /dev/null
+++ b/sysdeps/unix/sw_64/rt-sysdep.S
@@ -0,0 +1 @@
+#include <sysdep.S>
diff --git a/sysdeps/unix/sw_64/sysdep.S b/sysdeps/unix/sw_64/sysdep.S
new file mode 100644
index 00000000..306184c3
--- /dev/null
+++ b/sysdeps/unix/sw_64/sysdep.S
@@ -0,0 +1,65 @@
+/* Copyright (C) 1993-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Brendan Kehoe (brendan@zen.org).
+
+   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/>.  */
+
+#include <sysdep.h>
+#include <features.h>
+
+#if defined(PIC)
+	/* Put this at the end of libc's text segment so that all of
+	   the direct branches from the syscalls are forward, and
+	   thus predicted not taken.  */
+	.section .text.last, "ax", @progbits
+#else
+	.text
+#endif
+
+#if IS_IN (libc)
+# define SYSCALL_ERROR_ERRNO __libc_errno
+#else
+# define SYSCALL_ERROR_ERRNO errno
+#endif
+
+	.align 4
+	.globl	__syscall_error
+	.ent	__syscall_error
+__syscall_error:
+	/* When building a shared library, we branch here without having
+	   loaded the GP.  Nor, since it was a direct branch, have we
+	   loaded PV with our address.
+
+	   When building a static library, we tail call here from another
+	   object file, possibly with a different GP, and must return with
+	   the GP of our caller in place so that linker relaxation works.
+
+	   Both issues are solved by computing the GP into T1 instead of
+	   clobbering the traditional GP register.  */
+	.prologue 0
+	mov	v0, t0
+	br	t1, 1f
+1:	ldih	t1, 0(t1) !gpdisp!1
+	sys_call HMC_rdunique
+
+	ldi	t1, 0(t1) !gpdisp!1
+	ldl	t1, SYSCALL_ERROR_ERRNO(t1) !gottprel
+	addl	v0, t1, t1
+	ldi	v0, -1
+
+	stw	t0, 0(t1)
+	ret
+
+	.end __syscall_error
diff --git a/sysdeps/unix/sysv/linux/sw_64/arch-syscall.h b/sysdeps/unix/sysv/linux/sw_64/arch-syscall.h
new file mode 100644
index 00000000..62597a14
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sw_64/arch-syscall.h
@@ -0,0 +1,376 @@
+/* AUTOGENERATED by update-syscall-lists.py.  */
+#define __NR_accept 99
+#define __NR_accept4 502
+#define __NR_access 33
+#define __NR_acct 51
+#define __NR_add_key 439
+#define __NR_adjtimex 366
+#define __NR_afs_syscall 338
+#define __NR_bdflush 300
+#define __NR_bind 104
+#define __NR_bpf 170
+#define __NR_brk 17
+#define __NR_cachestat 190
+#define __NR_capget 368
+#define __NR_capset 369
+#define __NR_chdir 12
+#define __NR_chmod 15
+#define __NR_chown 16
+#define __NR_chroot 61
+#define __NR_clock_adjtime 499
+#define __NR_clock_getres 421
+#define __NR_clock_gettime 420
+#define __NR_clock_nanosleep 422
+#define __NR_clock_settime 419
+#define __NR_clone 312
+#define __NR_clone3 282
+#define __NR_close 6
+#define __NR_close_range 283
+#define __NR_connect 98
+#define __NR_copy_file_range 515
+#define __NR_create_module 306
+#define __NR_delete_module 308
+#define __NR_dipc 373
+#define __NR_dup 41
+#define __NR_dup2 90
+#define __NR_dup3 487
+#define __NR_epoll_create 407
+#define __NR_epoll_create1 486
+#define __NR_epoll_ctl 408
+#define __NR_epoll_pwait 474
+#define __NR_epoll_pwait2 180
+#define __NR_epoll_wait 409
+#define __NR_eventfd 478
+#define __NR_eventfd2 485
+#define __NR_execve 59
+#define __NR_execveat 513
+#define __NR_exit 1
+#define __NR_exit_group 405
+#define __NR_faccessat 462
+#define __NR_faccessat2 286
+#define __NR_fadvise64 413
+#define __NR_fallocate 480
+#define __NR_fanotify_init 494
+#define __NR_fanotify_mark 495
+#define __NR_fchdir 13
+#define __NR_fchmod 124
+#define __NR_fchmodat 461
+#define __NR_fchmodat2 191
+#define __NR_fchown 123
+#define __NR_fchownat 453
+#define __NR_fcntl 92
+#define __NR_fdatasync 447
+#define __NR_fgetxattr 387
+#define __NR_finit_module 507
+#define __NR_flistxattr 390
+#define __NR_flock 131
+#define __NR_fork 2
+#define __NR_fremovexattr 393
+#define __NR_fsconfig 278
+#define __NR_fsetxattr 384
+#define __NR_fsmount 279
+#define __NR_fsopen 277
+#define __NR_fspick 280
+#define __NR_fstat 91
+#define __NR_fstat64 427
+#define __NR_fstatat64 455
+#define __NR_fstatfs 329
+#define __NR_fstatfs64 230
+#define __NR_fsync 95
+#define __NR_ftruncate 130
+#define __NR_futex 394
+#define __NR_futex_waitv 188
+#define __NR_futimesat 454
+#define __NR_get_kernel_syms 309
+#define __NR_get_mempolicy 430
+#define __NR_get_robust_list 467
+#define __NR_getcpu 473
+#define __NR_getcwd 367
+#define __NR_getdents 305
+#define __NR_getdents64 377
+#define __NR_getegid 179
+#define __NR_geteuid 177
+#define __NR_getgid 178
+#define __NR_getgroups 79
+#define __NR_gethostname 87
+#define __NR_getitimer 361
+#define __NR_getpeername 141
+#define __NR_getpgid 233
+#define __NR_getpgrp 63
+#define __NR_getpid 174
+#define __NR_getppid 175
+#define __NR_getpriority 298
+#define __NR_getrandom 511
+#define __NR_getresgid 372
+#define __NR_getresuid 344
+#define __NR_getrlimit 144
+#define __NR_getrusage 364
+#define __NR_getsid 234
+#define __NR_getsockname 150
+#define __NR_getsockopt 118
+#define __NR_getsysinfo 256
+#define __NR_gettid 378
+#define __NR_gettimeofday 359
+#define __NR_getuid 176
+#define __NR_getxattr 385
+#define __NR_getxgid 47
+#define __NR_getxpid 20
+#define __NR_getxuid 24
+#define __NR_init_module 307
+#define __NR_inotify_add_watch 445
+#define __NR_inotify_init 444
+#define __NR_inotify_init1 489
+#define __NR_inotify_rm_watch 446
+#define __NR_io_cancel 402
+#define __NR_io_destroy 399
+#define __NR_io_getevents 400
+#define __NR_io_pgetevents 403
+#define __NR_io_setup 398
+#define __NR_io_submit 401
+#define __NR_io_uring_enter 273
+#define __NR_io_uring_register 274
+#define __NR_io_uring_setup 272
+#define __NR_ioctl 54
+#define __NR_ioprio_get 443
+#define __NR_ioprio_set 442
+#define __NR_kcmp 506
+#define __NR_kexec_load 448
+#define __NR_keyctl 441
+#define __NR_kill 37
+#define __NR_landlock_add_rule 184
+#define __NR_landlock_create_ruleset 183
+#define __NR_landlock_restrict_self 185
+#define __NR_lchown 208
+#define __NR_lgetxattr 386
+#define __NR_link 9
+#define __NR_linkat 458
+#define __NR_listen 106
+#define __NR_listxattr 388
+#define __NR_llistxattr 389
+#define __NR_lookup_dcookie 406
+#define __NR_lremovexattr 392
+#define __NR_lseek 19
+#define __NR_lsetxattr 383
+#define __NR_lstat 68
+#define __NR_lstat64 426
+#define __NR_madvise 75
+#define __NR_mbind 429
+#define __NR_membarrier 172
+#define __NR_memfd_create 512
+#define __NR_migrate_pages 449
+#define __NR_mincore 375
+#define __NR_mkdir 136
+#define __NR_mkdirat 451
+#define __NR_mknod 14
+#define __NR_mknodat 452
+#define __NR_mlock 314
+#define __NR_mlock2 173
+#define __NR_mlockall 316
+#define __NR_mmap 71
+#define __NR_mount 302
+#define __NR_mount_setattr 181
+#define __NR_move_mount 276
+#define __NR_move_pages 472
+#define __NR_mprotect 74
+#define __NR_mq_getsetattr 437
+#define __NR_mq_notify 436
+#define __NR_mq_open 432
+#define __NR_mq_timedreceive 435
+#define __NR_mq_timedsend 434
+#define __NR_mq_unlink 433
+#define __NR_mremap 341
+#define __NR_msgctl 200
+#define __NR_msgget 201
+#define __NR_msgrcv 202
+#define __NR_msgsnd 203
+#define __NR_msync 217
+#define __NR_munlock 315
+#define __NR_munlockall 317
+#define __NR_munmap 73
+#define __NR_name_to_handle_at 497
+#define __NR_nanosleep 340
+#define __NR_nfsservctl 342
+#define __NR_odd_getpriority 100
+#define __NR_odd_sigprocmask 48
+#define __NR_oldumount 321
+#define __NR_open 45
+#define __NR_open_by_handle_at 498
+#define __NR_open_tree 275
+#define __NR_openat 450
+#define __NR_openat2 284
+#define __NR_pciconfig_iobase 376
+#define __NR_pciconfig_read 345
+#define __NR_pciconfig_write 346
+#define __NR_perf_event_open 493
+#define __NR_personality 324
+#define __NR_pidfd_getfd 285
+#define __NR_pidfd_open 281
+#define __NR_pidfd_send_signal 271
+#define __NR_pipe 42
+#define __NR_pipe2 488
+#define __NR_pivot_root 374
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_pkey_mprotect 288
+#define __NR_poll 94
+#define __NR_ppoll 464
+#define __NR_prctl 348
+#define __NR_pread64 349
+#define __NR_preadv 490
+#define __NR_preadv2 516
+#define __NR_prlimit64 496
+#define __NR_process_madvise 287
+#define __NR_process_mrelease 187
+#define __NR_process_vm_readv 504
+#define __NR_process_vm_writev 505
+#define __NR_pselect6 463
+#define __NR_ptrace 26
+#define __NR_pwrite64 350
+#define __NR_pwritev 491
+#define __NR_pwritev2 517
+#define __NR_query_module 347
+#define __NR_quotactl 148
+#define __NR_quotactl_fd 182
+#define __NR_read 3
+#define __NR_readahead 379
+#define __NR_readlink 58
+#define __NR_readlinkat 460
+#define __NR_readv 120
+#define __NR_reboot 311
+#define __NR_recv 102
+#define __NR_recvfrom 125
+#define __NR_recvmmsg 479
+#define __NR_recvmsg 113
+#define __NR_remap_file_pages 410
+#define __NR_removexattr 391
+#define __NR_rename 128
+#define __NR_renameat 457
+#define __NR_renameat2 510
+#define __NR_request_key 440
+#define __NR_restart_syscall 412
+#define __NR_rmdir 137
+#define __NR_rseq 404
+#define __NR_rt_sigaction 352
+#define __NR_rt_sigpending 354
+#define __NR_rt_sigprocmask 353
+#define __NR_rt_sigqueueinfo 356
+#define __NR_rt_sigreturn 351
+#define __NR_rt_sigsuspend 357
+#define __NR_rt_sigtimedwait 355
+#define __NR_rt_tgsigqueueinfo 492
+#define __NR_sched_get_priority_max 335
+#define __NR_sched_get_priority_min 336
+#define __NR_sched_getaffinity 396
+#define __NR_sched_getattr 509
+#define __NR_sched_getparam 331
+#define __NR_sched_getscheduler 333
+#define __NR_sched_rr_get_interval 337
+#define __NR_sched_setaffinity 395
+#define __NR_sched_setattr 508
+#define __NR_sched_setparam 330
+#define __NR_sched_setscheduler 332
+#define __NR_sched_yield 334
+#define __NR_seccomp 514
+#define __NR_select 358
+#define __NR_semctl 204
+#define __NR_semget 205
+#define __NR_semop 206
+#define __NR_semtimedop 423
+#define __NR_send 101
+#define __NR_sendfile 370
+#define __NR_sendmmsg 503
+#define __NR_sendmsg 114
+#define __NR_sendto 133
+#define __NR_set_mempolicy 431
+#define __NR_set_mempolicy_home_node 189
+#define __NR_set_robust_list 466
+#define __NR_set_tid_address 411
+#define __NR_setdomainname 166
+#define __NR_setfsgid 326
+#define __NR_setfsuid 325
+#define __NR_setgid 132
+#define __NR_setgroups 80
+#define __NR_sethostname 88
+#define __NR_setitimer 362
+#define __NR_setns 501
+#define __NR_setpgid 39
+#define __NR_setpgrp 82
+#define __NR_setpriority 96
+#define __NR_setregid 127
+#define __NR_setresgid 371
+#define __NR_setresuid 343
+#define __NR_setreuid 126
+#define __NR_setrlimit 145
+#define __NR_setsid 147
+#define __NR_setsockopt 105
+#define __NR_setsysinfo 257
+#define __NR_settimeofday 360
+#define __NR_setuid 23
+#define __NR_setxattr 382
+#define __NR_shmat 209
+#define __NR_shmctl 210
+#define __NR_shmdt 211
+#define __NR_shmget 212
+#define __NR_shutdown 134
+#define __NR_sigaction 156
+#define __NR_sigaltstack 235
+#define __NR_signalfd 476
+#define __NR_signalfd4 484
+#define __NR_sigpending 52
+#define __NR_sigprocmask 299
+#define __NR_sigreturn 103
+#define __NR_sigsuspend 111
+#define __NR_socket 97
+#define __NR_socketcall 119
+#define __NR_socketpair 135
+#define __NR_splice 468
+#define __NR_stat 67
+#define __NR_stat64 425
+#define __NR_statfs 328
+#define __NR_statfs64 229
+#define __NR_statx 518
+#define __NR_swapoff 304
+#define __NR_swapon 322
+#define __NR_symlink 57
+#define __NR_symlinkat 459
+#define __NR_sync 36
+#define __NR_sync_file_range 469
+#define __NR_syncfs 500
+#define __NR_sysfs 254
+#define __NR_sysinfo 318
+#define __NR_syslog 310
+#define __NR_tee 470
+#define __NR_tgkill 424
+#define __NR_timer_create 414
+#define __NR_timer_delete 418
+#define __NR_timer_getoverrun 417
+#define __NR_timer_gettime 416
+#define __NR_timer_settime 415
+#define __NR_timerfd 477
+#define __NR_timerfd_create 481
+#define __NR_timerfd_gettime 483
+#define __NR_timerfd_settime 482
+#define __NR_times 323
+#define __NR_tkill 381
+#define __NR_truncate 129
+#define __NR_tuxcall 397
+#define __NR_umask 60
+#define __NR_umount 22
+#define __NR_umount2 22
+#define __NR_uname 339
+#define __NR_unlink 10
+#define __NR_unlinkat 456
+#define __NR_unshare 465
+#define __NR_uselib 313
+#define __NR_userfaultfd 171
+#define __NR_ustat 327
+#define __NR_utimensat 475
+#define __NR_utimes 363
+#define __NR_vfork 66
+#define __NR_vhangup 76
+#define __NR_vmsplice 471
+#define __NR_vserver 428
+#define __NR_wait4 365
+#define __NR_waitid 438
+#define __NR_write 4
+#define __NR_writev 121
diff --git a/sysdeps/unix/sysv/linux/sw_64/clone.S b/sysdeps/unix/sysv/linux/sw_64/clone.S
new file mode 100644
index 00000000..6f08adae
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sw_64/clone.S
@@ -0,0 +1,117 @@
+/* Copyright (C) 1996-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>, 1996.
+
+   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/>.  */
+
+/* clone() is even more special than fork() as it mucks with stacks
+   and invokes a function in the right context after its all over.  */
+
+#include <sysdep.h>
+#define _ERRNO_H	1
+#include <bits/errno.h>
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags,
+	     void *arg, pid_t *ptid, void *tls, pid_t *ctid);
+
+   Note that everything past ARG is technically optional, based
+   on FLAGS, and that CTID is arg 7, and thus is on the stack.
+   However, since a load from top-of-stack better be legal always,
+   we don't bother checking FLAGS.  */
+
+	.text
+	.align	4
+	.globl	__clone
+	.ent	__clone
+	.usepv	__clone, USEPV_PROF
+
+	cfi_startproc
+__clone:
+#ifdef PROF
+	.set noat
+	ldgp	gp,0(pv)
+	ldi	AT, _mcount
+	call	AT, (AT), _mcount
+	.set at
+#endif
+
+	/* Sanity check arguments.  */
+	ldi	v0, EINVAL
+	beq	a0, SYSCALL_ERROR_LABEL	/* no NULL function pointers */
+	bic     a1, 0xf,a1 /*Align sp. By zyl */
+	beq	a1, SYSCALL_ERROR_LABEL	/* no NULL stack pointers */
+
+	/* Save the fn ptr and arg on the new stack.  */
+	subl	a1, 32, a1
+	stl	a0, 0(a1)
+	stl	a3, 8(a1)
+	stl	a2, 16(a1)
+
+	/* The syscall is of the form clone(flags, usp, ptid, ctid, tls).
+	   Shift the flags, ptid, ctid, tls arguments into place; the
+	   child_stack argument is already correct.  */
+	mov	a2, a0
+	mov	a4, a2
+	ldl	a3, 0(sp)
+	mov	a5, a4
+
+	/* Do the system call.  */
+	ldi	v0, __NR_clone
+	sys_call HMC_callsys
+
+	bne	a3, SYSCALL_ERROR_LABEL
+	beq	v0, thread_start
+
+	/* Successful return from the parent.  */
+	ret
+
+PSEUDO_END(__clone)
+	cfi_endproc
+
+/* Load up the arguments to the function.  Put this block of code in
+   its own function so that we can terminate the stack trace with our
+   debug info.  */
+
+	.align	4
+	.ent thread_start
+	cfi_startproc
+thread_start:
+	mov	0, fp
+	cfi_def_cfa_register(fp)
+	cfi_undefined(ra)
+
+	/* Load up the arguments.  */
+	ldl	pv, 0(sp)
+	ldl	a0, 8(sp)
+	addl	sp, 32, sp
+
+	/* Call the user's function.  */
+	call	ra, (pv)
+	ldgp	gp, 0(ra)
+
+	mov     v0, a0
+	ldi	v0, __NR_exit
+	sys_call HMC_callsys
+
+	/* Die horribly.  */
+	.align	4
+	halt
+
+	.align	4
+	cfi_endproc
+	.end thread_start
+
+libc_hidden_def (__clone)
+weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/sw_64/syscall.S b/sysdeps/unix/sysv/linux/sw_64/syscall.S
new file mode 100644
index 00000000..286b9925
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sw_64/syscall.S
@@ -0,0 +1,70 @@
+/* Copyright (C) 1996-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by David Mosberger <davidm@azstarnet.com>, 1996.
+
+   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>
+
+/*
+ * This is for COMPATIBILITY with Linux/x86 only.  Linux/Sw_64 system
+ * calls return an error indication in a3.  This allows arbitrary 64bit
+ * values to be returned in v0 (because negative values are not
+ * mistaken as error numbers).  However, C allows only one value to
+ * be returned, so the interface below foflds the error indication passed in
+ * a3 back into v0: it sets v0 to -errno if an error occurs.  Thus,
+ * no negative 64bit numbers can be returned.  To avoid this problem,
+ * use assembly stubs wherever possible/convenient.
+ *
+ * Usage:
+ *
+ * long	syscall(syscall_number, arg1, arg2, arg3, arg4, arg5, arg6)
+ *
+ * syscall_number = the index of the system call we're invoking
+ * arg1-arg6 = up to 6 integer arguments to the system call
+ *
+ * We need to do some arg shifting: the kernel expects the
+ * syscall number in v0 and the first six args in a0-a5.
+ *
+ */
+
+
+LEAF(__syscall, 0)
+#ifdef PROF
+	ldgp	gp, 0(pv)
+	.set noat
+	ldi	AT, _mcount
+	call	AT, (AT), _mcount
+	.set at
+	.prologue 1
+#else
+	.prologue 0
+#endif
+
+	mov	a0, v0		/* Syscall number -> v0 */
+	mov	a1, a0		/* arg1-arg5 -> a0-a4 */
+	mov	a2, a1
+	mov	a3, a2
+	mov	a4, a3
+	mov	a5, a4
+	ldl	a5,0(sp)	/* arg6 -> a5 */
+
+	sys_call HMC_callsys	/* Invoke system call */
+	bne	a3, SYSCALL_ERROR_LABEL
+	ret
+
+PSEUDO_END(__syscall)
+
+weak_alias (__syscall, syscall)
diff --git a/sysdeps/unix/sysv/linux/sw_64/sysdep.h b/sysdeps/unix/sysv/linux/sw_64/sysdep.h
new file mode 100644
index 00000000..f047c609
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sw_64/sysdep.h
@@ -0,0 +1,355 @@
+/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995.
+
+   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 _LINUX_SW_64_SYSDEP_H
+#define _LINUX_SW_64_SYSDEP_H 1
+
+/* There is some commonality.  */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
+#include <sysdeps/unix/sysdep.h>
+#include <dl-sysdep.h> /* Defines RTLD_PRIVATE_ERRNO.  */
+
+#include <tls.h>
+
+/* For Linux we can use the system call table in the header file
+	/usr/include/asm/unistd.h
+   of the kernel.  But these symbols do not follow the SYS_* syntax
+   so we have to redefine the `SYS_ify' macro here.  */
+#undef SYS_ify
+#define SYS_ify(syscall_name) __NR_##syscall_name
+
+#define SINGLE_THREAD_BY_GLOBAL 1
+
+#ifdef __ASSEMBLER__
+#  include <asm/hmcall.h>
+#  include <sw_64/regdef.h>
+
+#  define __LABEL(x) x##:
+
+#  define LEAF(name, framesize)					       \
+    .globl name;							      \
+    .align 4;								 \
+    .ent name, 0;							     \
+    __LABEL (name).frame sp, framesize, ra
+
+#  define ENTRY(name)							 \
+    .globl name;							      \
+    .align 4;								 \
+    .ent name, 0;							     \
+    __LABEL (name).frame sp, 0, ra
+
+/* Mark the end of function SYM.  */
+#  undef END
+#  define END(sym) .end sym
+
+#  ifdef PROF
+#    define PSEUDO_PROF						       \
+      .set noat;							      \
+      ldi AT, _mcount;							\
+      call AT, (AT), _mcount;						 \
+      .set at
+#  else
+#    define PSEUDO_PROF
+#  endif
+
+#  ifdef PROF
+#    define PSEUDO_PROLOGUE						   \
+      .frame sp, 0, ra;						       \
+      ldgp gp, 0(pv);							 \
+      PSEUDO_PROF;							    \
+      .prologue 1
+#  elif defined PIC
+#    define PSEUDO_PROLOGUE						   \
+      .frame sp, 0, ra;						       \
+      .prologue 0
+#  else
+#    define PSEUDO_PROLOGUE						   \
+      .frame sp, 0, ra;						       \
+      ldgp gp, 0(pv);							 \
+      .prologue 1
+#  endif /* PROF */
+
+#  ifdef PROF
+#    define USEPV_PROF std
+#  else
+#    define USEPV_PROF no
+#  endif
+
+#  undef SYSCALL_ERROR_LABEL
+#  if RTLD_PRIVATE_ERRNO
+#    define SYSCALL_ERROR_LABEL $syscall_error
+#    define SYSCALL_ERROR_HANDLER					     \
+    $syscall_error:							   \
+      stw v0, rtld_errno (gp) !gprel;					 \
+      ldi v0, -1;							     \
+      ret
+#    define SYSCALL_ERROR_FALLTHRU
+#  elif defined(PIC)
+#    define SYSCALL_ERROR_LABEL __syscall_error !samegp
+#    define SYSCALL_ERROR_HANDLER
+#    define SYSCALL_ERROR_FALLTHRU br SYSCALL_ERROR_LABEL
+#  else
+#    define SYSCALL_ERROR_LABEL $syscall_error
+#    define SYSCALL_ERROR_HANDLER					     \
+    $syscall_error:							   \
+      jmp $31, __syscall_error
+#    define SYSCALL_ERROR_FALLTHRU
+#  endif /* RTLD_PRIVATE_ERRNO */
+
+/* Overridden by specific syscalls.  */
+#  undef PSEUDO_PREPARE_ARGS
+#  define PSEUDO_PREPARE_ARGS /* Nothing.  */
+
+#  define PSEUDO(name, syscall_name, args)				    \
+    .globl name;							      \
+    .align 4;								 \
+    .ent name, 0;							     \
+    __LABEL (name)							    \
+    PSEUDO_PROLOGUE;							  \
+    PSEUDO_PREPARE_ARGS						       \
+    ldi v0, SYS_ify (syscall_name);					   \
+    sys_call HMC_callsys;						     \
+    bne a3, SYSCALL_ERROR_LABEL
+
+#  undef PSEUDO_END
+#  define PSEUDO_END(sym)						     \
+    SYSCALL_ERROR_HANDLER;						    \
+    END (sym)
+
+#  define PSEUDO_NOERRNO(name, syscall_name, args)			    \
+    .globl name;							      \
+    .align 4;								 \
+    .ent name, 0;							     \
+    __LABEL (name)							    \
+    PSEUDO_PROLOGUE;							  \
+    PSEUDO_PREPARE_ARGS						       \
+    ldi v0, SYS_ify (syscall_name);					   \
+    sys_call HMC_callsys;
+
+#  undef PSEUDO_END_NOERRNO
+#  define PSEUDO_END_NOERRNO(sym) END (sym)
+
+#  define ret_NOERRNO ret
+
+#  define PSEUDO_ERRVAL(name, syscall_name, args)			     \
+    .globl name;							      \
+    .align 4;								 \
+    .ent name, 0;							     \
+    __LABEL (name)							    \
+    PSEUDO_PROLOGUE;							  \
+    PSEUDO_PREPARE_ARGS						       \
+    ldi v0, SYS_ify (syscall_name);					   \
+    sys_call HMC_callsys;
+
+#  undef PSEUDO_END_ERRVAL
+#  define PSEUDO_END_ERRVAL(sym) END (sym)
+
+#  define ret_ERRVAL ret
+
+#  define r0 v0
+#  define r1 a4
+
+#  define MOVE(x, y) mov x, y
+
+#else /* !ASSEMBLER */
+
+#define HAVE_CLOCK_GETTIME_VSYSCALL     "__vdso_clock_gettime"
+#define HAVE_CLOCK_GETTIME64_VSYSCALL   "__vdso_clock_gettime64"
+
+#define INTERNAL_SYSCALL(name, nr, args...) \
+	internal_syscall##nr(__NR_##name, args)
+
+#  define INTERNAL_SYSCALL_NCS(name, nr, args...)			     \
+    internal_syscall##nr (name, args)
+
+/* The normal Sw_64 calling convention sign-extends 32-bit quantties
+   no matter what the "real" sign of the 32-bit type.  We want to
+   preserve that when filling in values for the kernel.  */
+#  define syscall_promote(arg)						\
+    (sizeof (arg) == 4 ? (long int) (int) (long int) (arg) : (long int) (arg))
+
+#  define internal_syscall_clobbers					   \
+    "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$22", "$23", "$24",      \
+	"$25", "$27", "$28", "memory"
+
+/* It is moderately important optimization-wise to limit the lifetime
+   of the hard-register variables as much as possible.  Thus we copy
+   in/out as close to the asm as possible.  */
+
+#  define internal_syscall0(name, args...)				    \
+    ({									\
+      register long int _sc_19 __asm__("$19");				\
+      register long int _sc_0 = name;					 \
+      __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2"		      \
+			   : "+v"(_sc_0), "=r"(_sc_19)			\
+			   :						  \
+			   : internal_syscall_clobbers, "$16", "$17", "$18",  \
+			     "$20", "$21");				   \
+      _sc_19 != 0 ? -_sc_0 : _sc_0;					   \
+    })
+
+#  define internal_syscall1(name, arg1)				       \
+    ({									\
+      register long int _tmp_16 = syscall_promote (arg1);		     \
+      register long int _sc_0 = name;					 \
+      register long int _sc_16 __asm__("$16") = _tmp_16;		      \
+      register long int _sc_19 __asm__("$19");				\
+      __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3"		   \
+			   : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16)	  \
+			   :						  \
+			   : internal_syscall_clobbers, "$17", "$18", "$20",  \
+			     "$21");					  \
+      _sc_19 != 0 ? -_sc_0 : _sc_0;					   \
+    })
+
+#  define internal_syscall2(name, arg1, arg2)				 \
+    ({									\
+      register long int _tmp_16 = syscall_promote (arg1);		     \
+      register long int _tmp_17 = syscall_promote (arg2);		     \
+      register long int _sc_0 = name;					 \
+      register long int _sc_16 __asm__("$16") = _tmp_16;		      \
+      register long int _sc_17 __asm__("$17") = _tmp_17;		      \
+      register long int _sc_19 __asm__("$19");				\
+      __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4"		\
+			   : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16),	 \
+			     "+r"(_sc_17)				     \
+			   :						  \
+			   : internal_syscall_clobbers, "$18", "$20", "$21"); \
+      _sc_19 != 0 ? -_sc_0 : _sc_0;					   \
+    })
+
+#  define internal_syscall3(name, arg1, arg2, arg3)			   \
+    ({									\
+      register long int _tmp_16 = syscall_promote (arg1);		     \
+      register long int _tmp_17 = syscall_promote (arg2);		     \
+      register long int _tmp_18 = syscall_promote (arg3);		     \
+      register long int _sc_0 = name;					 \
+      register long int _sc_16 __asm__("$16") = _tmp_16;		      \
+      register long int _sc_17 __asm__("$17") = _tmp_17;		      \
+      register long int _sc_18 __asm__("$18") = _tmp_18;		      \
+      register long int _sc_19 __asm__("$19");				\
+      __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5"	     \
+			   : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16),	 \
+			     "+r"(_sc_17), "+r"(_sc_18)		       \
+			   :						  \
+			   : internal_syscall_clobbers, "$20", "$21");	\
+      _sc_19 != 0 ? -_sc_0 : _sc_0;					   \
+    })
+
+#  define internal_syscall4(name, arg1, arg2, arg3, arg4)		     \
+    ({									\
+      register long int _tmp_16 = syscall_promote (arg1);		     \
+      register long int _tmp_17 = syscall_promote (arg2);		     \
+      register long int _tmp_18 = syscall_promote (arg3);		     \
+      register long int _tmp_19 = syscall_promote (arg4);		     \
+      register long int _sc_0 = name;					 \
+      register long int _sc_16 __asm__("$16") = _tmp_16;		      \
+      register long int _sc_17 __asm__("$17") = _tmp_17;		      \
+      register long int _sc_18 __asm__("$18") = _tmp_18;		      \
+      register long int _sc_19 __asm__("$19") = _tmp_19;		      \
+      __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5 %6"	  \
+			   : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16),	 \
+			     "+r"(_sc_17), "+r"(_sc_18)		       \
+			   :						  \
+			   : internal_syscall_clobbers, "$20", "$21");	\
+      _sc_19 != 0 ? -_sc_0 : _sc_0;					   \
+    })
+
+#  define internal_syscall5(name, arg1, arg2, arg3, arg4, arg5)	       \
+    ({									\
+      register long int _tmp_16 = syscall_promote (arg1);		     \
+      register long int _tmp_17 = syscall_promote (arg2);		     \
+      register long int _tmp_18 = syscall_promote (arg3);		     \
+      register long int _tmp_19 = syscall_promote (arg4);		     \
+      register long int _tmp_20 = syscall_promote (arg5);		     \
+      register long int _sc_0 = name;					 \
+      register long int _sc_16 __asm__("$16") = _tmp_16;		      \
+      register long int _sc_17 __asm__("$17") = _tmp_17;		      \
+      register long int _sc_18 __asm__("$18") = _tmp_18;		      \
+      register long int _sc_19 __asm__("$19") = _tmp_19;		      \
+      register long int _sc_20 __asm__("$20") = _tmp_20;		      \
+      __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5 %6 %7"       \
+			   : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16),	 \
+			     "+r"(_sc_17), "+r"(_sc_18), "+r"(_sc_20)	 \
+			   :						  \
+			   : internal_syscall_clobbers, "$21");	       \
+      _sc_19 != 0 ? -_sc_0 : _sc_0;					   \
+    })
+
+#  define internal_syscall6(name, arg1, arg2, arg3, arg4, arg5, arg6)	 \
+    ({									\
+      register long int _tmp_16 = syscall_promote (arg1);		     \
+      register long int _tmp_17 = syscall_promote (arg2);		     \
+      register long int _tmp_18 = syscall_promote (arg3);		     \
+      register long int _tmp_19 = syscall_promote (arg4);		     \
+      register long int _tmp_20 = syscall_promote (arg5);		     \
+      register long int _tmp_21 = syscall_promote (arg6);		     \
+      register long int _sc_0 = name;					 \
+      register long int _sc_16 __asm__("$16") = _tmp_16;		      \
+      register long int _sc_17 __asm__("$17") = _tmp_17;		      \
+      register long int _sc_18 __asm__("$18") = _tmp_18;		      \
+      register long int _sc_19 __asm__("$19") = _tmp_19;		      \
+      register long int _sc_20 __asm__("$20") = _tmp_20;		      \
+      register long int _sc_21 __asm__("$21") = _tmp_21;		      \
+      __asm__ __volatile__("sys_call 0x83 # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"    \
+			   : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16),	 \
+			     "+r"(_sc_17), "+r"(_sc_18), "+r"(_sc_20),	\
+			     "+r"(_sc_21)				     \
+			   :						  \
+			   : internal_syscall_clobbers);		      \
+      _sc_19 != 0 ? -_sc_0 : _sc_0;					   \
+    })
+#endif /* ASSEMBLER */
+
+/* Pointer mangling support.  Note that tls access is slow enough that
+   we don't deoptimize things by placing the pointer check value there.  */
+
+#ifdef __ASSEMBLER__
+#  if IS_IN(rtld)
+#    define PTR_MANGLE(dst, src, tmp)					 \
+      ldih tmp, __pointer_chk_guard_local ($29) !gprelhigh;		   \
+      ldl tmp, __pointer_chk_guard_local (tmp) !gprellow;		     \
+      xor src, tmp, dst
+#    define PTR_MANGLE2(dst, src, tmp) xor src, tmp, dst
+#  elif defined SHARED
+#    define PTR_MANGLE(dst, src, tmp)					 \
+      ldl tmp, __pointer_chk_guard;					   \
+      xor src, tmp, dst
+#  else
+#    define PTR_MANGLE(dst, src, tmp)					 \
+      ldl tmp, __pointer_chk_guard_local;				     \
+      xor src, tmp, dst
+#  endif
+#  define PTR_MANGLE2(dst, src, tmp) xor src, tmp, dst
+#  define PTR_DEMANGLE(dst, tmp) PTR_MANGLE (dst, dst, tmp)
+#  define PTR_DEMANGLE2(dst, tmp) PTR_MANGLE2 (dst, dst, tmp)
+#else
+#  include <stdint.h>
+#  if (IS_IN(rtld) || (!defined SHARED && (IS_IN(libc) || IS_IN(libpthread))))
+extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
+#    define PTR_MANGLE(var)						   \
+      (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
+#  else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#    define PTR_MANGLE(var)						   \
+      (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
+#  endif
+#  define PTR_DEMANGLE(var) PTR_MANGLE (var)
+#endif /* ASSEMBLER */
+
+#endif /* _LINUX_SW_64_SYSDEP_H  */
diff --git a/sysdeps/unix/sysv/linux/sw_64/vfork.S b/sysdeps/unix/sysv/linux/sw_64/vfork.S
new file mode 100644
index 00000000..a79eb93a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sw_64/vfork.S
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004-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 <tcb-offsets.h>
+
+ENTRY(__libc_vfork)
+	PSEUDO_PROLOGUE
+
+	/* Load the thread pointer value in A1 across the vfork.  */
+	sys_call        0x9e
+	mov	v0, a1
+
+	ldi	v0, SYS_ify(vfork)
+	sys_call HMC_callsys
+
+	/* Normal error check and return.  */
+	bne	a3, SYSCALL_ERROR_LABEL
+	ret
+
+PSEUDO_END (__libc_vfork)
+
+#if IS_IN (libc)
+weak_alias (__libc_vfork, vfork)
+strong_alias (__libc_vfork, __vfork)
+libc_hidden_def (__vfork)
+#endif
-- 
2.25.1

