Ver Fonte

loongarch: add basic static only support

Waldemar Brodkorb há 1 semana atrás
pai
commit
2f20790600

+ 8 - 0
extra/Configs/Config.in

@@ -30,6 +30,7 @@ choice
 	default TARGET_ia64 if DESIRED_TARGET_ARCH = "ia64"
 	default TARGET_kvx if DESIRED_TARGET_ARCH = "kvx"
 	default TARGET_lm32 if DESIRED_TARGET_ARCH = "lm32"
+	default TARGET_loongarch if DESIRED_TARGET_ARCH = "loongarch"
 	default TARGET_m68k if DESIRED_TARGET_ARCH = "m68k"
 	default TARGET_metag if DESIRED_TARGET_ARCH = "metag"
 	default TARGET_microblaze if DESIRED_TARGET_ARCH = "microblaze"
@@ -99,6 +100,9 @@ config TARGET_kvx
 config TARGET_lm32
 	bool "lm32"
 
+config TARGET_loongarch
+	bool "loongarch"
+
 config TARGET_m68k
 	bool "m68k"
 
@@ -229,6 +233,10 @@ if TARGET_lm32
 source "extra/Configs/Config.lm32"
 endif
 
+if TARGET_loongarch
+source "extra/Configs/Config.loongarch"
+endif
+
 if TARGET_m68k
 source "extra/Configs/Config.m68k"
 endif

+ 15 - 0
extra/Configs/Config.loongarch

@@ -0,0 +1,15 @@
+#
+# For a description of the syntax of this configuration file,
+# see extra/config/Kconfig-language.txt
+#
+
+config TARGET_ARCH
+	string
+	default "loongarch"
+
+config FORCE_OPTIONS_FOR_ARCH
+	bool
+	default y
+	select ARCH_LITTLE_ENDIAN
+	select ARCH_HAS_MMU
+	select ARCH_HAS_NO_LDSO

+ 10 - 0
libc/sysdeps/linux/loongarch/Makefile

@@ -0,0 +1,10 @@
+# Makefile for uClibc-ng
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_srcdir=../../../../
+top_builddir=../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules

+ 6 - 0
libc/sysdeps/linux/loongarch/Makefile.arch

@@ -0,0 +1,6 @@
+# Makefile for uClibc-ng
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+CSRC-y := 
+SSRC-y := clone.S __longjmp.S setjmp.S sysdep.S

+ 56 - 0
libc/sysdeps/linux/loongarch/__longjmp.S

@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* longjmp.
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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 <sys/asm.h>
+
+ENTRY (__longjmp)
+	REG_L ra, a0, 0*SZREG
+	REG_L sp, a0, 1*SZREG
+	REG_L x,  a0, 2*SZREG
+	REG_L fp, a0, 3*SZREG
+	REG_L s0, a0, 4*SZREG
+	REG_L s1, a0, 5*SZREG
+	REG_L s2, a0, 6*SZREG
+	REG_L s3, a0, 7*SZREG
+	REG_L s4, a0, 8*SZREG
+	REG_L s5, a0, 9*SZREG
+	REG_L s6, a0, 10*SZREG
+	REG_L s7, a0, 11*SZREG
+	REG_L s8, a0, 12*SZREG
+
+#ifndef __loongarch_soft_float
+	FREG_L fs0, a0, 13*SZREG + 0*SZFREG
+	FREG_L fs1, a0, 13*SZREG + 1*SZFREG
+	FREG_L fs2, a0, 13*SZREG + 2*SZFREG
+	FREG_L fs3, a0, 13*SZREG + 3*SZFREG
+	FREG_L fs4, a0, 13*SZREG + 4*SZFREG
+	FREG_L fs5, a0, 13*SZREG + 5*SZFREG
+	FREG_L fs6, a0, 13*SZREG + 6*SZFREG
+	FREG_L fs7, a0, 13*SZREG + 7*SZFREG
+#endif
+
+	sltui	a0, a1, 1
+	ADD	a0, a0, a1	 # a0 = (a1 == 0) ? 1 : a1
+	jirl	zero, ra, 0
+
+END (__longjmp)
+libc_hidden_def(__longjmp)

+ 18 - 0
libc/sysdeps/linux/loongarch/bits/endian.h

@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* This file should define __BYTE_ORDER as appropriate for the machine
+   in question.  See string/endian.h for how to define it.
+
+   If only the stub bits/endian.h applies to a particular configuration,
+   bytesex.h is generated by running a program on the host machine.
+   So if cross-compiling to a machine with a different byte order,
+   the bits/endian.h file for that machine must exist.  */
+
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+#define __BYTE_ORDER __LITTLE_ENDIAN

+ 229 - 0
libc/sysdeps/linux/loongarch/bits/fcntl.h

