Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 535c611d authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

s390/string: provide asm lib functions for memcpy and memcmp



Our memcpy and memcmp variants were implemented by calling the corresponding
gcc builtin variants.
However gcc is free to replace a call to __builtin_memcmp with a call to memcmp
which, when called, will result in an endless recursion within memcmp.
So let's provide asm variants and also fix the variants that are used for
uncompressing the kernel image.
In addition remove all other occurences of builtin function calls.

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 68d9884d
Loading
Loading
Loading
Loading
+24 −21
Original line number Diff line number Diff line
@@ -71,34 +71,37 @@ void *memset(void *s, int c, size_t n)
{
	char *xs;

	if (c == 0)
		return __builtin_memset(s, 0, n);

	xs = (char *) s;
	if (n > 0)
		do {
	xs = s;
	while (n--)
		*xs++ = c;
		} while (--n > 0);
	return s;
}

void *memcpy(void *__dest, __const void *__src, size_t __n)
void *memcpy(void *dest, const void *src, size_t n)
{
	return __builtin_memcpy(__dest, __src, __n);
	const char *s = src;
	char *d = dest;

	while (n--)
		*d++ = *s++;
	return dest;
}

void *memmove(void *__dest, __const void *__src, size_t __n)
void *memmove(void *dest, const void *src, size_t n)
{
	char *d;
	const char *s;

	if (__dest <= __src)
		return __builtin_memcpy(__dest, __src, __n);
	d = __dest + __n;
	s = __src + __n;
	while (__n--)
	const char *s = src;
	char *d = dest;

	if (d <= s) {
		while (n--)
			*d++ = *s++;
	} else {
		d += n;
		s += n;
		while (n--)
			*--d = *--s;
	return __dest;
	}
	return dest;
}

static void error(char *x)
+0 −8
Original line number Diff line number Diff line
@@ -96,7 +96,6 @@ static inline char *strcat(char *dst, const char *src)

static inline char *strcpy(char *dst, const char *src)
{
#if __GNUC__ < 4
	register int r0 asm("0") = 0;
	char *ret = dst;

@@ -106,14 +105,10 @@ static inline char *strcpy(char *dst, const char *src)
		: "+&a" (dst), "+&a" (src) : "d" (r0)
		: "cc", "memory");
	return ret;
#else
	return __builtin_strcpy(dst, src);
#endif
}

static inline size_t strlen(const char *s)
{
#if __GNUC__ < 4
	register unsigned long r0 asm("0") = 0;
	const char *tmp = s;

@@ -122,9 +117,6 @@ static inline size_t strlen(const char *s)
		"	jo	0b"
		: "+d" (r0), "+a" (tmp) :  : "cc");
	return r0 - (unsigned long) s;
#else
	return __builtin_strlen(s);
#endif
}

static inline size_t strnlen(const char * s, size_t n)
+2 −0
Original line number Diff line number Diff line
@@ -8,3 +8,5 @@ EXPORT_SYMBOL(_mcount);
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
EXPORT_SYMBOL(sie64a);
#endif
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
+2 −1
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@

lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
obj-y += usercopy.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o
obj-$(CONFIG_64BIT) += mem64.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o

arch/s390/lib/mem32.S

0 → 100644
+92 −0
Original line number Diff line number Diff line
/*
 * String handling functions.
 *
 * Copyright IBM Corp. 2012
 */

#include <linux/linkage.h>

/*
 * memset implementation
 *
 * This code corresponds to the C construct below. We do distinguish
 * between clearing (c == 0) and setting a memory array (c != 0) simply
 * because nearly all memset invocations in the kernel clear memory and
 * the xc instruction is preferred in such cases.
 *
 * void *memset(void *s, int c, size_t n)
 * {
 *	if (likely(c == 0))
 *		return __builtin_memset(s, 0, n);
 *	return __builtin_memset(s, c, n);
 * }
 */
ENTRY(memset)
	basr	%r5,%r0
.Lmemset_base:
	ltr	%r4,%r4
	bzr	%r14
	ltr	%r3,%r3
	jnz	.Lmemset_fill
	ahi	%r4,-1
	lr	%r3,%r4
	srl	%r3,8
	ltr	%r3,%r3
	lr	%r1,%r2
	je	.Lmemset_clear_rest
.Lmemset_clear_loop:
	xc	0(256,%r1),0(%r1)
	la	%r1,256(%r1)
	brct	%r3,.Lmemset_clear_loop
.Lmemset_clear_rest:
	ex	%r4,.Lmemset_xc-.Lmemset_base(%r5)
	br	%r14
.Lmemset_fill:
	stc	%r3,0(%r2)
	chi	%r4,1
	lr	%r1,%r2
	ber	%r14
	ahi	%r4,-2
	lr	%r3,%r4
	srl	%r3,8
	ltr	%r3,%r3
	je	.Lmemset_fill_rest
.Lmemset_fill_loop:
	mvc	1(256,%r1),0(%r1)
	la	%r1,256(%r1)
	brct	%r3,.Lmemset_fill_loop
.Lmemset_fill_rest:
	ex	%r4,.Lmemset_mvc-.Lmemset_base(%r5)
	br	%r14
.Lmemset_xc:
	xc	0(1,%r1),0(%r1)
.Lmemset_mvc:
	mvc	1(1,%r1),0(%r1)

/*
 * memcpy implementation
 *
 * void *memcpy(void *dest, const void *src, size_t n)
 */
ENTRY(memcpy)
	basr	%r5,%r0
.Lmemcpy_base:
	ltr	%r4,%r4
	bzr	%r14
	ahi	%r4,-1
	lr	%r0,%r4
	srl	%r0,8
	ltr	%r0,%r0
	lr	%r1,%r2
	jnz	.Lmemcpy_loop
.Lmemcpy_rest:
	ex	%r4,.Lmemcpy_mvc-.Lmemcpy_base(%r5)
	br	%r14
.Lmemcpy_loop:
	mvc	0(256,%r1),0(%r3)
	la	%r1,256(%r1)
	la	%r3,256(%r3)
	brct	%r0,.Lmemcpy_loop
	j	.Lmemcpy_rest
.Lmemcpy_mvc:
	mvc	0(1,%r1),0(%r3)
Loading