mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-24 13:33:08 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			253 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Optimized, inlined string functions.  S/390 version.
 | |
|    Copyright (C) 2000-2016 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
 | |
| 
 | |
| /* Compare S1 and S2.  */
 | |
| #define _HAVE_STRING_ARCH_strcmp 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.  */
 |