@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#ifndef	_FCNTL_H
+# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
+#endif
+
+#include <sys/types.h>
+#ifdef __USE_GNU
+# include <bits/uio.h>
+#endif
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	  0003
+#define O_RDONLY	    00
+#define O_WRONLY	    01
+#define O_RDWR		    02
+#define O_CREAT		  0100	/* not fcntl */
+#define O_EXCL		  0200	/* not fcntl */
+#define O_NOCTTY	  0400	/* not fcntl */
+#define O_TRUNC		 01000	/* not fcntl */
+#define O_APPEND	 02000
+#define O_NONBLOCK	 04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		010000
+#define O_FSYNC		O_SYNC
+#define O_ASYNC		020000
+
+#ifdef __USE_XOPEN2K8
+# define O_DIRECTORY   0200000	/* Must be a directory.	 */
+# define O_NOFOLLOW    0400000	/* Do not follow links.	 */
+# define O_CLOEXEC    02000000	/* Set close_on_exec.  */
+#endif
+
+#ifdef __USE_GNU
+# define O_DIRECT	040000	/* Direct disk access.	*/
+# define O_NOATIME    01000000	/* Do not set atime.  */
+# define O_PATH	     010000000  /* Resolve pathname but do not open file.  */
+# define O_TMPFILE   020200000  /* Atomically create nameless file.  */
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define O_LARGEFILE   0100000
+#endif
+
+/* For now Linux has synchronisity options for data and read operations.
+   We define the symbols here but let them do the same as O_SYNC since
+   this is a superset.	*/
+#if defined __USE_POSIX199309 || defined __USE_UNIX98
+# define O_DSYNC	O_SYNC	/* Synchronize data.  */
+# define O_RSYNC	O_SYNC	/* Synchronize read operations.	 */
+#endif
+
+/* Values for the second argument to `fcntl'.  */
+#define F_DUPFD		0	/* Duplicate file descriptor.  */
+#define F_GETFD		1	/* Get file descriptor flags.  */
+#define F_SETFD		2	/* Set file descriptor flags.  */
+#define F_GETFL		3	/* Get file status flags.  */
+#define F_SETFL		4	/* Set file status flags.  */
+
+#define F_GETLK		5	/* Get record locking info.  */
+#define F_SETLK		6	/* Set record locking info (non-blocking).  */
+#define F_SETLKW	7	/* Set record locking info (blocking).	*/
+
+/* Same as standard, since we always have 64-bit offsets.  */
+#define F_GETLK64	F_GETLK		/* Get record locking info.  */
+#define F_SETLK64	F_SETLK		/* Set record locking info (non-blocking).  */
+#define F_SETLKW64	F_SETLKW	/* Set record locking info (blocking).	*/
+
+#if defined __USE_BSD || defined __USE_XOPEN2K
+# define F_SETOWN	8	/* Get owner of socket (receiver of SIGIO).  */
+# define F_GETOWN	9	/* Set owner of socket (receiver of SIGIO).  */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETSIG	10	/* Set number of signal to be sent.  */
+# define F_GETSIG	11	/* Get number of signal to be sent.  */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETLEASE	1024	/* Set a lease.	 */
+# define F_GETLEASE	1025	/* Enquire what lease is active.  */
+# define F_NOTIFY	1026	/* Request notfications on a directory.	 */
+# define F_SETPIPE_SZ	1031    /* Set pipe page size array.  */
+# define F_GETPIPE_SZ	1032    /* Get pipe page size array.  */
+#endif
+#if defined __USE_XOPEN2K8 || defined __USE_GNU
+# define F_DUPFD_CLOEXEC 1030	/* Duplicate file descriptor with
+				   close-on-exit set on new fd.  */
+#endif
+
+/* For F_[GET|SET]FL.  */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* For posix fcntl() and `l_type' field of a `struct flock' for lockf().  */
+#define F_RDLCK		0	/* Read lock.  */
+#define F_WRLCK		1	/* Write lock.	*/
+#define F_UNLCK		2	/* Remove lock.	 */
+
+/* For old implementation of bsd flock().  */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+#ifdef __USE_BSD
+/* Operations for bsd flock(), also used by the kernel implementation.	*/
+# define LOCK_SH	1	/* shared lock */
+# define LOCK_EX	2	/* exclusive lock */
+# define LOCK_NB	4	/* or'd with one of the above to prevent
+				   blocking */
+# define LOCK_UN	8	/* remove lock */
+#endif
+
+#ifdef __USE_GNU
+# define LOCK_MAND	32	/* This is a mandatory flock:	*/
+# define LOCK_READ	64	/* ... which allows concurrent read operations.	 */
+# define LOCK_WRITE	128	/* ... which allows concurrent write operations.  */
+# define LOCK_RW	192	/* ... Which allows concurrent read & write operations.	 */
+#endif
+
+#ifdef __USE_GNU
+/* Types of directory notifications that may be requested with F_NOTIFY.  */
+# define DN_ACCESS	0x00000001	/* File accessed.  */
+# define DN_MODIFY	0x00000002	/* File modified.  */
+# define DN_CREATE	0x00000004	/* File created.  */
+# define DN_DELETE	0x00000008	/* File removed.  */
+# define DN_RENAME	0x00000010	/* File renamed.  */
+# define DN_ATTRIB	0x00000020	/* File changed attibutes.  */
+# define DN_MULTISHOT	0x80000000	/* Don't remove notifier.  */
+#endif
+
+struct flock
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+#ifndef __USE_FILE_OFFSET64
+    __off_t l_start;	/* Offset where the lock begins.  */
+    __off_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#else
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#endif
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+
+#ifdef __USE_LARGEFILE64
+struct flock64
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+#endif
+
+/* Define some more compatibility macros to be backward compatible with
+   BSD systems which did not managed to hide these kernel macros.  */
+#ifdef	__USE_BSD
+# define FAPPEND	O_APPEND
+# define FFSYNC		O_FSYNC
+# define FASYNC		O_ASYNC
+# define FNONBLOCK	O_NONBLOCK
+# define FNDELAY	O_NDELAY
+#endif /* Use BSD.  */
+
+/* Advise to `posix_fadvise'.  */
+#ifdef __USE_XOPEN2K
+# define POSIX_FADV_NORMAL	0 /* No further special treatment.  */
+# define POSIX_FADV_RANDOM	1 /* Expect random page references.  */
+# define POSIX_FADV_SEQUENTIAL	2 /* Expect sequential page references.	 */
+# define POSIX_FADV_WILLNEED	3 /* Will need these pages.  */
+# define POSIX_FADV_DONTNEED	4 /* Don't need these pages.  */
+# define POSIX_FADV_NOREUSE	5 /* Data will be accessed once.  */
+#endif
+
+#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__
+/* Flags for SYNC_FILE_RANGE.  */
+# define SYNC_FILE_RANGE_WAIT_BEFORE	1 /* Wait upon writeout of all pages
+					     in the range before performing the
+					     write.  */
+# define SYNC_FILE_RANGE_WRITE		2 /* Initiate writeout of all those
+					     dirty pages in the range which are
+					     not presently under writeback.  */
+# define SYNC_FILE_RANGE_WAIT_AFTER	4 /* Wait upon writeout of all pages in
+					     the range after performing the
+					     write.  */
+
+/* Flags for SPLICE and VMSPLICE.  */
+# define SPLICE_F_MOVE		1	/* Move pages instead of copying.  */
+# define SPLICE_F_NONBLOCK	2	/* Don't block on the pipe splicing
+					   (but we may still block on the fd
+					   we splice from/to).  */
+# define SPLICE_F_MORE		4	/* Expect more data.  */
+# define SPLICE_F_GIFT		8	/* Pages passed in are a gift.  */
+#endif
+
+__BEGIN_DECLS
+
+#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__
+
+/* Provide kernel hint to read ahead.  */
+extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count)
+    __THROW;
+
+/* Selective file content synch'ing.  */
+extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to,
+			    unsigned int __flags);
+
+/* Splice address range into a pipe.  */
+extern ssize_t vmsplice (int __fdout, const struct iovec *__iov,
+			 size_t __count, unsigned int __flags);
+
+/* Splice two files together.  */
+extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout,
+		       __off64_t *__offout, size_t __len,
+		       unsigned int __flags);
+
+/* In-kernel implementation of tee for pipe buffers.  */
+extern ssize_t tee (int __fdin, int __fdout, size_t __len,
+		    unsigned int __flags);
+
+#endif
+__END_DECLS
+
+/* Include generic Linux declarations.  */
+#include <bits/fcntl-linux.h>

