Blame sysdeps/s390/multiarch/wcsrchr-vx.S

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