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

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