+ 49 - 0
libc/sysdeps/linux/loongarch/bits/kernel_types.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Note that we use the exact same include guard #define names
+ * as asm/posix_types.h.  This will avoid gratuitous conflicts
+ * with the posix_types.h kernel header, and will ensure that
+ * our private content, and not the kernel header, will win.
+ *  -Erik
+ */
+#ifndef __ASM_GENERIC_POSIX_TYPES_H
+#define __ASM_GENERIC_POSIX_TYPES_H
+
+#include <asm/bitsperlong.h>
+
+typedef unsigned long		__kernel_dev_t;
+typedef unsigned long		__kernel_ino_t;
+typedef unsigned int		__kernel_mode_t;
+typedef unsigned int		__kernel_nlink_t;
+typedef long			__kernel_off_t;
+typedef int			__kernel_pid_t;
+typedef int 			__kernel_ipc_pid_t;
+typedef unsigned int		__kernel_uid_t;
+typedef unsigned int		__kernel_gid_t;
+typedef unsigned long		__kernel_size_t;
+typedef long			__kernel_ssize_t;
+typedef long			__kernel_ptrdiff_t;
+typedef long			__kernel_time_t;
+typedef long			__kernel_suseconds_t;
+typedef long			__kernel_clock_t;
+typedef int			__kernel_daddr_t;
+typedef char *			__kernel_caddr_t;
+typedef unsigned short		__kernel_uid16_t;
+typedef unsigned short		__kernel_gid16_t;
+typedef unsigned int		__kernel_uid32_t;
+typedef unsigned int		__kernel_gid32_t;
+typedef unsigned short 		__kernel_old_uid_t;
+typedef unsigned short 		__kernel_old_gid_t;
+typedef long long		__kernel_loff_t;
+typedef unsigned int		__kernel_old_dev_t;
+typedef long			__kernel_long_t;
+typedef unsigned long		__kernel_ulong_t;
+
+typedef struct {
+	int	val[2];
+} __kernel_fsid_t;
+
+#endif /* __ASM_GENERIC_POSIX_TYPES_H */

