1/* Vector optimized 32/64 bit S/390 version of wcsncmp. 2 Copyright (C) 2015-2022 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-wcsncmp.h> 20#if HAVE_WCSNCMP_Z13 21 22# include "sysdep.h" 23# include "asm-syntax.h" 24 25 .text 26 27/* int wcsncmp (const wchar_t *s1, const wchar_t *s2, size_t n) 28 Compare at most n characters of two strings. 29 30 Register usage: 31 -r0=tmp 32 -r1=tmp 33 -r2=s1 34 -r3=s2 35 -r4=n 36 -r5=current_len 37 -v16=part of s1 38 -v17=part of s2 39 -v18=index of unequal 40*/ 41ENTRY(WCSNCMP_Z13) 42 .machine "z13" 43 .machinemode "zarch_nohighgprs" 44 45# if !defined __s390x__ 46 llgfr %r4,%r4 47# endif /* !defined __s390x__ */ 48 49 clgije %r4,0,.Lend_equal /* Nothing to do if n == 0. */ 50 51 /* Check range of n and convert to byte-count. */ 52# ifdef __s390x__ 53 tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */ 54 lghi %r1,-4 /* Max byte-count is 18446744073709551612. */ 55# else 56 tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */ 57 llilf %r1,4294967292 /* Max byte-count is 4294967292. */ 58# endif /* !__s390x__ */ 59 sllg %r4,%r4,2 /* Convert character-count to byte-count. */ 60 locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ 61 62 /* Check first character without vector load. */ 63 lghi %r5,4 /* current_len = 4 bytes. */ 64 /* Check s1/2[0]. */ 65 lt %r0,0(%r2) 66 l %r1,0(%r3) 67 je .Lend_cmp_one_char 68 crjne %r0,%r1,.Lend_cmp_one_char 69 70.Lloop: 71 vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */ 72 vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */ 73 lcbb %r0,0(%r5,%r2),6 /* Get loaded byte count of s1. */ 74 jo .Llt16_1 /* Jump away if vector not fully loaded. */ 75 lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */ 76 jo .Llt16_2 /* Jump away if vector not fully loaded. */ 77 aghi %r5,16 /* Both vectors are fully loaded. */ 78 vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */ 79 clgrjhe %r5,%r4,.Llastcmp /* If current_len >= n ->last compare. */ 80 jno .Lfound 81 82 vlbb %v17,0(%r5,%r3),6 83 vlbb %v16,0(%r5,%r2),6 84 lcbb %r0,0(%r5,%r2),6 85 jo .Llt16_1 86 lcbb %r1,0(%r5,%r3),6 87 jo .Llt16_2 88 aghi %r5,16 89 vfenezfs %v18,%v16,%v17 90 clgrjhe %r5,%r4,.Llastcmp 91 jno .Lfound 92 93 vlbb %v17,0(%r5,%r3),6 94 vlbb %v16,0(%r5,%r2),6 95 lcbb %r0,0(%r5,%r2),6 96 jo .Llt16_1 97 lcbb %r1,0(%r5,%r3),6 98 jo .Llt16_2 99 aghi %r5,16 100 vfenezfs %v18,%v16,%v17 101 clgrjhe %r5,%r4,.Llastcmp 102 jno .Lfound 103 104 vlbb %v17,0(%r5,%r3),6 105 vlbb %v16,0(%r5,%r2),6 106 lcbb %r0,0(%r5,%r2),6 107 jo .Llt16_1 108 lcbb %r1,0(%r5,%r3),6 109 jo .Llt16_2 110 aghi %r5,16 111 vfenezfs %v18,%v16,%v17 112 clgrjhe %r5,%r4,.Llastcmp 113 jno .Lfound 114 115 j .Lloop 116 117.Llt16_1: 118 lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */ 119.Llt16_2: 120 clr %r0,%r1 /* Compare logical. */ 121 locrh %r0,%r1 /* Compute minimum of bytes loaded. */ 122 nill %r0,65532 /* Align bytes loaded to full characters. */ 123 jz .Lcmp_one_char /* Jump away if no full char is available. */ 124.Llt_cmp: 125 algfr %r5,%r0 /* Add smallest loaded bytes to current_len. */ 126 vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */ 127 clgrj %r5,%r4,10,.Llastcmp /* If current_len >= n -> last compare */ 128 vlgvb %r1,%v18,7 /* Get not equal index or 16 if all equal. */ 129 clrjl %r1,%r0,.Lfound /* Jump away if miscompare is within 130 loaded bytes; (index < loaded-bytes) */ 131 j .Lloop 132 133.Lcmp_one_char: 134 /* At least one of both strings is not 4-byte aligned 135 and there is no full character before next block-boundary. 136 Compare one character to get over the boundary and 137 proceed with normal loop! */ 138 vlef %v16,0(%r5,%r2),0 /* Load one character. */ 139 lghi %r0,4 /* Loaded byte count is 4. */ 140 vlef %v17,0(%r5,%r3),0 141 j .Llt_cmp /* Proceed with comparision. */ 142 143.Llastcmp: 144 /* Use comparision result only if located within first n characters. 145 %r0: loaded byte count in vreg; 146 %r5: current_len; 147 %r4: n; 148 (current_len - n): [0...16[ 149 First ignored match index: loaded bytes - (current_len-n): ]0...16] 150 */ 151 slgr %r5,%r4 /* %r5 = current_len - n. */ 152 slr %r0,%r5 /* %r0 = first ignored match index. */ 153 vlgvb %r4,%v18,7 /* Get not equal index or 16 if all equal. */ 154 clrjl %r4,%r0,.Lfound2 /* Jump away if miscompare is within 155 loaded bytes and below n bytes. */ 156.Lend_equal: 157 lghi %r2,0 158 br %r14 159 160.Lfound: 161 /* Difference or end of string. */ 162 /* vfenezf found an unequal element or zero. 163 This instruction compares unsigned words, but wchar_t is signed. 164 Thus we have to compare the found element again. */ 165 vlgvb %r4,%v18,7 /* Extract not equal byte-index. */ 166.Lfound2: 167 srl %r4,2 /* And convert it to character-index. */ 168 vlgvf %r0,%v16,0(%r4) /* Load character-values. */ 169 vlgvf %r1,%v17,0(%r4) 170.Lend_cmp_one_char: 171 cr %r0,%r1 172 je .Lend_equal 173 lghi %r2,1 174 lghi %r1,-1 175 locgrl %r2,%r1 176 br %r14 177END(WCSNCMP_Z13) 178 179# if ! HAVE_WCSNCMP_IFUNC 180strong_alias (WCSNCMP_Z13, wcsncmp) 181# endif 182#endif 183