1/* Vector optimized 32/64 bit S/390 version of wcsnlen. 2 Copyright (C) 2015-2021 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19#include <ifunc-wcsnlen.h> 20#if HAVE_WCSNLEN_Z13 21 22# include "sysdep.h" 23# include "asm-syntax.h" 24 25 .text 26 27/* size_t wcsnlen (const wchar_t *s, size_t maxlen) 28 Returns the number of characters in s or at most maxlen. 29 30 Register usage: 31 -r1=tmp 32 -r2=address of string 33 -r3=maxlen (number of characters to be read) 34 -r4=tmp 35 -r5=current_len and return_value 36 -v16=part of s 37*/ 38ENTRY(WCSNLEN_Z13) 39 40 .machine "z13" 41 .machinemode "zarch_nohighgprs" 42 43# if !defined __s390x__ 44 llgfr %r3,%r3 45# endif /* !defined __s390x__ */ 46 47 clgfi %r3,0 /* if maxlen == 0, return 0. */ 48 locgre %r2,%r3 49 ber %r14 50 51 vlbb %v16,0(%r2),6 /* Load s until next 4k-byte boundary. */ 52 lcbb %r1,0(%r2),6 /* Get bytes to 4k-byte boundary or 16. */ 53 llgfr %r1,%r1 /* Convert 32bit to 64bit. */ 54 55 tmll %r2,3 /* Test if s is 4-byte aligned? */ 56 jne .Lfallback /* And use common-code variant if not. */ 57 58 /* Check range of maxlen and convert to byte-count. */ 59# ifdef __s390x__ 60 tmhh %r3,49152 /* Test bit 0 or 1 of maxlen. */ 61 lghi %r4,-4 /* Max byte-count is 18446744073709551612. */ 62# else 63 tmlh %r3,49152 /* Test bit 0 or 1 of maxlen. */ 64 llilf %r4,4294967292 /* Max byte-count is 4294967292. */ 65# endif /* !__s390x__ */ 66 sllg %r3,%r3,2 /* Convert character-count to byte-count. */ 67 locgrne %r3,%r4 /* Use max byte-count, if bit 0/1 was one. */ 68 69 vfenezf %v16,%v16,%v16 /* Find element not equal with zero search. */ 70 clgr %r1,%r3 71 locgrh %r1,%r3 /* loaded_byte_count 72 = min (loaded_byte_count, maxlen) */ 73 74 vlgvb %r5,%v16,7 /* Load zero index or 16 if not found. */ 75 clrjl %r5,%r1,.Lend /* Found zero within loaded bytes -> return. */ 76 77 clgr %r1,%r3 /* If loaded_byte_count == maxlen -> end. */ 78 locgre %r5,%r3 79 je .Lend 80 81 /* Align s to 16 byte. */ 82 risbgn %r4,%r2,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15. */ 83 lghi %r5,16 /* current_len = 16. */ 84 slr %r5,%r4 /* Compute bytes to 16bytes boundary. */ 85 86 lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ 87 aghi %r1,64 88 clgrjl %r1,%r3,.Lloop64 89 90 /* Find zero in max 64byte with aligned s. */ 91.Llt64: 92 vl %v16,0(%r5,%r2) /* Load s. */ 93 vfenezfs %v16,%v16,%v16 /* Find element not equal with zero search. */ 94 je .Lfound /* Jump away if zero was found. */ 95 aghi %r5,16 96 clgrjhe %r5,%r3,.Lfound /* If current_len >= maxlen -> end. */ 97 vl %v16,0(%r5,%r2) 98 vfenezfs %v16,%v16,%v16 99 je .Lfound 100 aghi %r5,16 101 clgrjhe %r5,%r3,.Lfound 102 vl %v16,0(%r5,%r2) 103 vfenezfs %v16,%v16,%v16 104 je .Lfound 105 aghi %r5,16 106 clgrjhe %r5,%r3,.Lfound 107 vl %v16,0(%r5,%r2) 108 vfenezfs %v16,%v16,%v16 109 j .Lfound 110 111.Lfound48: 112 aghi %r5,16 113.Lfound32: 114 aghi %r5,16 115.Lfound16: 116 aghi %r5,16 117.Lfound: 118 vlgvb %r4,%v16,7 /* Load byte index of zero or 16 if no zero. */ 119 algr %r5,%r4 120 121 clgr %r5,%r3 122 locgrh %r5,%r3 /* Return min (current_len, maxlen). */ 123.Lend: 124 srlg %r2,%r5,2 /* Convert byte-count to character-count. */ 125 br %r14 126 127 /* Find zero in 16byte aligned loop. */ 128.Lloop64: 129 vl %v16,0(%r5,%r2) /* Load s. */ 130 vfenezfs %v16,%v16,%v16 /* Find element not equal with zero search. */ 131 je .Lfound /* Jump away if zero was found. */ 132 vl %v16,16(%r5,%r2) 133 vfenezfs %v16,%v16,%v16 134 je .Lfound16 135 vl %v16,32(%r5,%r2) 136 vfenezfs %v16,%v16,%v16 137 je .Lfound32 138 vl %v16,48(%r5,%r2) 139 vfenezfs %v16,%v16,%v16 140 je .Lfound48 141 142 aghi %r5,64 143 lgr %r1,%r5 /* If %r5 + 64 < maxlen? -> loop64. */ 144 aghi %r1,64 145 clgrjl %r1,%r3,.Lloop64 146 147 j .Llt64 148 149.Lfallback: 150 jg WCSNLEN_C 151END(WCSNLEN_Z13) 152 153# if ! HAVE_WCSNLEN_IFUNC 154strong_alias (WCSNLEN_Z13, __wcsnlen) 155weak_alias (__wcsnlen, wcsnlen) 156# endif 157#endif 158