+ 46 - 0
libc/sysdeps/linux/loongarch/bits/setjmp.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Define the machine-dependent type `jmp_buf'.
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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 _LOONGARCH_BITS_SETJMP_H
+#define _LOONGARCH_BITS_SETJMP_H
+
+typedef struct __jmp_buf_internal_tag
+{
+  /* Program counter.  */
+  long int __pc;
+  /* Stack pointer.  */
+  long int __sp;
+  /* Reserved */
+  long int __x;
+  /* Frame pointer.  */
+  long int __fp;
+  /* Callee-saved registers.  */
+  long int __regs[9];
+
+#ifndef __loongarch_soft_float
+  /* Callee-saved floating point registers.  */
+  double __fpregs[8];
+#endif
+
+} __jmp_buf[1];
+
+#endif /* _LOONGARCH_BITS_SETJMP_H */

+ 31 - 0
libc/sysdeps/linux/loongarch/bits/stackinfo.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+   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 file contains a bit of information about the stack allocation
+   of the processor.  Since there is no general truth we can't say
+   anything here.  */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H	1
+
+#define _STACK_GROWS_DOWN	1
+
+#endif	/* stackinfo.h */

+ 144 - 0
libc/sysdeps/linux/loongarch/bits/stat.h

@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#ifndef _SYS_STAT_H
+# error "Never include <bits/stat.h> directly; use <sys/stat.h> instead."
+#endif
+
+#include <bits/align64bit.h>
+#include <bits/wordsize.h>
+#include <endian.h>
+
+/* Versions of the `struct stat' data structure.  */
+#define _STAT_VER_LINUX_OLD	1
+#define _STAT_VER_KERNEL	1
+#define _STAT_VER_SVR4		2
+#define _STAT_VER_LINUX		3
+#define _STAT_VER		_STAT_VER_LINUX	/* The one defined below.  */
+
+/* Versions of the `xmknod' interface.  */
+#define _MKNOD_VER_LINUX	1
+#define _MKNOD_VER_SVR4		2
+#define _MKNOD_VER		_MKNOD_VER_LINUX /* The bits defined below.  */
+
+/*
+ * This struct is exactly the same with the stat64 one because kvx is 64 bit
+ */
+struct stat
+  {
+    unsigned long long st_dev;			/* Device. */
+    unsigned long long st_ino;			/* 32bit file serial number. */
+    unsigned int st_mode;			/* File mode.  */
+    unsigned int st_nlink;			/* Link count.  */
+    unsigned int st_uid;			/* User ID of the file's owner.	*/
+    unsigned int st_gid;			/* Group ID of the file's group.*/
+    unsigned long long st_rdev;			/* Device number, if device.  */
+    unsigned long long _pad1;
+    __off_t st_size;				/* SIze of file, in bytes. */
+    int st_blksize;				/* Optimal block size for I/O. */
+    int __pad2;
+    long long st_blocks;			/* Number 512-byte blocks allocated */
+#if defined(__USE_MISC) || defined(__USE_XOPEN2K8)
+    /* Nanosecond resolution timestamps are stored in a format
+       equivalent to 'struct timespec'.  This is the type used
+       whenever possible but the Unix namespace rules do not allow the
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    struct timespec st_atim;			/* Time of last access.  */
+    struct timespec st_mtim;			/* Time of last modification.  */
+    struct timespec st_ctim;			/* Time of last status change.  */
+# define st_atime st_atim.tv_sec		/* Backward compatibility.  */
+# define st_mtime st_mtim.tv_sec
+# define st_ctime st_ctim.tv_sec
+#else
+    long int st_atime;				/* Time of last access. */
+    unsigned long int st_atime_nsec;
+    long int st_mtime;				/* Time of last modification. */
+    unsigned long int st_mtime_nsec;
+    long int st_ctime;				/* Time of last status change. */
+    unsigned long int st_ctime_nsec;
+#endif
+    unsigned int __uclibc_unused4;
+    unsigned int __uclibc_unused5;
+  } __ARCH_64BIT_ALIGNMENT__;
+
+
+#ifdef __USE_LARGEFILE64
+struct stat64
+  {
+    unsigned long long st_dev;			/* Device. */
+    unsigned long long st_ino;			/* 32bit file serial number. */
+    unsigned int st_mode;			/* File mode.  */
+    unsigned int st_nlink;			/* Link count.  */
+    unsigned int st_uid;			/* User ID of the file's owner.	*/
+    unsigned int st_gid;			/* Group ID of the file's group.*/
+    unsigned long long st_rdev;			/* Device number, if device.  */
+    unsigned long long __pad3;
+    long long st_size;				/* Size of file, in bytes. */
+    int st_blksize;				/* Optimal block size for I/O. */
+    int __pad4;
+    long long st_blocks;			/* Number 512-byte blocks allocated */
+# if defined(__USE_MISC) || defined(__USE_XOPEN2K8)
+    /* Nanosecond resolution timestamps are stored in a format
+       equivalent to 'struct timespec'.  This is the type used
+       whenever possible but the Unix namespace rules do not allow the
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    struct timespec st_atim; 			/* Time of last access.  */
+    struct timespec st_mtim; 			/* Time of last modification.  */
+    struct timespec st_ctim; 			/* Time of last status change.  */
+# else
+    long int st_atime;				/* Time of last access. */
+    unsigned long int st_atime_nsec;
+    long int st_mtime;				/* Time of last modification. */
+    unsigned long int st_mtime_nsec;
+    long int st_ctime;				/* Time of last status change. */
+    unsigned long int st_ctime_nsec;
+# endif
+    unsigned int __uclibc_unused4;
+    unsigned int __uclibc_unused5;
+};
+#endif
+
+/* Tell code we have these members.  */
+#define	_STATBUF_ST_BLKSIZE
+#define _STATBUF_ST_RDEV
+/* Nanosecond resolution time values are supported.  */
+#define _STATBUF_ST_NSEC
+
+/* Encoding of the file mode.  */
+
+#define	__S_IFMT	0170000	/* These bits determine file type.  */
+
+/* File types.  */
+#define	__S_IFDIR	0040000	/* Directory.  */
+#define	__S_IFCHR	0020000	/* Character device.  */
+#define	__S_IFBLK	0060000	/* Block device.  */
+#define	__S_IFREG	0100000	/* Regular file.  */
+#define	__S_IFIFO	0010000	/* FIFO.  */
+#define	__S_IFLNK	0120000	/* Symbolic link.  */
+#define	__S_IFSOCK	0140000	/* Socket.  */
+
+/* POSIX.1b objects.  Note that these macros always evaluate to zero.  But
+   they do it by enforcing the correct use of the macros.  */
+#define __S_TYPEISMQ(buf)  ((buf)->st_mode - (buf)->st_mode)
+#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode)
+#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode)
+
+/* Protection bits.  */
+
+#define	__S_ISUID	04000	/* Set user ID on execution.  */
+#define	__S_ISGID	02000	/* Set group ID on execution.  */
+#define	__S_ISVTX	01000	/* Save swapped text after use (sticky).  */
+#define	__S_IREAD	0400	/* Read by owner.  */
+#define	__S_IWRITE	0200	/* Write by owner.  */
+#define	__S_IEXEC	0100	/* Execute by owner.  */
+
+#ifdef __USE_ATFILE
+# define UTIME_NOW	((1l << 30) - 1l)
+# define UTIME_OMIT	((1l << 30) - 2l)
+#endif

