From 672a303852353ba9299f6f50190fca8b3abe4c1d Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Fri, 2 Oct 2020 16:24:55 +0200 Subject: kvx: add support for kvx arch to uClibc-ng MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds support for Kalray VLIW family (kvx) Kalray kv3 core is embedded in Kalray Coolidge SoC. This core which is the third of the KV family has the following features: 32/64 bits execution mode 6-issue VLIW architecture 64 x 64bits general purpose registers SIMD instructions little-endian In order to build a usable toolchain, build scripts are provided at the following address: https://github.com/kalray/build-scripts. Kalray uses FOSS which is available at https://github.com/kalray This includes Linux kernel, uClibc-ng, gcc, binutils, etc. Signed-off-by: Clément Léger Signed-off-by: Guillaume Thouvenin Signed-off-by: Laurent Thevenoux Signed-off-by: Marc Poulhies Signed-off-by: Marius Gligor Signed-off-by: Yann Sionneau --- MAINTAINERS | 4 + README | 2 +- Rules.mak | 6 +- extra/Configs/Config.in | 8 + extra/Configs/Config.kvx | 18 ++ extra/Configs/defconfigs/kvx/defconfig | 1 + include/elf.h | 87 +++++- ldso/ldso/kvx/dl-startup.h | 104 +++++++ ldso/ldso/kvx/dl-syscalls.h | 1 + ldso/ldso/kvx/dl-sysdep.h | 99 +++++++ ldso/ldso/kvx/dl-tlsdesc.S | 33 +++ ldso/ldso/kvx/elfinterp.c | 302 +++++++++++++++++++++ ldso/ldso/kvx/resolve.S | 17 ++ libc/string/kvx/Makefile | 13 + libc/string/kvx/memcpy.S | 221 +++++++++++++++ libc/string/kvx/memset.S | 146 ++++++++++ libc/sysdeps/linux/kvx/Makefile | 13 + libc/sysdeps/linux/kvx/Makefile.arch | 10 + libc/sysdeps/linux/kvx/__longjmp.S | 53 ++++ libc/sysdeps/linux/kvx/__syscall_error.c | 19 ++ libc/sysdeps/linux/kvx/bits/atomic.h | 141 ++++++++++ libc/sysdeps/linux/kvx/bits/endian.h | 13 + libc/sysdeps/linux/kvx/bits/fcntl.h | 226 +++++++++++++++ libc/sysdeps/linux/kvx/bits/fenv.h | 106 ++++++++ libc/sysdeps/linux/kvx/bits/kernel_types.h | 42 +++ libc/sysdeps/linux/kvx/bits/posix_types.h | 14 + libc/sysdeps/linux/kvx/bits/sem.h | 84 ++++++ libc/sysdeps/linux/kvx/bits/setjmp.h | 46 ++++ libc/sysdeps/linux/kvx/bits/stackinfo.h | 29 ++ libc/sysdeps/linux/kvx/bits/statfs.h | 64 +++++ libc/sysdeps/linux/kvx/bits/syscalls.h | 80 ++++++ libc/sysdeps/linux/kvx/bits/uClibc_arch_features.h | 41 +++ libc/sysdeps/linux/kvx/bits/wordsize.h | 9 + libc/sysdeps/linux/kvx/bsd-_setjmp.S | 18 ++ libc/sysdeps/linux/kvx/bsd-setjmp.S | 17 ++ libc/sysdeps/linux/kvx/cachectl.c | 15 + libc/sysdeps/linux/kvx/clone.S | 100 +++++++ libc/sysdeps/linux/kvx/crt1.S | 83 ++++++ libc/sysdeps/linux/kvx/crti.S | 31 +++ libc/sysdeps/linux/kvx/crtn.S | 33 +++ libc/sysdeps/linux/kvx/jmpbuf-offsets.h | 50 ++++ libc/sysdeps/linux/kvx/jmpbuf-unwind.h | 30 ++ libc/sysdeps/linux/kvx/setjmp.S | 59 ++++ libc/sysdeps/linux/kvx/sys/cachectl.h | 21 ++ libc/sysdeps/linux/kvx/sys/procfs.h | 101 +++++++ libc/sysdeps/linux/kvx/sys/ucontext.h | 29 ++ libc/sysdeps/linux/kvx/sys/user.h | 27 ++ libc/sysdeps/linux/kvx/sysdep.h | 49 ++++ libc/sysdeps/linux/kvx/vfork.S | 47 ++++ libm/kvx/Makefile.arch | 22 ++ libm/kvx/feclearexcept.c | 20 ++ libm/kvx/fegetenv.c | 21 ++ libm/kvx/fegetexceptflag.c | 24 ++ libm/kvx/fegetround.c | 16 ++ libm/kvx/feholdexcept.c | 26 ++ libm/kvx/feraiseexcept.c | 24 ++ libm/kvx/fesetenv.c | 23 ++ libm/kvx/fesetexceptflag.c | 24 ++ libm/kvx/fesetround.c | 21 ++ libm/kvx/fetestexcept.c | 21 ++ libm/kvx/feupdateenv.c | 24 ++ libpthread/nptl/sysdeps/kvx/Makefile.arch | 9 + libpthread/nptl/sysdeps/kvx/dl-tls.h | 47 ++++ libpthread/nptl/sysdeps/kvx/libc-tls.c | 26 ++ libpthread/nptl/sysdeps/kvx/pthread_spin_lock.c | 60 ++++ libpthread/nptl/sysdeps/kvx/pthread_spin_trylock.c | 26 ++ libpthread/nptl/sysdeps/kvx/pthreaddef.h | 26 ++ libpthread/nptl/sysdeps/kvx/tcb-offsets.sym | 6 + libpthread/nptl/sysdeps/kvx/tls.h | 160 +++++++++++ libpthread/nptl/sysdeps/kvx/unwind-forcedunwind.c | 165 +++++++++++ libpthread/nptl/sysdeps/pthread/Makefile.in | 2 + .../nptl/sysdeps/unix/sysv/linux/kvx/Makefile | 13 + .../nptl/sysdeps/unix/sysv/linux/kvx/Makefile.arch | 14 + .../unix/sysv/linux/kvx/bits/pthreadtypes.h | 166 +++++++++++ .../sysdeps/unix/sysv/linux/kvx/bits/semaphore.h | 30 ++ .../sysdeps/unix/sysv/linux/kvx/createthread.c | 14 + libpthread/nptl/sysdeps/unix/sysv/linux/kvx/fork.c | 11 + .../sysdeps/unix/sysv/linux/kvx/pthread_once.c | 77 ++++++ .../sysdeps/unix/sysv/linux/kvx/sysdep-cancel.h | 43 +++ utils/ldd.c | 5 + 80 files changed, 3925 insertions(+), 3 deletions(-) create mode 100644 extra/Configs/Config.kvx create mode 100644 extra/Configs/defconfigs/kvx/defconfig create mode 100644 ldso/ldso/kvx/dl-startup.h create mode 100644 ldso/ldso/kvx/dl-syscalls.h create mode 100644 ldso/ldso/kvx/dl-sysdep.h create mode 100644 ldso/ldso/kvx/dl-tlsdesc.S create mode 100644 ldso/ldso/kvx/elfinterp.c create mode 100644 ldso/ldso/kvx/resolve.S create mode 100644 libc/string/kvx/Makefile create mode 100644 libc/string/kvx/memcpy.S create mode 100644 libc/string/kvx/memset.S create mode 100644 libc/sysdeps/linux/kvx/Makefile create mode 100644 libc/sysdeps/linux/kvx/Makefile.arch create mode 100644 libc/sysdeps/linux/kvx/__longjmp.S create mode 100644 libc/sysdeps/linux/kvx/__syscall_error.c create mode 100644 libc/sysdeps/linux/kvx/bits/atomic.h create mode 100644 libc/sysdeps/linux/kvx/bits/endian.h create mode 100644 libc/sysdeps/linux/kvx/bits/fcntl.h create mode 100644 libc/sysdeps/linux/kvx/bits/fenv.h create mode 100644 libc/sysdeps/linux/kvx/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/kvx/bits/posix_types.h create mode 100644 libc/sysdeps/linux/kvx/bits/sem.h create mode 100644 libc/sysdeps/linux/kvx/bits/setjmp.h create mode 100644 libc/sysdeps/linux/kvx/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/kvx/bits/statfs.h create mode 100644 libc/sysdeps/linux/kvx/bits/syscalls.h create mode 100644 libc/sysdeps/linux/kvx/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/kvx/bits/wordsize.h create mode 100644 libc/sysdeps/linux/kvx/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/kvx/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/kvx/cachectl.c create mode 100644 libc/sysdeps/linux/kvx/clone.S create mode 100644 libc/sysdeps/linux/kvx/crt1.S create mode 100644 libc/sysdeps/linux/kvx/crti.S create mode 100644 libc/sysdeps/linux/kvx/crtn.S create mode 100644 libc/sysdeps/linux/kvx/jmpbuf-offsets.h create mode 100644 libc/sysdeps/linux/kvx/jmpbuf-unwind.h create mode 100644 libc/sysdeps/linux/kvx/setjmp.S create mode 100644 libc/sysdeps/linux/kvx/sys/cachectl.h create mode 100644 libc/sysdeps/linux/kvx/sys/procfs.h create mode 100644 libc/sysdeps/linux/kvx/sys/ucontext.h create mode 100644 libc/sysdeps/linux/kvx/sys/user.h create mode 100644 libc/sysdeps/linux/kvx/sysdep.h create mode 100644 libc/sysdeps/linux/kvx/vfork.S create mode 100644 libm/kvx/Makefile.arch create mode 100644 libm/kvx/feclearexcept.c create mode 100644 libm/kvx/fegetenv.c create mode 100644 libm/kvx/fegetexceptflag.c create mode 100644 libm/kvx/fegetround.c create mode 100644 libm/kvx/feholdexcept.c create mode 100644 libm/kvx/feraiseexcept.c create mode 100644 libm/kvx/fesetenv.c create mode 100644 libm/kvx/fesetexceptflag.c create mode 100644 libm/kvx/fesetround.c create mode 100644 libm/kvx/fetestexcept.c create mode 100644 libm/kvx/feupdateenv.c create mode 100644 libpthread/nptl/sysdeps/kvx/Makefile.arch create mode 100644 libpthread/nptl/sysdeps/kvx/dl-tls.h create mode 100644 libpthread/nptl/sysdeps/kvx/libc-tls.c create mode 100644 libpthread/nptl/sysdeps/kvx/pthread_spin_lock.c create mode 100644 libpthread/nptl/sysdeps/kvx/pthread_spin_trylock.c create mode 100644 libpthread/nptl/sysdeps/kvx/pthreaddef.h create mode 100644 libpthread/nptl/sysdeps/kvx/tcb-offsets.sym create mode 100644 libpthread/nptl/sysdeps/kvx/tls.h create mode 100644 libpthread/nptl/sysdeps/kvx/unwind-forcedunwind.c create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/Makefile create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/Makefile.arch create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/bits/pthreadtypes.h create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/bits/semaphore.h create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/createthread.c create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/fork.c create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/pthread_once.c create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/kvx/sysdep-cancel.h diff --git a/MAINTAINERS b/MAINTAINERS index 650d9b5bb..039b16895 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23,3 +23,7 @@ Stafford Horne Xtensa: Max Filippov + +KVX: +Clément Léger +Yann Sionneau diff --git a/README b/README index be53d0217..cb3a9ff57 100644 --- a/README +++ b/README @@ -12,7 +12,7 @@ Porting applications from glibc to uClibc-ng typically involves just recompiling the source code. uClibc-ng even supports shared libraries and threading. It currently runs on standard Linux and MMU-less (also known as µClinux) systems with support for Alpha, ARC, ARM, Blackfin, CRIS, FR-V, HPPA, -IA64, LM32, M68K/Coldfire, Metag, Microblaze, MIPS, MIPS64, NDS32, NIOS2, +IA64, KVX, LM32, M68K/Coldfire, Metag, Microblaze, MIPS, MIPS64, NDS32, NIOS2, OpenRisc, PowerPC, SuperH, Sparc, Tile, x86, x86_64 and Xtensa processors. If you are building an embedded Linux system and you find that glibc is eating diff --git a/Rules.mak b/Rules.mak index 55e88d462..e9aebeaab 100644 --- a/Rules.mak +++ b/Rules.mak @@ -144,7 +144,7 @@ SHARED_LIBNAME := $(LIBC).so.$(ABI_VERSION) UCLIBC_LDSO_NAME := ld-uClibc ARCH_NATIVE_BIT := 32 -ifneq ($(findstring $(TARGET_ARCH) , hppa64 ia64 powerpc64 s390x sparc64 x86_64 ),) +ifneq ($(findstring $(TARGET_ARCH) , hppa64 ia64 powerpc64 s390x sparc64 x86_64 kvx ),) UCLIBC_LDSO_NAME := ld64-uClibc ARCH_NATIVE_BIT := 64 else @@ -465,6 +465,10 @@ ifeq ($(TARGET_ARCH),csky) CPU_CFLAGS-$(ARCH_BIG_ENDIAN) += -mbig-endian endif +ifeq ($(TARGET_ARCH),kvx) + CPU_CFLAGS-$(CONFIG_KVX) += -march=kvx +endif + ifeq ($(TARGET_ARCH),m68k) # -fPIC is only supported for 68020 and above. It is not supported # for 68000, 68010, or Coldfire. diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index fff434b40..7dca9e305 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -28,6 +28,7 @@ choice default TARGET_hppa if DESIRED_TARGET_ARCH = "hppa" default TARGET_i386 if DESIRED_TARGET_ARCH = "i386" 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_m68k if DESIRED_TARGET_ARCH = "m68k" default TARGET_metag if DESIRED_TARGET_ARCH = "metag" @@ -91,6 +92,9 @@ config TARGET_i386 config TARGET_ia64 bool "ia64" +config TARGET_kvx + bool "kvx" + config TARGET_lm32 bool "lm32" @@ -192,6 +196,10 @@ if TARGET_ia64 source "extra/Configs/Config.ia64" endif +if TARGET_kvx +source "extra/Configs/Config.kvx" +endif + if TARGET_lm32 source "extra/Configs/Config.lm32" endif diff --git a/extra/Configs/Config.kvx b/extra/Configs/Config.kvx new file mode 100644 index 000000000..398ffceaa --- /dev/null +++ b/extra/Configs/Config.kvx @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "kvx" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + select UCLIBC_HAS_FPU + select UCLIBC_HAS_FENV + select UCLIBC_HAS_WCHAR + select DO_C99_MATH diff --git a/extra/Configs/defconfigs/kvx/defconfig b/extra/Configs/defconfigs/kvx/defconfig new file mode 100644 index 000000000..c80e6ce8e --- /dev/null +++ b/extra/Configs/defconfigs/kvx/defconfig @@ -0,0 +1 @@ +TARGET_kvx=y diff --git a/include/elf.h b/include/elf.h index d1be3bc1b..7d66d70a4 100644 --- a/include/elf.h +++ b/include/elf.h @@ -273,9 +273,10 @@ typedef struct #define EM_ARCV2 195 /* ARCv2 Cores */ #define EM_RISCV 243 /* RISC-V */ #define EM_CSKY 252 /* C-SKY Cores */ +#define EM_KVX 256 /* Kalray VLIW core of the MPPA processor family */ /* NEXT FREE NUMBER: Increment this after adding your official arch number */ -#define EM_NUM 253 +#define EM_NUM 257 /* If it is necessary to assign new unofficial EM_* values, please pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision @@ -1253,6 +1254,90 @@ typedef struct #define ELF64_M_SIZE(info) ELF32_M_SIZE (info) #define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) +/* 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 + /* C-SKY relocs. */ #define R_CKCORE_NONE 0 diff --git a/ldso/ldso/kvx/dl-startup.h b/ldso/ldso/kvx/dl-startup.h new file mode 100644 index 000000000..9784c2345 --- /dev/null +++ b/ldso/ldso/kvx/dl-startup.h @@ -0,0 +1,104 @@ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2016 Waldemar Brodkorb + * Copyright (C) 2018 Kalray Inc. + * + * Ported from GNU libc + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Copyright (C) 1995-2016 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 + . */ + +#include + +/* This is the first bit of code, ever, executed in user space of a dynamically + * linked ELF. + * The kernel jumps on this with the following stack layout: + * argc argument counter (integer) + * argv[0] program name (pointer) + * argv[1..argc-1] program args (pointers) + * NULL + * env[0...N] environment variables (pointers) + * NULL + * auxvt[0...N] Auxiliary Vector Table elements (mixed types) + * + * We should call _dl_start($sp) (the argument should point to the previously + * described memory layout). + * + * Next we should skip N arguments (N == _dl_skip_args). + * Those correspond to the arguments which are consumed by the dynamic loader + * if it is called directly as a program, which is possible when + * __LDSO_STANDALONE_SUPPORT__ is defined. + * + * We eventually end up calling the main executable's _start (from ctr1.S). + * The address of this _start is returned by _dl_start (in $r0). + * + * We should call this with one argument (in $r0): the address of _dl_fini() + */ +__asm__("\ +.text \n\ +.globl _start \n\ +.type _start, %function \n\ +_start: \n\ + copyd $r0 = $sp \n\ + copyd $r18 = $sp \n\ + andd $sp = $sp, -32 \n\ + call _dl_start \n\ + ;; \n\ +.globl _dl_start_user \n\ +.type _dl_start_user, %function \n\ +_dl_start_user: \n\ + pcrel $r1 = @gotaddr() \n\ + copyd $r5 = $r0 \n\ + copyd $sp = $r18 \n\ + ;; \n\ + ld $r2 = @gotoff(_dl_skip_args)[$r1] \n\ + addd $r0 = $r1, @gotoff(_dl_fini) \n\ + ;; \n\ + lwz $r3 = 0[$sp] \n\ + ;; \n\ + sbfw $r4 = $r2, $r3 \n\ + addx8d $sp = $r2, $sp \n\ + ;; \n\ + sd 0[$sp] = $r4 \n\ + icall $r5 \n\ + ;; \n\ +"); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, + ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym) +{ + switch (ELF_R_TYPE(rpnt->r_info)) { + case R_KVX_NONE: + break; + case R_KVX_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_KVX_RELATIVE: + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + _dl_exit(1); + } +} diff --git a/ldso/ldso/kvx/dl-syscalls.h b/ldso/ldso/kvx/dl-syscalls.h new file mode 100644 index 000000000..f40c4fd31 --- /dev/null +++ b/ldso/ldso/kvx/dl-syscalls.h @@ -0,0 +1 @@ +/* stub for arch-specific syscall issues */ diff --git a/ldso/ldso/kvx/dl-sysdep.h b/ldso/ldso/kvx/dl-sysdep.h new file mode 100644 index 000000000..9bb20ca8e --- /dev/null +++ b/ldso/ldso/kvx/dl-sysdep.h @@ -0,0 +1,99 @@ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen + * Copyright (C) 2017-2018 by Waldemar Brodkorb + * Copyright (C) 2018 Kalray Inc. + + * Ported from GNU C Library + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Copyright (C) 1995-2017 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 + . */ + +/* Defines that this system uses RELOCA. */ +#define ELF_USES_RELOCA + +#include +#include + +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_KVX +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "kvx" + +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +#define elf_machine_type_class(type) \ + ((((type) == R_KVX_JMP_SLOT || (type) == R_KVX_64_DTPMOD || \ + (type) == R_KVX_64_DTPOFF \ + || (type) == R_KVX_64_TPOFF) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_KVX_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. */ +extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden; +static __always_inline ElfW(Addr) __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + unsigned long *ptr; + __asm__("\n" + "pcrel %0 = @gotaddr()\n" + ";;\n" : "=r"(ptr) :: ); + return *ptr; +} + +/* Return the run-time load address of the shared object. */ + +static __always_inline ElfW(Addr) __attribute__ ((unused)) +elf_machine_load_address (void) +{ + /* To figure out the load address we use the definition that for any symbol: + dynamic_addr(symbol) = static_addr(symbol) + load_addr + + _DYNAMIC sysmbol is used here as its link-time address stored in + the special unrelocated first GOT entry. */ + + extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; + return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic (); +} + +static __always_inline void +elf_machine_relative(Elf64_Addr load_off, const Elf64_Addr rel_addr, + Elf64_Word relative_count) +{ + Elf64_Rela *rpnt = (Elf64_Rela*)rel_addr; + --rpnt; + do { + Elf64_Addr *const reloc_addr = (Elf64_Addr*)(load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/ldso/ldso/kvx/dl-tlsdesc.S b/ldso/ldso/kvx/dl-tlsdesc.S new file mode 100644 index 000000000..d0a55b985 --- /dev/null +++ b/ldso/ldso/kvx/dl-tlsdesc.S @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 Kalray Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#if defined __UCLIBC_HAS_TLS__ +#error NOT IMPLEMENTED: THIS IS A SKELETON + .text + + .hidden _dl_tlsdesc_return + .global _dl_tlsdesc_return + .type _dl_tlsdesc_return,%function + .align 2 +_dl_tlsdesc_return: + errop + ;; +.size _dl_tlsdesc_return, .-_dl_tlsdesc_return + +#ifdef SHARED + + .hidden _dl_tlsdesc_dynamic + .global _dl_tlsdesc_dynamic + .type _dl_tlsdesc_dynamic,%function + cfi_startproc + .align 2 +_dl_tlsdesc_dynamic: + errop + ;; + cfi_endproc + .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic + +#endif // SHARED +#endif // __UCLIBC_HAS_TLS__ diff --git a/ldso/ldso/kvx/elfinterp.c b/ldso/ldso/kvx/elfinterp.c new file mode 100644 index 000000000..9efcf83ff --- /dev/null +++ b/ldso/ldso/kvx/elfinterp.c @@ -0,0 +1,302 @@ +/* KVX ELF shared library loader suppport + * + * Copyright (C) 2001-2004 Erik Andersen + * Copyright (C) 2016-2017 Waldemar Brodkorb + * Copyright (C) 2018 Kalray Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +#include "ldso.h" + +#if defined(USE_TLS) && USE_TLS +#include "dl-tls.h" +#include "tlsdeschtab.h" +#endif + +extern int _dl_linux_resolve(void); + +/* Uncomment when some relocs will be handled lazily */ +#if 0 +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of jump instruction to fix up */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\tpatched %x ==> %x @ %x", *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + return (unsigned long)new_addr; +} +#endif + +static int +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res==0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; +#if defined USE_TLS && USE_TLS + struct elf_resolve *tls_tpnt = NULL; +#endif + struct symbol_ref sym_ref; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symbol_addr = 0; + symname = strtab + sym_ref.sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (unlikely (!symbol_addr && + (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) && + (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))) { + return 1; + } + if (_dl_trace_prelink) { + _dl_debug_lookup (symname, tpnt, &symtab[symtab_index], + &sym_ref, elf_machine_type_class(reloc_type)); + } +#if defined USE_TLS && USE_TLS + tls_tpnt = sym_ref.tpnt; +#endif + } else { + /* + * Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. + */ + symbol_addr = sym_ref.sym->st_value; +#if defined USE_TLS && USE_TLS + tls_tpnt = tpnt; +#endif + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_KVX_NONE: + break; + case R_KVX_GLOB_DAT: + case R_KVX_64: + case R_KVX_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_KVX_COPY: + if (symbol_addr) { + _dl_memcpy((char *)reloc_addr, (char *)symbol_addr, + sym_ref.sym->st_size); + } + break; + +#if defined USE_TLS && USE_TLS + case R_KVX_64_TPOFF: + CHECK_STATIC_TLS ((struct link_map *) tls_tpnt); + *reloc_addr = tls_tpnt->l_tls_offset + symbol_addr + rpnt->r_addend - TLS_TCB_SIZE; + break; + case R_KVX_64_DTPMOD: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + case R_KVX_64_DTPOFF: + *reloc_addr = symbol_addr; + break; +#endif + default: + return -1; /*call _dl_exit(1) */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) { + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); + } +#endif + + return 0; +} + +/* uncomment when PLT relocs will be handled lazily */ +#if 0 +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_KVX_NONE: + break; + case R_KVX_JMP_SLOT64: + *reloc_addr += tpnt->loadaddr; + break; +#if defined USE_TLS && USE_TLS +#error Not even close to be ready +#endif + default: + return -1; /*call _dl_exit(1) */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) { + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); + } +#endif + + return 0; +} +#endif + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, &_dl_loaded_modules->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/kvx/resolve.S b/ldso/ldso/kvx/resolve.S new file mode 100644 index 000000000..6e7c3143c --- /dev/null +++ b/ldso/ldso/kvx/resolve.S @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2018 Kalray Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#warning NOT IMPLEMENTED: THIS IS A SKELETON + + .text + .globl _dl_linux_resolve + .type _dl_linux_resolve, %function + .align 2 + +_dl_linux_resolve: + errop + ;; + +.size _dl_linux_resolve, .-_dl_linux_resolve diff --git a/libc/string/kvx/Makefile b/libc/string/kvx/Makefile new file mode 100644 index 000000000..0a95346fd --- /dev/null +++ b/libc/string/kvx/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# 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.in +include $(top_srcdir)Makerules diff --git a/libc/string/kvx/memcpy.S b/libc/string/kvx/memcpy.S new file mode 100644 index 000000000..290e705b4 --- /dev/null +++ b/libc/string/kvx/memcpy.S @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2020 Kalray Inc. + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB + * in this tarball. + */ + +#include + +.align 16 +ENTRY(memcpy) + cb.deqz $r2? .Lreturn + compd.geu $r3 = $r2, 256 + copyd $r6 = $r0 + ;; + cb.deqz $r3? .Lremaining_256 + ;; + lq.u $r32r33 = 0[$r1] + addd $r2 = $r2, -256 + ;; + lq.u $r34r35 = 16[$r1] + ;; + lq.u $r36r37 = 32[$r1] + srld $r7 = $r2, 8 + ;; + lq.u $r38r39 = 48[$r1] + ;; + lq.u $r40r41 = 64[$r1] + ;; + lq.u $r42r43 = 80[$r1] + ;; + lq.u $r44r45 = 96[$r1] + ;; + lq.u $r46r47 = 112[$r1] + ;; + lq.u $r48r49 = 128[$r1] + ;; + lq.u $r50r51 = 144[$r1] + ;; + lq.u $r52r53 = 160[$r1] + ;; + lq.u $r54r55 = 176[$r1] + ;; + lq.u $r56r57 = 192[$r1] + ;; + lq.u $r58r59 = 208[$r1] + compd.geu $r3 = $r2, 256 + ;; + lq.u $r60r61 = 224[$r1] + ;; + lq.u $r62r63 = 240[$r1] + addd $r1 = $r1, 256 + ;; + cb.deqz $r7? .Lstreaming_loop_end + ;; + loopdo $r7? .Lstreaming_loop_end + ;; + sq 0[$r0] = $r32r33 + addd $r2 = $r2, -256 + ;; + lq.u $r32r33 = 0[$r1] + ;; + sq 16[$r0] = $r34r35 + ;; + lq.u $r34r35 = 16[$r1] + ;; + sq 32[$r0] = $r36r37 + ;; + lq.u $r36r37 = 32[$r1] + ;; + sq 48[$r0] = $r38r39 + ;; + lq.u $r38r39 = 48[$r1] + ;; + sq 64[$r0] = $r40r41 + ;; + lq.u $r40r41 = 64[$r1] + ;; + sq 80[$r0] = $r42r43 + ;; + lq.u $r42r43 = 80[$r1] + ;; + sq 96[$r0] = $r44r45 + ;; + lq.u $r44r45 = 96[$r1] + ;; + sq 112[$r0] = $r46r47 + ;; + lq.u $r46r47 = 112[$r1] + ;; + sq 128[$r0] = $r48r49 + ;; + lq.u $r48r49 = 128[$r1] + ;; + sq 144[$r0] = $r50r51 + ;; + lq.u $r50r51 = 144[$r1] + ;; + sq 160[$r0] = $r52r53 + ;; + lq.u $r52r53 = 160[$r1] + ;; + sq 176[$r0] = $r54r55 + ;; + lq.u $r54r55 = 176[$r1] + ;; + sq 192[$r0] = $r56r57 + ;; + lq.u $r56r57 = 192[$r1] + ;; + sq 208[$r0] = $r58r59 + ;; + lq.u $r58r59 = 208[$r1] + ;; + sq 224[$r0] = $r60r61 + ;; + lq.u $r60r61 = 224[$r1] + ;; + sq 240[$r0] = $r62r63 + addd $r0 = $r0, 256 + ;; + lq.u $r62r63 = 240[$r1] + addd $r1 = $r1, 256 + ;; + .Lstreaming_loop_end: + sq 0[$r0] = $r32r33 + ;; + sq 16[$r0] = $r34r35 + ;; + sq 32[$r0] = $r36r37 + ;; + sq 48[$r0] = $r38r39 + ;; + sq 64[$r0] = $r40r41 + ;; + sq 80[$r0] = $r42r43 + ;; + sq 96[$r0] = $r44r45 + ;; + sq 112[$r0] = $r46r47 + ;; + sq 128[$r0] = $r48r49 + ;; + sq 144[$r0] = $r50r51 + ;; + sq 160[$r0] = $r52r53 + ;; + sq 176[$r0] = $r54r55 + ;; + sq 192[$r0] = $r56r57 + ;; + sq 208[$r0] = $r58r59 + ;; + sq 224[$r0] = $r60r61 + ;; + sq 240[$r0] = $r62r63 + addd $r0 = $r0, 256 + ;; +.Lremaining_256: + andd $r11 = $r2, 16 + srld $r7 = $r2, 5 + ;; + cb.deqz $r7? .Lloop_32_end + ;; + loopdo $r7? .Lloop_32_end + ;; + lo $r32r33r34r35 = 0[$r1] + addd $r1 = $r1, 32 + addd $r2 = $r2, -32 + ;; + so 0[$r0] = $r32r33r34r35 + addd $r0 = $r0, 32 + ;; + .Lloop_32_end: + andd $r10 = $r2, 8 + andd $r9 = $r2, 4 + cb.deqz $r11? .Lloop_remaining_16 + lq.u.dnez $r11? $r32r33 = 0[$r1] + ;; + sq 0[$r0] = $r32r33 + addd $r1 = $r1, 16 + addd $r0 = $r0, 16 + ;; +.Lloop_remaining_16: + andd $r8 = $r2, 2 + andd $r7 = $r2, 1 + cb.deqz $r10? .Lloop_remaining_8 + ld.dnez $r10? $r32 = 0[$r1] + ;; + sd 0[$r0] = $r32 + addd $r1 = $r1, 8 + addd $r0 = $r0, 8 + ;; +.Lloop_remaining_8: + cb.deqz $r9? .Lloop_remaining_4 + lwz.dnez $r9? $r32 = 0[$r1] + ;; + sw 0[$r0] = $r32 + addd $r1 = $r1, 4 + addd $r0 = $r0, 4 + ;; +.Lloop_remaining_4: + cb.deqz $r8? .Lloop_remaining_2 + lhz.dnez $r8? $r32 = 0[$r1] + ;; + sh 0[$r0] = $r32 + addd $r1 = $r1, 2 + addd $r0 = $r0, 2 + ;; +.Lloop_remaining_2: + lbz.dnez $r7? $r32 = 0[$r1] + ;; + sb.dnez $r7? 0[$r0] = $r32 + ;; +.Lreturn: + copyd $r0 = $r6 + ret + ;; +END(memcpy) + +libc_hidden_def(memcpy) diff --git a/libc/string/kvx/memset.S b/libc/string/kvx/memset.S new file mode 100644 index 000000000..45023a68f --- /dev/null +++ b/libc/string/kvx/memset.S @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2019 Kalray Inc. + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB + * in this tarball. + */ + +#define REPLICATE_BYTE_MASK 0x0101010101010101 +#define MIN_SIZE_FOR_ALIGN 128 + +/* + * Optimized memset for kvx architecture + * + * In order to optimize memset on kvx, we can use various things: + * - conditionnal store which avoid branch penalty + * - store half/word/double/quad/octuple to store up to 16 bytes at a time + * - hardware loop for steady cases. + * + * First, we start by checking if the size is below a minimum size. If so, we + * skip the alignment part. Indeed, the kvx supports misalignment and the + * penalty for letting it do unaligned accesses is lower than trying to + * realigning us. So for small sizes, we don't even bother to realign. + * In order to create the 64 bits pattern, we use sbmm to replicate the pattern + * on all bits on a register in one call. + * Once alignment has been reached, we can do the hardware loop using store + * octuple in order to optimize throughput. Care must be taken to align hardware + * loops on at least 8 bytes for performances. + * Once the main loop has been done, we finish the copy by checking length to do + * the necessary calls to store remaining bytes. + */ + +#include + +.align 16 +ENTRY(memset) + /* Preserve return value */ + copyd $r3 = $r0 + /* Replicate the first pattern byte on all bytes */ + sbmm8 $r32 = $r1, REPLICATE_BYTE_MASK + /* Check if length < MIN_SIZE_FOR_ALIGN */ + compd.geu $r7 = $r2, MIN_SIZE_FOR_ALIGN + /* Invert address to compute what we need to copy to be aligned on 32 bytes */ + negd $r5 = $r0 + ;; + /* Check if we are aligned on 32 bytes */ + andw $r9 = $r0, 0x1F + /* Compute the length that will be copied to align on 32 bytes boundary */ + andw $r6 = $r5, 0x1F + /* + * If size < MIN_SIZE_FOR_ALIGN bits, directly go to so, it will be done + * unaligned but that is still better that what we can do with sb + */ + cb.deqz $r7? .Laligned_32 + ;; + /* Remove unaligned part from length */ + sbfd $r2 = $r6, $r2 + /* If we are already aligned on 32 bytes, jump to main "so" loop */ + cb.deqz $r9? .Laligned_32 + /* Check if we need to copy 1 byte */ + andw $r4 = $r5, (1 << 0) + ;; + /* If we are not aligned, store byte */ + sb.dnez $r4? [$r0] = $r32 + /* Check if we need to copy 2 bytes */ + andw $r4 = $r5, (1 << 1) + /* Add potentially copied part for next store offset */ + addd $r0 = $r0, $r4 + ;; + sh.dnez $r4? [$r0] = $r32 + /* Check if we need to copy 4 bytes */ + andw $r4 = $r5, (1 << 2) + addd $r0 = $r0, $r4 + ;; + sw.dnez $r4? [$r0] = $r32 + /* Check if we need to copy 8 bytes */ + andw $r4 = $r5, (1 << 3) + addd $r0 = $r0, $r4 + /* Copy second part of pattern for sq */ + copyd $r33 = $r32 + ;; + sd.dnez $r4? [$r0] = $r32 + /* Check if we need to copy 16 bytes */ + andw $r4 = $r5, (1 << 4) + addd $r0 = $r0, $r4 + ;; + sq.dnez $r4? [$r0] = $r32r33 + addd $r0 = $r0, $r4 + ;; +.Laligned_32: + /* Copy second part of pattern for sq */ + copyd $r33 = $r32 + /* Prepare amount of data for 32 bytes store */ + srld $r10 = $r2, 5 + nop + nop + ;; + copyq $r34r35 = $r32, $r33 + /* Remaining bytes for 16 bytes store */ + andw $r8 = $r2, (1 << 4) + make $r11 = 32 + /* Check if there are enough data for 32 bytes store */ + cb.deqz $r10? .Laligned_32_done + ;; + loopdo $r10, .Laligned_32_done + ;; + so 0[$r0] = $r32r33r34r35 + addd $r0 = $r0, $r11 + ;; + .Laligned_32_done: + /* + * Now that we have handled every aligned bytes using 'so', we can + * handled the remainder of length using store by decrementing size + * We also exploit the fact we are aligned to simply check remaining + * size */ + sq.dnez $r8? [$r0] = $r32r33 + addd $r0 = $r0, $r8 + /* Remaining bytes for 8 bytes store */ + andw $r8 = $r2, (1 << 3) + cb.deqz $r2? .Lmemset_done + ;; + sd.dnez $r8? [$r0] = $r32 + addd $r0 = $r0, $r8 + /* Remaining bytes for 4 bytes store */ + andw $r8 = $r2, (1 << 2) + ;; + sw.dnez $r8? [$r0] = $r32 + addd $r0 = $r0, $r8 + /* Remaining bytes for 2 bytes store */ + andw $r8 = $r2, (1 << 1) + ;; + sh.dnez $r8? [$r0] = $r32 + addd $r0 = $r0, $r8 + ;; + sb.odd $r2? [$r0] = $r32 + /* Restore original value */ + copyd $r0 = $r3 + ret + ;; +.Lmemset_done: + /* Restore original value */ + copyd $r0 = $r3 + ret + ;; +END(memset) + +libc_hidden_def(memset) diff --git a/libc/sysdeps/linux/kvx/Makefile b/libc/sysdeps/linux/kvx/Makefile new file mode 100644 index 000000000..633c91f3e --- /dev/null +++ b/libc/sysdeps/linux/kvx/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# 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 diff --git a/libc/sysdeps/linux/kvx/Makefile.arch b/libc/sysdeps/linux/kvx/Makefile.arch new file mode 100644 index 000000000..3ad290915 --- /dev/null +++ b/libc/sysdeps/linux/kvx/Makefile.arch @@ -0,0 +1,10 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC-y := __syscall_error.c +CSRC-$(UCLIBC_LINUX_SPECIFIC) += cachectl.c +SSRC-y := setjmp.S bsd-setjmp.S bsd-_setjmp.S __longjmp.S clone.S vfork.S diff --git a/libc/sysdeps/linux/kvx/__longjmp.S b/libc/sysdeps/linux/kvx/__longjmp.S new file mode 100644 index 000000000..fbfefe81c --- /dev/null +++ b/libc/sysdeps/linux/kvx/__longjmp.S @@ -0,0 +1,53 @@ +/* + * This file is subject to the terms and conditions of the LGPL V2.1 + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2018 Kalray Inc. + */ + +#include +#define _SETJMP_H +#define _ASM +#include +#include + +/** + * void __longjmp(__jmp_buf __env, int __val) + */ +ENTRY(__longjmp) + /* Load $ra and $csinto r40r41 */ + lq $r40r41 = JMPBUF_RA_CS_OFFSET[$r0] + ;; + /* Load $r36r37r38r39 with r12(sp) r14 r18 r19 */ + lo $r36r37r38r39 = (JMPBUF_REGS_OFFSET)[$r0] + set $ra = $r40 + ;; + /* Load $lc, $le and $ls */ + lo $r32r33r34r35 = JMPBUF_LC_LE_LS_OFFSET[$r0] + copyd $sp = $r36 + copyd $r14 = $r37 + set $cs = $r41 + ;; + /* Load r20r21r22r23 */ + lo $r20r21r22r23 = (JMPBUF_REGS_OFFSET + QUAD_REG_SIZE)[$r0] + copyd $r18 = $r38 + copyd $r19 = $r39 + set $lc = $r32 + ;; + /* Load r24r25r26r27 */ + lo $r24r25r26r27 = (JMPBUF_REGS_OFFSET + 2 * QUAD_REG_SIZE)[$r0] + set $le = $r33 + ;; + /* Load r28r29r30r31 */ + lo $r28r29r30r31 = (JMPBUF_REGS_OFFSET + 3 * QUAD_REG_SIZE)[$r0] + set $ls = $r34 + /* Copy retval */ + copyd $r0 = $r1 + ;; + /* According to man, if retval is equal to 0, then we should return 1 */ + cmoved.deqz $r0? $r0 = 1 + ret + ;; +END(__longjmp) +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/kvx/__syscall_error.c b/libc/sysdeps/linux/kvx/__syscall_error.c new file mode 100644 index 000000000..d534ee7d4 --- /dev/null +++ b/libc/sysdeps/linux/kvx/__syscall_error.c @@ -0,0 +1,19 @@ +/* + * This file is subject to the terms and conditions of the LGPL V2.1 + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2018 Kalray Inc. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +long __syscall_error(int err_no) attribute_hidden; +long __syscall_error(int err_no) +{ + __set_errno(-err_no); + return -1; +} diff --git a/libc/sysdeps/linux/kvx/bits/atomic.h b/libc/sysdeps/linux/kvx/bits/atomic.h new file mode 100644 index 000000000..3c423e9ba --- /dev/null +++ b/libc/sysdeps/linux/kvx/bits/atomic.h @@ -0,0 +1,141 @@ +/* Copyright (C) 2010-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maxim Kuvyrkov , 2010. + + 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 + . */ + +#ifndef _KVX_BITS_ATOMIC_H +#define _KVX_BITS_ATOMIC_H + +#include + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#ifndef atomic_full_barrier +# define atomic_full_barrier() do { atomic_read_barrier(); \ + atomic_write_barrier(); } while(0) +#endif + +#ifndef atomic_read_barrier +# define atomic_read_barrier() __builtin_kvx_dinval() +#endif + +#ifndef atomic_write_barrier +# define atomic_write_barrier() __builtin_kvx_fence() +#endif + +/* + * On kvx, we have a boolean compare and swap which means that the operation + * returns only the success of operation. + * If operation succeeds, this is simple, we just need to return the provided + * old value. However, if it fails, we need to load the value to return it for + * the caller. If the loaded value is different from the "old" provided by the + * caller, we can return it since it will mean it failed. + * However, if for some reason the value we read is equal to the old value + * provided by the caller, we can't simply return it or the caller will think it + * succeeded. So if the value we read is the same as the "old" provided by + * the caller, we try again until either we succeed or we fail with a different + * value than the provided one. + */ +#define __cmpxchg(ptr, old, new, op_suffix, load_suffix) \ +({ \ + register unsigned long __rn __asm__("r62"); \ + register unsigned long __ro __asm__("r63"); \ + __asm__ __volatile__ ( \ + /* Fence to guarantee previous store to be committed */ \ + "fence\n" \ + /* Init "expect" with previous value */ \ + "copyd $r63 = %[rOld]\n" \ + ";;\n" \ + "1:\n" \ + /* Init "update" value with new */ \ + "copyd $r62 = %[rNew]\n" \ + ";;\n" \ + "acswap" #op_suffix " 0[%[rPtr]], $r62r63\n" \ + ";;\n" \ + /* if acswap succeeds, simply return */ \ + "cb.dnez $r62? 2f\n" \ + ";;\n" \ + /* We failed, load old value */ \ + "l" #op_suffix #load_suffix" $r63 = 0[%[rPtr]]\n" \ + ";;\n" \ + /* Check if equal to "old" one */ \ + "compd.ne $r62 = $r63, %[rOld]\n" \ + ";;\n" \ + /* If different from "old", return it to caller */ \ + "cb.deqz $r62? 1b\n" \ + ";;\n" \ + "2:\n" \ + : "+r" (__rn), "+r" (__ro) \ + : [rPtr] "r" (ptr), [rOld] "r" (old), [rNew] "r" (new) \ + : "memory"); \ + (__ro); \ +}) + +#define cmpxchg(ptr, o, n) \ +({ \ + unsigned long __cmpxchg__ret; \ + switch (sizeof(*(ptr))) { \ + case 4: \ + __cmpxchg__ret = __cmpxchg((ptr), (o), (n), w, s); \ + break; \ + case 8: \ + __cmpxchg__ret = __cmpxchg((ptr), (o), (n), d, ); \ + break; \ + } \ + (__typeof(*(ptr))) (__cmpxchg__ret); \ +}) + +#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + cmpxchg((mem), (oldval), (newval)) + + +#define atomic_exchange_acq(mem, newval) \ +({ \ + unsigned long __aea__ret, __aea__old; \ + volatile __typeof((mem)) __aea__m = (mem); \ + do { \ + __aea__old = *__aea__m; \ + __aea__ret = atomic_compare_and_exchange_val_acq((mem), \ + (newval), (__aea__old));\ + } while (__aea__old != __aea__ret); \ + (__aea__old); \ +}) + +#endif diff --git a/libc/sysdeps/linux/kvx/bits/endian.h b/libc/sysdeps/linux/kvx/bits/endian.h new file mode 100644 index 000000000..03a1b7f0c --- /dev/null +++ b/libc/sysdeps/linux/kvx/bits/endian.h @@ -0,0 +1,13 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2018 Kalray Inc. + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/kvx/bits/fcntl.h b/libc/sysdeps/linux/kvx/bits/fcntl.h new file mode 100644 index 000000000..c1815b44f --- /dev/null +++ b/libc/sysdeps/linux/kvx/bits/fcntl.h @@ -0,0 +1,226 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2018 Kalray Inc. + */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#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. */ +#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_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */ +# define F_GETPIPE_SZ 1032 /* Get pipe page size array. */ +#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 diff --git a/libc/sysdeps/linux/kvx/bits/fenv.h b/libc/sysdeps/linux/kvx/bits/fenv.h new file mode 100644 index 000000000..445ec7aff --- /dev/null +++ b/libc/sysdeps/linux/kvx/bits/fenv.h @@ -0,0 +1,106 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 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 + . */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +/* $cs register number for use in kvx builtins */ +#define KVX_SFR_CS 4 + +/* Each core of the Coolidge processor has a coprocessor. They share + the CS register but have distinct bit-fields for their + floating-point environment. This implementation synchronizes them + in such a way that they cannot be managed separately. */ + +/* Compute Status ($cs) register contains the following bit-fields for + floating-point execption flags. + + Bit-field Condition of the IEEE 754 binary floating-point standard + --------- -------------------------------------------------------- + IO