mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-11-03 20:53:13 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			253 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Optimized, inlined string functions.  S/390 version.
 | 
						|
   Copyright (C) 2000-2014 Free Software Foundation, Inc.
 | 
						|
   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
 | 
						|
   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
 | 
						|
   <http://www.gnu.org/licenses/>.  */
 | 
						|
 | 
						|
#ifndef _STRING_H
 | 
						|
# error "Never use <bits/string.h> directly; include <string.h> instead."
 | 
						|
#endif
 | 
						|
 | 
						|
/* The s390 processors can access unaligned multi-byte variables.  */
 | 
						|
#define _STRING_ARCH_unaligned	1
 | 
						|
 | 
						|
/* We only provide optimizations if the user selects them and if
 | 
						|
   GNU CC is used.  */
 | 
						|
#if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \
 | 
						|
    && defined __GNUC__ && __GNUC__ >= 2
 | 
						|
 | 
						|
#ifndef __STRING_INLINE
 | 
						|
# ifndef __extern_inline
 | 
						|
#  define __STRING_INLINE inline
 | 
						|
# else
 | 
						|
#  define __STRING_INLINE __extern_inline
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
#define _HAVE_STRING_ARCH_strlen 1
 | 
						|
#ifndef _FORCE_INLINES
 | 
						|
#define strlen(str) __strlen_g ((str))
 | 
						|
 | 
						|
__STRING_INLINE size_t __strlen_g (const char *) __asm__ ("strlen");
 | 
						|
 | 
						|
__STRING_INLINE size_t
 | 
						|