+ 210 - 0
libc/sysdeps/linux/loongarch/bits/syscalls.h

@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Assembly macros for LoongArch.
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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 <sys/regdef.h>
+
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+  internal_syscall##nr (number, err, args)
+
+#define internal_syscall0(number, err, dummy...) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0"); \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "=r"(__a0) \
+		       : "r"(__a7) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define internal_syscall1(number, err, arg0) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      long int _arg0 = (long int) (arg0); \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0") = _arg0; \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "+r"(__a0) \
+		       : "r"(__a7) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define internal_syscall2(number, err, arg0, arg1) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      long int _arg0 = (long int) (arg0); \
+      long int _arg1 = (long int) (arg1); \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0") = _arg0; \
+      register long int __a1 __asm__ ("$a1") = _arg1; \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "+r"(__a0) \
+		       : "r"(__a7), "r"(__a1) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define internal_syscall3(number, err, arg0, arg1, arg2) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      long int _arg0 = (long int) (arg0); \
+      long int _arg1 = (long int) (arg1); \
+      long int _arg2 = (long int) (arg2); \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0") = _arg0; \
+      register long int __a1 __asm__ ("$a1") = _arg1; \
+      register long int __a2 __asm__ ("$a2") = _arg2; \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "+r"(__a0) \
+		       : "r"(__a7), "r"(__a1), "r"(__a2) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define internal_syscall4(number, err, arg0, arg1, arg2, arg3) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      long int _arg0 = (long int) (arg0); \
+      long int _arg1 = (long int) (arg1); \
+      long int _arg2 = (long int) (arg2); \
+      long int _arg3 = (long int) (arg3); \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0") = _arg0; \
+      register long int __a1 __asm__ ("$a1") = _arg1; \
+      register long int __a2 __asm__ ("$a2") = _arg2; \
+      register long int __a3 __asm__ ("$a3") = _arg3; \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "+r"(__a0) \
+		       : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      long int _arg0 = (long int) (arg0); \
+      long int _arg1 = (long int) (arg1); \
+      long int _arg2 = (long int) (arg2); \
+      long int _arg3 = (long int) (arg3); \
+      long int _arg4 = (long int) (arg4); \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0") = _arg0; \
+      register long int __a1 __asm__ ("$a1") = _arg1; \
+      register long int __a2 __asm__ ("$a2") = _arg2; \
+      register long int __a3 __asm__ ("$a3") = _arg3; \
+      register long int __a4 __asm__ ("$a4") = _arg4; \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "+r"(__a0) \
+		       : "r"(__a7), "r"(__a1), "r"(__a2), \
+			 "r"(__a3), "r"(__a4) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      long int _arg0 = (long int) (arg0); \
+      long int _arg1 = (long int) (arg1); \
+      long int _arg2 = (long int) (arg2); \
+      long int _arg3 = (long int) (arg3); \
+      long int _arg4 = (long int) (arg4); \
+      long int _arg5 = (long int) (arg5); \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0") = _arg0; \
+      register long int __a1 __asm__ ("$a1") = _arg1; \
+      register long int __a2 __asm__ ("$a2") = _arg2; \
+      register long int __a3 __asm__ ("$a3") = _arg3; \
+      register long int __a4 __asm__ ("$a4") = _arg4; \
+      register long int __a5 __asm__ ("$a5") = _arg5; \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "+r"(__a0) \
+		       : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \
+			 "r"(__a4), "r"(__a5) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \
+  ({ \
+    long int _sys_result; \
+\
+    { \
+      long int _arg0 = (long int) (arg0); \
+      long int _arg1 = (long int) (arg1); \
+      long int _arg2 = (long int) (arg2); \
+      long int _arg3 = (long int) (arg3); \
+      long int _arg4 = (long int) (arg4); \
+      long int _arg5 = (long int) (arg5); \
+      long int _arg6 = (long int) (arg6); \
+      register long int __a7 __asm__ ("$a7") = number; \
+      register long int __a0 __asm__ ("$a0") = _arg0; \
+      register long int __a1 __asm__ ("$a1") = _arg1; \
+      register long int __a2 __asm__ ("$a2") = _arg2; \
+      register long int __a3 __asm__ ("$a3") = _arg3; \
+      register long int __a4 __asm__ ("$a4") = _arg4; \
+      register long int __a5 __asm__ ("$a5") = _arg5; \
+      register long int __a6 __asm__ ("$a6") = _arg6; \
+      __asm__ volatile ("syscall 0\n\t" \
+		       : "+r"(__a0) \
+		       : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \
+			 "r"(__a4), "r"(__a5), "r"(__a6) \
+		       : __SYSCALL_CLOBBERS); \
+      _sys_result = __a0; \
+    } \
+    _sys_result; \
+  })
+
+#define __SYSCALL_CLOBBERS \
+  "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+

