mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [RFC PATCH] add kvx arch
@ 2022-07-11 15:23 Jonathan Borne
  0 siblings, 0 replies; only message in thread
From: Jonathan Borne @ 2022-07-11 15:23 UTC (permalink / raw)
  To: musl; +Cc: Yann Sionneau, Jonathan Borne, Jules Maselbas

From: Yann Sionneau <ysionneau@kalray.eu>

Author: Yann Sionneau <ysionneau@kalray.eu>
Author: Jonathan Borne <jborne@kalray.eu>
Author: Jules Maselbas <jmaselbas@kalray.eu>

The Kalray VLIW processor family (kvx) has the following features:
 - 32/64 bits execution mode
 - 6-issue VLIW architecture
 - 64 x 64bits general purpose registers
 - SIMD instructions
 - little-endian
 - deep learning co-processor

The port has been tested on real hardware and qemu using buildroot
linux images. Kvx-musl-linux is booting. This is the current status
of libc-test:

FAIL src/api/*
FAIL src/functional/stat-static.exe [status 1]
FAIL src/functional/stat.exe [status 1]
FAIL src/functional/strptime-static.exe [status 1]
FAIL src/functional/strptime.exe [status 1]
FAIL src/math/acoshl.exe [status 1]
FAIL src/math/asinhl.exe [status 1]
FAIL src/math/erfcl.exe [status 1]
FAIL src/math/exp2l.exe [status 1]
FAIL src/math/lgammal.exe [status 1]
FAIL src/math/powf.exe [status 1]
FAIL src/math/powl.exe [status 1]
FAIL src/math/tgammal.exe [status 1]
FAIL src/regression/malloc-brk-fail-static.exe [status 1]
FAIL src/regression/malloc-brk-fail.exe [status 1]
FAIL src/regression/raise-race-static.exe [timed out]
FAIL src/regression/raise-race.exe [timed out]
FAIL src/regression/statvfs-static.exe [status 1]
FAIL src/regression/statvfs.exe [status 1]

Some of those test are expected to fail
[[https://www.openwall.com/lists/musl/2019/10/31/5]]

 - src/functional/stat.c:23: st.st_mtime<=t failed:1653986841 > 1546301075
 Modification time is in the future due to wrong system time in
 qemu/buildroot environment.

 - src/functional/strptime:
    src/functional/strptime.c:23: "%F": failed to parse "1856-07-10"
    src/functional/strptime.c:23: "%s": failed to parse "683078400"
    src/functional/strptime.c:47: "%z": failed to parse "+0200"
    src/functional/strptime.c:47: "%z": failed to parse "-0530"
    src/functional/strptime.c:47: "%z": failed to parse "-06"
 Input formats %F, %s and %z are not conforming to POSIX.

 - src/math/* fails because of precision errors.

 - src/regression/malloc-brk-fail:
    src/regression/malloc-brk-fail.c:41: malloc(10000) failed
 Kernel dependent.

 - src/regression/raise-race.exe
 take time to complete and triggers a TIMEOUT.

 - src/api:
    _PC_TIMESTAMP_RESOLUTION and _SC_XOPEN_UUCP are undeclared

Signed-off-by: Yann Sionneau <ysionneau@kalray.eu>
Signed-off-by: Jonathan Borne <jborne@kalray.eu>
Signed-off-by: Jules Maselbas <jmaselbas@kalray.eu>
---

For more information about the kvx arch:
[[https://www.barebox.org/doc/latest/boards/kvx.html]]

Our linux port is available here:
[[https://github.com/kalray/linux_coolidge]]

Any feedback, comment, review of our port would be greatly appreciated.

Thank you very much for all the wonderful work that has been done on musl.

Best Regards.
Jonathan

 COPYRIGHT                          |   3 +
 arch/kvx/atomic_arch.h             |  56 ++++++
 arch/kvx/bits/alltypes.h.in        |  33 ++++
 arch/kvx/bits/fenv.h               |  86 +++++++++
 arch/kvx/bits/float.h              |  16 ++
 arch/kvx/bits/limits.h             |   6 +
 arch/kvx/bits/posix.h              |   2 +
 arch/kvx/bits/ptrace.h             |   6 +
 arch/kvx/bits/setjmp.h             |   1 +
 arch/kvx/bits/signal.h             |  77 ++++++++
 arch/kvx/bits/stat.h               |  18 ++
 arch/kvx/bits/stdint.h             |  20 ++
 arch/kvx/bits/syscall.h.in         | 298 +++++++++++++++++++++++++++++
 arch/kvx/bits/user.h               |  18 ++
 arch/kvx/crt_arch.h                |  19 ++
 arch/kvx/kstat.h                   |  22 +++
 arch/kvx/pthread_arch.h            |  14 ++
 arch/kvx/reloc.h                   |  17 ++
 arch/kvx/syscall_arch.h            | 130 +++++++++++++
 configure                          |   1 +
 include/elf.h                      |  88 ++++++++-
 include/sys/cachectl.h             |   9 +-
 src/fenv/kvx/fenv.c                |  60 ++++++
 src/linux/cache.c                  |   8 +
 src/math/kvx/fma.c                 |   9 +
 src/math/kvx/fmaf.c                |   9 +
 src/setjmp/kvx/longjmp.S           |  32 ++++
 src/setjmp/kvx/setjmp.S            |  46 +++++
 src/signal/kvx/sigsetjmp.S         |  31 +++
 src/thread/kvx/__set_thread_area.c |  12 ++
 src/thread/kvx/clone.s             |  54 ++++++
 src/thread/kvx/syscall_cp.S        |  34 ++++
 32 files changed, 1233 insertions(+), 2 deletions(-)
 create mode 100644 arch/kvx/atomic_arch.h
 create mode 100644 arch/kvx/bits/alltypes.h.in
 create mode 100644 arch/kvx/bits/fenv.h
 create mode 100644 arch/kvx/bits/float.h
 create mode 100644 arch/kvx/bits/limits.h
 create mode 100644 arch/kvx/bits/posix.h
 create mode 100644 arch/kvx/bits/ptrace.h
 create mode 100644 arch/kvx/bits/setjmp.h
 create mode 100644 arch/kvx/bits/signal.h
 create mode 100644 arch/kvx/bits/stat.h
 create mode 100644 arch/kvx/bits/stdint.h
 create mode 100644 arch/kvx/bits/syscall.h.in
 create mode 100644 arch/kvx/bits/user.h
 create mode 100644 arch/kvx/crt_arch.h
 create mode 100644 arch/kvx/kstat.h
 create mode 100644 arch/kvx/pthread_arch.h
 create mode 100644 arch/kvx/reloc.h
 create mode 100644 arch/kvx/syscall_arch.h
 create mode 100644 src/fenv/kvx/fenv.c
 create mode 100644 src/math/kvx/fma.c
 create mode 100644 src/math/kvx/fmaf.c
 create mode 100644 src/setjmp/kvx/longjmp.S
 create mode 100644 src/setjmp/kvx/setjmp.S
 create mode 100644 src/signal/kvx/sigsetjmp.S
 create mode 100644 src/thread/kvx/__set_thread_area.c
 create mode 100644 src/thread/kvx/clone.s
 create mode 100644 src/thread/kvx/syscall_cp.S

diff --git a/COPYRIGHT b/COPYRIGHT
index c1628e9a..fcf84f94 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -160,6 +160,9 @@ The powerpc port was also originally written by Richard Pennington,
 and later supplemented and integrated by John Spencer. It is licensed
 under the standard MIT terms.

+The kvx port is Copyright © 2022, Kalray S.A.
+It is licensed under the standard MIT terms.
+
 All other files which have no copyright comments are original works
 produced specifically for use as part of this library, written either
 by Rich Felker, the main author of the library, or by one or more
diff --git a/arch/kvx/atomic_arch.h b/arch/kvx/atomic_arch.h
new file mode 100644
index 00000000..cf6a4787
--- /dev/null
+++ b/arch/kvx/atomic_arch.h
@@ -0,0 +1,56 @@
+/*
+ * Atomic compare and exchange: Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
+ */
+#define __cmpxchg(ptr, old, new, op_suffix) \
+({ \
+	__typeof((ptr)) __cxc__ptr = (ptr);                             \
+	register unsigned long __cxc__rn __asm__("$r62") = (unsigned long) (new); \
+	register unsigned long __cxc__ro __asm__("$r63") = (unsigned long) (old); \
+	do {                                                            \
+		__asm__ __volatile__ (                                  \
+			"acswap" #op_suffix " 0[%[rPtr]], $r62r63\n"    \
+			: "+r" (__cxc__rn), "+r" (__cxc__ro)            \
+			: [rPtr] "r" (__cxc__ptr)                       \
+			: "memory");                                    \
+		/* Success */                                           \
+		if (__cxc__rn) {                                        \
+			__cxc__ro = (unsigned long) (old);              \
+			break;                                          \
+		}                                                       \
+		/* We failed, read value */                             \
+		__cxc__ro = (unsigned long) *(__cxc__ptr);              \
+		if (__cxc__ro != (unsigned long) (old))                 \
+			break;                                          \
+		/* __cxc__rn has been cloberred by cmpxch result */     \
+		__cxc__rn = (unsigned long) (new);                      \
+	} while (1);                                                    \
+	(__cxc__ro);                                                    \
+})
+
+#define cmpxchg(ptr, o, n) \
+({ \
+	unsigned long __cmpxchg__ret;                                   \
+	switch (sizeof(*(ptr))) {                                       \
+	case 4:                                                         \
+		__cmpxchg__ret = __cmpxchg((ptr), (o), (n), w);         \
+		break;                                                  \
+	case 8:                                                         \
+		__cmpxchg__ret = __cmpxchg((ptr), (o), (n), d);         \
+		break;                                                  \
+	}                                                               \
+	(__typeof(*(ptr))) (__cmpxchg__ret);                            \
+})
+
+#define a_cas a_cas
+static inline int a_cas(volatile int *p, int t, int s)
+{
+	return cmpxchg(p, t, s);
+}
+
+#define a_cas_p a_cas_p
+static inline void *a_cas_p(volatile void *p, void *t, void *s)
+{
+	return (void *)a_cas(p, (uintptr_t)t, (uintptr_t)s);
+}
diff --git a/arch/kvx/bits/alltypes.h.in b/arch/kvx/bits/alltypes.h.in
new file mode 100644
index 00000000..3600edcd
--- /dev/null
+++ b/arch/kvx/bits/alltypes.h.in
@@ -0,0 +1,33 @@
+#define _Addr long
+#define _Int64 long
+#define _Reg long
+
+#define __BYTE_ORDER 1234
+
+#define __LONG_MAX 0x7fffffffffffffffL
+
+TYPEDEF __builtin_va_list va_list;
+TYPEDEF __builtin_va_list __isoc_va_list;
+
+#ifndef __cplusplus
+TYPEDEF int wchar_t;
+#endif
+
+TYPEDEF int blksize_t;
+TYPEDEF unsigned int nlink_t;
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
+
+TYPEDEF long time_t;
+TYPEDEF long suseconds_t;
+
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
+TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/arch/kvx/bits/fenv.h b/arch/kvx/bits/fenv.h
new file mode 100644
index 00000000..5f442e3d
--- /dev/null
+++ b/arch/kvx/bits/fenv.h
@@ -0,0 +1,86 @@
+/*
+ * Each core of the Coolidge processor have a coprocessor. They share
+ * the CS register but have distinct bit-fields for their
+ * floating-point environment.
+ * This implementation allow them to be managed separately.
+ *
+ * Compute Status ($cs) register contains the following bit-fields for
+ * floating-point exception flags.
+ *
+ * Bit-field Condition of the IEEE 754 binary floating-point standard
+ * --------- --------------------------------------------------------
+ * IO        Invalid Operation
+ * DZ        Divide by Zero
+ * OV        Overflow
+ * UN        Underflow
+ * IN        Inexact
+ * XIO       Invalid Operation (coprocessor)
+ * XDZ       Divide by Zero (coprocessor)
+ * XOV       Overflow (coprocessor)
+ * XUN       Underflow (coprocessor)
+ * XIN       Inexact (coprocessor)
+ */
+
+#define FE_INVALID   0x02
+#define FE_DIVBYZERO 0x04
+#define FE_OVERFLOW  0x08
+#define FE_UNDERFLOW 0x10
+#define FE_INEXACT   0x20
+
+#define FE_X_INVALID   0x0200
+#define FE_X_DIVBYZERO 0x0400
+#define FE_X_OVERFLOW  0x0800
+#define FE_X_UNDERFLOW 0x1000
+#define FE_X_INEXACT   0x2000
+
+#define _FE_EXCEPT (FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW|FE_INEXACT)
+#define _FE_X_EXCEPT \
+	(FE_X_INVALID|FE_X_DIVBYZERO|FE_X_OVERFLOW|FE_X_UNDERFLOW|FE_X_INEXACT)
+
+#define FE_ALL_EXCEPT (_FE_EXCEPT|_FE_X_EXCEPT)
+
+/*
+ * Compute Status ($cs) register contains the following bit-fields for
+ * floating-point rounding modes.
+ *
+ * Following table describes both the RM and XRM (coproc) bit-fields.
+ *
+ * Value Rounding Mode of the IEEE 754 binary floating-point standard
+ * ----- ------------------------------------------------------------
+ * 0b00  to nearest even
+ * 0b01  toward +inf
+ * 0b10  toward -inf
+ * 0b11  toward zero
+ */
+
+#define _FE_TONEAREST  0
+#define _FE_UPWARD     1
+#define _FE_DOWNWARD   2
+#define _FE_TOWARDZERO 3
+
+#define _FE_X_TONEAREST  0
+#define _FE_X_UPWARD     1
+#define _FE_X_DOWNWARD   2
+#define _FE_X_TOWARDZERO 3
+
+#define FE_TONEAREST  ((_FE_TONEAREST  << 16) | (_FE_X_TONEAREST  << 20))
+#define FE_UPWARD     ((_FE_UPWARD     << 16) | (_FE_X_UPWARD     << 20))
+#define FE_DOWNWARD   ((_FE_DOWNWARD   << 16) | (_FE_X_DOWNWARD   << 20))
+#define FE_TOWARDZERO ((_FE_TOWARDZERO << 16) | (_FE_X_TOWARDZERO << 20))
+
+#define FE_RND_MASK FE_TOWARDZERO
+
+/*
+ * The type representing all floating-point status flags collectively.
+ * The environment is simply a copy from the FPU related bits in the
+ * CS register, but can be improved in the future.
+ */
+typedef unsigned long fexcept_t;
+/*
+ * The type representing the entire floating-point environment.
+ * The environment is simply a copy from the FPU related bits in the CS
+ * register.
+ */
+typedef	unsigned long fenv_t;
+
+#define FE_DFL_ENV      ((const fenv_t *) -1)
diff --git a/arch/kvx/bits/float.h b/arch/kvx/bits/float.h
new file mode 100644
index 00000000..c4a655e7
--- /dev/null
+++ b/arch/kvx/bits/float.h
@@ -0,0 +1,16 @@
+#define FLT_EVAL_METHOD 0
+
+#define LDBL_TRUE_MIN 4.94065645841246544177e-324L
+#define LDBL_MIN 2.22507385850720138309e-308L
+#define LDBL_MAX 1.79769313486231570815e+308L
+#define LDBL_EPSILON 2.22044604925031308085e-16L
+
+#define LDBL_MANT_DIG 53
+#define LDBL_MIN_EXP (-1021)
+#define LDBL_MAX_EXP 1024
+
+#define LDBL_DIG 15
+#define LDBL_MIN_10_EXP (-307)
+#define LDBL_MAX_10_EXP 308
+
+#define DECIMAL_DIG 17
diff --git a/arch/kvx/bits/limits.h b/arch/kvx/bits/limits.h
new file mode 100644
index 00000000..f4dab602
--- /dev/null
+++ b/arch/kvx/bits/limits.h
@@ -0,0 +1,6 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define LONG_BIT 64
+#endif
+
+#define LLONG_MAX  0x7fffffffffffffffLL
diff --git a/arch/kvx/bits/posix.h b/arch/kvx/bits/posix.h
new file mode 100644
index 00000000..c37b94c1
--- /dev/null
+++ b/arch/kvx/bits/posix.h
@@ -0,0 +1,2 @@
+#define _POSIX_V6_LP64_OFF64  1
+#define _POSIX_V7_LP64_OFF64  1
diff --git a/arch/kvx/bits/ptrace.h b/arch/kvx/bits/ptrace.h
new file mode 100644
index 00000000..258c9f1d
--- /dev/null
+++ b/arch/kvx/bits/ptrace.h
@@ -0,0 +1,6 @@
+#ifndef _BITS_PTRACE_H
+#define _BITS_PTRACE_H 1
+
+enum __ptrace_request { __ptrace__dummy };
+
+#endif
diff --git a/arch/kvx/bits/setjmp.h b/arch/kvx/bits/setjmp.h
new file mode 100644
index 00000000..54bc2610
--- /dev/null
+++ b/arch/kvx/bits/setjmp.h
@@ -0,0 +1 @@
+typedef unsigned long __jmp_buf[22];
diff --git a/arch/kvx/bits/signal.h b/arch/kvx/bits/signal.h
new file mode 100644
index 00000000..d12d6951
--- /dev/null
+++ b/arch/kvx/bits/signal.h
@@ -0,0 +1,77 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define MINSIGSTKSZ 6144
+#define SIGSTKSZ 12288
+#endif
+
+typedef unsigned long greg_t;
+typedef unsigned long gregset_t[64];
+
+typedef struct sigcontext {
+	unsigned long regs[64];
+	unsigned long lc, le, ls, ra, cs, pc;
+} mcontext_t;
+
+struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+};
+
+typedef struct __ucontext {
+	unsigned long uc_flags;
+	struct __ucontext *uc_link;
+	stack_t uc_stack;
+	mcontext_t uc_mcontext;
+	sigset_t uc_sigmask;
+} ucontext_t;
+
+#define SA_NOCLDSTOP  1
+#define SA_NOCLDWAIT  2
+#define SA_SIGINFO    4
+#define SA_ONSTACK    0x08000000
+#define SA_RESTART    0x10000000
+#define SA_NODEFER    0x40000000
+#define SA_RESETHAND  0x80000000
+#define SA_RESTORER   0x04000000
+
+#endif
+
+#define SIGHUP    1
+#define SIGINT    2
+#define SIGQUIT   3
+#define SIGILL    4
+#define SIGTRAP   5
+#define SIGABRT   6
+#define SIGIOT    SIGABRT
+#define SIGBUS    7
+#define SIGFPE    8
+#define SIGKILL   9
+#define SIGUSR1   10
+#define SIGSEGV   11
+#define SIGUSR2   12
+#define SIGPIPE   13
+#define SIGALRM   14
+#define SIGTERM   15
+#define SIGSTKFLT 16
+#define SIGCHLD   17
+#define SIGCONT   18
+#define SIGSTOP   19
+#define SIGTSTP   20
+#define SIGTTIN   21
+#define SIGTTOU   22
+#define SIGURG    23
+#define SIGXCPU   24
+#define SIGXFSZ   25
+#define SIGVTALRM 26
+#define SIGPROF   27
+#define SIGWINCH  28
+#define SIGIO     29
+#define SIGPOLL   29
+#define SIGPWR    30
+#define SIGSYS    31
+#define SIGUNUSED SIGSYS
+
+#define _NSIG 65
diff --git a/arch/kvx/bits/stat.h b/arch/kvx/bits/stat.h
new file mode 100644
index 00000000..33c62155
--- /dev/null
+++ b/arch/kvx/bits/stat.h
@@ -0,0 +1,18 @@
+struct stat {
+    dev_t st_dev;                       /* Device.                          */
+    ino_t st_ino;                       /* 32bit file serial number         */
+    mode_t st_mode;                     /* File mode.                       */
+    nlink_t st_nlink;                   /* Link count.                      */
+    uid_t st_uid;                       /* User ID of the file's owner.     */
+    gid_t st_gid;                       /* Group ID of the file's group.    */
+    dev_t st_rdev;                      /* Device number, if device.        */
+    unsigned long long _pad1;
+    off_t st_size;                      /* Size of file, in bytes.          */
+    blksize_t st_blksize;               /* Optimal block size for I/O.      */
+    int __pad2;
+    blkcnt_t st_blocks;                 /* Number 512-byte blocks allocated */
+    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.      */
+    unsigned int __unused[2];
+};
diff --git a/arch/kvx/bits/stdint.h b/arch/kvx/bits/stdint.h
new file mode 100644
index 00000000..1bb147f2
--- /dev/null
+++ b/arch/kvx/bits/stdint.h
@@ -0,0 +1,20 @@
+typedef int32_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+#define INT_FAST16_MIN  INT32_MIN
+#define INT_FAST32_MIN  INT32_MIN
+
+#define INT_FAST16_MAX  INT32_MAX
+#define INT_FAST32_MAX  INT32_MAX
+
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN      INT64_MIN
+#define INTPTR_MAX      INT64_MAX
+#define UINTPTR_MAX     UINT64_MAX
+#define PTRDIFF_MIN     INT64_MIN
+#define PTRDIFF_MAX     INT64_MAX
+#define SIZE_MAX        UINT64_MAX
diff --git a/arch/kvx/bits/syscall.h.in b/arch/kvx/bits/syscall.h.in
new file mode 100644
index 00000000..233d7383
--- /dev/null
+++ b/arch/kvx/bits/syscall.h.in
@@ -0,0 +1,298 @@
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_renameat 38
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs 43
+#define __NR_fstatfs 44
+#define __NR_truncate 45
+#define __NR_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile 71
+#define __NR_pselect6 72
+#define __NR_ppoll 73
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_fstatat 79
+#define __NR_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range2 84
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_timerfd_settime 86
+#define __NR_timerfd_gettime 87
+#define __NR_utimensat 88
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_futex 98
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_nanosleep 101
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_gettime 108
+#define __NR_timer_getoverrun 109
+#define __NR_timer_settime 110
+#define __NR_timer_delete 111
+#define __NR_clock_settime 112
+#define __NR_clock_gettime 113
+#define __NR_clock_getres 114
+#define __NR_clock_nanosleep 115
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_sched_rr_get_interval 127
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigtimedwait 137
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrlimit 163
+#define __NR_setrlimit 164
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_gettimeofday 169
+#define __NR_settimeofday 170
+#define __NR_adjtimex 171
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_timedsend 182
+#define __NR_mq_timedreceive 183
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semtimedop 192
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap 222
+#define __NR_fadvise64 223
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_recvmmsg 243
+#define __NR_arch_specific_syscall 244
+#define __NR_wait4 260
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_clock_adjtime 266
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_statx 291
+#define __NR_io_pgetevents 292
+#define __NR_rseq 293
+#define __NR_kexec_file_load 294
+#define __NR_pidfd_send_signal 424
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_openat2 437
+#define __NR_pidfd_getfd 438
+#define __NR_faccessat2	439
+#define __NR_cachectl (__NR_arch_specific_syscall)
diff --git a/arch/kvx/bits/user.h b/arch/kvx/bits/user.h
new file mode 100644
index 00000000..d317b6ec
--- /dev/null
+++ b/arch/kvx/bits/user.h
@@ -0,0 +1,18 @@
+#define ELF_NREG 64
+
+struct user_regs_struct
+{
+  /* GPR */
+  unsigned long long gpr_regs[ELF_NREG];
+
+  /* SFR */
+  unsigned long lc;
+  unsigned long le;
+  unsigned long ls;
+  unsigned long ra;
+  unsigned long cs;
+  unsigned long spc;
+};
+
+typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NREG];
+typedef struct {} elf_fpregset_t;
diff --git a/arch/kvx/crt_arch.h b/arch/kvx/crt_arch.h
new file mode 100644
index 00000000..b5708079
--- /dev/null
+++ b/arch/kvx/crt_arch.h
@@ -0,0 +1,19 @@
+__asm__(
+".text \n"
+".weak _DYNAMIC \n"
+".hidden _DYNAMIC \n"
+".global " START " \n"
+".type " START ",@function \n"
+START ": \n"
+"make $fp = 0 \n"
+"copyd $r0 = $sp \n"
+"andd $sp = $sp, -32 \n"
+";; \n"
+"pcrel $r1 = @pcrel(_DYNAMIC) \n"
+"set $cs = $fp \n"
+";; \n"
+"goto " START "_c \n"
+";; \n"
+"errop \n"
+";; \n"
+);
diff --git a/arch/kvx/kstat.h b/arch/kvx/kstat.h
new file mode 100644
index 00000000..0250fa8a
--- /dev/null
+++ b/arch/kvx/kstat.h
@@ -0,0 +1,22 @@
+struct kstat {
+	dev_t st_dev;
+	ino_t st_ino;
+	mode_t st_mode;
+	nlink_t st_nlink;
+	uid_t st_uid;
+	gid_t st_gid;
+	dev_t st_rdev;
+	unsigned int    __pad0;
+	off_t st_size;
+	blksize_t st_blksize;
+	unsigned int    __pad1;
+	blkcnt_t st_blocks;
+
+	long st_atime_sec;
+	long st_atime_nsec;
+	long st_mtime_sec;
+	long st_mtime_nsec;
+	long st_ctime_sec;
+	long st_ctime_nsec;
+	long __unused[2];
+};
diff --git a/arch/kvx/pthread_arch.h b/arch/kvx/pthread_arch.h
new file mode 100644
index 00000000..d471b16d
--- /dev/null
+++ b/arch/kvx/pthread_arch.h
@@ -0,0 +1,14 @@
+/* kvx uses variant I, but with the twist that tp points to the end of TCB */
+static inline uintptr_t __get_tp()
+{
+	uintptr_t tp;
+	__asm__ ("copyd %0 = $r13\n"
+		 ";;"
+		 : "=r" (tp));
+	return tp;
+}
+
+#define MC_PC pc
+#define GAP_ABOVE_TP 0
+#define TLS_ABOVE_TP
+#define TPOFF_K (0)
diff --git a/arch/kvx/reloc.h b/arch/kvx/reloc.h
new file mode 100644
index 00000000..938e70a4
--- /dev/null
+++ b/arch/kvx/reloc.h
@@ -0,0 +1,17 @@
+#define LDSO_ARCH "kvx"
+
+#define NO_LEGACY_INITFINI
+
+#define REL_SYMBOLIC    R_KVX_64
+#define REL_GOT         R_KVX_GLOB_DAT
+#define REL_PLT         R_KVX_JMP_SLOT
+#define REL_RELATIVE    R_KVX_RELATIVE
+#define REL_COPY        R_KVX_COPY
+#define REL_DTPMOD      R_KVX_64_DTPMOD
+#define REL_DTPOFF      R_KVX_64_DTPOFF
+#define REL_TPOFF       R_KVX_64_TPOFF
+
+#define CRTJMP(pc, sp) __asm__ __volatile__(\
+	"copyd $sp = %1\n" \
+	"igoto %0\n" \
+	";;\n" : : "r"(pc), "r"(sp) : "memory")
diff --git a/arch/kvx/syscall_arch.h b/arch/kvx/syscall_arch.h
new file mode 100644
index 00000000..bba40c12
--- /dev/null
+++ b/arch/kvx/syscall_arch.h
@@ -0,0 +1,130 @@
+#ifndef __clang__
+
+/*
+ * Mark all arguments registers as per ABI in the range r1-r5 as
+ * clobbered when they are not used for the invocation of the scall
+ */
+#define ASM_CLOBBERS "cc", "memory",\
+	"r7", "r8", "r9", "r10", "r11",	/* unused argument registers */ \
+	"r15",                          /* struct pointer            */ \
+	"r16", "r17",                   /* veneer registers          */ \
+					/* 32->63 are caller-saved   */ \
+	"r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",         \
+	"r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",         \
+	"r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",         \
+	"r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63"
+
+static __inline long __syscall0(long n)
+{
+	register unsigned long _ret __asm__("r0");
+	register unsigned long _scno  __asm__("r6") = n;
+
+	__asm__ __volatile__("scall %[r_scno]"
+		     : "=r" (_ret)
+		     : [r_scno] "r" (_scno)
+		     :  "r1", "r2", "r3", "r4", "r5", ASM_CLOBBERS );
+	return _ret;
+}
+
+static __inline long __syscall1(long n, long a)
+{
+	register unsigned long _ret __asm__("r0") = a;
+	register unsigned long _scno  __asm__("r6") = n;
+
+	__asm__ __volatile__("scall %[r_scno]"
+		     : "=r" (_ret)
+		     : [r_scno] "r" (_scno), "r"(_ret)
+		     :  "r1", "r2", "r3", "r4", "r5", ASM_CLOBBERS );
+	return _ret;
+}
+
+static __inline long __syscall2(long n, long a, long b)
+{
+	register unsigned long _ret __asm__("r0") = a;
+	register unsigned long _b __asm__("r1") = b;
+	register unsigned long _scno  __asm__("r6") = n;
+
+	__asm__ __volatile__("scall %[r_scno]"
+		     : "=r" (_ret)
+		     : [r_scno] "r" (_scno), "r"(_ret), "r"(_b)
+		     :  "r2", "r3", "r4", "r5", ASM_CLOBBERS );
+	return _ret;
+}
+
+static __inline long __syscall3(long n, long a, long b, long c)
+{
+	register unsigned long _ret __asm__("r0") = a;
+	register unsigned long _b __asm__("r1") = b;
+	register unsigned long _c __asm__("r2") = c;
+	register unsigned long _scno  __asm__("r6") = n;
+
+	__asm__ __volatile__("scall %[r_scno]"
+		     : "=r" (_ret)
+		     : [r_scno] "r" (_scno), "r"(_ret), "r"(_b), "r"(_c)
+		     :  "r3", "r4", "r5", ASM_CLOBBERS );
+	return _ret;
+}
+
+static __inline long __syscall4(long n, long a, long b, long c, long d)
+{
+	register unsigned long _ret __asm__("r0") = a;
+	register unsigned long _b __asm__("r1") = b;
+	register unsigned long _c __asm__("r2") = c;
+	register unsigned long _d __asm__("r3") = d;
+	register unsigned long _scno  __asm__("r6") = n;
+
+	__asm__ __volatile__("scall %[r_scno]"
+		     : "=r" (_ret)
+		     : [r_scno] "r" (_scno), "r"(_ret), "r"(_b), "r"(_c), "r"(_d)
+		     :  "r4", "r5", ASM_CLOBBERS );
+	return _ret;
+}
+
+static __inline long __syscall5(long n, long a, long b, long c, long d, long e)
+{
+	register unsigned long _ret __asm__("r0") = a;
+	register unsigned long _b __asm__("r1") = b;
+	register unsigned long _c __asm__("r2") = c;
+	register unsigned long _d __asm__("r3") = d;
+	register unsigned long _e __asm__("r4") = e;
+	register unsigned long _scno  __asm__("r6") = n;
+
+	__asm__ __volatile__("scall %[r_scno]"
+		     : "=r" (_ret)
+		     : [r_scno] "r" (_scno), "r"(_ret), "r"(_b), "r"(_c), "r"(_d), "r"(_e)
+		     :  "r5", ASM_CLOBBERS );
+	return _ret;
+}
+
+static __inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
+{
+	register unsigned long _ret __asm__("r0") = a;
+	register unsigned long _b __asm__("r1") = b;
+	register unsigned long _c __asm__("r2") = c;
+	register unsigned long _d __asm__("r3") = d;
+	register unsigned long _e __asm__("r4") = e;
+	register unsigned long _f __asm__("r5") = f;
+	register unsigned long _scno  __asm__("r6") = n;
+
+	__asm__ __volatile__("scall %[r_scno]"
+		     : "=r" (_ret)
+		     : [r_scno] "r" (_scno), "r"(_ret), "r"(_b), "r"(_c), "r"(_d), "r"(_e), "r"(_f)
+		     : ASM_CLOBBERS );
+	return _ret;
+}
+
+#else
+
+#undef SYSCALL_NO_INLINE
+#define SYSCALL_NO_INLINE
+
+#endif
+
+#define __SYSCALL_LL_E(x) (x)
+#define __SYSCALL_LL_O(x) (x)
+
+/*
+ * Syscall handlers in kvx-linux for msgctl, semctl and shmctl
+ * don't expect the IPC_64 flag.
+ */
+#define IPC_64 0
diff --git a/configure b/configure
index 6f5453f5..04768bbb 100755
--- a/configure
+++ b/configure
@@ -338,6 +338,7 @@ powerpc*|ppc*) ARCH=powerpc ;;
 riscv64*) ARCH=riscv64 ;;
 sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
 s390x*) ARCH=s390x ;;
