Blame sysdeps/s390/strrchr-vx.S

Packit 6c4009
/* Vector optimized 32/64 bit S/390 version of strrchr.
Packit 6c4009
   Copyright (C) 2015-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit Service 1de18b
#include <ifunc-strrchr.h>
Packit Service 1de18b
Packit Service 1de18b
#if HAVE_STRRCHR_Z13
Packit 6c4009
Packit 6c4009
# include "sysdep.h"
Packit 6c4009
# include "asm-syntax.h"
Packit 6c4009
Packit 6c4009
	.text
Packit 6c4009
Packit 6c4009
/* char *strrchr (const char *s, int c)
Packit 6c4009
   Locate the last character c in string.
Packit 6c4009
Packit 6c4009
   Register usage:
Packit 6c4009
   -r0=loaded bytes in first part of s.
Packit 6c4009
   -r1=pointer to last occurence of c or NULL if not found.
Packit 6c4009
   -r2=s
Packit 6c4009
   -r3=c
Packit 6c4009
   -r4=tmp
Packit 6c4009
   -r5=current_len
Packit 6c4009
   -v16=part of s
Packit 6c4009
   -v17=index of found element
Packit 6c4009
   -v18=replicated c
Packit 6c4009
   -v19=part of s with last occurence of c.
Packit 6c4009
   -v20=permute pattern
Packit 6c4009
*/
Packit Service 1de18b
ENTRY(STRRCHR_Z13)
Packit 6c4009
	.machine "z13"
Packit 6c4009
	.machinemode "zarch_nohighgprs"
Packit 6c4009
Packit 6c4009
	vlbb	%v16,0(%r2),6	/* Load s until next 4k-byte boundary.  */
Packit 6c4009
	lcbb	%r0,0(%r2),6	/* Get bytes to 4k-byte boundary or 16.  */
Packit 6c4009
Packit 6c4009
	vlvgb	%v18,%r3,0	/* Generate vector which elements are all c.
Packit 6c4009
				   if c > 255, c will be truncated.  */
Packit 6c4009
	vrepb	%v18,%v18,0
Packit 6c4009
Packit 6c4009
	lghi	%r1,-1		/* Currently no c found.  */
Packit 6c4009
	lghi	%r5,0		/* current_len = 0.  */
Packit 6c4009
Packit 6c4009
	vfeezbs	%v17,%v16,%v18	/* Find element equal or zero.  */
Packit 6c4009
	vlgvb	%r4,%v17,7	/* Load byte index of c/zero or 16.  */
Packit 6c4009
	clrjl	%r4,%r0,.Lfound_first_part /* Found c/zero in loaded bytes.  */
Packit 6c4009
.Lalign:
Packit 6c4009
	/* Align s to 16 byte.  */
Packit 6c4009
	risbgn	%r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15.  */
Packit 6c4009
	lghi	%r5,16		/* current_len = 16.  */
Packit 6c4009
	slr	%r5,%r4		/* Compute bytes to 16bytes boundary.  */
Packit 6c4009
Packit 6c4009
.Lloop:
Packit 6c4009
	vl	%v16,0(%r5,%r2) /* Load s.  */
Packit 6c4009
	vfeezbs	%v17,%v16,%v18	/* Find element equal with zero search.  */
Packit 6c4009
	jno	.Lfound		/* Found c/zero (cc=0|1|2).  */
Packit 6c4009
	vl	%v16,16(%r5,%r2)
Packit 6c4009
	vfeezbs	%v17,%v16,%v18
Packit 6c4009
	jno	.Lfound16
Packit 6c4009
	vl	%v16,32(%r5,%r2)
Packit 6c4009
	vfeezbs	%v17,%v16,%v18
Packit 6c4009
	jno	.Lfound32
Packit 6c4009
	vl	%v16,48(%r5,%r2)
Packit 6c4009
	vfeezbs	%v17,%v16,%v18
Packit 6c4009
	jno	.Lfound48
Packit 6c4009
Packit 6c4009
	aghi	%r5,64
Packit 6c4009
	j	.Lloop		/* No character and no zero -> loop.  */
Packit 6c4009
Packit 6c4009
.Lfound48:
Packit 6c4009
	la	%r5,16(%r5)	/* Use la since aghi would clobber cc.  */
Packit 6c4009
.Lfound32:
Packit 6c4009
	la	%r5,16(%r5)
Packit 6c4009
.Lfound16:
Packit 6c4009
	la	%r5,16(%r5)
Packit 6c4009
.Lfound:
Packit 6c4009
	je	.Lzero		/* Found zero, but no c before that zero.  */
Packit 6c4009
	/* Save this part of s to check for further matches after reaching
Packit 6c4009
	   the end of the complete string.  */
Packit 6c4009
	vlr	%v19,%v16
Packit 6c4009
	lgr	%r1,%r5
Packit 6c4009
Packit 6c4009
	jh	.Lzero		/* Found a zero after the found c.  */
Packit 6c4009
	aghi	%r5,16		/* Start search of next part of s.  */
Packit 6c4009
	j	.Lloop
Packit 6c4009
Packit 6c4009
.Lfound_first_part:
Packit 6c4009
	/* This code is only executed if the found c/zero is whithin loaded
Packit 6c4009
	   bytes. If no c/zero was found (cc==3) the found index = 16, thus
Packit 6c4009
	   this code is not called.
Packit 6c4009
	   Resulting condition code of vector find element equal:
Packit 6c4009
	   cc==0: no c, found zero
Packit 6c4009
	   cc==1: c found, no zero
Packit 6c4009
	   cc==2: c found, found zero after c
Packit 6c4009
	   cc==3: no c, no zero (this case can be ignored).  */