+ 49 - 0
libc/sysdeps/linux/loongarch/bits/uClibc_arch_features.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/*
+ * Track misc arch-specific features that aren't config options
+ */
+
+#ifndef _BITS_UCLIBC_ARCH_FEATURES_H
+#define _BITS_UCLIBC_ARCH_FEATURES_H
+
+/* instruction used when calling abort() to kill yourself */
+#define __UCLIBC_ABORT_INSTRUCTION__ ""
+
+/* can your target use syscall6() for mmap ? */
+#define __UCLIBC_MMAP_HAS_6_ARGS__
+
+/* does your target use statx */
+#define __UCLIBC_HAVE_STATX__
+
+/* does your target align 64bit values in register pairs ? (32bit arches only) */
+#undef __UCLIBC_SYSCALL_ALIGN_64BIT__
+
+/* does your target have a broken create_module() ? */
+#undef __UCLIBC_BROKEN_CREATE_MODULE__
+
+/* does your target have to worry about older [gs]etrlimit() ? */
+#undef __UCLIBC_HANDLE_OLDER_RLIMIT__
+
+/* does your target have an asm .set ? */
+#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__
+
+/* define if target supports .weak */
+#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__
+
+/* define if target supports .weakext */
+#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__
+
+/* define if target supports CFI pseudo ops */
+#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__
+
+/* define if target supports IEEE signed zero floats */
+#define __UCLIBC_HAVE_SIGNED_ZERO__
+
+/* only weird assemblers generally need this */
+#undef __UCLIBC_ASM_LINE_SEP__
+
+#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */

+ 6 - 0
libc/sysdeps/linux/loongarch/bits/wordsize.h

@@ -0,0 +1,6 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define __WORDSIZE	64

+ 97 - 0
libc/sysdeps/linux/loongarch/clone.S

@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* The clone syscall wrapper.
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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/>.  */
+
+/* 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 <sys/asm.h>
+#include <sys/syscall.h>
+#define _ERRNO_H  1
+#include <bits/errno.h>
+
+#define L(label) .L##label
+/* Align reg to 2^n.  Used in assembly.  */
+#define REG_ALIGN_ASM(reg, n) bstrins.d reg, zero, (n-1), 0
+#define STACK_ALIGN 16
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+   void *parent_tidptr, void *tls, void *child_tidptr) */
+
+ENTRY (__clone)
+
+	/* Align stack to 16.  */
+	REG_ALIGN_ASM (a1, 4)
+
+	/* Sanity check arguments.  */
+	beq		a0, zero, L (invalid) /* No NULL function pointers.  */
+	beq		a1, zero, L (invalid) /* No NULL stack pointers.  */
+
+	ADDI 		a1, a1, -STACK_ALIGN /* Reserve argument save space.  */
+	REG_S		a0, a1, 0   /* Save function pointer.  */
+	REG_S		a3, a1, SZREG   /* Save argument pointer.  */
+
+	/* The syscall expects the args to be in different slots.  */
+	or		a0, a2, zero
+	or		a2, a4, zero
+	or		a3, a6, zero
+	or		a4, a5, zero
+
+	/* Do the system call.  */
+	LI		a7,__NR_clone
+	syscall		0
+
+	blt		a0, zero ,L (error)
+	beq		a0, zero, L (thread_start)
+
+	/* Successful return from the parent.  */
+	ret
+
+L (invalid):
+	LI		a0, -EINVAL
+
+	/* Something bad happened -- no child created.  */
+L (error):
+	b		__syscall_error
+
+END (__clone)
+
+/* 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.  */
+ENTRY (__thread_start)
+L (thread_start):
+
+	/* Restore the arg for user's function.  */
+	REG_L		a1, sp, 0   /* Function pointer.  */
+	REG_L		a0, sp, SZREG   /* Argument pointer.  */
+
+	/* Call the user's function.  */
+	jirl		ra, a1, 0
+
+	/* Call exit with the function's return value.  */
+	LI		a7, __NR_exit
+	syscall		0
+
+	END (__thread_start)
+
+libc_hidden_def (__clone)
+weak_alias (__clone, clone)

+ 30 - 0
libc/sysdeps/linux/loongarch/crt1.S

@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+.text
+.globl _start
+.type _start,@function
+
+_start:
+    /* rtld_fini */
+    or      $r9,  $r4,  $r0
+
+    /* main */
+    la.global $r4, main
+
+    /* argc */
+    ld.d    $r5,  $r3, 0
+
+    /* argv */
+    addi.d  $r6,  $r3, 8
+
+    /* init/fini */
+    move    $r7,  $r0
+    move    $r8,  $r0
+
+    /* stack_end */
+    or      $r10, $r3, $r0
+
+    bl      __uClibc_main

+ 18 - 0
libc/sysdeps/linux/loongarch/crti.S

@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+    .section .init,"ax",@progbits
+    .globl _init
+    .type _init,@function
+_init:
+    addi.d  $sp,$sp,-16
+    st.d    $ra,$sp,8
+
+    .section .fini,"ax",@progbits
+    .globl _fini
+    .type _fini,@function
+_fini:
+    addi.d  $sp,$sp,-16
+    st.d    $ra,$sp,8

+ 14 - 0
libc/sysdeps/linux/loongarch/crtn.S

@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+    .section .init,"ax",@progbits
+    ld.d    $ra,$sp,8
+    addi.d  $sp,$sp,16
+    jr      $ra
+
+    .section .fini,"ax",@progbits
+    ld.d    $ra,$sp,8
+    addi.d  $sp,$sp,16
+    jr      $ra

+ 64 - 0
libc/sysdeps/linux/loongarch/setjmp.S