+kvx*) ARCH=kvx ;;
 unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
 *) fail "$0: unknown or unsupported target \"$target\"" ;;
 esac
diff --git a/include/elf.h b/include/elf.h
index 86e2f0bb..5460f453 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -315,7 +315,8 @@ typedef struct {
 #define EM_RISCV	243
 #define EM_BPF		247
 #define EM_CSKY		252
-#define EM_NUM		253
+#define EM_KVX		256
+#define EM_NUM		257

 #define EM_ALPHA	0x9026

@@ -3229,6 +3230,91 @@ enum
 #define R_OR1K_TLS_DTPOFF	33
 #define R_OR1K_TLS_DTPMOD	34

+/* KVX relocs */
+#define R_KVX_NONE                                   0
+#define R_KVX_16                                     1
+#define R_KVX_32                                     2
+#define R_KVX_64                                     3
+#define R_KVX_S16_PCREL                              4
+#define R_KVX_PCREL17                                5
+#define R_KVX_PCREL27                                6
+#define R_KVX_32_PCREL                               7
+#define R_KVX_S37_PCREL_LO10                         8
+#define R_KVX_S37_PCREL_UP27                         9
+#define R_KVX_S43_PCREL_LO10                        10
+#define R_KVX_S43_PCREL_UP27                        11
+#define R_KVX_S43_PCREL_EX6                         12
+#define R_KVX_S64_PCREL_LO10                        13
+#define R_KVX_S64_PCREL_UP27                        14
+#define R_KVX_S64_PCREL_EX27                        15
+#define R_KVX_64_PCREL                              16
+#define R_KVX_S16                                   17
+#define R_KVX_S32_LO5                               18
+#define R_KVX_S32_UP27                              19
+#define R_KVX_S37_LO10                              20
+#define R_KVX_S37_UP27                              21
+#define R_KVX_S37_GOTOFF_LO10                       22
+#define R_KVX_S37_GOTOFF_UP27                       23
+#define R_KVX_S43_GOTOFF_LO10                       24
+#define R_KVX_S43_GOTOFF_UP27                       25
+#define R_KVX_S43_GOTOFF_EX6                        26
+#define R_KVX_32_GOTOFF                             27
+#define R_KVX_64_GOTOFF                             28
+#define R_KVX_32_GOT                                29
+#define R_KVX_S37_GOT_LO10                          30
+#define R_KVX_S37_GOT_UP27                          31
+#define R_KVX_S43_GOT_LO10                          32
+#define R_KVX_S43_GOT_UP27                          33
+#define R_KVX_S43_GOT_EX6                           34
+#define R_KVX_64_GOT                                35
+#define R_KVX_GLOB_DAT                              36
+#define R_KVX_COPY                                  37
+#define R_KVX_JMP_SLOT                              38
+#define R_KVX_RELATIVE                              39
+#define R_KVX_S43_LO10                              40
+#define R_KVX_S43_UP27                              41
+#define R_KVX_S43_EX6                               42
+#define R_KVX_S64_LO10                              43
+#define R_KVX_S64_UP27                              44
+#define R_KVX_S64_EX27                              45
+#define R_KVX_S37_GOTADDR_LO10                      46
+#define R_KVX_S37_GOTADDR_UP27                      47
+#define R_KVX_S43_GOTADDR_LO10                      48
+#define R_KVX_S43_GOTADDR_UP27                      49
+#define R_KVX_S43_GOTADDR_EX6                       50
+#define R_KVX_S64_GOTADDR_LO10                      51
+#define R_KVX_S64_GOTADDR_UP27                      52
+#define R_KVX_S64_GOTADDR_EX27                      53
+#define R_KVX_64_DTPMOD                             54
+#define R_KVX_64_DTPOFF                             55
+#define R_KVX_S37_TLS_DTPOFF_LO10                   56
+#define R_KVX_S37_TLS_DTPOFF_UP27                   57
+#define R_KVX_S43_TLS_DTPOFF_LO10                   58
+#define R_KVX_S43_TLS_DTPOFF_UP27                   59
+#define R_KVX_S43_TLS_DTPOFF_EX6                    60
+#define R_KVX_S37_TLS_GD_LO10                       61
+#define R_KVX_S37_TLS_GD_UP27                       62
+#define R_KVX_S43_TLS_GD_LO10                       63
+#define R_KVX_S43_TLS_GD_UP27                       64
+#define R_KVX_S43_TLS_GD_EX6                        65
+#define R_KVX_S37_TLS_LD_LO10                       66
+#define R_KVX_S37_TLS_LD_UP27                       67
+#define R_KVX_S43_TLS_LD_LO10                       68
+#define R_KVX_S43_TLS_LD_UP27                       69
+#define R_KVX_S43_TLS_LD_EX6                        70
+#define R_KVX_64_TPOFF                              71
+#define R_KVX_S37_TLS_IE_LO10                       72
+#define R_KVX_S37_TLS_IE_UP27                       73
+#define R_KVX_S43_TLS_IE_LO10                       74
+#define R_KVX_S43_TLS_IE_UP27                       75
+#define R_KVX_S43_TLS_IE_EX6                        76
+#define R_KVX_S37_TLS_LE_LO10                       77
+#define R_KVX_S37_TLS_LE_UP27                       78
+#define R_KVX_S43_TLS_LE_LO10                       79
+#define R_KVX_S43_TLS_LE_UP27                       80
+#define R_KVX_S43_TLS_LE_EX6                        81
+
+
 #define R_BPF_NONE		0
 #define R_BPF_MAP_FD		1

diff --git a/include/sys/cachectl.h b/include/sys/cachectl.h
index f3b896a8..6b586f3e 100644
--- a/include/sys/cachectl.h
+++ b/include/sys/cachectl.h
@@ -10,8 +10,15 @@ extern "C" {
 #define BCACHE (ICACHE|DCACHE)
 #define CACHEABLE 0
 #define UNCACHEABLE 1
-
+
+#ifdef __kvx__
+#include <asm/cachectl.h>
+
+int cachectl(void *, size_t, unsigned long, unsigned long);
+#else
 int cachectl(void *, int, int);
+#endif
+
 int cacheflush(void *, int, int);
 int _flush_cache(void *, int, int);

diff --git a/src/fenv/kvx/fenv.c b/src/fenv/kvx/fenv.c
new file mode 100644
index 00000000..aca9dd9c
--- /dev/null
+++ b/src/fenv/kvx/fenv.c
@@ -0,0 +1,60 @@
+#include <fenv.h>
+#define KVX_SFR_CS 4
+#define EMPTY_MASK 0
+
+static inline void set_clr_cs(int setmask, int clrmask)
+{
+	__builtin_kvx_wfxl(KVX_SFR_CS, ((long long)setmask << 32) | clrmask);
+}
+
+int feclearexcept(int excepts)
+{
+	excepts &= FE_ALL_EXCEPT;
+	set_clr_cs(EMPTY_MASK, excepts);
+	return 0;
+}
+
+int feraiseexcept(int excepts)
+{
+	excepts &= FE_ALL_EXCEPT;
+	set_clr_cs(excepts, EMPTY_MASK);
+	return 0;
+}
+
+int fetestexcept(int excepts)
+{
+	fexcept_t flags;
+	excepts &= FE_ALL_EXCEPT;
+	flags = __builtin_kvx_get(KVX_SFR_CS);
+	return (flags & excepts);
+}
+
+int fegetround(void)
+{
+	fenv_t rm;
+	rm = __builtin_kvx_get(KVX_SFR_CS);
+	return rm & FE_RND_MASK;
+}
+
+int __fesetround(int r)
+{
+	r &= FE_RND_MASK;
+	set_clr_cs(r, FE_RND_MASK);
+	return 0;
+}
+
+int fegetenv(fenv_t *envp)
+{
+	fenv_t fe;
+	fe = __builtin_kvx_get(KVX_SFR_CS);
+	*envp = (fe & (FE_ALL_EXCEPT | FE_RND_MASK));
+	return 0;
+}
+
+int fesetenv(const fenv_t *envp)
+{
+	fenv_t fe = (envp != FE_DFL_ENV ? *envp : 0);
+	fe &= (FE_ALL_EXCEPT | FE_RND_MASK);
+	set_clr_cs(fe, FE_ALL_EXCEPT | FE_RND_MASK);
+	return 0;
+}
diff --git a/src/linux/cache.c b/src/linux/cache.c
index 0eb051c2..ea39b256 100644
--- a/src/linux/cache.c
+++ b/src/linux/cache.c
@@ -1,6 +1,7 @@
 #include <errno.h>
 #include "syscall.h"
 #include "atomic.h"
+#include <stddef.h>

 #ifdef SYS_cacheflush
 int _flush_cache(void *addr, int len, int op)
@@ -11,10 +12,17 @@ weak_alias(_flush_cache, cacheflush);
 #endif

 #ifdef SYS_cachectl
+#if __kvx__
+int __cachectl(void *addr, size_t len, unsigned long cache, unsigned long flags)
+{
+	return syscall(SYS_cachectl, addr, len, cache, flags);
+}
+#else
 int __cachectl(void *addr, int len, int op)
 {
 	return syscall(SYS_cachectl, addr, len, op);
 }
+#endif
 weak_alias(__cachectl, cachectl);
 #endif

diff --git a/src/math/kvx/fma.c b/src/math/kvx/fma.c
new file mode 100644
index 00000000..4d4b99ec
--- /dev/null
+++ b/src/math/kvx/fma.c
@@ -0,0 +1,9 @@
+#include <math.h>
+
+double fma(double x, double y, double z)
+{
+	__asm__ ("ffmad %0 = %1, %2\n"
+		 ";;\n"
+		 : "+r"(z) : "r"(x), "r"(y));
+	return z;
+}
diff --git a/src/math/kvx/fmaf.c b/src/math/kvx/fmaf.c
new file mode 100644
index 00000000..757d75d1
--- /dev/null
+++ b/src/math/kvx/fmaf.c
@@ -0,0 +1,9 @@
+#include <math.h>
+
+float fmaf(float x, float y, float z)
+{
+	__asm__ ("ffmaw %0 = %1, %2\n"
+		 ";;\n"
+		 : "+r"(z) : "r"(x), "r"(y));
+	return z;
+}
diff --git a/src/setjmp/kvx/longjmp.S b/src/setjmp/kvx/longjmp.S
new file mode 100644
index 00000000..9135e2d1
--- /dev/null
+++ b/src/setjmp/kvx/longjmp.S
@@ -0,0 +1,32 @@
+#define REG_SIZE 8
+
+/* void __longjmp(__jmp_buf __env, int __val) */
+.global _longjmp
+.global longjmp
+.type _longjmp,@function
+.type longjmp,@function
+_longjmp:
+longjmp:
+	lo $r40r41r42r43 = (0 * REG_SIZE)[$r0]
+	;;
+	lo $r44r45r46r47 = (18 * REG_SIZE)[$r0]
+	set $ra = $r40
+	copyd $sp = $r41
+	;;
+	lo $r20r21r22r23 = (4 * REG_SIZE)[$r0]
+	set $cs = $r42
+	copyd $r14 = $r43
+	;;
+	lo $r24r25r26r27 = (8 * REG_SIZE)[$r0]
+	set $lc = $r44
+	;;
+	lo $r28r29r30r31 = (12 * REG_SIZE)[$r0]
+	set $le = $r45
+	;;
+	lq $r18r19 = (16 * REG_SIZE)[$r0]
+	set $ls = $r46
+	;;
+	/* According to man, if retval is equal to 0, then we should return 1 */
+	maxud $r0 = $r1, 1
+	ret
+	;;
diff --git a/src/setjmp/kvx/setjmp.S b/src/setjmp/kvx/setjmp.S
new file mode 100644
index 00000000..5b93da76
--- /dev/null
+++ b/src/setjmp/kvx/setjmp.S
@@ -0,0 +1,46 @@
+#define REG_SIZE 8
+
+/*
+ * int setjmp(jmpbuf env)
+ * Save the user context to $r0 (jmpbuf)
+ * jmpbuf layout:
+ * [0]  = $ra,  $sp,  $cs,  $r14,
+ * [4]  = $r20, $r21, $r22, $r23,
+ * [8]  = $r24, $r25, $r26, $r27,
+ * [12] = $r28, $r29, $r30, $r31,
+ * [16] = $r18, $r19,
+ * [18] = $lc,  $le,  $ls,  xxxx
+ */
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+	sq (16 * REG_SIZE)[$r0] = $r18r19
+	get $r40 = $ra
+	copyd $r41 = $sp
+	;;
+	so (4 * REG_SIZE)[$r0] = $r20r21r22r23
+	get $r42 = $cs
+	copyd $r43 = $r14
+	;;
+	so (0 * REG_SIZE)[$r0] = $r40r41r42r43
+	get $r40 = $lc
+	;;
+	so (8 * REG_SIZE)[$r0] = $r24r25r26r27
+	get $r41 = $le
+	;;
+	so (12 * REG_SIZE)[$r0] = $r28r29r30r31
+	get $r42 = $ls
+	;;
+	so (18 * REG_SIZE)[$r0] = $r40r41r42r43
+	make $r0 = 0
+	ret
+	;;
diff --git a/src/signal/kvx/sigsetjmp.S b/src/signal/kvx/sigsetjmp.S
new file mode 100644
index 00000000..8bc5eb80
--- /dev/null
+++ b/src/signal/kvx/sigsetjmp.S
@@ -0,0 +1,31 @@
+#define JMP_BUF_SIZE 176
+#define SS_OFFSET JMP_BUF_SIZE+8+8
+
+.global sigsetjmp
+.global __sigsetjmp
+.type sigsetjmp,@function
+.type __sigsetjmp@function
+sigsetjmp:
+__sigsetjmp:
+.hidden ___setjmp
+	cb.deqz $r1? ___setjmp
+	;;
+	get $r2 = $ra
+	;;
+	sd (JMP_BUF_SIZE)[$r0] = $r2
+	;;
+	call ___setjmp
+	sd (SS_OFFSET)[$r0] = $r18
+	copyd $r18 = $r0
+	;;
+	copyd $r1 = $r0
+	copyd $r0 = $r18
+	ld $r2 = (JMP_BUF_SIZE)[$r18]
+	;;
+	ld $r18 = (SS_OFFSET)[$r0]
+	set $ra = $r2
+	;;
+
+.hidden __sigsetjmp_tail
+	goto __sigsetjmp_tail
+	;;
diff --git a/src/thread/kvx/__set_thread_area.c b/src/thread/kvx/__set_thread_area.c
new file mode 100644
index 00000000..e2867461
--- /dev/null
+++ b/src/thread/kvx/__set_thread_area.c
@@ -0,0 +1,12 @@
+#include "pthread_impl.h"
+#include "libc.h"
+#include <elf.h>
+
+int __set_thread_area(void *p)
+{
+        __asm__ __volatile__ ("copyd $r13 = %[tp]\n;;\n"
+                              : /* "No outputs. */
+                              : [tp] "r"(p)
+                              : "r13");
+        return 0;
+}
diff --git a/src/thread/kvx/clone.s b/src/thread/kvx/clone.s
new file mode 100644
index 00000000..0ec83760
--- /dev/null
+++ b/src/thread/kvx/clone.s
@@ -0,0 +1,54 @@
+/*
+ * __clone(func, stack, flags, arg, ptid, tls, ctid)
+ *         r0,   r1,    r2,    r3,  r4,   r5,  r6
+ *
+ * sys_clone(flags, stack, ptid, ctid, tls)
+ *           r0,    r1,    r2,   r3,   r4
+ */
+.global __clone
+.hidden __clone
+.type __clone,%function
+__clone:
+	/* align stack */
+	andd $r1 = $r1, -32
+	;;
+	/* Set clone_flags */
+	copyd $r0 = $r2
+	addd $r1 = $r1, -32
+	/* Save fn ($r0) on child stack */
+	sd -32[$r1] = $r0
+	;;
+	/* Save args ($r3) on child stack */
+	sd 8[$r1] = $r3
+	/* Set parent_tidptr */
+	copyd $r2 = $r4
+	/* Set child_tidptr */
+	copyd $r3 = $r6
+	/* Set tls */
+	copyd $r4 = $r5
+	;;
+	scall 220 /* __NR_clone */
+	;;
+	/* If 0, then we are the child */
+	cb.deqz $r0, 1f
+	;;
+	/* Else we are the parent */
+	ret
+	;;
+
+	/* Let's get the child running the correct function */
+1:
+	/* get fn from stack */
+	ld $r1 = 0[$sp]
+	;;
+	/* Get args from stack */
+	ld $r0 = 8[$sp]
+	addd $sp = $sp, 32
+	;;
+	icall $r1
+	;;
+	scall 93 /* __NR_exit */
+	;;
+	/* We should never ever get here ! */
+	errop
+	;;
diff --git a/src/thread/kvx/syscall_cp.S b/src/thread/kvx/syscall_cp.S
new file mode 100644
index 00000000..34be7871
--- /dev/null
+++ b/src/thread/kvx/syscall_cp.S
@@ -0,0 +1,34 @@
+.global __cp_begin
+.hidden __cp_begin
+.global __cp_end
+.hidden __cp_end
+.global __cp_cancel
+.hidden __cp_cancel
+.hidden __cancel
+.global __syscall_cp_asm
+.hidden __syscall_cp_asm
+.type   __syscall_cp_asm,@function
+__syscall_cp_asm:
+__cp_begin:
+	lwz $r0 = 0[$r0]
+	;;
+	cb.dnez $r0? __cp_cancel
+	;;
+	copyd $r16 = $r1
+	copyd $r0 = $r2
+	copyd $r1 = $r3
+	copyd $r2 = $r4
+	;;
+	copyd $r3 = $r5
+	copyd $r4 = $r6
+	copyd $r5 = $r7
+	copyd $r6 = $r16
+	;;
+	scall $r6
+	;;
+__cp_end:
+	ret
+	;;
+__cp_cancel:
+	goto	__cancel
+	;;
--
2.17.1








^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-07-11 15:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-11 15:23 [musl] [RFC PATCH] add kvx arch Jonathan Borne

Code repositories for project(s) associated with this inbox:

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).