diff options
26 files changed, 649 insertions, 48 deletions
@@ -532,6 +532,7 @@ endif  ifeq ($(TARGET_ARCH),arc)  	CPU_CFLAGS-y += -mlock -mswape  	CPU_CFLAGS-$(CONFIG_ARC_CPU_700) += -mA7 +	CPU_CFLAGS-$(CONFIG_ARC_CPU_HS) += -mcpu=archs  	CPU_LDFLAGS-y += $(CPU_CFLAGS) -marclinux  endif diff --git a/extra/Configs/Config.arc b/extra/Configs/Config.arc index dc32ba4fb..c5406c457 100644 --- a/extra/Configs/Config.arc +++ b/extra/Configs/Config.arc @@ -20,6 +20,29 @@ config CONFIG_ARC_CPU_700  	help  	  ARCompact ISA based ARC CPU +config CONFIG_ARC_CPU_HS +	bool "ARC-HS" +	select ARCH_HAS_MMU +	help +	  Next Generation ARCv2 ISA based Processors + +endchoice + +choice +	prompt "MMU Page Size" +	default CONFIG_ARC_PAGE_SIZE_8K + +config CONFIG_ARC_PAGE_SIZE_8K +	bool "8KB" +	help +	  Choose between 4k, 8k (default) or 16k + +config CONFIG_ARC_PAGE_SIZE_16K +	bool "16KB" + +config CONFIG_ARC_PAGE_SIZE_4K +	bool "4KB" +  endchoice  choice diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index c1a2d5ac9..18b323781 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -257,6 +257,7 @@ config TARGET_SUBARCH  	default "i486" if CONFIG_486  	default "i586" if CONFIG_586  	default "i686" if CONFIG_686 +	default "arcv2" if CONFIG_ARC_CPU_HS  	default ""  source "extra/Configs/Config.in.arch" @@ -421,11 +422,11 @@ config LDSO_RUNPATH  	  should be safe for most people.  config LDSO_RUNPATH_OF_EXECUTABLE -	bool "Use executables RPATH/RUNPATH when searching for libraries." +	bool "Use executables RUNPATH/RPATH when searching for libraries."  	depends on LDSO_RUNPATH  	default n  	help -	  Use the executables RPATH/RUNPATH to find to find libraries even +	  Use the executables RUNPATH/RPATH to find to find libraries even  	  though this behavour is not standard.  Setting this option causes  	  the uclibc dynamic linker behavour to match the glibc dynamic linker. diff --git a/extra/Configs/defconfigs/arc/arcv2_defconfig b/extra/Configs/defconfigs/arc/arcv2_defconfig new file mode 100644 index 000000000..d3a7dc7b2 --- /dev/null +++ b/extra/Configs/defconfigs/arc/arcv2_defconfig @@ -0,0 +1,33 @@ +CONFIG_ARC_CPU_HS=y +ARCH_WANTS_LITTLE_ENDIAN=y +# UCLIBC_HAS_FPU is not set +DO_C99_MATH=y +KERNEL_HEADERS="%KERNEL_HEADERS%" +# DOPIC is not set +# LDSO_CACHE_SUPPORT is not set +LDSO_RUNPATH=y +# LDSO_SAFE_RUNPATH is not set +LINUXTHREADS_OLD=y +PTHREADS_DEBUG_SUPPORT=y +UCLIBC_HAS_OBSTACK=y +UCLIBC_SUSV2_LEGACY=y +UCLIBC_SUSV3_LEGACY=y +UCLIBC_SUSV4_LEGACY=y +UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y +UCLIBC_HAS_OBSOLETE_BSD_SIGNAL=y +UCLIBC_SV4_DEPRECATED=y +UCLIBC_HAS_RPC=y +UCLIBC_HAS_FULL_RPC=y +UCLIBC_HAS_RESOLVER_SUPPORT=y +UCLIBC_HAS_LIBRESOLV_STUB=y +UCLIBC_HAS_LOCALE=y +UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y +UCLIBC_HAS_NFTW=y +UCLIBC_HAS_FTW=y +UCLIBC_HAS_GNU_GLOB=y +RUNTIME_PREFIX="%RUNTIME_PREFIX%" +DEVEL_PREFIX="%DEVEL_PREFIX%" +CROSS_COMPILER_PREFIX="arc-linux-uclibc-" +# DOSTRIP is not set +SUPPORT_LD_DEBUG=y +UCLIBC_HAS_BACKTRACE=y diff --git a/extra/Configs/defconfigs/arc/defconfig b/extra/Configs/defconfigs/arc/defconfig index 2dca4f9b3..490bc2267 100644 --- a/extra/Configs/defconfigs/arc/defconfig +++ b/extra/Configs/defconfigs/arc/defconfig @@ -23,6 +23,7 @@ UCLIBC_HAS_LOCALE=y  UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y  UCLIBC_HAS_NFTW=y  UCLIBC_HAS_FTW=y +UCLIBC_HAS_GNU_GLOB=y  RUNTIME_PREFIX="%RUNTIME_PREFIX%"  DEVEL_PREFIX="%DEVEL_PREFIX%"  CROSS_COMPILER_PREFIX="arc-linux-uclibc-" diff --git a/extra/Configs/defconfigs/arc/tb10x_defconfig b/extra/Configs/defconfigs/arc/tb10x_defconfig index 60065f97d..405a4eac7 100644 --- a/extra/Configs/defconfigs/arc/tb10x_defconfig +++ b/extra/Configs/defconfigs/arc/tb10x_defconfig @@ -30,6 +30,7 @@ UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y  UCLIBC_HAS_PRINTF_M_SPEC=y  UCLIBC_HAS_NFTW=y  UCLIBC_HAS_FTW=y +UCLIBC_HAS_GNU_GLOB=y  RUNTIME_PREFIX="%RUNTIME_PREFIX%"  DEVEL_PREFIX="%DEVEL_PREFIX%"  CROSS_COMPILER_PREFIX="arc-linux-uclibc-" diff --git a/include/elf.h b/include/elf.h index fc6086489..68ec7d75f 100644 --- a/include/elf.h +++ b/include/elf.h @@ -258,7 +258,6 @@ typedef struct  #define EM_MN10200	90		/* Matsushita MN10200 */  #define EM_PJ		91		/* picoJava */  #define EM_OPENRISC	92		/* OpenRISC 32-bit embedded processor */ -#define EM_ARC_A5	93		/* ARC Cores Tangent-A5 */  #define EM_ARCOMPACT	93		/* ARCompact ISA based Cores: ARC 700 */  #define EM_XTENSA	94		/* Tensilica Xtensa Architecture */  #define EM_IP2K		101		/* Ubicom IP2022 micro controller */ @@ -267,8 +266,13 @@ typedef struct  #define EM_BLACKFIN	106		/* Analog Devices Blackfin */  #define EM_ALTERA_NIOS2	113	/* Altera Nios II soft-core processor */  #define EM_CRX		114		/* National Semiconductor CRX */ -#define EM_NUM		95  #define EM_TI_C6000	140 +#define EM_METAG	174		/* Imagination Technologies Meta */ +#define EM_MICROBLAZE	189	/* Xilinx Microblaze */ +#define EM_ARCV2	195		/* ARCv2 Cores */ + +/* NEXT FREE NUMBER: Increment this after adding your official arch number */ +#define EM_NUM		196  /* If it is necessary to assign new unofficial EM_* values, please pick large     random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision @@ -282,22 +286,9 @@ typedef struct     unofficial e_machine number should eventually ask registry@caldera.com for     an officially blessed number to be added to the list above.  */ -/* Imagination Technologies Meta */ -#define EM_METAG        174 - -/* picoJava */ -#define EM_PJ_OLD	99 -  /* Cygnus PowerPC ELF backend.  Written in the absence of an ABI.  */  #define EM_CYGNUS_POWERPC 0x9025 -/* Old version of Sparc v9, from before the ABI; this should be -   removed shortly.  */ -#define EM_OLD_SPARCV9	11 - -/* Old version of PowerPC, this should be removed shortly. */ -#define EM_PPC_OLD	17 -  /* (Deprecated) Temporary number for the OpenRISC processor.  */  #define EM_OR32		0x8472 @@ -376,9 +367,6 @@ typedef struct   */  #define EM_MICROBLAZE_OLD   0xbaab -/* Xilinx Microblaze (official) */ -#define EM_MICROBLAZE   189 -  /* Legal values for e_version (version).  */  #define EV_NONE		0		/* Invalid ELF version */ @@ -565,6 +553,7 @@ typedef struct  #define STB_WEAK	2		/* Weak symbol */  #define	STB_NUM		3		/* Number of defined types.  */  #define STB_LOOS	10		/* Start of OS-specific */ +#define STB_GNU_UNIQUE	10		/* Unique symbol.  */  #define STB_HIOS	12		/* End of OS-specific */  #define STB_LOPROC	13		/* Start of processor-specific */  #define STB_HIPROC	15		/* End of processor-specific */ @@ -580,6 +569,7 @@ typedef struct  #define STT_TLS		6		/* Symbol is thread-local data object*/  #define	STT_NUM		7		/* Number of defined types.  */  #define STT_LOOS	10		/* Start of OS-specific */ +#define STT_GNU_IFUNC	10		/* Symbol is indirect code object */  #define STT_HIOS	12		/* End of OS-specific */  #define STT_LOPROC	13		/* Start of processor-specific */  #define STT_HIPROC	15		/* End of processor-specific */ diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h index 08b3bade8..ca62a2c04 100644 --- a/ldso/ldso/arc/dl-sysdep.h +++ b/ldso/ldso/arc/dl-sysdep.h @@ -69,11 +69,16 @@ do {									\  } while(0)  /* Here we define the magic numbers that this dynamic loader should accept */ +#ifdef __A7__  #define MAGIC1 EM_ARCOMPACT +#define ELF_TARGET "ARCompact"	/* For error messages */ +#elif defined(__HS__) +#define MAGIC1 EM_ARCV2 +#define ELF_TARGET "ARCv2"	/* For error messages */ +#endif +  #undef  MAGIC2 -/* Used for error messages */ -#define ELF_TARGET "ARC"  struct elf_resolve;  extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, @@ -81,6 +86,8 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,  extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden; +#ifdef __A7__ +/* using "C" causes an indirection via __umodsi3 -> __udivmodsi4 */  #define do_rem(result, n, base)  ((result) =				\  									\  	__builtin_constant_p (base) ? (n) % (unsigned) (base) :		\ @@ -95,6 +102,10 @@ extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden;  		r1;							\  	})								\  ) +#elif defined(__HS__) +/* ARCv2 has hardware assisted divide/mod */ +#define do_rem(result, n, base)  ((result) = (n) % (unsigned) (base)) +#endif  /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or     TLS variable so PLT entries should not be allowed to define the value. diff --git a/ldso/ldso/arc/elfinterp.c b/ldso/ldso/arc/elfinterp.c index d26c94705..7c31d3ac7 100644 --- a/ldso/ldso/arc/elfinterp.c +++ b/ldso/ldso/arc/elfinterp.c @@ -11,7 +11,11 @@   */  #include "ldso.h" +#ifdef __A7__  #define ARC_PLT_SIZE	12 +#else +#define ARC_PLT_SIZE	16 +#endif  unsigned long  _dl_linux_resolver(struct elf_resolve *tpnt, unsigned int plt_pc) diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index d42b91281..49b516390 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -326,6 +326,38 @@ struct elf_resolve *_dl_load_shared_library(unsigned rflags, struct dyn_elf **rp  	if (tpnt1 != NULL)  		return tpnt1; +#ifdef __LDSO_RUNPATH_OF_EXECUTABLE__ +	/* Very last resort, try the executable's DT_RUNPATH and DT_RPATH */ +	/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#shobj_dependencies +	 * The set of directories specified by a given DT_RUNPATH entry is +	 * used to find only the immediate dependencies of the executable or +	 * shared object containing the DT_RUNPATH entry. That is, it is +	 * used only for those dependencies contained in the DT_NEEDED +	 * entries of the dynamic structure containing the DT_RUNPATH entry, +	 * itself. One object's DT_RUNPATH entry does not affect the search +	 * for any other object's dependencies. +	 * +	 * glibc (around 2.19) violates this and the usual suspects are +	 * abusing this bug^Wrelaxed, user-friendly behaviour. +	 */ + +	pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RUNPATH]; +	if (pnt) { +		pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB]; +		_dl_if_debug_dprint("\tsearching exe's RUNPATH='%s'\n", pnt); +		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL) +			return tpnt1; +	} +	pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RPATH]; +	if (pnt) { +		pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB]; +		_dl_if_debug_dprint("\tsearching exe's RPATH='%s'\n", pnt); +		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL) +			return tpnt1; +	} +#endif + +  goof:  	/* Well, we shot our wad on that one.  All we can do now is punt */  	if (_dl_internal_error_number) diff --git a/libc/string/arc/arcv2/memcpy.S b/libc/string/arc/arcv2/memcpy.S new file mode 100644 index 000000000..7573daf51 --- /dev/null +++ b/libc/string/arc/arcv2/memcpy.S @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include <features.h> +#include <sysdep.h> + +#ifdef __LITTLE_ENDIAN__ +# define SHIFT_1(RX,RY,IMM)	asl	RX, RY, IMM	; << +# define SHIFT_2(RX,RY,IMM)	lsr	RX, RY, IMM	; >> +# define MERGE_1(RX,RY,IMM)	asl	RX, RY, IMM +# define MERGE_2(RX,RY,IMM) +# define EXTRACT_1(RX,RY,IMM)	and	RX, RY, 0xFFFF +# define EXTRACT_2(RX,RY,IMM)	lsr	RX, RY, IMM +#else +# define SHIFT_1(RX,RY,IMM)	lsr	RX, RY, IMM	; >> +# define SHIFT_2(RX,RY,IMM)	asl	RX, RY, IMM	; << +# define MERGE_1(RX,RY,IMM)	asl	RX, RY, IMM	; << +# define MERGE_2(RX,RY,IMM)	asl	RX, RY, IMM	; << +# define EXTRACT_1(RX,RY,IMM)	lsr	RX, RY, IMM +# define EXTRACT_2(RX,RY,IMM)	lsr	RX, RY, 0x08 +#endif + +#ifdef __LL64__ +# define PREFETCH_READ(RX)	prefetch [RX, 56] +# define PREFETCH_WRITE(RX)	prefetchw [RX, 64] +# define LOADX(DST,RX)		ldd.ab	DST, [RX, 8] +# define STOREX(SRC,RX)		std.ab	SRC, [RX, 8] +# define ZOLSHFT		5 +# define ZOLAND			0x1F +#else +# define PREFETCH_READ(RX)	prefetch [RX, 28] +# define PREFETCH_WRITE(RX)	prefetchw [RX, 32] +# define LOADX(DST,RX)		ld.ab	DST, [RX, 4] +# define STOREX(SRC,RX)		st.ab	SRC, [RX, 4] +# define ZOLSHFT		4 +# define ZOLAND			0xF +#endif + +ENTRY(memcpy) +	prefetch  [r1]		; Prefetch the read location +	prefetchw [r0]		; Prefetch the write location +	mov.f	0, r2 +;;; if size is zero +	jz.d	[blink] +	mov	r3, r0		; don't clobber ret val + +;;; if size <= 8 +	cmp	r2, 8 +	bls.d	@.Lsmallchunk +	mov.f	lp_count, r2 + +	and.f	r4, r0, 0x03 +	rsub	lp_count, r4, 4 +	lpnz	@.Laligndestination +	;; LOOP BEGIN +	ldb.ab	r5, [r1,1] +	sub	r2, r2, 1 +	stb.ab	r5, [r3,1] +.Laligndestination: + +;;; Check the alignment of the source +	and.f	r4, r1, 0x03 +	bnz.d	@.Lsourceunaligned + +;;; CASE 0: Both source and destination are 32bit aligned +;;; Convert len to Dwords, unfold x4 +	lsr.f	lp_count, r2, ZOLSHFT +	lpnz	@.Lcopy32_64bytes +	;; LOOP START +	LOADX (r6, r1) +	PREFETCH_READ (r1) +	PREFETCH_WRITE (r3) +	LOADX (r8, r1) +	LOADX (r10, r1) +	LOADX (r4, r1) +	STOREX (r6, r3) +	STOREX (r8, r3) +	STOREX (r10, r3) +	STOREX (r4, r3) +.Lcopy32_64bytes: + +	and.f	lp_count, r2, ZOLAND ;Last remaining 31 bytes +.Lsmallchunk: +	lpnz	@.Lcopyremainingbytes +	;; LOOP START +	ldb.ab	r5, [r1,1] +	stb.ab	r5, [r3,1] +.Lcopyremainingbytes: + +	j	[blink] +;;; END CASE 0 + +.Lsourceunaligned: +	cmp	r4, 2 +	beq.d	@.LunalignedOffby2 +	sub	r2, r2, 1 + +	bhi.d	@.LunalignedOffby3 +	ldb.ab	r5, [r1, 1] + +;;; CASE 1: The source is unaligned, off by 1 +	;; Hence I need to read 1 byte for a 16bit alignment +	;; and 2bytes to reach 32bit alignment +	ldh.ab	r6, [r1, 2] +	sub	r2, r2, 2 +	;; Convert to words, unfold x2 +	lsr.f	lp_count, r2, 3 +	MERGE_1 (r6, r6, 8) +	MERGE_2 (r5, r5, 24) +	or	r5, r5, r6 + +	;; Both src and dst are aligned +	lpnz	@.Lcopy8bytes_1 +	;; LOOP START +	ld.ab	r6, [r1, 4] +	prefetch [r1, 28]	;Prefetch the next read location +	ld.ab	r8, [r1,4] +	prefetchw [r3, 32]	;Prefetch the next write location + +	SHIFT_1	(r7, r6, 24) +	or	r7, r7, r5 +	SHIFT_2	(r5, r6, 8) + +	SHIFT_1	(r9, r8, 24) +	or	r9, r9, r5 +	SHIFT_2	(r5, r8, 8) + +	st.ab	r7, [r3, 4] +	st.ab	r9, [r3, 4] +.Lcopy8bytes_1: + +	;; Write back the remaining 16bits +	EXTRACT_1 (r6, r5, 16) +	sth.ab	r6, [r3, 2] +	;; Write back the remaining 8bits +	EXTRACT_2 (r5, r5, 16) +	stb.ab	r5, [r3, 1] + +	and.f	lp_count, r2, 0x07 ;Last 8bytes +	lpnz	@.Lcopybytewise_1 +	;; LOOP START +	ldb.ab	r6, [r1,1] +	stb.ab	r6, [r3,1] +.Lcopybytewise_1: +	j	[blink] + +.LunalignedOffby2: +;;; CASE 2: The source is unaligned, off by 2 +	ldh.ab	r5, [r1, 2] +	sub	r2, r2, 1 + +	;; Both src and dst are aligned +	;; Convert to words, unfold x2 +	lsr.f	lp_count, r2, 3 +#ifdef __BIG_ENDIAN__ +	asl.nz	r5, r5, 16 +#endif +	lpnz	@.Lcopy8bytes_2 +	;; LOOP START +	ld.ab	r6, [r1, 4] +	prefetch [r1, 28]	;Prefetch the next read location +	ld.ab	r8, [r1,4] +	prefetchw [r3, 32]	;Prefetch the next write location + +	SHIFT_1	(r7, r6, 16) +	or	r7, r7, r5 +	SHIFT_2	(r5, r6, 16) + +	SHIFT_1	(r9, r8, 16) +	or	r9, r9, r5 +	SHIFT_2	(r5, r8, 16) + +	st.ab	r7, [r3, 4] +	st.ab	r9, [r3, 4] +.Lcopy8bytes_2: + +#ifdef __BIG_ENDIAN__ +	lsr.nz	r5, r5, 16 +#endif +	sth.ab	r5, [r3, 2] + +	and.f	lp_count, r2, 0x07 ;Last 8bytes +	lpnz	@.Lcopybytewise_2 +	;; LOOP START +	ldb.ab	r6, [r1,1] +	stb.ab	r6, [r3,1] +.Lcopybytewise_2: +	j	[blink] + +.LunalignedOffby3: +;;; CASE 3: The source is unaligned, off by 3 +;;; Hence, I need to read 1byte for achieve the 32bit alignment + +	;; Both src and dst are aligned +	;; Convert to words, unfold x2 +	lsr.f	lp_count, r2, 3 +#ifdef __BIG_ENDIAN__ +	asl.ne	r5, r5, 24 +#endif +	lpnz	@.Lcopy8bytes_3 +	;; LOOP START +	ld.ab	r6, [r1, 4] +	prefetch [r1, 28]	;Prefetch the next read location +	ld.ab	r8, [r1,4] +	prefetchw [r3, 32]	;Prefetch the next write location + +	SHIFT_1	(r7, r6, 8) +	or	r7, r7, r5 +	SHIFT_2	(r5, r6, 24) + +	SHIFT_1	(r9, r8, 8) +	or	r9, r9, r5 +	SHIFT_2	(r5, r8, 24) + +	st.ab	r7, [r3, 4] +	st.ab	r9, [r3, 4] +.Lcopy8bytes_3: + +#ifdef __BIG_ENDIAN__ +	lsr.nz	r5, r5, 24 +#endif +	stb.ab	r5, [r3, 1] + +	and.f	lp_count, r2, 0x07 ;Last 8bytes +	lpnz	@.Lcopybytewise_3 +	;; LOOP START +	ldb.ab	r6, [r1,1] +	stb.ab	r6, [r3,1] +.Lcopybytewise_3: +	j	[blink] + +END(memcpy) +libc_hidden_def(memcpy) diff --git a/libc/string/arc/arcv2/memset.S b/libc/string/arc/arcv2/memset.S new file mode 100644 index 000000000..d076ad1cd --- /dev/null +++ b/libc/string/arc/arcv2/memset.S @@ -0,0 +1,85 @@ + +/* + * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include <features.h> +#include <sysdep.h> + +#ifdef DONT_USE_PREALLOC +#define PREWRITE(A,B)	prefetchw [(A),(B)] +#else +#define PREWRITE(A,B)	prealloc [(A),(B)] +#endif + +ENTRY(memset) +	prefetchw [r0]		; Prefetch the write location +	mov.f	0, r2 +;;; if size is zero +	jz.d	[blink] +	mov	r3, r0		; don't clobber ret val + +;;; if length < 8 +	brls.d.nt	r2, 8, .Lsmallchunk +	mov.f	lp_count,r2 + +	and.f	r4, r0, 0x03 +	rsub	lp_count, r4, 4 +	lpnz	@.Laligndestination +	;; LOOP BEGIN +	stb.ab	r1, [r3,1] +	sub	r2, r2, 1 +.Laligndestination: + +;;; Destination is aligned +	and	r1, r1, 0xFF +	asl	r4, r1, 8 +	or	r4, r4, r1 +	asl	r5, r4, 16 +	or	r5, r5, r4 +	mov	r4, r5 + +	sub3	lp_count, r2, 8 +	cmp     r2, 64 +	bmsk.hi	r2, r2, 5 +	mov.ls	lp_count, 0 +	add3.hi	r2, r2, 8 + +;;; Convert len to Dwords, unfold x8 +	lsr.f	lp_count, lp_count, 6 +	lpnz	@.Lset64bytes +	;; LOOP START +	PREWRITE(r3, 64)	;Prefetch the next write location +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +.Lset64bytes: + +	lsr.f	lp_count, r2, 5 ;Last remaining  max 124 bytes +	lpnz	.Lset32bytes +	;; LOOP START +	prefetchw [r3, 32]	;Prefetch the next write location +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +	std.ab	r4, [r3, 8] +.Lset32bytes: + +	and.f	lp_count, r2, 0x1F ;Last remaining 31 bytes +.Lsmallchunk: +	lpnz	.Lcopy3bytes +	;; LOOP START +	stb.ab	r1, [r3, 1] +.Lcopy3bytes: + +	j	[blink] + +END(memset) +libc_hidden_def(memset) diff --git a/libc/string/arc/arcv2/strcmp.S b/libc/string/arc/arcv2/strcmp.S new file mode 100644 index 000000000..2e0e64a0c --- /dev/null +++ b/libc/string/arc/arcv2/strcmp.S @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include <features.h> +#include <sysdep.h> + +ENTRY(strcmp) +	or	r2, r0, r1 +	bmsk_s	r2, r2, 1 +	brne	r2, 0, @.Lcharloop + +;;; s1 and s2 are word aligned +	ld.ab	r2, [r0, 4] + +	mov_s	r12, 0x01010101 +	ror	r11, r12 +	.align  4 +.LwordLoop: +	ld.ab	r3, [r1, 4] +	;; Detect NULL char in str1 +	sub	r4, r2, r12 +	ld.ab	r5, [r0, 4] +	bic	r4, r4, r2 +	and	r4, r4, r11 +	brne.d.nt	r4, 0, .LfoundNULL +	;; Check if the read locations are the same +	cmp	r2, r3 +	beq.d	.LwordLoop +	mov.eq	r2, r5 + +	;; A match is found, spot it out +#ifdef __LITTLE_ENDIAN__ +	swape	r3, r3 +	mov_s	r0, 1 +	swape	r2, r2 +#else +	mov_s	r0, 1 +#endif +	cmp_s	r2, r3 +	j_s.d	[blink] +	bset.lo	r0, r0, 31 + +	.align 4 +.LfoundNULL: +#ifdef __BIG_ENDIAN__ +	swape	r4, r4 +	swape	r2, r2 +	swape	r3, r3 +#endif +	;; Find null byte +	ffs	r0, r4 +	bmsk	r2, r2, r0 +	bmsk	r3, r3, r0 +	swape	r2, r2 +	swape	r3, r3 +	;; make the return value +	sub.f	r0, r2, r3 +	mov.hi	r0, 1 +	j_s.d	[blink] +	bset.lo	r0, r0, 31 + +	.align 4 +.Lcharloop: +	ldb.ab	r2, [r0, 1] +	ldb.ab	r3, [r1, 1] +	nop +	breq	r2, 0, .Lcmpend +	breq	r2, r3, .Lcharloop + +	.align 4 +.Lcmpend: +	j_s.d	[blink] +	sub	r0, r2, r3 +END(strcmp) +libc_hidden_def(strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/arc/memcmp.S b/libc/string/arc/memcmp.S index 4c0e39143..a60757e7a 100644 --- a/libc/string/arc/memcmp.S +++ b/libc/string/arc/memcmp.S @@ -24,14 +24,32 @@ ENTRY(memcmp)  	ld	r4,[r0,0]  	ld	r5,[r1,0]  	lsr.f	lp_count,r3,3 +#ifdef __HS__ +	/* In ARCv2 a branch can't be the last instruction in a zero overhead +	 * loop. +	 * So we move the branch to the start of the loop, duplicate it +	 * after the end, and set up r12 so that the branch isn't taken +	 *  initially. +	 */ +	mov_s	r12,WORD2 +	lpne	.Loop_end +	brne	WORD2,r12,.Lodd +	ld	WORD2,[r0,4] +#else  	lpne	.Loop_end  	ld_s	WORD2,[r0,4] +#endif  	ld_s	r12,[r1,4]  	brne	r4,r5,.Leven  	ld.a	r4,[r0,8]  	ld.a	r5,[r1,8] +#ifdef __HS__ +.Loop_end: +	brne	WORD2,r12,.Lodd +#else  	brne	WORD2,r12,.Lodd  .Loop_end: +#endif  	asl_s	SHIFT,SHIFT,3  	bhs_s	.Last_cmp  	brne	r4,r5,.Leven @@ -99,14 +117,25 @@ ENTRY(memcmp)  	ldb	r4,[r0,0]  	ldb	r5,[r1,0]  	lsr.f	lp_count,r3 +#ifdef __HS__ +	mov	r12,r3  	lpne	.Lbyte_end +	brne	r3,r12,.Lbyte_odd +#else +	lpne	.Lbyte_end +#endif  	ldb_s	r3,[r0,1]  	ldb	r12,[r1,1]  	brne	r4,r5,.Lbyte_even  	ldb.a	r4,[r0,2]  	ldb.a	r5,[r1,2] +#ifdef __HS__ +.Lbyte_end: +	brne	r3,r12,.Lbyte_odd +#else  	brne	r3,r12,.Lbyte_odd  .Lbyte_end: +#endif  	bcc	.Lbyte_even  	brne	r4,r5,.Lbyte_even  	ldb_s	r3,[r0,1] diff --git a/libc/sysdeps/linux/arc/bits/syscalls.h b/libc/sysdeps/linux/arc/bits/syscalls.h index 5da6aadb3..248ef7844 100644 --- a/libc/sysdeps/linux/arc/bits/syscalls.h +++ b/libc/sysdeps/linux/arc/bits/syscalls.h @@ -98,7 +98,11 @@ extern int __syscall_error (int);   * for syscall itself.   *-------------------------------------------------------------------------*/ -#define ARC_TRAP_INSN  "trap0	\n\t" +#ifdef __A7__ +#define ARC_TRAP_INSN	"trap0		\n\t" +#elif defined(__HS__) +#define ARC_TRAP_INSN	"trap_s 0	\n\t" +#endif  #define INTERNAL_SYSCALL_NCS(nm, err, nr_args, args...)	\  ({							\ @@ -176,7 +180,11 @@ extern int __syscall_error (int);  #else +#ifdef __A7__  #define ARC_TRAP_INSN	trap0 +#elif defined(__HS__) +#define ARC_TRAP_INSN	trap_s 0 +#endif  #endif /* __ASSEMBLER__ */ diff --git a/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h b/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h index 8af6eca4c..451575586 100755 --- a/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/arc/bits/uClibc_arch_features.h @@ -47,4 +47,11 @@  /* The default ';' is a comment on ARC. */  #define __UCLIBC_ASM_LINE_SEP__ ` +/* does your target align 64bit values in register pairs ? (32bit arches only) */ +#if defined(__A7__) +#undef __UCLIBC_SYSCALL_ALIGN_64BIT__ +#else +#define __UCLIBC_SYSCALL_ALIGN_64BIT__ +#endif +  #endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in index 9d41771e2..8ee956b6b 100644 --- a/libc/sysdeps/linux/common/Makefile.in +++ b/libc/sysdeps/linux/common/Makefile.in @@ -45,6 +45,7 @@ CSRC-$(UCLIBC_LINUX_SPECIFIC) += \  	sendfile.c \  	setfsgid.c \  	setfsuid.c \ +	setns.c \  	setresgid.c \  	setresuid.c \  	signalfd.c \ diff --git a/libc/sysdeps/linux/common/bits/sched.h b/libc/sysdeps/linux/common/bits/sched.h index a5eb6ee55..9d05314f5 100644 --- a/libc/sysdeps/linux/common/bits/sched.h +++ b/libc/sysdeps/linux/common/bits/sched.h @@ -1,7 +1,6 @@  /* Definitions of constants and data structure for POSIX 1003.1b-1993     scheduling interface. -   Copyright (C) 1996-1999,2001-2003,2005,2006,2007,2008 -   Free Software Foundation, Inc. +   Copyright (C) 1996-2015 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 @@ -26,14 +25,17 @@  /* Scheduling algorithms.  */ -#define SCHED_OTHER	0 -#define SCHED_FIFO	1 -#define SCHED_RR	2 +#define SCHED_OTHER		0 +#define SCHED_FIFO		1 +#define SCHED_RR		2  #ifdef __USE_GNU -# define SCHED_BATCH	3 +# define SCHED_BATCH		3 +# define SCHED_IDLE		5 + +# define SCHED_RESET_ON_FORK	0x40000000  #endif -#ifdef __USE_MISC +#ifdef __USE_GNU  /* Cloning flags.  */  # define CSIGNAL       0x000000ff /* Signal mask to be sent at exit.  */  # define CLONE_VM      0x00000100 /* Set if VM shared between processes.  */ @@ -58,7 +60,6 @@  				      force CLONE_PTRACE on this clone.  */  # define CLONE_CHILD_SETTID 0x01000000 /* Store TID in userlevel buffer in  					  the child.  */ -# define CLONE_STOPPED 0x02000000 /* Start in stopped state.  */  # define CLONE_NEWUTS	0x04000000	/* New utsname group.  */  # define CLONE_NEWIPC	0x08000000	/* New ipcs.  */  # define CLONE_NEWUSER	0x10000000	/* New user namespace.  */ @@ -75,7 +76,7 @@ struct sched_param  __BEGIN_DECLS -#ifdef __USE_MISC +#ifdef __USE_GNU  /* Clone current process.  */  extern int clone (int (*__fn) (void *__arg), void *__child_stack,  		  int __flags, void *__arg, ...) __THROW; @@ -85,8 +86,12 @@ extern int unshare (int __flags) __THROW;  /* Get index of currently used CPU.  */  extern int sched_getcpu (void) __THROW; + +/* Switch process to namespace of type NSTYPE indicated by FD.  */ +extern int setns (int __fd, int __nstype) __THROW;  #endif +  __END_DECLS  #endif	/* need schedparam */ @@ -124,7 +129,11 @@ typedef struct  } cpu_set_t;  /* Access functions for CPU masks.  */ -# define __CPU_ZERO_S(setsize, cpusetp) \ +# if __GNUC_PREREQ (2, 91) +#  define __CPU_ZERO_S(setsize, cpusetp) \ +  do __builtin_memset (cpusetp, '\0', setsize); while (0) +# else +#  define __CPU_ZERO_S(setsize, cpusetp) \    do {									      \      size_t __i;								      \      size_t __imax = (setsize) / sizeof (__cpu_mask);			      \ @@ -132,47 +141,53 @@ typedef struct      for (__i = 0; __i < __imax; ++__i)					      \        __bits[__i] = 0;							      \    } while (0) +# endif  # define __CPU_SET_S(cpu, setsize, cpusetp) \    (__extension__							      \     ({ size_t __cpu = (cpu);						      \ -      __cpu < 8 * (setsize)						      \ +      __cpu / 8 < (setsize)						      \        ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]		      \  	 |= __CPUMASK (__cpu))						      \        : 0; }))  # define __CPU_CLR_S(cpu, setsize, cpusetp) \    (__extension__							      \     ({ size_t __cpu = (cpu);						      \ -      __cpu < 8 * (setsize)						      \ +      __cpu / 8 < (setsize)						      \        ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]		      \  	 &= ~__CPUMASK (__cpu))						      \        : 0; }))  # define __CPU_ISSET_S(cpu, setsize, cpusetp) \    (__extension__							      \     ({ size_t __cpu = (cpu);						      \ -      __cpu < 8 * (setsize)						      \ -      ? ((((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]	      \ +      __cpu / 8 < (setsize)						      \ +      ? ((((const __cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]	      \  	  & __CPUMASK (__cpu))) != 0					      \        : 0; }))  # define __CPU_COUNT_S(setsize, cpusetp) \    __sched_cpucount (setsize, cpusetp) -# define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \ +# if __GNUC_PREREQ (2, 91) +#  define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \ +  (__builtin_memcmp (cpusetp1, cpusetp2, setsize) == 0) +# else +#  define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \    (__extension__							      \ -   ({ __cpu_mask *__arr1 = (cpusetp1)->__bits;				      \ -      __cpu_mask *__arr2 = (cpusetp2)->__bits;				      \ +   ({ const __cpu_mask *__arr1 = (cpusetp1)->__bits;			      \ +      const __cpu_mask *__arr2 = (cpusetp2)->__bits;			      \        size_t __imax = (setsize) / sizeof (__cpu_mask);			      \        size_t __i;							      \        for (__i = 0; __i < __imax; ++__i)				      \  	if (__arr1[__i] != __arr2[__i])					      \  	  break;							      \        __i == __imax; })) +# endif  # define __CPU_OP_S(setsize, destset, srcset1, srcset2, op) \    (__extension__							      \     ({ cpu_set_t *__dest = (destset);					      \ -      __cpu_mask *__arr1 = (srcset1)->__bits;				      \ -      __cpu_mask *__arr2 = (srcset2)->__bits;				      \ +      const __cpu_mask *__arr1 = (srcset1)->__bits;			      \ +      const __cpu_mask *__arr2 = (srcset2)->__bits;			      \        size_t __imax = (setsize) / sizeof (__cpu_mask);			      \        size_t __i;							      \        for (__i = 0; __i < __imax; ++__i)				      \ diff --git a/libc/sysdeps/linux/common/eventfd.c b/libc/sysdeps/linux/common/eventfd.c index 96597ab33..500b0c002 100644 --- a/libc/sysdeps/linux/common/eventfd.c +++ b/libc/sysdeps/linux/common/eventfd.c @@ -15,7 +15,7 @@   * eventfd()   */  #if defined __NR_eventfd || defined __NR_eventfd2 -int eventfd (int count, int flags) +int eventfd (unsigned int count, int flags)  {  #if defined __NR_eventfd2    return INLINE_SYSCALL (eventfd2, 2, count, flags); diff --git a/libc/sysdeps/linux/common/posix_fadvise.c b/libc/sysdeps/linux/common/posix_fadvise.c index 14bbeeea1..74d8409c0 100644 --- a/libc/sysdeps/linux/common/posix_fadvise.c +++ b/libc/sysdeps/linux/common/posix_fadvise.c @@ -41,9 +41,17 @@ int posix_fadvise(int fd, off_t offset, off_t len, int advice)  #  if __WORDSIZE == 64  	ret = INTERNAL_SYSCALL(fadvise64_64, err, 4, fd, offset, len, advice);  #  else -#   if defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) || defined(__arm__) +#   if defined (__arm__) || \ +      (defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && (defined(__powerpc__) || defined(__xtensa__))) +	/* arch with 64-bit data in even reg alignment #1: [powerpc/xtensa] +	 * custom syscall handler (rearranges @advice to avoid register hole punch) */  	ret = INTERNAL_SYSCALL(fadvise64_64, err, 6, fd, advice,  			OFF_HI_LO (offset), OFF_HI_LO (len)); +#   elif defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) +	/* arch with 64-bit data in even reg alignment #2: [arcv2/others-in-future] +	 * stock syscall handler in kernel (reg hole punched) */ +	ret = INTERNAL_SYSCALL(fadvise64_64, err, 7, fd, 0, +			OFF_HI_LO (offset), OFF_HI_LO (len), advice);  #   else  	ret = INTERNAL_SYSCALL(fadvise64_64, err, 6, fd,  			OFF_HI_LO (offset), OFF_HI_LO (len), advice); diff --git a/libc/sysdeps/linux/common/posix_fadvise64.c b/libc/sysdeps/linux/common/posix_fadvise64.c index 5d8989121..37fb269ca 100644 --- a/libc/sysdeps/linux/common/posix_fadvise64.c +++ b/libc/sysdeps/linux/common/posix_fadvise64.c @@ -24,9 +24,18 @@ int posix_fadvise64(int fd, off64_t offset, off64_t len, int advice)  {  	INTERNAL_SYSCALL_DECL (err);  	/* ARM has always been funky. */ -# if defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) || defined(__arm__) +#if defined (__arm__) || \ +    (defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && (defined(__powerpc__) || defined(__xtensa__))) +	/* arch with 64-bit data in even reg alignment #1: [powerpc/xtensa] +	 * custom syscall handler (rearranges @advice to avoid register hole punch) */  	int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advice,  			OFF64_HI_LO (offset), OFF64_HI_LO (len)); +#elif defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) +	/* arch with 64-bit data in even reg alignment #2: [arcv2/others-in-future] +	 * stock syscall handler in kernel (reg hole punched) */ +	int ret = INTERNAL_SYSCALL (fadvise64_64, err, 7, fd, 0, +			OFF64_HI_LO (offset), OFF64_HI_LO (len), +			advice);  # else  	int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd,  			OFF64_HI_LO (offset), OFF64_HI_LO (len), diff --git a/libc/sysdeps/linux/common/setns.c b/libc/sysdeps/linux/common/setns.c new file mode 100644 index 000000000..a697720b9 --- /dev/null +++ b/libc/sysdeps/linux/common/setns.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * setns() for uClibc + * + * Copyright (C) 2015 Bernhard Reutner-Fischer <uclibc@uclibc.org> + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> +#include <sched.h> + +#ifdef __NR_setns +_syscall2(int, setns, int, fd, int, nstype) +#endif diff --git a/libc/sysdeps/linux/common/stubs.c b/libc/sysdeps/linux/common/stubs.c index 57c4664aa..2c50307aa 100644 --- a/libc/sysdeps/linux/common/stubs.c +++ b/libc/sysdeps/linux/common/stubs.c @@ -346,6 +346,10 @@ make_stub(setfsgid)  make_stub(setfsuid)  #endif +#if !defined __NR_setns && defined __UCLIBC_LINUX_SPECIFIC__ +make_stub(setns) +#endif +  #if !defined __NR_setresgid32 && !defined __NR_setresgid && defined __UCLIBC_LINUX_SPECIFIC__  make_stub(setresgid)  #endif diff --git a/libc/sysdeps/linux/common/sync_file_range.c b/libc/sysdeps/linux/common/sync_file_range.c index 6cd7e94d6..db797de62 100644 --- a/libc/sysdeps/linux/common/sync_file_range.c +++ b/libc/sysdeps/linux/common/sync_file_range.c @@ -24,7 +24,11 @@ static int __NC(sync_file_range)(int fd, off64_t offset, off64_t nbytes, unsigne  {  #  if defined __powerpc__ && __WORDSIZE == 64  	return INLINE_SYSCALL(sync_file_range, 4, fd, flags, offset, nbytes); -#  elif defined __mips__ && _MIPS_SIM == _ABIO32 +#  elif (defined __mips__ && _MIPS_SIM == _ABIO32) || \ +	(defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && !(defined(__powerpc__) || defined(__xtensa__))) +	/* arch with 64-bit data in even reg alignment #2: [arcv2/others-in-future] +	 * stock syscall handler in kernel (reg hole punched) +	 * see libc/sysdeps/linux/common/posix_fadvise.c for more details */  	return INLINE_SYSCALL(sync_file_range, 7, fd, 0,  			OFF64_HI_LO(offset), OFF64_HI_LO(nbytes), flags);  #  elif defined __NR_sync_file_range2 diff --git a/libc/sysdeps/linux/common/sys/eventfd.h b/libc/sysdeps/linux/common/sys/eventfd.h index 91b265b2c..a47b5fecf 100644 --- a/libc/sysdeps/linux/common/sys/eventfd.h +++ b/libc/sysdeps/linux/common/sys/eventfd.h @@ -31,7 +31,7 @@ __BEGIN_DECLS  /* Return file descriptor for generic event channel.  Set initial     value to COUNT.  */ -extern int eventfd (int __count, int __flags) __THROW; +extern int eventfd (unsigned int __count, int __flags) __THROW;  /* Read event counter and possibly wait for events.  */  extern int eventfd_read (int __fd, eventfd_t *__value); diff --git a/libc/sysdeps/linux/sparc/bits/eventfd.h b/libc/sysdeps/linux/sparc/bits/eventfd.h index bed9f093b..e348cc6fb 100644 --- a/libc/sysdeps/linux/sparc/bits/eventfd.h +++ b/libc/sysdeps/linux/sparc/bits/eventfd.h @@ -22,7 +22,7 @@  /* Flags for eventfd.  */  enum    { -    EFD_SEMAPHORE = 1, +    EFD_SEMAPHORE = 0x000001,  #define EFD_SEMAPHORE EFD_SEMAPHORE      EFD_CLOEXEC = 0x400000,  #define EFD_CLOEXEC EFD_CLOEXEC  | 