@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* setjmp for LoongArch.
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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 <sys/asm.h>
+
+ENTRY (_setjmp)
+	li.w		a1,0
+	b		HIDDEN_JUMPTARGET (__sigsetjmp)
+END (_setjmp)
+
+ENTRY (setjmp)
+	li.w		a1,1
+END (setjmp)
+
+ENTRY (__sigsetjmp)
+	REG_S ra, a0, 0*SZREG
+	REG_S sp, a0, 1*SZREG
+	REG_S x,  a0, 2*SZREG
+	REG_S fp, a0, 3*SZREG
+	REG_S s0, a0, 4*SZREG
+	REG_S s1, a0, 5*SZREG
+	REG_S s2, a0, 6*SZREG
+	REG_S s3, a0, 7*SZREG
+	REG_S s4, a0, 8*SZREG
+	REG_S s5, a0, 9*SZREG
+	REG_S s6, a0, 10*SZREG
+	REG_S s7, a0, 11*SZREG
+	REG_S s8, a0, 12*SZREG
+
+#ifndef __loongarch_soft_float
+	FREG_S fs0, a0, 13*SZREG + 0*SZFREG
+	FREG_S fs1, a0, 13*SZREG + 1*SZFREG
+	FREG_S fs2, a0, 13*SZREG + 2*SZFREG
+	FREG_S fs3, a0, 13*SZREG + 3*SZFREG
+	FREG_S fs4, a0, 13*SZREG + 4*SZFREG
+	FREG_S fs5, a0, 13*SZREG + 5*SZFREG
+	FREG_S fs6, a0, 13*SZREG + 6*SZFREG
+	FREG_S fs7, a0, 13*SZREG + 7*SZFREG
+#endif
+
+	b		__sigjmp_save
+END (__sigsetjmp)
+
+hidden_def (__sigsetjmp)
+weak_alias (_setjmp, __GI__setjmp)

+ 104 - 0
libc/sysdeps/linux/loongarch/sys/asm.h

@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Miscellaneous macros.
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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 _SYS_ASM_H
+#define _SYS_ASM_H
+
+#include <sys/regdef.h>
+
+/* Macros to handle different pointer/register sizes for 32/64-bit code.  */
+#if __loongarch_grlen == 64
+#define SZREG 8
+#define REG_L ld.d
+#define REG_S st.d
+#define SRLI srli.d
+#define SLLI slli.d
+#define ADDI addi.d
+#define ADD  add.d
+#define SUB  sub.d
+#define LI  li.d
+#define BSTRINS  bstrins.d
+
+#elif __loongarch_grlen == 32
+
+#define SZREG 4
+#define REG_L ld.w
+#define REG_S st.w
+#define SRLI srli.w
+#define SLLI slli.w
+#define ADDI addi.w
+#define ADD  add.w
+#define SUB  sub.w
+#define LI  li.w
+#define BSTRINS  bstrins.w
+
+#else
+#error __loongarch_grlen must equal 32 or 64
+#endif
+
+#if __loongarch_frlen == 64
+  #define SZFREG 8
+  #define FREG_L fld.d
+  #define FREG_S fst.d
+#elif __loongarch_frlen == 32
+  #define SZFREG 4
+  #define FREG_L fld.s
+  #define FREG_S fst.s
+#endif
+
+#define SZVREG 16
+#define SZXREG 32
+
+/*  Declare leaf routine.
+    The usage of macro LEAF/ENTRY is as follows:
+    1. LEAF(fcn) -- the align value of fcn is .align 3 (default value)
+    2. LEAF(fcn, 6) -- the align value of fcn is .align 6
+*/
+#define LEAF_IMPL(symbol, aln, ...)	\
+	.text;				\
+	.globl symbol;			\
+	.align aln;			\
+	.type symbol, @function;	\
+symbol:
+
+
+#define LEAF(...) LEAF_IMPL(__VA_ARGS__, 3)
+#define ENTRY(...) LEAF(__VA_ARGS__)
+
+#define	LEAF_NO_ALIGN(symbol)		\
+	.text;				\
+	.globl	symbol;			\
+	.type	symbol, @function;	\
+symbol:
+
+#define ENTRY_NO_ALIGN(symbol) LEAF_NO_ALIGN(symbol)
+
+
+/* Mark end of function.  */
+#undef END
+#define END(function) \
+  .size function, .- function;
+
+/* Stack alignment.  */
+#define ALMASK ~15
+
+#endif /* sys/asm.h */

+ 172 - 0
libc/sysdeps/linux/loongarch/sys/regdef.h