Packit 6c4009
	je	.Lzero		/* Found zero, but no c before that zero.  */
Packit 6c4009
Packit 6c4009
	locgrne	%r1,%r5		/* Mark c as found in first part of s.  */
Packit 6c4009
	vlr	%v19,%v16
Packit 6c4009
Packit 6c4009
	jl	.Lalign		/* No zero (e.g. if vr was fully loaded)
Packit 6c4009
				   -> Align and loop afterwards.  */
Packit 6c4009
Packit 6c4009
	/* Found a zero in vr. If vr was not fully loaded due to block
Packit 6c4009
	   boundary, the remaining bytes are filled with zero and we can't
Packit 6c4009
	   rely on zero indication of condition code here!  */
Packit 6c4009
Packit 6c4009
	vfenezb	%v17,%v16,%v16	/* Find zero.  */
Packit 6c4009
	vlgvb	%r4,%v17,7	/* Load byte index of zero or 16.  */
Packit 6c4009
	clrjl	%r4,%r0,.Lzero	/* Zero within loaded bytes -> end.  */
Packit 6c4009
	j	.Lalign		/* Align and loop afterwards.  */
Packit 6c4009
Packit 6c4009
.Lend_searched_zero:
Packit 6c4009
	vlgvb	%r4,%v17,7	/* Load byte index of zero.  */
Packit 6c4009
	algr	%r5,%r4
Packit 6c4009
	la	%r2,0(%r5,%r2)	/* Return pointer to zero.  */
Packit 6c4009
	br	%r14
Packit 6c4009
Packit 6c4009
.Lzero:
Packit 6c4009
	/* Reached end of string. Check if one c was found before.  */
Packit 6c4009
	clije	%r3,0,.Lend_searched_zero /* Found zero and c is zero.  */
Packit 6c4009
Packit 6c4009
	cgfi	%r1,-1		/* No c found -> return NULL.  */
Packit 6c4009
	locghie	%r2,0
Packit 6c4009
	ber	%r14
Packit 6c4009
Packit 6c4009
	larl	%r3,.Lpermute_mask /* Load permute mask.  */
Packit 6c4009
	vl	%v20,0(%r3)
Packit 6c4009
Packit 6c4009
	/* c was found and is part of v19.  */
Packit 6c4009
	vfenezb	%v17,%v19,%v19	/* Find zero.  */
Packit 6c4009
	vlgvb	%r4,%v17,7	/* Load byte index of zero or 16.  */
Packit 6c4009
Packit 6c4009
	clgfi	%r5,0		/* Loaded byte count in v19 is 16, ...  */
Packit 6c4009
	lochine	%r0,16		/* ... if v19 is not the first part of s.  */
Packit 6c4009
	ahi	%r0,-1		/* Convert byte count to highest index.  */
Packit 6c4009
Packit 6c4009
	clr	%r0,%r4
Packit 6c4009
	locrl	%r4,%r0		/* r4 = min (zero-index, highest-index).  */
Packit 6c4009
Packit 6c4009
	/* Right-shift of v19 to mask bytes after zero.  */
Packit 6c4009
	clije	%r4,15,.Lzero_permute /* No shift is needed if highest index
Packit 6c4009
					 in vr is 15.  */
Packit 6c4009
	lhi	%r0,15
Packit 6c4009
	slr	%r0,%r4		/* Compute byte count for vector shift right.  */
Packit 6c4009
	sll	%r0,3		/* Convert to bit count.  */
Packit 6c4009
	vlvgb	%v17,%r0,7
Packit 6c4009
	vsrlb	%v19,%v19,%v17	/* Vector shift right by byte by number of bytes
Packit 6c4009
				   specified in bits 1-4 of byte 7 in v17.   */
Packit 6c4009
Packit 6c4009
	/* Reverse bytes in v19.  */
Packit 6c4009
.Lzero_permute:
Packit 6c4009
	vperm	%v19,%v19,%v19,%v20 /* Permute v19 to reversed order.  */
Packit 6c4009
Packit 6c4009
	/* Find c in reversed v19.  */
Packit 6c4009
	vfeeb	%v19,%v19,%v18	/* Find c.  */
Packit 6c4009
	la	%r2,0(%r1,%r2)
Packit 6c4009
	vlgvb	%r3,%v19,7	/* Load byte index of c.  */
Packit 6c4009
Packit 6c4009
	/* Compute index in real s and return.  */
Packit 6c4009
	slgr	%r4,%r3
Packit 6c4009
	la	%r2,0(%r4,%r2)	/* Return pointer to zero.  */
Packit 6c4009
	br	%r14
Packit 6c4009
.Lpermute_mask:
Packit 6c4009
	.byte	0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08
Packit 6c4009
	.byte	0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
Packit Service 1de18b
END(STRRCHR_Z13)
Packit Service 1de18b
Packit Service 1de18b
# if ! HAVE_STRRCHR_IFUNC
Packit Service 1de18b
strong_alias (STRRCHR_Z13, strrchr)
Packit Service 1de18b
weak_alias (strrchr, rindex)
Packit Service 1de18b
# endif
Packit Service 1de18b
Packit Service 1de18b
# if ! HAVE_STRRCHR_C && defined SHARED && IS_IN (libc)
Packit Service 1de18b
strong_alias (STRRCHR_Z13, __GI_strrchr)
Packit Service 1de18b
# endif
Packit Service 1de18b
Packit Service 1de18b
#endif /* HAVE_STRRCHR_Z13  */