Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/pcre2/src/pcre2_jit_neon_inc.h
9898 views
1
/*************************************************
2
* Perl-Compatible Regular Expressions *
3
*************************************************/
4
5
/* PCRE is a library of functions to support regular expressions whose syntax
6
and semantics are as close as possible to those of the Perl 5 language.
7
8
Written by Philip Hazel
9
This module by Zoltan Herczeg and Sebastian Pop
10
Original API code Copyright (c) 1997-2012 University of Cambridge
11
New API code Copyright (c) 2016-2019 University of Cambridge
12
13
-----------------------------------------------------------------------------
14
Redistribution and use in source and binary forms, with or without
15
modification, are permitted provided that the following conditions are met:
16
17
* Redistributions of source code must retain the above copyright notice,
18
this list of conditions and the following disclaimer.
19
20
* Redistributions in binary form must reproduce the above copyright
21
notice, this list of conditions and the following disclaimer in the
22
documentation and/or other materials provided with the distribution.
23
24
* Neither the name of the University of Cambridge nor the names of its
25
contributors may be used to endorse or promote products derived from
26
this software without specific prior written permission.
27
28
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
-----------------------------------------------------------------------------
40
*/
41
42
# if defined(FFCS)
43
# if defined(FF_UTF)
44
# define FF_FUN ffcs_utf
45
# else
46
# define FF_FUN ffcs
47
# endif
48
49
# elif defined(FFCS_2)
50
# if defined(FF_UTF)
51
# define FF_FUN ffcs_2_utf
52
# else
53
# define FF_FUN ffcs_2
54
# endif
55
56
# elif defined(FFCS_MASK)
57
# if defined(FF_UTF)
58
# define FF_FUN ffcs_mask_utf
59
# else
60
# define FF_FUN ffcs_mask
61
# endif
62
63
# elif defined(FFCPS_0)
64
# if defined (FF_UTF)
65
# define FF_FUN ffcps_0_utf
66
# else
67
# define FF_FUN ffcps_0
68
# endif
69
70
# elif defined (FFCPS_1)
71
# if defined (FF_UTF)
72
# define FF_FUN ffcps_1_utf
73
# else
74
# define FF_FUN ffcps_1
75
# endif
76
77
# elif defined (FFCPS_DEFAULT)
78
# if defined (FF_UTF)
79
# define FF_FUN ffcps_default_utf
80
# else
81
# define FF_FUN ffcps_default
82
# endif
83
# endif
84
85
#if (defined(__GNUC__) && defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ ) \
86
|| (defined(__clang__) \
87
&& ((__clang_major__ == 3 && __clang_minor__ >= 3) || (__clang_major__ > 3)))
88
__attribute__((no_sanitize_address))
89
#endif
90
static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 **str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
91
#undef FF_FUN
92
{
93
quad_word qw;
94
int_char ic;
95
96
SLJIT_UNUSED_ARG(offs1);
97
SLJIT_UNUSED_ARG(offs2);
98
99
ic.x = chars;
100
101
#if defined(FFCS)
102
sljit_u8 c1 = ic.c.c1;
103
vect_t vc1 = VDUPQ(c1);
104
105
#elif defined(FFCS_2)
106
sljit_u8 c1 = ic.c.c1;
107
vect_t vc1 = VDUPQ(c1);
108
sljit_u8 c2 = ic.c.c2;
109
vect_t vc2 = VDUPQ(c2);
110
111
#elif defined(FFCS_MASK)
112
sljit_u8 c1 = ic.c.c1;
113
vect_t vc1 = VDUPQ(c1);
114
sljit_u8 mask = ic.c.c2;
115
vect_t vmask = VDUPQ(mask);
116
#endif
117
118
#if defined(FFCPS)
119
compare_type compare1_type = compare_match1;
120
compare_type compare2_type = compare_match1;
121
vect_t cmp1a, cmp1b, cmp2a, cmp2b;
122
const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
123
PCRE2_UCHAR char1a = ic.c.c1;
124
PCRE2_UCHAR char2a = ic.c.c3;
125
126
# ifdef FFCPS_CHAR1A2A
127
cmp1a = VDUPQ(char1a);
128
cmp2a = VDUPQ(char2a);
129
cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
130
cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
131
# else
132
PCRE2_UCHAR char1b = ic.c.c2;
133
PCRE2_UCHAR char2b = ic.c.c4;
134
if (char1a == char1b)
135
{
136
cmp1a = VDUPQ(char1a);
137
cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
138
}
139
else
140
{
141
sljit_u32 bit1 = char1a ^ char1b;
142
if (is_powerof2(bit1))
143
{
144
compare1_type = compare_match1i;
145
cmp1a = VDUPQ(char1a | bit1);
146
cmp1b = VDUPQ(bit1);
147
}
148
else
149
{
150
compare1_type = compare_match2;
151
cmp1a = VDUPQ(char1a);
152
cmp1b = VDUPQ(char1b);
153
}
154
}
155
156
if (char2a == char2b)
157
{
158
cmp2a = VDUPQ(char2a);
159
cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
160
}
161
else
162
{
163
sljit_u32 bit2 = char2a ^ char2b;
164
if (is_powerof2(bit2))
165
{
166
compare2_type = compare_match1i;
167
cmp2a = VDUPQ(char2a | bit2);
168
cmp2b = VDUPQ(bit2);
169
}
170
else
171
{
172
compare2_type = compare_match2;
173
cmp2a = VDUPQ(char2a);
174
cmp2b = VDUPQ(char2b);
175
}
176
}
177
# endif
178
179
*str_ptr += IN_UCHARS(offs1);
180
#endif
181
182
#if PCRE2_CODE_UNIT_WIDTH != 8
183
vect_t char_mask = VDUPQ(0xff);
184
#endif
185
186
#if defined(FF_UTF)
187
restart:;
188
#endif
189
190
#if defined(FFCPS)
191
if (*str_ptr >= str_end)
192
return NULL;
193
sljit_u8 *p1 = *str_ptr - diff;
194
#endif
195
sljit_s32 align_offset = ((uint64_t)*str_ptr & 0xf);
196
*str_ptr = (sljit_u8 *) ((uint64_t)*str_ptr & ~0xf);
197
vect_t data = VLD1Q(*str_ptr);
198
#if PCRE2_CODE_UNIT_WIDTH != 8
199
data = VANDQ(data, char_mask);
200
#endif
201
202
#if defined(FFCS)
203
vect_t eq = VCEQQ(data, vc1);
204
205
#elif defined(FFCS_2)
206
vect_t eq1 = VCEQQ(data, vc1);
207
vect_t eq2 = VCEQQ(data, vc2);
208
vect_t eq = VORRQ(eq1, eq2);
209
210
#elif defined(FFCS_MASK)
211
vect_t eq = VORRQ(data, vmask);
212
eq = VCEQQ(eq, vc1);
213
214
#elif defined(FFCPS)
215
# if defined(FFCPS_DIFF1)
216
vect_t prev_data = data;
217
# endif
218
219
vect_t data2;
220
if (p1 < *str_ptr)
221
{
222
data2 = VLD1Q(*str_ptr - diff);
223
#if PCRE2_CODE_UNIT_WIDTH != 8
224
data2 = VANDQ(data2, char_mask);
225
#endif
226
}
227
else
228
data2 = shift_left_n_lanes(data, offs1 - offs2);
229
230
if (compare1_type == compare_match1)
231
data = VCEQQ(data, cmp1a);
232
else
233
data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
234
235
if (compare2_type == compare_match1)
236
data2 = VCEQQ(data2, cmp2a);
237
else
238
data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
239
240
vect_t eq = VANDQ(data, data2);
241
#endif
242
243
VST1Q(qw.mem, eq);
244
/* Ignore matches before the first STR_PTR. */
245
if (align_offset < 8)
246
{
247
qw.dw[0] >>= align_offset * 8;
248
if (qw.dw[0])
249
{
250
*str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
251
goto match;
252
}
253
if (qw.dw[1])
254
{
255
*str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
256
goto match;
257
}
258
}
259
else
260
{
261
qw.dw[1] >>= (align_offset - 8) * 8;
262
if (qw.dw[1])
263
{
264
*str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
265
goto match;
266
}
267
}
268
*str_ptr += 16;
269
270
while (*str_ptr < str_end)
271
{
272
vect_t orig_data = VLD1Q(*str_ptr);
273
#if PCRE2_CODE_UNIT_WIDTH != 8
274
orig_data = VANDQ(orig_data, char_mask);
275
#endif
276
data = orig_data;
277
278
#if defined(FFCS)
279
eq = VCEQQ(data, vc1);
280
281
#elif defined(FFCS_2)
282
eq1 = VCEQQ(data, vc1);
283
eq2 = VCEQQ(data, vc2);
284
eq = VORRQ(eq1, eq2);
285
286
#elif defined(FFCS_MASK)
287
eq = VORRQ(data, vmask);
288
eq = VCEQQ(eq, vc1);
289
#endif
290
291
#if defined(FFCPS)
292
# if defined (FFCPS_DIFF1)
293
data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
294
# else
295
data2 = VLD1Q(*str_ptr - diff);
296
# if PCRE2_CODE_UNIT_WIDTH != 8
297
data2 = VANDQ(data2, char_mask);
298
# endif
299
# endif
300
301
# ifdef FFCPS_CHAR1A2A
302
data = VCEQQ(data, cmp1a);
303
data2 = VCEQQ(data2, cmp2a);
304
# else
305
if (compare1_type == compare_match1)
306
data = VCEQQ(data, cmp1a);
307
else
308
data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
309
if (compare2_type == compare_match1)
310
data2 = VCEQQ(data2, cmp2a);
311
else
312
data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
313
# endif
314
315
eq = VANDQ(data, data2);
316
#endif
317
318
VST1Q(qw.mem, eq);
319
if (qw.dw[0])
320
*str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
321
else if (qw.dw[1])
322
*str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
323
else {
324
*str_ptr += 16;
325
#if defined (FFCPS_DIFF1)
326
prev_data = orig_data;
327
#endif
328
continue;
329
}
330
331
match:;
332
if (*str_ptr >= str_end)
333
/* Failed match. */
334
return NULL;
335
336
#if defined(FF_UTF)
337
if (utf_continue((PCRE2_SPTR)*str_ptr - offs1))
338
{
339
/* Not a match. */
340
*str_ptr += IN_UCHARS(1);
341
goto restart;
342
}
343
#endif
344
345
/* Match. */
346
#if defined (FFCPS)
347
*str_ptr -= IN_UCHARS(offs1);
348
#endif
349
return *str_ptr;
350
}
351
352
/* Failed match. */
353
return NULL;
354
}
355
356