__strlen_g (const char *__str)
 | 
						|
{
 | 
						|
    char *__ptr, *__tmp;
 | 
						|
 | 
						|
    __ptr = (char *) 0;
 | 
						|
    __tmp = (char *) __str;
 | 
						|
    __asm__ __volatile__ ("   la    0,0\n"
 | 
						|
			  "0: srst  %0,%1\n"
 | 
						|
			  "   jo    0b\n"
 | 
						|
			  : "+&a" (__ptr), "+&a" (__tmp) :
 | 
						|
			  : "cc", "memory", "0" );
 | 
						|
    return (size_t) (__ptr - __str);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Copy SRC to DEST.  */
 | 
						|
#define _HAVE_STRING_ARCH_strcpy 1
 | 
						|
#ifndef _FORCE_INLINES
 | 
						|
#define strcpy(dest, src) __strcpy_g ((dest), (src))
 | 
						|
 | 
						|
__STRING_INLINE char *__strcpy_g (char *, const char *) __asm ("strcpy");
 | 
						|
 | 
						|
__STRING_INLINE char *
 | 
						|
__strcpy_g (char *__dest, const char *__src)
 | 
						|
{
 | 
						|
    char *tmp = __dest;
 | 
						|
 | 
						|
    __asm__ __volatile__ ("   la    0,0\n"
 | 
						|
			  "0: mvst  %0,%1\n"
 | 
						|
			  "   jo    0b"
 | 
						|
			  : "+&a" (__dest), "+&a" (__src) :
 | 
						|
			  : "cc", "memory", "0" );
 | 
						|
    return tmp;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#define _HAVE_STRING_ARCH_strncpy 1
 | 
						|
#ifndef _FORCE_INLINES
 | 
						|
#define strncpy(dest, src, n) __strncpy_g ((dest), (src), (n))
 | 
						|
 | 
						|
__STRING_INLINE char *__strncpy_g (char *, const char *, size_t)
 | 
						|
     __asm__ ("strncpy");
 | 
						|
 | 
						|
__STRING_INLINE char *
 | 
						|
__strncpy_g (char *__dest, const char *__src, size_t __n)
 | 
						|
{
 | 
						|
    char *__ret = __dest;
 | 
						|
    char *__ptr;
 | 
						|
    size_t __diff;
 | 
						|
 | 
						|
    if (__n > 0) {
 | 
						|
      __diff = (size_t) (__dest - __src);
 | 
						|
      __ptr = (char *) __src;
 | 
						|
      __asm__ __volatile__ ("   j     1f\n"
 | 
						|
			    "0: la    %0,1(%0)\n"
 | 
						|
			    "1: icm   0,1,0(%0)\n"
 | 
						|
			    "   stc   0,0(%2,%0)\n"
 | 
						|
			    "   jz    3f\n"
 | 
						|
#if defined(__s390x__)
 | 
						|
			    "   brctg %1,0b\n"
 | 
						|
#else
 | 
						|
			    "   brct  %1,0b\n"
 | 
						|
#endif
 | 
						|
			    "   j     4f\n"
 | 
						|
			    "2: la    %0,1(%0)\n"
 | 
						|
			    "   stc   0,0(%2,%0)\n"
 | 
						|
#if defined(__s390x__)
 | 
						|
			    "3: brctg %1,2b\n"
 | 
						|
#else
 | 
						|
			    "3: brct  %1,2b\n"
 | 
						|
#endif
 | 
						|
			    "4:"
 | 
						|
			    : "+&a" (__ptr), "+&a" (__n) : "a" (__diff)
 | 
						|
			    : "cc", "memory", "0" );
 | 
						|
    }
 | 
						|
    return __ret;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Append SRC onto DEST.  */
 | 
						|
#define _HAVE_STRING_ARCH_strcat 1
 | 
						|
#ifndef _FORCE_INLINES
 | 
						|
#define strcat(dest, src) __strcat_g ((dest), (src))
 | 
						|
 | 
						|
__STRING_INLINE char *__strcat_g (char *, const char *) __asm__ ("strcat");
 | 
						|
 | 
						|
__STRING_INLINE char *
 | 
						|
__strcat_g (char *__dest, const char *__src)
 | 
						|
{
 | 
						|
    char *__ret = __dest;
 | 
						|
    char *__ptr, *__tmp;
 | 
						|
 | 
						|
    /* Move __ptr to the end of __dest.  */
 | 
						|
    __ptr = (char *) 0;
 | 
						|
    __tmp = __dest;
 | 
						|
    __asm__ __volatile__ ("   la    0,0\n"
 | 
						|
			  "0: srst  %0,%1\n"
 | 
						|
			  "   jo    0b\n"
 | 
						|
			  : "+&a" (__ptr), "+&a" (__tmp) :
 | 
						|
			  : "cc", "0" );
 | 
						|
 | 
						|
    /* Now do the copy.  */
 | 
						|
    __asm__ __volatile__ ("   la    0,0\n"
 | 
						|
			  "0: mvst  %0,%1\n"
 | 
						|
			  "   jo    0b"
 | 
						|
			  : "+&a" (__ptr), "+&a" (__src) :
 | 
						|
			  : "cc", "memory", "0" );
 | 
						|
    return __ret;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Append no more than N characters from SRC onto DEST.  */
 | 
						|
#define _HAVE_STRING_ARCH_strncat 1
 | 
						|
#ifndef _FORCE_INLINES
 | 
						|
#define strncat(dest, src, n) __strncat_g ((dest), (src), (n))
 | 
						|
 | 
						|
__STRING_INLINE char *__strncat_g (char *, const char *, size_t)
 | 
						|
     __asm__ ("strncat");
 | 
						|
 | 
						|
__STRING_INLINE char *
 | 
						|
__strncat_g (char *__dest, const char *__src, size_t __n)
 | 
						|
{
 | 
						|
    char *__ret = __dest;
 | 
						|
    char *__ptr, *__tmp;
 | 
						|
    size_t __diff;
 | 
						|
 | 
						|
    if (__n > 0) {
 | 
						|
      /* Move __ptr to the end of __dest.  */
 | 
						|
      __ptr = (char *) 0;
 | 
						|
      __tmp = __dest;
 | 
						|
      __asm__ __volatile__ ("   la    0,0\n"
 | 
						|
			    "0: srst  %0,%1\n"
 | 
						|
			  "   jo    0b\n"
 | 
						|
			    : "+&a" (__ptr), "+&a" (__tmp) :
 | 
						|
			    : "cc", "memory", "0" );
 | 
						|
 | 
						|
      __diff = (size_t) (__ptr - __src);
 | 
						|
      __tmp = (char *) __src;
 | 
						|
      __asm__ __volatile__ ("   j     1f\n"
 | 
						|
			    "0: la    %0,1(%0)\n"
 | 
						|
			    "1: icm   0,1,0(%0)\n"
 | 
						|
			    "   stc   0,0(%2,%0)\n"
 | 
						|
			    "   jz    2f\n"
 | 
						|
#if defined(__s390x__)
 | 
						|
			    "   brctg %1,0b\n"
 | 
						|
#else
 | 
						|
			    "   brct  %1,0b\n"
 | 
						|
#endif
 | 
						|
			    "   slr   0,0\n"
 | 
						|
			    "   stc   0,1(%2,%0)\n"
 | 
						|
			    "2:"
 | 
						|
			    : "+&a" (__tmp), "+&a" (__n) : "a" (__diff)
 | 
						|
			    : "cc", "memory", "0" );
 | 
						|
 | 
						|
    }
 | 
						|
    return __ret;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Search N bytes of S for C.  */
 | 
						|
#define _HAVE_STRING_ARCH_memchr 1
 | 
						|
#ifndef _FORCE_INLINES
 | 
						|
__STRING_INLINE void *
 | 
						|
memchr (const void *__str, int __c, size_t __n)
 | 
						|
{
 | 
						|
    char *__ptr, *__tmp;
 | 
						|
 | 
						|
    __tmp = (char *) __str;
 | 
						|
    __ptr = (char *) __tmp + __n;
 | 
						|
    __asm__ __volatile__ ("   lhi   0,0xff\n"
 | 
						|
			  "   nr    0,%2\n"
 | 
						|
			  "0: srst  %0,%1\n"
 | 
						|
			  "   jo    0b\n"
 | 
						|
			  "   brc   13,1f\n"
 | 
						|
			  "   la    %0,0\n"
 | 
						|
			  "1:"
 | 
						|
			  : "+&a" (__ptr), "+&a" (__tmp) : "d" (__c)
 | 
						|
			  : "cc", "memory", "0" );
 | 
						|
    return __ptr;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Search N bytes of S for C.  */
 | 
						|
#define _HAVE_STRING_ARCH_memchr 1
 | 
						|
#ifndef _FORCE_INLINES
 | 
						|
__STRING_INLINE int
 | 
						|
strcmp (const char *__s1, const char *__s2)
 | 
						|
{
 | 
						|
    char *__p1, *__p2;
 | 
						|
    int __ret;
 | 
						|
 | 
						|
    __p1 = (char *) __s1;
 | 
						|
    __p2 = (char *) __s2;
 | 
						|
    __asm__ __volatile__ ("   slr   0,0\n"
 | 
						|
			  "0: clst  %1,%2\n"
 | 
						|
			  "   jo    0b\n"
 | 
						|
			  "   ipm   %0\n"
 | 
						|
			  "   srl   %0,28"
 | 
						|
			  : "=d" (__ret), "+&a" (__p1), "+&a" (__p2) :
 | 
						|
			  : "cc", "memory", "0" );
 | 
						|
    __ret = (__ret == 0) ? 0 : (__ret == 1) ? -1 : 1;
 | 
						|
    return __ret;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#endif	/* Use string inlines && GNU CC.  */
 |