@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Register Macro definitions
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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 _SYS_REGDEF_H
+#define _SYS_REGDEF_H
+
+#define zero $r0
+#define ra $r1
+#define tp $r2
+#define sp $r3
+#define a0 $r4
+#define a1 $r5
+#define a2 $r6
+#define a3 $r7
+#define a4 $r8
+#define a5 $r9
+#define a6 $r10
+#define a7 $r11
+#define v0 $r4
+#define v1 $r5
+#define t0 $r12
+#define t1 $r13
+#define t2 $r14
+#define t3 $r15
+#define t4 $r16
+#define t5 $r17
+#define t6 $r18
+#define t7 $r19
+#define t8 $r20
+#define x $r21
+#define fp $r22
+#define s0 $r23
+#define s1 $r24
+#define s2 $r25
+#define s3 $r26
+#define s4 $r27
+#define s5 $r28
+#define s6 $r29
+#define s7 $r30
+#define s8 $r31
+
+#define fa0 $f0
+#define fa1 $f1
+#define fa2 $f2
+#define fa3 $f3
+#define fa4 $f4
+#define fa5 $f5
+#define fa6 $f6
+#define fa7 $f7
+#define fv0 $f0
+#define fv1 $f1
+#define ft0 $f8
+#define ft1 $f9
+#define ft2 $f10
+#define ft3 $f11
+#define ft4 $f12
+#define ft5 $f13
+#define ft6 $f14
+#define ft7 $f15
+#define ft8 $f16
+#define ft9 $f17
+#define ft10 $f18
+#define ft11 $f19
+#define ft12 $f20
+#define ft13 $f21
+#define ft14 $f22
+#define ft15 $f23
+#define fs0 $f24
+#define fs1 $f25
+#define fs2 $f26
+#define fs3 $f27
+#define fs4 $f28
+#define fs5 $f29
+#define fs6 $f30
+#define fs7 $f31
+#define fcc0 $fcc0
+#define fcc1 $fcc1
+#define fcc2 $fcc2
+#define fcc3 $fcc3
+#define fcc4 $fcc4
+#define fcc5 $fcc5
+#define fcc6 $fcc6
+#define fcc7 $fcc7
+#define fcsr0 $fcsr0
+
+#define vr0 $vr0
+#define vr1 $vr1
+#define vr2 $vr2
+#define vr3 $vr3
+#define vr4 $vr4
+#define vr5 $vr5
+#define vr6 $vr6
+#define vr7 $vr7
+#define vr8 $vr8
+#define vr9 $vr9
+#define vr10 $vr10
+#define vr11 $vr11
+#define vr12 $vr12
+#define vr13 $vr13
+#define vr14 $vr14
+#define vr15 $vr15
+#define vr16 $vr16
+#define vr17 $vr17
+#define vr18 $vr18
+#define vr19 $vr19
+#define vr20 $vr20
+#define vr21 $vr21
+#define vr22 $vr22
+#define vr23 $vr23
+#define vr24 $vr24
+#define vr25 $vr25
+#define vr26 $vr26
+#define vr27 $vr27
+#define vr28 $vr28
+#define vr29 $vr29
+#define vr30 $vr30
+#define vr31 $vr31
+
+#define xr0 $xr0
+#define xr1 $xr1
+#define xr2 $xr2
+#define xr3 $xr3
+#define xr4 $xr4
+#define xr5 $xr5
+#define xr6 $xr6
+#define xr7 $xr7
+#define xr7 $xr7
+#define xr8 $xr8
+#define xr9 $xr9
+#define xr10 $xr10
+#define xr11 $xr11
+#define xr12 $xr12
+#define xr13 $xr13
+#define xr14 $xr14
+#define xr15 $xr15
+#define xr16 $xr16
+#define xr17 $xr17
+#define xr18 $xr18
+#define xr19 $xr19
+#define xr20 $xr20
+#define xr21 $xr21
+#define xr22 $xr22
+#define xr23 $xr23
+#define xr24 $xr24
+#define xr25 $xr25
+#define xr26 $xr26
+#define xr27 $xr27
+#define xr28 $xr28
+#define xr29 $xr29
+#define xr30 $xr30
+#define xr31 $xr31
+
+#endif /* _SYS_REGDEF_H */

+ 64 - 0
libc/sysdeps/linux/loongarch/sys/ucontext.h

@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* struct ucontext definition.
+   Copyright (C) 2022-2026 Free Software Foundation, Inc.
+
+   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/>.  */
+
+/* Don't rely on this, the interface is currently messed up and may need to
+   be broken to be fixed.  */
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H 1
+
+#include <features.h>
+
+#ifdef __USE_MISC
+#define LARCH_NGREG 32
+
+#define LARCH_REG_RA 1
+#define LARCH_REG_SP 3
+#define LARCH_REG_S0 23
+#define LARCH_REG_S1 24
+#define LARCH_REG_A0 4
+#define LARCH_REG_S2 25
+#define LARCH_REG_NARGS 8
+
+typedef unsigned long int greg_t;
+/* Container for all general registers.  */
+typedef greg_t gregset_t[32];
+#endif
+
+typedef struct mcontext_t
+{
+  unsigned long long __pc;
+  unsigned long long __gregs[32];
+  unsigned int __flags;
+  unsigned long long __extcontext[0] __attribute__((__aligned__(16)));
+} mcontext_t;
+
+/* Userlevel context.  */
+typedef struct ucontext_t
+{
+  unsigned long int __uc_flags;
+  struct ucontext_t *uc_link;
+  stack_t uc_stack;
+  sigset_t uc_sigmask;
+  mcontext_t uc_mcontext;
+} ucontext_t;
+
+#endif /* sys/ucontext.h */

+ 47 - 0
libc/sysdeps/linux/loongarch/sysdep.S

@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2026 Waldemar Brodkorb <wbx@uclibc-ng.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* syscall error handlers
+   Copyright (C) 2022-2026 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/>.  */
+
+#include <sys/asm.h>
+
+#define L(label) .L##label
+
+ENTRY (__syscall_error)
+/* Fall through to __syscall_set_errno */
+END (__syscall_error)
+
+/* Non-standard calling convention: argument in a0, return address in t0,
+   and clobber only t1.
+ */
+ENTRY (__syscall_set_errno)
+
+/* We got here because a0 < 0, but only codes in the range [-4095, -1]
+   represent errors.  Otherwise, just return the result normally.
+ */
+	LI		t1, -4096
+	bgeu		t1, a0, L (out)
+	sub.w		a0, zero, a0
+	st.w		a0, t1, 0
+	LI		a0, -1
+L (out):
+	ret
+END (__syscall_set_errno)