1 /* Vector optimized 32/64 bit S/390 version of strstr.
2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #include <ifunc-strstr.h>
20 #if HAVE_STRSTR_ARCH13
22 # include "asm-syntax.h"
25 /* char *strstr (const char *haystack=r2, const char *needle=r3)
26 Locate a substring. */
29 .machinemode "zarch_nohighgprs"
31 jo .Lneedle_on_bb /* Needle on block-boundary? */
32 vl %v18,0(%r3),6 /* Load needle. */
33 vfenezb %v19,%v18,%v18 /* v19[7] contains the length of needle. */
35 vlgvb %r4,%v19,7 /* Get index of zero or 16 if not found. */
36 lghi %r5,17 /* See below: min-skip-partial-match-index. */
37 cgibe %r4,0,0(%r14) /* Test if needle is zero and return. */
39 /* The vstrs instruction is able to handle needles up to a length of 16,
40 but then we may have to load the next part of haystack with a
41 small offset. This will be slow - see examples:
42 haystack =mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm...mmmmmmmmmmmmmmmmmmma
43 needle = mmmmmmmmmmmmmma0
44 => needle_len=15; vstrs reports a partial match; haystack+=2
45 haystack =mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm...mmmmmmmmmmmmmmmmmmma
46 needle = mmmmmmmma0000000
47 => needle_len=9; vstrs reports a partial match; haystack+=8 */
48 # if ! HAVE_STRSTR_Z13
49 # error The arch13 variant of strstr needs the z13 variant of strstr!
54 /* In case of a partial match, the vstrs instruction returns the index
55 of the partial match in a vector-register. Then we have to
56 reload the string at the "current-position plus this index" and run
57 vstrs again in order to determine if it was a full match or no match.
58 Transferring this index from vr to gr, compute the haystack-address
59 and loading with vl is quite slow as all instructions have data
60 dependencies. Thus we assume, that a partial match is always at the
61 first possible index and just load the next part of haystack from
62 there instead of waiting until the correct index is computed:
63 min-skip-partial-match-index = (16 - n_len) + 1 */
68 jo .Lloop_haystack_on_bb /* Haystack on block-boundary? */
69 vl %v16,0(%r2) /* Load next part of haystack. */
70 .Lloop_haystack_loaded:
71 /* Vector string search with zero search (cc=0 => no match). */
72 vstrs %v20,%v16,%v18,%v19,0,2
73 jne .Lloop_vstrs_nonzero_cc
74 lcbb %r1,16(%r2),6 /* Next part of haystack. */
75 jo .Lloop_haystack_on_bb16
77 vstrs %v20,%v16,%v18,%v19,0,2
78 jne .Lloop_vstrs_nonzero_cc16
79 lcbb %r1,32(%r2),6 /* Next part of haystack. */
80 jo .Lloop_haystack_on_bb32
82 vstrs %v20,%v16,%v18,%v19,0,2
83 jne .Lloop_vstrs_nonzero_cc32
84 lcbb %r1,48(%r2),6 /* Next part of haystack. */
85 jo .Lloop_haystack_on_bb48
87 vstrs %v20,%v16,%v18,%v19,0,2
88 jne .Lloop_vstrs_nonzero_cc48
92 .Lloop_vstrs_nonzero_cc48:
94 .Lloop_vstrs_nonzero_cc32:
96 .Lloop_vstrs_nonzero_cc16:
98 .Lloop_vstrs_nonzero_cc:
99 jh .Lend_match_found /* cc == 2 (full match) */
100 jl .Lend_no_match /* cc == 1 (no match, end of string) */
101 /* cc == 3 (partial match) See above: min-skip-partial-match-index! */
102 lcbb %r1,0(%r5,%r2),6
104 jo .Lloop_haystack_on_bb
106 vstrs %v20,%v16,%v18,%v19,0,2
107 .Lloop_vstrs_nonzero_cc_loop:
112 lcbb %r1,0(%r2),6 /* Next part of haystack. */
113 jo .Lloop_haystack_on_bb
115 vstrs %v20,%v16,%v18,%v19,0,2
120 lcbb %r1,0(%r2),6 /* Next part of haystack. */
121 jo .Lloop_haystack_on_bb
123 vstrs %v20,%v16,%v18,%v19,0,2
128 lcbb %r1,0(%r2),6 /* Next part of haystack. */
129 jo .Lloop_haystack_on_bb
131 vstrs %v20,%v16,%v18,%v19,0,2
132 j .Lloop_vstrs_nonzero_cc_loop
142 .Lloop_haystack_on_bb48:
144 .Lloop_haystack_on_bb32:
146 .Lloop_haystack_on_bb16:
148 .Lloop_haystack_on_bb:
149 /* Haystack located on page-boundary. */
150 ahi %r1,-1 /* vll needs highest index instead of count. */
153 vfenezb %v17,%v16,%v16 /* Search zero in loaded haystack bytes. */
154 veclb %v17,%v21 /* Zero index <= loaded byte index? */
155 jle .Lloop_haystack_loaded /* -> v16 contains full haystack. */
156 vl %v16,0(%r2) /* Load haystack beyond page boundary. */
157 j .Lloop_haystack_loaded
160 /* Needle located on page-boundary. */
161 ahi %r1,-1 /* vll needs highest index instead of count. */
164 vfenezb %v19,%v18,%v18 /* Search zero in loaded needle bytes. */
165 veclb %v19,%v21 /* Zero index <= max loaded byte index? */
166 jle .Lneedle_loaded /* -> v18 contains full needle. */
167 vl %v18,0(%r3) /* Load needle beyond page boundary. */
168 vfenezb %v19,%v18,%v18
172 # if ! HAVE_STRSTR_IFUNC
173 strong_alias (STRSTR_ARCH13, strstr)
176 # if STRSTR_Z13_ONLY_USED_AS_FALLBACK && defined SHARED && IS_IN (libc)
177 strong_alias (STRSTR_ARCH13, __GI_strstr)