Home | History | Annotate | Download | only in string
      1 /*
      2 Copyright (c) 2011 Intel Corporation
      3 All rights reserved.
      4 
      5 Redistribution and use in source and binary forms, with or without
      6 modification, are permitted provided that the following conditions are met:
      7 
      8     * Redistributions of source code must retain the above copyright notice,
      9     * this list of conditions and the following disclaimer.
     10 
     11     * Redistributions in binary form must reproduce the above copyright notice,
     12     * this list of conditions and the following disclaimer in the documentation
     13     * and/or other materials provided with the distribution.
     14 
     15     * Neither the name of Intel Corporation nor the names of its contributors
     16     * may be used to endorse or promote products derived from this software
     17     * without specific prior written permission.
     18 
     19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     23 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 */
     30 
     31 #ifndef L
     32 # define L(label)	.L##label
     33 #endif
     34 
     35 #ifndef cfi_startproc
     36 # define cfi_startproc	.cfi_startproc
     37 #endif
     38 
     39 #ifndef cfi_endproc
     40 # define cfi_endproc	.cfi_endproc
     41 #endif
     42 
     43 #ifndef cfi_rel_offset
     44 # define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
     45 #endif
     46 
     47 #ifndef cfi_restore
     48 # define cfi_restore(reg)	.cfi_restore reg
     49 #endif
     50 
     51 #ifndef cfi_adjust_cfa_offset
     52 # define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
     53 #endif
     54 
     55 #ifndef ENTRY
     56 # define ENTRY(name)	\
     57 	.type name, @function;	\
     58 	.globl name;	\
     59 	.p2align 4;	\
     60 name:	\
     61 	cfi_startproc
     62 #endif
     63 
     64 #ifndef END
     65 # define END(name)	\
     66 	cfi_endproc;	\
     67 	.size name, .-name
     68 #endif
     69 
     70 #define CFI_PUSH(REG)	\
     71 	cfi_adjust_cfa_offset (4);	\
     72 	cfi_rel_offset (REG, 0)
     73 
     74 #define CFI_POP(REG)	\
     75 	cfi_adjust_cfa_offset (-4);	\
     76 	cfi_restore (REG)
     77 
     78 #define PUSH(REG)	pushl REG;	CFI_PUSH (REG)
     79 #define POP(REG)	popl REG;	CFI_POP (REG)
     80 
     81 #define PARMS  8
     82 #define ENTRANCE PUSH(%edi);
     83 #define RETURN  POP(%edi);	ret;	CFI_PUSH(%edi);
     84 
     85 #define STR1  PARMS
     86 #define STR2  STR1+4
     87 
     88 	.text
     89 ENTRY (wcsrchr)
     90 
     91 	ENTRANCE
     92 	mov	STR1(%esp), %ecx
     93 	movd	STR2(%esp), %xmm1
     94 
     95 	mov	%ecx, %edi
     96 	punpckldq %xmm1, %xmm1
     97 	pxor	%xmm2, %xmm2
     98 	punpckldq %xmm1, %xmm1
     99 
    100 /* ECX has OFFSET. */
    101 	and	$63, %ecx
    102 	cmp	$48, %ecx
    103 	ja	L(crosscache)
    104 
    105 /* unaligned string. */
    106 	movdqu	(%edi), %xmm0
    107 	pcmpeqd	%xmm0, %xmm2
    108 	pcmpeqd	%xmm1, %xmm0
    109 /* Find where NULL is.  */
    110 	pmovmskb %xmm2, %ecx
    111 /* Check if there is a match.  */
    112 	pmovmskb %xmm0, %eax
    113 	add	$16, %edi
    114 
    115 	test	%eax, %eax
    116 	jnz	L(unaligned_match1)
    117 
    118 	test	%ecx, %ecx
    119 	jnz	L(return_null)
    120 
    121 	and	$-16, %edi
    122 
    123 	PUSH	(%esi)
    124 
    125 	xor	%edx, %edx
    126 	jmp	L(loop)
    127 
    128 	CFI_POP	(%esi)
    129 
    130 	.p2align 4
    131 L(unaligned_match1):
    132 	test	%ecx, %ecx
    133 	jnz	L(prolog_find_zero_1)
    134 
    135 	PUSH	(%esi)
    136 
    137 /* Save current match */
    138 	mov	%eax, %edx
    139 	mov	%edi, %esi
    140 	and	$-16, %edi
    141 	jmp	L(loop)
    142 
    143 	CFI_POP	(%esi)
    144 
    145 	.p2align 4
    146 L(crosscache):
    147 /* Hancle unaligned string.  */
    148 	and	$15, %ecx
    149 	and	$-16, %edi
    150 	pxor	%xmm3, %xmm3
    151 	movdqa	(%edi), %xmm0
    152 	pcmpeqd	%xmm0, %xmm3
    153 	pcmpeqd	%xmm1, %xmm0
    154 /* Find where NULL is.  */
    155 	pmovmskb %xmm3, %edx
    156 /* Check if there is a match.  */
    157 	pmovmskb %xmm0, %eax
    158 /* Remove the leading bytes.  */
    159 	shr	%cl, %edx
    160 	shr	%cl, %eax
    161 	add	$16, %edi
    162 
    163 	test	%eax, %eax
    164 	jnz	L(unaligned_match)
    165 
    166 	test	%edx, %edx
    167 	jnz	L(return_null)
    168 
    169 	PUSH	(%esi)
    170 
    171 	xor	%edx, %edx
    172 	jmp	L(loop)
    173 
    174 	CFI_POP	(%esi)
    175 
    176 	.p2align 4
    177 L(unaligned_match):
    178 	test	%edx, %edx
    179 	jnz	L(prolog_find_zero)
    180 
    181 	PUSH	(%esi)
    182 
    183 	mov	%eax, %edx
    184 	lea	(%edi, %ecx), %esi
    185 
    186 /* Loop start on aligned string.  */
    187 	.p2align 4
    188 L(loop):
    189 	movdqa	(%edi), %xmm0
    190 	pcmpeqd	%xmm0, %xmm2
    191 	add	$16, %edi
    192 	pcmpeqd	%xmm1, %xmm0
    193 	pmovmskb %xmm2, %ecx
    194 	pmovmskb %xmm0, %eax
    195 	or	%eax, %ecx
    196 	jnz	L(matches)
    197 
    198 	movdqa	(%edi), %xmm3
    199 	pcmpeqd	%xmm3, %xmm2
    200 	add	$16, %edi
    201 	pcmpeqd	%xmm1, %xmm3
    202 	pmovmskb %xmm2, %ecx
    203 	pmovmskb %xmm3, %eax
    204 	or	%eax, %ecx
    205 	jnz	L(matches)
    206 
    207 	movdqa	(%edi), %xmm4
    208 	pcmpeqd	%xmm4, %xmm2
    209 	add	$16, %edi
    210 	pcmpeqd	%xmm1, %xmm4
    211 	pmovmskb %xmm2, %ecx
    212 	pmovmskb %xmm4, %eax
    213 	or	%eax, %ecx
    214 	jnz	L(matches)
    215 
    216 	movdqa	(%edi), %xmm5
    217 	pcmpeqd	%xmm5, %xmm2
    218 	add	$16, %edi
    219 	pcmpeqd	%xmm1, %xmm5
    220 	pmovmskb %xmm2, %ecx
    221 	pmovmskb %xmm5, %eax
    222 	or	%eax, %ecx
    223 	jz	L(loop)
    224 
    225 	.p2align 4
    226 L(matches):
    227 	test	%eax, %eax
    228 	jnz	L(match)
    229 L(return_value):
    230 	test	%edx, %edx
    231 	jz	L(return_null_1)
    232 	mov	%edx, %eax
    233 	mov	%esi, %edi
    234 
    235 	POP	(%esi)
    236 
    237 	test	%ah, %ah
    238 	jnz	L(match_third_or_fourth_wchar)
    239 	test	$15 << 4, %al
    240 	jnz	L(match_second_wchar)
    241 	lea	-16(%edi), %eax
    242 	RETURN
    243 
    244 	CFI_PUSH	(%esi)
    245 
    246 	.p2align 4
    247 L(return_null_1):
    248 	POP	(%esi)
    249 
    250 	xor	%eax, %eax
    251 	RETURN
    252 
    253 	CFI_PUSH	(%esi)
    254 
    255 	.p2align 4
    256 L(match):
    257 	pmovmskb %xmm2, %ecx
    258 	test	%ecx, %ecx
    259 	jnz	L(find_zero)
    260 /* save match info */
    261 	mov	%eax, %edx
    262 	mov	%edi, %esi
    263 	jmp	L(loop)
    264 
    265 	.p2align 4
    266 L(find_zero):
    267 	test	%cl, %cl
    268 	jz	L(find_zero_in_third_or_fourth_wchar)
    269 	test	$15, %cl
    270 	jz	L(find_zero_in_second_wchar)
    271 	and	$1, %eax
    272 	jz	L(return_value)
    273 
    274 	POP	(%esi)
    275 
    276 	lea	-16(%edi), %eax
    277 	RETURN
    278 
    279 	CFI_PUSH	(%esi)
    280 
    281 	.p2align 4
    282 L(find_zero_in_second_wchar):
    283 	and	$1 << 5 - 1, %eax
    284 	jz	L(return_value)
    285 
    286 	POP	(%esi)
    287 
    288 	test	$15 << 4, %al
    289 	jnz	L(match_second_wchar)
    290 	lea	-16(%edi), %eax
    291 	RETURN
    292 
    293 	CFI_PUSH	(%esi)
    294 
    295 	.p2align 4
    296 L(find_zero_in_third_or_fourth_wchar):
    297 	test	$15, %ch
    298 	jz	L(find_zero_in_fourth_wchar)
    299 	and	$1 << 9 - 1, %eax
    300 	jz	L(return_value)
    301 
    302 	POP	(%esi)
    303 
    304 	test	%ah, %ah
    305 	jnz	L(match_third_wchar)
    306 	test	$15 << 4, %al
    307 	jnz	L(match_second_wchar)
    308 	lea	-16(%edi), %eax
    309 	RETURN
    310 
    311 	CFI_PUSH	(%esi)
    312 
    313 	.p2align 4
    314 L(find_zero_in_fourth_wchar):
    315 
    316 	POP	(%esi)
    317 
    318 	test	%ah, %ah
    319 	jnz	L(match_third_or_fourth_wchar)
    320 	test	$15 << 4, %al
    321 	jnz	L(match_second_wchar)
    322 	lea	-16(%edi), %eax
    323 	RETURN
    324 
    325 	CFI_PUSH	(%esi)
    326 
    327 	.p2align 4
    328 L(match_second_wchar):
    329 	lea	-12(%edi), %eax
    330 	RETURN
    331 
    332 	.p2align 4
    333 L(match_third_or_fourth_wchar):
    334 	test	$15 << 4, %ah
    335 	jnz	L(match_fourth_wchar)
    336 	lea	-8(%edi), %eax
    337 	RETURN
    338 
    339 	.p2align 4
    340 L(match_third_wchar):
    341 	lea	-8(%edi), %eax
    342 	RETURN
    343 
    344 	.p2align 4
    345 L(match_fourth_wchar):
    346 	lea	-4(%edi), %eax
    347 	RETURN
    348 
    349 	.p2align 4
    350 L(return_null):
    351 	xor	%eax, %eax
    352 	RETURN
    353 
    354 	.p2align 4
    355 L(prolog_find_zero):
    356 	add	%ecx, %edi
    357 	mov     %edx, %ecx
    358 L(prolog_find_zero_1):
    359 	test	%cl, %cl
    360 	jz	L(prolog_find_zero_in_third_or_fourth_wchar)
    361 	test	$15, %cl
    362 	jz	L(prolog_find_zero_in_second_wchar)
    363 	and	$1, %eax
    364 	jz	L(return_null)
    365 
    366 	lea	-16(%edi), %eax
    367 	RETURN
    368 
    369 	.p2align 4
    370 L(prolog_find_zero_in_second_wchar):
    371 	and	$1 << 5 - 1, %eax
    372 	jz	L(return_null)
    373 
    374 	test	$15 << 4, %al
    375 	jnz	L(match_second_wchar)
    376 	lea	-16(%edi), %eax
    377 	RETURN
    378 
    379 	.p2align 4
    380 L(prolog_find_zero_in_third_or_fourth_wchar):
    381 	test	$15, %ch
    382 	jz	L(prolog_find_zero_in_fourth_wchar)
    383 	and	$1 << 9 - 1, %eax
    384 	jz	L(return_null)
    385 
    386 	test	%ah, %ah
    387 	jnz	L(match_third_wchar)
    388 	test	$15 << 4, %al
    389 	jnz	L(match_second_wchar)
    390 	lea	-16(%edi), %eax
    391 	RETURN
    392 
    393 	.p2align 4
    394 L(prolog_find_zero_in_fourth_wchar):
    395 	test	%ah, %ah
    396 	jnz	L(match_third_or_fourth_wchar)
    397 	test	$15 << 4, %al
    398 	jnz	L(match_second_wchar)
    399 	lea	-16(%edi), %eax
    400 	RETURN
    401 
    402 END (wcsrchr)
    403